diff --git a/.clang-format b/.clang-format index e98e5cd7..4e932d02 100644 --- a/.clang-format +++ b/.clang-format @@ -82,6 +82,7 @@ ForEachMacros: "spa_list_for_each", "spa_list_for_each_safe", "wl_list_for_each", + "wl_list_for_each_safe", "wl_array_for_each", "udev_list_entry_foreach", ] diff --git a/.github/cmake/CMakeLists.txt b/.github/cmake/CMakeLists.txt index 39ebaf8b..48757010 100644 --- a/.github/cmake/CMakeLists.txt +++ b/.github/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.0...3.5) project(ci_utils C CXX) set(txt "CC=${CMAKE_C_COMPILER} diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 3ae775af..22645006 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -15,34 +15,37 @@ jobs: fail-fast: false matrix: platform: - - { name: Android.mk } - - { name: CMake, cmake: 1, android_abi: "arm64-v8a", android_platform: 23, arch: "aarch64", artifact: "SDL-android-arm64", apk-artifact: "SDL-android-apks-arm64" } + - { name: "Android.mk" } + - { name: "CMake", cmake: 1, android_abi: "arm64-v8a", android_platform: 23, arch: "aarch64", artifact: "SDL-android-arm64", apk-artifact: "SDL-android-apks-arm64" } + - { name: "CMake (lean and mean)", cmake: 1, cppflags: "-DSDL_LEAN_AND_MEAN=1", android_abi: "arm64-v8a", android_platform: 23, arch: "aarch64", artifact: "SDL-lean-android-arm64", apk-artifact: "SDL-lean-android-apks-arm64" } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: nttld/setup-ndk@v1 id: setup_ndk with: local-cache: true ndk-version: r21e - name: Build (Android.mk) - if: ${{ matrix.platform.name == 'Android.mk' }} + if: ${{ contains(matrix.platform.name, 'Android.mk') }} run: | ./build-scripts/androidbuildlibs.sh - - uses: actions/setup-java@v3 - if: ${{ matrix.platform.name == 'CMake' }} + - uses: actions/setup-java@v4 + if: ${{ contains(matrix.platform.name, 'CMake') }} with: distribution: 'temurin' java-version: '11' - name: Setup (CMake) - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | sudo apt-get update sudo apt-get install ninja-build pkg-config - name: Configure (CMake) - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | cmake -S . -B build \ + -DCMAKE_C_FLAGS="${{ matrix.platform.cppflags }}" \ + -DCMAKE_CXX_FLAGS="${{ matrix.platform.cppflags }}" \ -Wdeprecated -Wdev -Werror \ -DCMAKE_TOOLCHAIN_FILE=${{ steps.setup_ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \ -DSDL_WERROR=ON \ @@ -59,25 +62,25 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -GNinja - name: Build (CMake) - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | cmake --build build --config Release --parallel --verbose - name: Build test apk's (CMake) - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | cmake --build build --config Release --parallel --verbose --target testaudiocapture-apk testcontroller-apk testmultiaudio-apk testsprite-apk - name: Install (CMake) - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | cmake --install build --config Release echo "SDL3_DIR=$(pwd)/prefix" >> $GITHUB_ENV ( cd prefix; find ) | LC_ALL=C sort -u - name: Package (CPack) - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | cmake --build build/ --config Release --target package - name: Verify CMake configuration files - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | cmake -S cmake/test -B cmake_config_build -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=${{ steps.setup_ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \ @@ -87,19 +90,19 @@ jobs: -DCMAKE_PREFIX_PATH=${{ env.SDL3_DIR }} cmake --build cmake_config_build --verbose - name: Verify sdl3.pc - if: ${{ matrix.platform.name == 'CMake' }} + if: ${{ contains(matrix.platform.name, 'CMake') }} run: | export CC="${{ steps.setup_ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=${{ matrix.platform.arch }}-none-linux-androideabi${{ matrix.platform.android_platform }}" export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 - if: ${{ matrix.platform.name == 'CMake' }} + - uses: actions/upload-artifact@v4 + if: ${{ contains(matrix.platform.name, 'CMake') }} with: if-no-files-found: error name: ${{ matrix.platform.artifact }} path: build/dist/SDL3* - - uses: actions/upload-artifact@v3 - if: ${{ matrix.platform.name == 'CMake' }} + - uses: actions/upload-artifact@v4 + if: ${{ contains(matrix.platform.name, 'CMake') }} with: if-no-files-found: error name: ${{ matrix.platform.apk-artifact }} diff --git a/.github/workflows/cpactions.yml b/.github/workflows/cpactions.yml index 7591c0dc..02ae6a42 100644 --- a/.github/workflows/cpactions.yml +++ b/.github/workflows/cpactions.yml @@ -26,9 +26,9 @@ jobs: install-cmd: 'sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1', } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build - uses: cross-platform-actions/action@v0.21.1 + uses: cross-platform-actions/action@v0.23.0 with: operating_system: ${{ matrix.platform.os }} architecture: ${{ matrix.platform.os-arch }} @@ -49,7 +49,7 @@ jobs: rm -rf build/CMakeFiles rm -rf build/docs - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: ${{ matrix.platform.artifact }} diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml index 116b811a..eedbb42b 100644 --- a/.github/workflows/emscripten.yml +++ b/.github/workflows/emscripten.yml @@ -10,8 +10,8 @@ jobs: emscripten: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: mymindstorm/setup-emsdk@v12 + - uses: actions/checkout@v4 + - uses: mymindstorm/setup-emsdk@v14 with: version: 3.1.35 - name: Install ninja @@ -51,7 +51,7 @@ jobs: -DTEST_SHARED=FALSE \ -DCMAKE_PREFIX_PATH=${{ env.SDL3_DIR }} cmake --build cmake_config_build --verbose - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-emscripten diff --git a/.github/workflows/haiku.yml b/.github/workflows/haiku.yml index 468d281d..b1caee98 100644 --- a/.github/workflows/haiku.yml +++ b/.github/workflows/haiku.yml @@ -8,7 +8,7 @@ jobs: name: Haiku container: haiku/cross-compiler:x86_64-r1beta4 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup dependencies run: | apt-get install pkg-config -y @@ -50,7 +50,7 @@ jobs: run: | export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-haiku diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index b36f29db..f791e89d 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -19,6 +19,6 @@ jobs: - { name: tvOS, target: SDL3, sdk: appletvos } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: xcodebuild -project Xcode/SDL/SDL.xcodeproj -target '${{ matrix.platform.target }}' -configuration Release -sdk ${{ matrix.platform.sdk }} clean build diff --git a/.github/workflows/loongarch64.yml b/.github/workflows/loongarch64.yml index f45e1fad..ae46e3e1 100644 --- a/.github/workflows/loongarch64.yml +++ b/.github/workflows/loongarch64.yml @@ -15,13 +15,13 @@ jobs: platform: - { toolchain-version: 2022.09.06 } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install build requirements run: | sudo apt-get update -y sudo apt-get install -y --no-install-recommends cmake ninja-build pkg-config tar wget - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 id: restore-cache with: path: /opt/cross-tools @@ -85,7 +85,7 @@ jobs: run: | export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-loongarch64 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9cfb6a84..66b68983 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,7 +89,7 @@ jobs: # Install oneAPI sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check that versioning is consistent # We only need to run this once: arbitrarily use the Linux/CMake build if: "runner.os == 'Linux'" @@ -149,7 +149,7 @@ jobs: ${{ matrix.platform.source_cmd }} export PKG_CONFIG_PATH=$(echo "${{ github.workspace }}/cmake_prefix/lib/pkgconfig" | sed -e 's#\\#/#g') cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: ${{ always() && steps.build.outcome == 'success' }} with: if-no-files-found: error diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml index 9195a94e..fa2b405f 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/msvc.yml @@ -17,8 +17,6 @@ jobs: platform: - { name: Windows (x64), flags: -A x64, project: VisualC/SDL.sln, projectflags: '/p:Platform=x64', artifact: 'SDL-VC-x64' } - { name: Windows (x86), flags: -A Win32, project: VisualC/SDL.sln, projectflags: '/p:Platform=Win32', artifact: 'SDL-VC-x86' } - - { name: Windows static VCRT (x64), flags: -A x64 -DSDL_FORCE_STATIC_VCRT=ON, artifact: 'SDL-VC-static-VCRT-x64' } - - { name: Windows static VCRT (x86), flags: -A Win32 -DSDL_FORCE_STATIC_VCRT=ON, artifact: 'SDL-VC-static-VCRT-x86' } - { name: Windows (clang-cl x64), flags: -T ClangCL -A x64, artifact: 'SDL-clang-cl-x64' } - { name: Windows (clang-cl x86), flags: -T ClangCL -A Win32, artifact: 'SDL-clang-cl-x86' } - { name: Windows (ARM), flags: -A ARM, artifact: 'SDL-VC-arm32', notests: true } @@ -27,7 +25,7 @@ jobs: project: VisualC-WinRT/SDL-UWP.sln, projectflags: '/p:Platform=x64 /p:WindowsTargetPlatformVersion=10.0.17763.0', artifact: 'SDL-VC-UWP' } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Create CMake project using SDL as a subproject shell: python run: | @@ -90,11 +88,11 @@ jobs: - name: Add msbuild to PATH if: ${{ matrix.platform.project != '' }} - uses: microsoft/setup-msbuild@v1.1.3 + uses: microsoft/setup-msbuild@v2 - name: Build msbuild if: ${{ matrix.platform.project != '' }} run: msbuild ${{ matrix.platform.project }} /m /p:BuildInParallel=true /p:Configuration=Release ${{ matrix.platform.projectflags }} - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: ${{ always() && steps.build.outcome == 'success' }} with: if-no-files-found: error diff --git a/.github/workflows/n3ds.yml b/.github/workflows/n3ds.yml index 42d6dd40..dcf99a12 100644 --- a/.github/workflows/n3ds.yml +++ b/.github/workflows/n3ds.yml @@ -12,7 +12,7 @@ jobs: container: image: devkitpro/devkitarm:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install build requirements run: | apt update @@ -58,7 +58,7 @@ jobs: run: | export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-n3ds diff --git a/.github/workflows/ppc64le.yml b/.github/workflows/ppc64le.yml index 36be9b2c..4d8190e3 100644 --- a/.github/workflows/ppc64le.yml +++ b/.github/workflows/ppc64le.yml @@ -12,7 +12,7 @@ jobs: container: image: dockcross/linux-ppc64le:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install build requirements run: | apt-get update -y @@ -54,7 +54,7 @@ jobs: run: | export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-ppc64le diff --git a/.github/workflows/ps2.yml b/.github/workflows/ps2.yml index 834ab99e..2b882161 100644 --- a/.github/workflows/ps2.yml +++ b/.github/workflows/ps2.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest container: ps2dev/ps2dev:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup dependencies run: | apk update @@ -53,7 +53,7 @@ jobs: export LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/gsKit/lib -L$PS2DEV/ps2sdk/ports/lib" export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-ps2 diff --git a/.github/workflows/psp.yml b/.github/workflows/psp.yml index 333bd64d..62adb841 100644 --- a/.github/workflows/psp.yml +++ b/.github/workflows/psp.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest container: pspdev/pspdev:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup dependencies run: | apk update @@ -54,7 +54,7 @@ jobs: export LDFLAGS="-L$PSPDEV/lib -L$PSPDEV/psp/lib -L$PSPDEV/psp/sdk/lib" export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-psp diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..98148710 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,425 @@ +name: 'release' +run-name: 'Create SDL release artifacts for ${{ inputs.commit }}' + +on: + workflow_dispatch: + inputs: + commit: + description: 'Commit of SDL' + required: true + +jobs: + + src: + runs-on: ubuntu-latest + outputs: + project: ${{ steps.releaser.outputs.project }} + version: ${{ steps.releaser.outputs.version }} + src-tar-gz: ${{ steps.releaser.outputs.src-tar-gz }} + src-tar-xz: ${{ steps.releaser.outputs.src-tar-xz }} + src-zip: ${{ steps.releaser.outputs.src-zip }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Set up SDL sources' + uses: actions/checkout@v4 + with: + path: 'SDL' + fetch-depth: 0 + - name: 'Build Source archive' + id: releaser + shell: bash + run: | + python build-scripts/build-release.py \ + --create source \ + --commit ${{ inputs.commit }} \ + --project SDL3 \ + --root "${{ github.workspace }}/SDL" \ + --github \ + --debug + - name: 'Store source archives' + uses: actions/upload-artifact@v4 + with: + name: sources + path: '${{ github.workspace}}/dist' + + linux-verify: + needs: [src] + runs-on: ubuntu-latest + steps: + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Unzip ${{ needs.src.outputs.src-zip }}' + id: zip + run: | + mkdir /tmp/zipdir + cd /tmp/zipdir + unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}" + echo "path=/tmp/zipdir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Compare contents of ${{ needs.src.outputs.src-zip }} and ${{ needs.src.outputs.src-tar-gz }}' + run: | + diff /tmp/zipdir /tmp/tardir + - name: 'Test versioning' + shell: bash + run: | + ${{ steps.tar.outputs.path }}/build-scripts/test-versioning.sh + - name: 'CMake (configure + build + tests)' + run: | + cmake -S ${{ steps.tar.outputs.path }} -B /tmp/build -DSDL_TEST_LIBRARY=TRUE -DSDL_TESTS=TRUE + cmake --build /tmp/build --verbose + ctest --test-dir /tmp/build --no-tests=error --output-on-failure + + dmg: + needs: [src] + runs-on: macos-latest + outputs: + dmg: ${{ steps.releaser.outputs.dmg }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Build SDL3.dmg' + id: releaser + shell: bash + run: | + python build-scripts/build-release.py \ + --create xcframework \ + --commit ${{ inputs.commit }} \ + --project SDL3 \ + --root "${{ steps.tar.outputs.path }}" \ + --github \ + --debug + - name: 'Store DMG image file' + uses: actions/upload-artifact@v4 + with: + name: dmg + path: '${{ github.workspace }}/dist' + + dmg-verify: + needs: [dmg, src] + runs-on: macos-latest + steps: + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Download ${{ needs.dmg.outputs.dmg }}' + uses: actions/download-artifact@v4 + with: + name: dmg + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: src + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Mount ${{ needs.dmg.outputs.dmg }}' + id: mount + run: | + hdiutil attach '${{ github.workspace }}/${{ needs.dmg.outputs.dmg }}' + mount_point="/Volumes/${{ needs.src.outputs.project }}" + if [ ! -d "$mount_point/${{ needs.src.outputs.project }}.xcframework" ]; then + echo "Cannot find ${{ needs.src.outputs.project }}.xcframework!" + exit 1 + fi + echo "mount_point=$mount_point">>$GITHUB_OUTPUT + - name: 'CMake (configure + build) Darwin' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_FULL=FALSE \ + -DTEST_STATIC=FALSE \ + -DTEST_TEST=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \ + -DCMAKE_SYSTEM_NAME=Darwin \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -Werror=dev \ + -B build_darwin + cmake --build build_darwin --config Release --verbose + - name: 'CMake (configure + build) iOS' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_FULL=FALSE \ + -DTEST_STATIC=FALSE \ + -DTEST_TEST=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -Werror=dev \ + -B build_ios + cmake --build build_ios --config Release --verbose + - name: 'CMake (configure + build) tvOS' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_FULL=FALSE \ + -DTEST_STATIC=FALSE \ + -DTEST_TEST=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -Werror=dev \ + -B build_tvos + cmake --build build_tvos --config Release --verbose + - name: 'CMake (configure + build) iOS simulator' + run: | + sysroot=$(xcodebuild -version -sdk iphonesimulator Path) + echo "sysroot=$sysroot" + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_FULL=FALSE \ + -DTEST_STATIC=FALSE \ + -DTEST_TEST=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_OSX_SYSROOT="${sysroot}" \ + -Werror=dev \ + -B build_ios_simulator + cmake --build build_ios_simulator --config Release --verbose + - name: 'CMake (configure + build) tvOS simulator' + run: | + sysroot=$(xcodebuild -version -sdk appletvsimulator Path) + echo "sysroot=$sysroot" + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_FULL=FALSE \ + -DTEST_STATIC=FALSE \ + -DTEST_TEST=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount_point }}" \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_OSX_SYSROOT="${sysroot}" \ + -Werror=dev \ + -B build_tvos_simulator + cmake --build build_tvos_simulator --config Release --verbose + + msvc: + needs: [src] + runs-on: windows-2019 + outputs: + VC-x86: ${{ steps.releaser.outputs.VC-x86 }} + VC-x64: ${{ steps.releaser.outputs.VC-x64 }} + VC-devel: ${{ steps.releaser.outputs.VC-devel }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Unzip ${{ needs.src.outputs.src-zip }}' + id: zip + run: | + mkdir C:\zipdir + cd C:\zipdir + unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}" + echo "path=C:\zipdir\${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$Env:GITHUB_OUTPUT + - name: 'Build MSVC binary archives' + id: releaser + run: | + python build-scripts/build-release.py ` + --create win32 ` + --commit ${{ inputs.commit }} ` + --project SDL3 ` + --root "${{ steps.zip.outputs.path }}" ` + --github ` + --debug + - name: 'Store MSVC archives' + uses: actions/upload-artifact@v4 + with: + name: win32 + path: '${{ github.workspace }}/dist' + + msvc-verify: + needs: [msvc, src] + runs-on: windows-latest + steps: + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Download MSVC binaries' + uses: actions/download-artifact@v4 + with: + name: win32 + path: '${{ github.workspace }}' + - name: 'Unzip ${{ needs.src.outputs.src-zip }}' + id: src + run: | + mkdir '${{ github.workspace }}/sources' + cd '${{ github.workspace }}/sources' + unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}" + echo "path=${{ github.workspace }}/sources/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT + - name: 'Unzip ${{ needs.msvc.outputs.VC-devel }}' + id: bin + run: | + mkdir '${{ github.workspace }}/vc' + cd '${{ github.workspace }}/vc' + unzip "${{ github.workspace }}/${{ needs.msvc.outputs.VC-devel }}" + echo "path=${{ github.workspace }}/vc/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT + - name: 'CMake (configure + build + tests) x86' + run: | + $env:PATH += ";${{ steps.bin.outputs.path }}/x86" + cmake -S "${{ steps.src.outputs.path }}/cmake/test" ` + -DTEST_FULL=TRUE ` + -DTEST_STATIC=FALSE ` + -DTEST_TEST=TRUE ` + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}" ` + -Werror=dev ` + -B build_x86 -A win32 + cmake --build build_x86 --config Release --verbose + ctest --test-dir build_x86 --no-tests=error -C Release --output-on-failure + - name: 'CMake (configure + build + tests) x64' + run: | + $env:PATH += ";${{ steps.bin.outputs.path }}/x86" + cmake -S "${{ steps.src.outputs.path }}/cmake/test" ` + -DTEST_FULL=TRUE ` + -DTEST_STATIC=FALSE ` + -DTEST_TEST=TRUE ` + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}" ` + -Werror=dev ` + -B build_x64 -A x64 + cmake --build build_x64 --config Release --verbose + ctest --test-dir build_x64 --no-tests=error -C Release --output-on-failure + + + mingw: + needs: [src] + runs-on: ubuntu-latest + outputs: + mingw-devel-tar-gz: ${{ steps.releaser.outputs.mingw-devel-tar-gz }} + mingw-devel-tar-xz: ${{ steps.releaser.outputs.mingw-devel-tar-xz }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Install Mingw toolchain' + run: | + sudo apt-get update -y + sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 ninja-build + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Build MinGW binary archives' + id: releaser + run: | + python build-scripts/build-release.py \ + --create mingw \ + --commit ${{ inputs.commit }} \ + --project SDL3 \ + --root "${{ steps.tar.outputs.path }}" \ + --github \ + --debug + - name: 'Store MinGW archives' + uses: actions/upload-artifact@v4 + with: + name: mingw + path: '${{ github.workspace }}/dist' + + mingw-verify: + needs: [mingw, src] + runs-on: ubuntu-latest + steps: + - name: 'Install Mingw toolchain' + run: | + sudo apt-get update -y + sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 ninja-build + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Download MinGW binaries' + uses: actions/download-artifact@v4 + with: + name: mingw + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: src + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Untar ${{ needs.mingw.outputs.mingw-devel-tar-gz }}' + id: bin + run: | + mkdir -p /tmp/mingw-tardir + tar -C /tmp/mingw-tardir -v -x -f "${{ github.workspace }}/${{ needs.mingw.outputs.mingw-devel-tar-gz }}" + echo "path=/tmp/mingw-tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'CMake (configure + build) i686' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DCMAKE_BUILD_TYPE="Release" \ + -DTEST_FULL=TRUE \ + -DTEST_STATIC=TRUE \ + -DTEST_TEST=TRUE \ + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}" \ + -DCMAKE_TOOLCHAIN_FILE="${{ steps.src.outputs.path }}/build-scripts/cmake-toolchain-mingw64-i686.cmake" \ + -DCMAKE_C_FLAGS="-DSDL_DISABLE_SSE4_2" \ + -Werror=dev \ + -B build_x86 + cmake --build build_x86 --config Release --verbose + - name: 'CMake (configure + build) x86_64' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DCMAKE_BUILD_TYPE="Release" \ + -DTEST_FULL=TRUE \ + -DTEST_STATIC=TRUE \ + -DTEST_TEST=TRUE \ + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }}" \ + -DCMAKE_TOOLCHAIN_FILE="${{ steps.src.outputs.path }}/build-scripts/cmake-toolchain-mingw64-x86_64.cmake" \ + -DCMAKE_C_FLAGS="-DSDL_DISABLE_SSE4_2" \ + -Werror=dev \ + -B build_x64 + cmake --build build_x64 --config Release --verbose diff --git a/.github/workflows/riscos.yml b/.github/workflows/riscos.yml index 2f1869e3..1fff8009 100644 --- a/.github/workflows/riscos.yml +++ b/.github/workflows/riscos.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Setup dependencies run: apt-get update && apt-get install -y cmake ninja-build - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Configure (CMake) if: ${{ contains(matrix.platform.name, 'CMake') }} run: | @@ -57,7 +57,7 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ ${{ matrix.platform.test_args }} cmake --build cmake_config_build --verbose - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: SDL-riscos diff --git a/.github/workflows/visionos.yml.disabled b/.github/workflows/visionos.yml.disabled index f697543b..d02a74f8 100644 --- a/.github/workflows/visionos.yml.disabled +++ b/.github/workflows/visionos.yml.disabled @@ -13,7 +13,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Configure run: | cmake -B build -GXcode -DCMAKE_SYSTEM_NAME=visionOS diff --git a/.github/workflows/vita.yml b/.github/workflows/vita.yml index 6c8f14a5..dddc4251 100644 --- a/.github/workflows/vita.yml +++ b/.github/workflows/vita.yml @@ -24,13 +24,13 @@ jobs: - { name: Vita (GLES w/ PVR_PSP2 + gles4vita), pvr: true, version: 3.9, artifact: SDL-vita-pvr } steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install build requirements run: | apk update apk add cmake ninja pkgconf bash tar - - uses: actions/cache/restore@v3 + - uses: actions/cache/restore@v4 id: restore-cache with: path: /vita/dependencies @@ -77,7 +77,7 @@ jobs: wget https://github.com/SonicMastr/gl4es4vita/releases/download/v$gl4es4vita_version-vita/vitasdk_stubs.zip -P/tmp unzip /tmp/vitasdk_stubs.zip -d/vita/dependencies/lib - - uses: actions/cache/save@v3 + - uses: actions/cache/save@v4 if: ${{ !steps.restore-cache.outputs.cache-hit }} with: path: /vita/dependencies @@ -129,7 +129,7 @@ jobs: export CC=arm-vita-eabi-gcc export PKG_CONFIG_PATH=${{ env.SDL3_DIR }}/lib/pkgconfig cmake/test/test_pkgconfig.sh - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: if-no-files-found: error name: ${{ matrix.platform.artifact }} diff --git a/.gitignore b/.gitignore index 9e577f49..87d76dac 100644 --- a/.gitignore +++ b/.gitignore @@ -79,7 +79,8 @@ VisualC/tests/testscale/sample.bmp VisualC/tests/testsprite/icon.bmp VisualC/tests/testyuv/testyuv.bmp VisualC-GDK/**/Layout -VisualC-GDK/shaders/*.h +src/render/direct3d12/D3D12_*_One.h +src/render/direct3d12/D3D12_*_Series.h # for Android android-project/local.properties diff --git a/Android.mk b/Android.mk index 3779eb53..a60a0d36 100644 --- a/Android.mk +++ b/Android.mk @@ -24,6 +24,9 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/audio/openslES/*.c) \ $(LOCAL_PATH)/src/atomic/SDL_atomic.c.arm \ $(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \ + $(wildcard $(LOCAL_PATH)/src/camera/*.c) \ + $(wildcard $(LOCAL_PATH)/src/camera/android/*.c) \ + $(wildcard $(LOCAL_PATH)/src/camera/dummy/*.c) \ $(wildcard $(LOCAL_PATH)/src/core/*.c) \ $(wildcard $(LOCAL_PATH)/src/core/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \ @@ -41,11 +44,15 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \ $(wildcard $(LOCAL_PATH)/src/locale/*.c) \ $(wildcard $(LOCAL_PATH)/src/locale/android/*.c) \ + $(wildcard $(LOCAL_PATH)/src/main/*.c) \ + $(wildcard $(LOCAL_PATH)/src/main/generic/*.c) \ $(wildcard $(LOCAL_PATH)/src/misc/*.c) \ $(wildcard $(LOCAL_PATH)/src/misc/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/power/*.c) \ $(wildcard $(LOCAL_PATH)/src/power/android/*.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/render/*.c) \ @@ -53,6 +60,8 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \ $(wildcard $(LOCAL_PATH)/src/thread/*.c) \ $(wildcard $(LOCAL_PATH)/src/thread/pthread/*.c) \ + $(wildcard $(LOCAL_PATH)/src/time/*.c) \ + $(wildcard $(LOCAL_PATH)/src/time/unix/*.c) \ $(wildcard $(LOCAL_PATH)/src/timer/*.c) \ $(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \ $(wildcard $(LOCAL_PATH)/src/video/*.c) \ diff --git a/CMakeLists.txt b/CMakeLists.txt index d19ad993..ce022579 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ endif() set(CMAKE_POLICY_DEFAULT_CMP0091 NEW) # See docs/release_checklist.md -project(SDL3 LANGUAGES C CXX VERSION "3.0.0") +project(SDL3 LANGUAGES C VERSION "3.1.0") if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(SDL3_SUBPROJECT OFF) @@ -133,8 +133,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. -# TODO: Windows can support libusb, the hid.c file just depends on Unix APIs -if((WINDOWS AND NOT WINDOWS_STORE) OR IOS OR TVOS OR VISIONOS OR ANDROID) +if(IOS OR TVOS OR VISIONOS OR ANDROID) set(SDL_HIDAPI_LIBUSB_AVAILABLE FALSE) else() set(SDL_HIDAPI_LIBUSB_AVAILABLE TRUE) @@ -153,14 +152,13 @@ endif() # Default option knobs set(SDL_LIBC_DEFAULT ON) set(SDL_SYSTEM_ICONV_DEFAULT ON) -if(WINDOWS) - set(SDL_LIBC_DEFAULT OFF) +if(WINDOWS OR IOS OR TVOS OR VISIONOS) set(SDL_SYSTEM_ICONV_DEFAULT OFF) endif() if(MSVC) - option(SDL_FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF) - if(SDL_FORCE_STATIC_VCRT) + 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() @@ -204,20 +202,12 @@ if(EMSCRIPTEN) # Set up default values for the currently supported set of subsystems: # Emscripten/Javascript does not have assembly support, a dynamic library # loading architecture, or low-level CPU inspection. - - # SDL_THREADS_DEFAULT now defaults to ON, but pthread support might be disabled by default. - # !!! FIXME: most of these subsystems should default to ON if there are dummy implementations to be used. - set(SDL_ASSEMBLY_DEFAULT OFF) set(SDL_SHARED_AVAILABLE OFF) - set(SDL_ATOMIC_DEFAULT OFF) - set(SDL_LOADSO_DEFAULT OFF) - set(SDL_CPUINFO_DEFAULT OFF) endif() if(VITA OR PSP OR PS2 OR N3DS OR RISCOS) set(SDL_SHARED_AVAILABLE OFF) - set(SDL_LOADSO_DEFAULT OFF) endif() if((RISCOS OR UNIX_SYS) AND NOT (LINUX OR NETBSD OR OPENBSD)) @@ -240,39 +230,44 @@ if(SDL_SHARED_DEFAULT AND SDL_STATIC_DEFAULT AND SDL_SHARED_AVAILABLE) endif() endif() -set(SDL_SUBSYSTEMS - Atomic - Audio - Video - Render - Events - Joystick - Haptic - Hidapi - Power - Threads - Timers - File - Loadso - CPUinfo - Filesystem - Sensor - Locale - Misc -) -foreach(_SUB IN LISTS SDL_SUBSYSTEMS) - string(TOUPPER ${_SUB} _OPT) - if(NOT DEFINED SDL_${_OPT}_DEFAULT) - set(SDL_${_OPT}_DEFAULT ON) +set(SDL_SUBSYSTEMS ) + +macro(define_sdl_subsystem _name) + cmake_parse_arguments("_ds" "" "" "DEPS" ${ARGN}) + string(TOUPPER ${_name} _uname) + if(NOT DEFINED SDL_${_uname}_DEFAULT) + set(SDL_${_uname}_DEFAULT ON) endif() - option(SDL_${_OPT} "Enable the ${_SUB} subsystem" ${SDL_${_OPT}_DEFAULT}) -endforeach() + if(_ds_DEPS) + cmake_dependent_option(SDL_${_uname} "Enable the ${_name} subsystem" "${SDL_${_uname}_DEFAULT}" "${_ds_DEPS}" OFF) + else() + option(SDL_${_uname} "Enable the ${_name} subsystem" "${SDL_${_uname}_DEFAULT}") + endif() + list(APPEND SDL_SUBSYSTEMS "${_name}") +endmacro() + +define_sdl_subsystem(Audio) +define_sdl_subsystem(Video) +define_sdl_subsystem(Render DEPS SDL_VIDEO) +define_sdl_subsystem(Camera DEPS SDL_VIDEO) +define_sdl_subsystem(Joystick) +define_sdl_subsystem(Haptic) +define_sdl_subsystem(Hidapi) +define_sdl_subsystem(Power) +define_sdl_subsystem(Sensor) +define_sdl_subsystem(Dialog) cmake_dependent_option(SDL_FRAMEWORK "Build SDL libraries as Apple Framework" OFF "APPLE" OFF) if(SDL_FRAMEWORK) set(SDL_STATIC_AVAILABLE FALSE) endif() +if(UNIX AND NOT ANDROID AND NOT RISCOS AND NOT SDL_FRAMEWORK) + set(SDL_RPATH_DEFAULT ON) +else() + set(SDL_RPATH_DEFAULT OFF) +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) @@ -303,54 +298,55 @@ set_option(SDL_LIBC "Use the system C library" ${SDL_LIBC_DEFAULT set_option(SDL_SYSTEM_ICONV "Use iconv() from system-installed libraries" ${SDL_SYSTEM_ICONV_DEFAULT}) set_option(SDL_LIBICONV "Prefer iconv() from libiconv, if available, over libc version" OFF) set_option(SDL_GCC_ATOMICS "Use gcc builtin atomics" ${SDL_GCC_ATOMICS_DEFAULT}) -dep_option(SDL_DBUS "Enable D-Bus support" ON ${UNIX_SYS} OFF) -set_option(SDL_DISKAUDIO "Support the disk writer audio driver" ON) -set_option(SDL_DUMMYAUDIO "Support the dummy audio driver" ON) -set_option(SDL_DUMMYVIDEO "Use dummy video driver" ON) -dep_option(SDL_IBUS "Enable IBus support" ON ${UNIX_SYS} OFF) -dep_option(SDL_OPENGL "Include OpenGL support" ON "NOT VISIONOS" OFF) -dep_option(SDL_OPENGLES "Include OpenGL ES support" ON "NOT VISIONOS" OFF) +dep_option(SDL_DBUS "Enable D-Bus support" ON "${UNIX_SYS}" OFF) +dep_option(SDL_DISKAUDIO "Support the disk writer audio driver" ON "SDL_AUDIO" OFF) +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) 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" OFF) -set_option(SDL_ALSA "Support the ALSA audio API" ${UNIX_SYS}) +dep_option(SDL_OSS "Support the OSS audio API" ${SDL_OSS_DEFAULT} "UNIX_SYS OR RISCOS;SDL_AUDIO" OFF) +dep_option(SDL_ALSA "Support the ALSA audio API" ${UNIX_SYS} "SDL_AUDIO" OFF) dep_option(SDL_ALSA_SHARED "Dynamically load ALSA audio support" ON "SDL_ALSA" OFF) -set_option(SDL_JACK "Support the JACK audio API" ${UNIX_SYS}) +dep_option(SDL_JACK "Support the JACK audio API" ${UNIX_SYS} "SDL_AUDIO" OFF) dep_option(SDL_JACK_SHARED "Dynamically load JACK audio support" ON "SDL_JACK" OFF) set_option(SDL_PIPEWIRE "Use Pipewire audio" ${UNIX_SYS}) dep_option(SDL_PIPEWIRE_SHARED "Dynamically load Pipewire support" ON "SDL_PIPEWIRE" OFF) -set_option(SDL_PULSEAUDIO "Use PulseAudio" ${UNIX_SYS}) +dep_option(SDL_PULSEAUDIO "Use PulseAudio" ${UNIX_SYS} "SDL_AUDIO" OFF) dep_option(SDL_PULSEAUDIO_SHARED "Dynamically load PulseAudio support" ON "SDL_PULSEAUDIO" OFF) -set_option(SDL_SNDIO "Support the sndio audio API" ${UNIX_SYS}) +dep_option(SDL_SNDIO "Support the sndio audio API" ${UNIX_SYS} "SDL_AUDIO" OFF) dep_option(SDL_SNDIO_SHARED "Dynamically load the sndio audio API" ON "SDL_SNDIO" OFF) -set_option(SDL_RPATH "Use an rpath when linking SDL" ${UNIX_SYS}) +set_option(SDL_RPATH "Use an rpath when linking SDL" ${SDL_RPATH_DEFAULT}) set_option(SDL_CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" ${SDL_CLOCK_GETTIME_DEFAULT}) -set_option(SDL_X11 "Use X11 video driver" ${UNIX_SYS}) +dep_option(SDL_X11 "Use X11 video driver" ${UNIX_SYS} "SDL_VIDEO" OFF) dep_option(SDL_X11_SHARED "Dynamically load X11 support" ON "SDL_X11" OFF) set(SDL_X11_OPTIONS Xcursor Xdbe XInput Xfixes Xrandr Xscrnsaver XShape) foreach(_SUB ${SDL_X11_OPTIONS}) string(TOUPPER "SDL_X11_${_SUB}" _OPT) dep_option(${_OPT} "Enable ${_SUB} support" ON "SDL_X11" OFF) endforeach() -set_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS}) +dep_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS} "SDL_VIDEO" OFF) dep_option(SDL_WAYLAND_SHARED "Dynamically load Wayland support" ON "SDL_WAYLAND" OFF) dep_option(SDL_WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF) dep_option(SDL_WAYLAND_LIBDECOR_SHARED "Dynamically load libdecor support" ON "SDL_WAYLAND_LIBDECOR;SDL_WAYLAND_SHARED" OFF) -dep_option(SDL_RPI "Use Raspberry Pi video driver" ON "UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) -dep_option(SDL_ROCKCHIP "Use ROCKCHIP Hardware Acceleration video driver" ON "UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) -set_option(SDL_COCOA "Use Cocoa video driver" ${APPLE}) -set_option(SDL_DIRECTX "Use DirectX for Windows audio/video" ${WINDOWS}) -set_option(SDL_XINPUT "Use Xinput for Windows" ${WINDOWS}) -set_option(SDL_WASAPI "Use the Windows WASAPI audio driver" ${WINDOWS}) -set_option(SDL_RENDER_D3D "Enable the Direct3D render driver" ${WINDOWS}) -set_option(SDL_RENDER_METAL "Enable the Metal render driver" ${APPLE}) +dep_option(SDL_RPI "Use Raspberry Pi video driver" ON "SDL_VIDEO;UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) +dep_option(SDL_ROCKCHIP "Use ROCKCHIP Hardware Acceleration video driver" ON "SDL_VIDEO;UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) +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_METAL "Enable the Metal render driver" ON "SDL_RENDER;${APPLE}" 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 "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF) -set_option(SDL_METAL "Enable Metal support" ${APPLE}) -set_option(SDL_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS}) +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_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) set_option(SDL_OFFSCREEN "Use offscreen video driver" ON) -dep_option(SDL_VIDEO_CAPTURE "Enable video capturing" ON SDL_VIDEO OFF) +dep_option(SDL_DUMMYCAMERA "Support the dummy camera driver" ON SDL_CAMERA OFF) option_string(SDL_BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" OFF) option_string(SDL_FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" OFF) dep_option(SDL_HIDAPI "Enable the HIDAPI subsystem" ON "NOT VISIONOS" OFF) @@ -390,14 +386,22 @@ if(SDL_SHARED) add_library(SDL3-shared SHARED) add_library(SDL3::SDL3-shared ALIAS SDL3-shared) SDL_AddCommonCompilerFlags(SDL3-shared) - target_compile_features(SDL3-shared PRIVATE c_std_99) + if ("c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES) + target_compile_features(SDL3-shared PRIVATE c_std_99) + else() + message(WARNING "target_compile_features does not know c_std_99 for C compiler") + endif() endif() if(SDL_STATIC) add_library(SDL3-static STATIC) add_library(SDL3::SDL3-static ALIAS SDL3-static) SDL_AddCommonCompilerFlags(SDL3-static) - target_compile_features(SDL3-static PRIVATE c_std_99) + if ("c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES) + target_compile_features(SDL3-static PRIVATE c_std_99) + else() + message(WARNING "target_compile_features does not know c_std_99 for C compiler") + endif() endif() if(SDL_TEST_LIBRARY) @@ -472,11 +476,13 @@ 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" @@ -489,7 +495,9 @@ sdl_glob_sources( "${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" @@ -584,7 +592,6 @@ if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC) cmake_pop_check_state() if(APPLE) - # FIXME: don't use deprecated declarations check_c_compiler_flag(-Wno-error=deprecated-declarations COMPILER_SUPPORTS_WNO_ERROR_DEPRECATED_DECLARATIONS) if(COMPILER_SUPPORTS_WNO_ERROR_DEPRECATED_DECLARATIONS) sdl_compile_options(PRIVATE "-Wno-error=deprecated-declarations") @@ -857,6 +864,7 @@ if(SDL_ASSEMBLY) cmake_pop_check_state() if(COMPILER_SUPPORTS_LSX AND HAVE_LSXINTRIN_H) + set_property(SOURCE "${SDL3_SOURCE_DIR}/src/video/yuv2rgb/yuv_rgb_lsx.c" APPEND PROPERTY COMPILE_OPTIONS "-mlsx") set(HAVE_LSX TRUE) endif() endif() @@ -1037,6 +1045,7 @@ if(SDL_LIBC) string.h strings.h sys/types.h + time.h wchar.h ) foreach(_HEADER IN LISTS headers_to_check) @@ -1052,7 +1061,7 @@ if(SDL_LIBC) set(symbols_to_check abs acos acosf asin asinf atan atan2 atan2f atanf atof atoi - bcopy bsearch + bcopy calloc ceil ceilf copysign copysignf cos cosf _Exit exp expf fabs fabsf floor floorf fmod fmodf fopen64 free fseeko fseeko64 @@ -1061,7 +1070,6 @@ if(SDL_LIBC) log log10 log10f logf lround lroundf _ltoa malloc memcmp memcpy memmove memset modf modff pow powf putenv - qsort realloc rindex round roundf scalbn scalbnf setenv sin sinf sqr sqrt sqrtf sscanf strchr strcmp strlcat strlcpy strlen strncmp strnlen @@ -1099,11 +1107,16 @@ if(SDL_LIBC) check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) check_symbol_exists(setjmp "setjmp.h" HAVE_SETJMP) check_symbol_exists(nanosleep "time.h" HAVE_NANOSLEEP) + check_symbol_exists(gmtime_r "time.h" HAVE_GMTIME_R) + check_symbol_exists(localtime_r "time.h" HAVE_LOCALTIME_R) + check_symbol_exists(nl_langinfo "langinfo.h" HAVE_NL_LANGINFO) check_symbol_exists(sysconf "unistd.h" HAVE_SYSCONF) check_symbol_exists(sysctlbyname "sys/types.h;sys/sysctl.h" HAVE_SYSCTLBYNAME) check_symbol_exists(getauxval "sys/auxv.h" HAVE_GETAUXVAL) check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_ELF_AUX_INFO) check_symbol_exists(poll "poll.h" HAVE_POLL) + check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE) + check_symbol_exists(posix_fallocate "fcntl.h" HAVE_POSIX_FALLOCATE) if(SDL_SYSTEM_ICONV) check_c_source_compiles(" @@ -1136,6 +1149,7 @@ if(SDL_LIBC) endif() check_struct_has_member("struct sigaction" "sa_sigaction" "signal.h" HAVE_SA_SIGACTION) + check_struct_has_member("struct stat" "st_mtim" "sys/stat.h" HAVE_ST_MTIM) endif() else() set(headers @@ -1189,11 +1203,28 @@ if(SDL_AUDIO) endif() endif() +if(SDL_CAMERA) + # CheckDummyCamera/CheckDiskCamera - valid for all platforms + if(SDL_DUMMYCAMERA) + set(SDL_CAMERA_DRIVER_DUMMY 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/dummy/*.c") + set(HAVE_DUMMYCAMERA TRUE) + set(HAVE_SDL_CAMERA TRUE) + endif() + # !!! FIXME: for later. + #if(SDL_DISKCAMERA) + # set(SDL_CAMERA_DRIVER_DISK 1) + # sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/disk/*.c") + # set(HAVE_DISKCAMERA TRUE) + # set(HAVE_SDL_CAMERA TRUE) + #endif() +endif() + if(UNIX OR APPLE) # Relevant for Unix/Darwin only set(DYNAPI_NEEDS_DLOPEN 1) CheckDLOPEN() - if(SDL_LOADSO AND HAVE_DLOPEN) + if(HAVE_DLOPEN) set(SDL_LOADSO_DLOPEN 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/dlopen/*.c") set(HAVE_SDL_LOADSO TRUE) @@ -1229,10 +1260,8 @@ if(ANDROID) sdl_sources("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") set_property(SOURCE "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-declaration-after-statement") - if(SDL_MISC) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/android/*.c") - set(HAVE_SDL_MISC TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/android/*.c") + set(HAVE_SDL_MISC TRUE) # SDL_spinlock.c Needs to be compiled in ARM mode. # There seems to be no better way currently to set the ARM mode. @@ -1261,19 +1290,25 @@ if(ANDROID) set(HAVE_SDL_AUDIO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_ANDROID 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/android/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + + set(SDL_FILESYSTEM_ANDROID 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/android/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) + + set(SDL_FSOPS_POSIX 1) # !!! FIXME: this might need something else for .apk data? + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) + if(SDL_HAPTIC) set(SDL_HAPTIC_ANDROID 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/android/*.c") set(HAVE_SDL_HAPTIC TRUE) endif() + if(SDL_HIDAPI) CheckHIDAPI() endif() + if(SDL_JOYSTICK) set(SDL_JOYSTICK_ANDROID 1) sdl_glob_sources( @@ -1282,30 +1317,40 @@ if(ANDROID) ) set(HAVE_SDL_JOYSTICK TRUE) endif() - if(SDL_LOADSO) - set(SDL_LOADSO_DLOPEN 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/dlopen/*.c") - set(HAVE_SDL_LOADSO TRUE) - endif() + + set(SDL_LOADSO_DLOPEN 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/dlopen/*.c") + set(HAVE_SDL_LOADSO TRUE) + if(SDL_POWER) set(SDL_POWER_ANDROID 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/power/android/*.c") set(HAVE_SDL_POWER TRUE) endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/android/*.c") - set(HAVE_SDL_LOCALE TRUE) - endif() - if(SDL_TIMERS) - set(SDL_TIMER_UNIX 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/android/*.c") + set(HAVE_SDL_LOCALE TRUE) + + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) + if(SDL_SENSOR) set(SDL_SENSOR_ANDROID 1) set(HAVE_SDL_SENSORS TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/sensor/android/*.c") endif() + + if(SDL_CAMERA) + set(SDL_CAMERA_DRIVER_ANDROID 1) + set(HAVE_CAMERA TRUE) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/android/*.c") + endif() + if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_ANDROID 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/android/*.c") @@ -1403,43 +1448,56 @@ elseif(EMSCRIPTEN) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/emscripten/*.c") set(HAVE_SDL_MAIN_CALLBACKS TRUE) - if(SDL_MISC) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/emscripten/*.c") - set(HAVE_SDL_MISC TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/emscripten/*.c") + set(HAVE_SDL_MISC TRUE) + if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_EMSCRIPTEN 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/emscripten/*.c") set(HAVE_SDL_AUDIO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_EMSCRIPTEN 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/emscripten/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) + + set(SDL_FILESYSTEM_EMSCRIPTEN 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/emscripten/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) + + set(SDL_FSOPS_POSIX 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) + + if(SDL_CAMERA) + set(SDL_CAMERA_DRIVER_EMSCRIPTEN 1) + set(HAVE_CAMERA TRUE) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/emscripten/*.c") endif() + if(SDL_JOYSTICK) set(SDL_JOYSTICK_EMSCRIPTEN 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/emscripten/*.c") set(HAVE_SDL_JOYSTICK TRUE) endif() + if(SDL_POWER) set(SDL_POWER_EMSCRIPTEN 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/power/emscripten/*.c") set(HAVE_SDL_POWER TRUE) endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/emscripten/*.c") - set(HAVE_SDL_LOCALE TRUE) - endif() - if(SDL_TIMERS) - set(SDL_TIMER_UNIX 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") - set(HAVE_SDL_TIMERS TRUE) - if(SDL_CLOCK_GETTIME) - set(HAVE_CLOCK_GETTIME 1) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/emscripten/*.c") + set(HAVE_SDL_LOCALE TRUE) + + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) + + if(SDL_CLOCK_GETTIME) + set(HAVE_CLOCK_GETTIME 1) endif() + if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_EMSCRIPTEN 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/emscripten/*.c") @@ -1516,6 +1574,9 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) ioctl(0, KDGKBENT, &kbe); return 0; }" HAVE_INPUT_KD) + check_c_source_compiles(" + #include + int main(int argc, char** argv) { return 0; }" HAVE_LINUX_VIDEODEV2_H) elseif(FREEBSD) check_c_source_compiles(" #include @@ -1539,6 +1600,12 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) }" HAVE_INPUT_WSCONS) endif() + if(SDL_CAMERA AND HAVE_LINUX_VIDEODEV2_H) + set(SDL_CAMERA_DRIVER_V4L2 1) + set(HAVE_CAMERA TRUE) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/v4l2/*.c") + endif() + if(HAVE_LINUX_INPUT_H) set(SDL_INPUT_LINUXEV 1) endif() @@ -1692,10 +1759,8 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) endif() endif() - if(SDL_MISC) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/unix/*.c") - set(HAVE_SDL_MISC TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/unix/*.c") + set(HAVE_SDL_MISC TRUE) if(SDL_POWER) if(LINUX) @@ -1705,22 +1770,32 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) endif() endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/unix/*.c") - set(HAVE_SDL_LOCALE TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/unix/*.c") + set(HAVE_SDL_LOCALE TRUE) - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_UNIX 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/unix/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + set(SDL_FILESYSTEM_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/unix/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) - if(SDL_TIMERS) - set(SDL_TIMER_UNIX 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") - set(HAVE_SDL_TIMERS TRUE) + set(SDL_STORAGE_GENERIC 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c") + if(LINUX) + set(SDL_STORAGE_STEAM 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c") endif() + set(HAVE_SDL_STORAGE 1) + + set(SDL_FSOPS_POSIX 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) + + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) set(SDL_RLD_FLAGS "") if(SDL_RPATH AND SDL_SHARED) @@ -1734,10 +1809,11 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) else() set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir}") endif() + set(HAVE_RPATH TRUE) elseif(SOLARIS) set(SDL_RLD_FLAGS "-R\${libdir}") + set(HAVE_RPATH TRUE) endif() - set(HAVE_RPATH TRUE) endif() if(QNX) @@ -1755,6 +1831,7 @@ elseif(WINDOWS) 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" @@ -1769,14 +1846,12 @@ elseif(WINDOWS) endif() endif() - if(SDL_MISC) - 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() - set(HAVE_SDL_MISC TRUE) + 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() + set(HAVE_SDL_MISC TRUE) # Check for DirectX if(SDL_DIRECTX) @@ -1863,10 +1938,6 @@ elseif(WINDOWS) endif() if(SDL_VIDEO) - # requires SDL_LOADSO on Windows (IME, DX, etc.) - if(NOT SDL_LOADSO) - message(FATAL_ERROR "SDL_VIDEO requires SDL_LOADSO, which is not enabled") - endif() if(WINDOWS_STORE) set(SDL_VIDEO_DRIVER_WINRT 1) sdl_glob_sources( @@ -1894,22 +1965,20 @@ elseif(WINDOWS) set(HAVE_SDL_VIDEO TRUE) endif() - if(SDL_THREADS) - set(SDL_THREAD_GENERIC_COND_SUFFIX 1) - set(SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1) - set(SDL_THREAD_WINDOWS 1) - sdl_sources( - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" - "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_syscond_cv.c" - "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_sysmutex.c" - "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_sysrwlock_srw.c" - "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_syssem.c" - "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_systhread.c" - "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_systls.c" - ) - set(HAVE_SDL_THREADS TRUE) - endif() + set(SDL_THREAD_GENERIC_COND_SUFFIX 1) + set(SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1) + set(SDL_THREAD_WINDOWS 1) + sdl_sources( + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" + "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_syscond_cv.c" + "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_sysmutex.c" + "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_sysrwlock_srw.c" + "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_syssem.c" + "${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) set(SDL_SENSOR_WINDOWS 1) @@ -1928,24 +1997,32 @@ elseif(WINDOWS) endif() endif() - if(SDL_LOCALE) - 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() - set(HAVE_SDL_LOCALE TRUE) + 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() + set(HAVE_SDL_LOCALE TRUE) - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_WINDOWS 1) - if(WINDOWS_STORE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/winrt/*.cpp") - else() - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/*.c") - endif() - set(HAVE_SDL_FILESYSTEM 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() + set(HAVE_SDL_FILESYSTEM TRUE) + + set(SDL_FSOPS_WINDOWS 1) + set(HAVE_SDL_FSOPS TRUE) + + 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(HAVE_SDL_STORAGE 1) # Libraries for Win32 native and MinGW if(NOT WINDOWS_STORE) @@ -1963,17 +2040,17 @@ elseif(WINDOWS) ) endif() - if(SDL_TIMERS) - set(SDL_TIMER_WINDOWS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/windows/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + set(SDL_TIME_WINDOWS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/windows/*.c") + set(HAVE_SDL_TIME TRUE) - if(SDL_LOADSO) - set(SDL_LOADSO_WINDOWS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/windows/*.c") - set(HAVE_SDL_LOADSO TRUE) - endif() + set(SDL_TIMER_WINDOWS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/windows/*.c") + set(HAVE_SDL_TIMERS TRUE) + + set(SDL_LOADSO_WINDOWS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/windows/*.c") + set(HAVE_SDL_LOADSO TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/windows/*.c") @@ -1995,6 +2072,10 @@ elseif(WINDOWS) if(SDL_VULKAN) 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() @@ -2024,19 +2105,19 @@ elseif(WINDOWS) set(HAVE_SDL_JOYSTICK TRUE) if(SDL_HAPTIC) - if((HAVE_DINPUT_H OR HAVE_XINPUT_H) AND NOT WINDOWS_STORE) + if(HAVE_DINPUT_H AND NOT WINDOWS_STORE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/windows/*.c") - if(HAVE_DINPUT_H) - set(SDL_HAPTIC_DINPUT 1) - endif() - if(HAVE_XINPUT_H) - set(SDL_HAPTIC_XINPUT 1) - endif() - else() - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/dummy/*.c") - set(SDL_HAPTIC_DUMMY 1) + set(SDL_HAPTIC_DINPUT 1) + set(HAVE_SDL_HAPTIC TRUE) endif() - set(HAVE_SDL_HAPTIC TRUE) + endif() + endif() + + if(SDL_CAMERA) + if(NOT WINDOWS_STORE) + set(HAVE_CAMERA TRUE) + set(SDL_CAMERA_DRIVER_MEDIAFOUNDATION 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/mediafoundation/*.c") endif() endif() @@ -2067,25 +2148,23 @@ elseif(APPLE) set(HAVE_SDL_MAIN_CALLBACKS TRUE) endif() - # Requires the darwin file implementation - if(SDL_FILE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") - set(HAVE_SDL_FILE TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") - if(IOS OR TVOS OR MACOSX OR DARWIN) - sdl_sources("${SDL3_SOURCE_DIR}/src/video/SDL_video_capture_apple.m") - endif() - - if(SDL_MISC) - if(IOS OR TVOS OR VISIONOS) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/ios/*.m") - else() - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/macos/*.m") + if(SDL_CAMERA) + if(IOS OR TVOS OR MACOSX OR DARWIN) + set(SDL_CAMERA_DRIVER_COREMEDIA 1) + set(HAVE_CAMERA TRUE) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/coremedia/*.m") endif() - set(HAVE_SDL_MISC TRUE) endif() + if(IOS OR TVOS OR VISIONOS) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/ios/*.m") + else() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/macos/*.m") + endif() + set(HAVE_SDL_MISC TRUE) + if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_COREAUDIO 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/coreaudio/*.m") @@ -2170,22 +2249,33 @@ elseif(APPLE) set(HAVE_SDL_POWER TRUE) endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/macos/*.m") - set(HAVE_SDL_LOCALE TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/macos/*.m") + set(HAVE_SDL_LOCALE TRUE) - if(SDL_TIMERS) - set(SDL_TIMER_UNIX 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_COCOA 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/cocoa/*.m") - set(HAVE_SDL_FILESYSTEM TRUE) + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) + + set(SDL_FILESYSTEM_COCOA 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/cocoa/*.m") + set(HAVE_SDL_FILESYSTEM TRUE) + + # TODO: SDL_STORAGE_ICLOUD + set(SDL_STORAGE_GENERIC 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c") + if(DARWIN OR MACOSX) + set(SDL_STORAGE_STEAM 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c") endif() + set(HAVE_SDL_STORAGE 1) + + set(SDL_FSOPS_POSIX 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) if(SDL_SENSOR) if(IOS OR VISIONOS) @@ -2244,6 +2334,10 @@ elseif(APPLE) if(SDL_VULKAN) 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() if(SDL_METAL) set(SDL_VIDEO_METAL 1) @@ -2334,7 +2428,13 @@ elseif(APPLE) CheckPTHREAD() + if(SDL_RPATH AND SDL_SHARED) + set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir}") + set(HAVE_RPATH TRUE) + endif() + elseif(HAIKU) + enable_language(CXX) if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_HAIKU 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/haiku/*.cc") @@ -2347,10 +2447,8 @@ elseif(HAIKU) set(HAVE_SDL_JOYSTICK TRUE) endif() - if(SDL_MISC) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/haiku/*.cc") - set(HAVE_SDL_MISC TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/haiku/*.cc") + set(HAVE_SDL_MISC TRUE) if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_HAIKU 1) @@ -2367,17 +2465,21 @@ elseif(HAIKU) endif() endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_HAIKU 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/haiku/*.cc") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + set(SDL_FILESYSTEM_HAIKU 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/haiku/*.cc") + set(HAVE_SDL_FILESYSTEM TRUE) - if(SDL_TIMERS) - set(SDL_TIMER_HAIKU 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/haiku/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + set(SDL_FSOPS_POSIX 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) + + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_HAIKU 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/haiku/*.c") + set(HAVE_SDL_TIMERS TRUE) if(SDL_POWER) set(SDL_POWER_HAIKU 1) @@ -2385,21 +2487,17 @@ elseif(HAIKU) set(HAVE_SDL_POWER TRUE) endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/haiku/*.cc") - set(HAVE_SDL_LOCALE TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/haiku/*.cc") + set(HAVE_SDL_LOCALE TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/haiku/*.cc") CheckPTHREAD() - sdl_link_dependency(base LIBS root be media game device textencoding) + sdl_link_dependency(base LIBS root be media game device textencoding tracker) elseif(RISCOS) - if(SDL_MISC) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/riscos/*.c") - set(HAVE_SDL_MISC TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/riscos/*.c") + set(HAVE_SDL_MISC TRUE) if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_RISCOS 1) @@ -2407,20 +2505,24 @@ elseif(RISCOS) set(HAVE_SDL_VIDEO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_RISCOS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/riscos/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + set(SDL_FILESYSTEM_RISCOS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/riscos/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) - if(SDL_TIMERS) - set(SDL_TIMER_UNIX 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") - set(HAVE_SDL_TIMERS TRUE) + set(SDL_FSOPS_POSIX 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) - if(SDL_CLOCK_GETTIME) - set(HAVE_CLOCK_GETTIME 1) - endif() + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) + + if(SDL_CLOCK_GETTIME) + set(HAVE_CLOCK_GETTIME 1) endif() CheckPTHREAD() @@ -2439,57 +2541,61 @@ elseif(VITA) set_property(SOURCE "${SDL3_SOURCE_DIR}/src/atomic/SDL_spinlock.c" APPEND_STRING PROPERTY COMPILE_FLAGS " -marm") endif() - if(SDL_MISC) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/vita/*.c") - set(HAVE_SDL_MISC TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/vita/*.c") + set(HAVE_SDL_MISC TRUE) if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_VITA 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/vita/*.c") set(HAVE_SDL_AUDIO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_VITA 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/vita/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + + set(SDL_FILESYSTEM_VITA 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/vita/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) + + # !!! FIXME: do we need a FSops implementation for this? + if(SDL_JOYSTICK) set(SDL_JOYSTICK_VITA 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/vita/*.c") set(HAVE_SDL_JOYSTICK TRUE) endif() + if(SDL_POWER) set(SDL_POWER_VITA 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/power/vita/*.c") set(HAVE_SDL_POWER TRUE) endif() - if(SDL_THREADS) - set(SDL_THREAD_VITA 1) - sdl_sources( - "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_sysmutex.c" - "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_syssem.c" - "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_systhread.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" - ) - set(HAVE_SDL_THREADS TRUE) - endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/vita/*.c") - set(HAVE_SDL_LOCALE TRUE) - endif() - if(SDL_TIMERS) - set(SDL_TIMER_VITA 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/vita/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + + set(SDL_THREAD_VITA 1) + sdl_sources( + "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_sysmutex.c" + "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_syssem.c" + "${SDL3_SOURCE_DIR}/src/thread/vita/SDL_systhread.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" + ) + set(HAVE_SDL_THREADS TRUE) + + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/vita/*.c") + set(HAVE_SDL_LOCALE TRUE) + + set(SDL_TIME_VITA 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/vita/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_VITA 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/vita/*.c") + set(HAVE_SDL_TIMERS TRUE) + if(SDL_SENSOR) set(SDL_SENSOR_VITA 1) set(HAVE_SDL_SENSORS TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/sensor/vita/*.c") endif() + if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_VITA 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/vita/*.c") @@ -2583,36 +2689,42 @@ elseif(PSP) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/psp/*.c") set(HAVE_SDL_AUDIO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_PSP 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/psp/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + + set(SDL_FILESYSTEM_PSP 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/psp/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) + + # !!! FIXME: do we need a FSops implementation for this? + if(SDL_JOYSTICK) set(SDL_JOYSTICK_PSP 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/psp/*.c") set(HAVE_SDL_JOYSTICK TRUE) endif() + if(SDL_POWER) set(SDL_POWER_PSP 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/power/psp/*.c") set(HAVE_SDL_POWER TRUE) endif() - if(SDL_THREADS) - set(SDL_THREAD_PSP 1) - sdl_glob_sources( - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" - "${SDL3_SOURCE_DIR}/src/thread/psp/*.c" - ) - set(HAVE_SDL_THREADS TRUE) - endif() - if(SDL_TIMERS) - set(SDL_TIMER_PSP 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/psp/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + + set(SDL_THREAD_PSP 1) + sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" + "${SDL3_SOURCE_DIR}/src/thread/psp/*.c" + ) + set(HAVE_SDL_THREADS TRUE) + + set(SDL_TIME_PSP 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/psp/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_PSP 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/psp/*.c") + set(HAVE_SDL_TIMERS TRUE) + if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_PSP 1) set(SDL_VIDEO_RENDER_PSP 1) @@ -2620,6 +2732,7 @@ elseif(PSP) set(SDL_VIDEO_OPENGL 1) set(HAVE_SDL_VIDEO TRUE) endif() + sdl_link_dependency(base LIBS GL @@ -2645,32 +2758,37 @@ elseif(PS2) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/ps2/*.c") set(HAVE_SDL_AUDIO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_PS2 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/ps2/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + + set(SDL_FILESYSTEM_PS2 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/ps2/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) + + # !!! FIXME: do we need a FSops implementation for this? + if(SDL_JOYSTICK) set(SDL_JOYSTICK_PS2 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/ps2/*.c") set(HAVE_SDL_JOYSTICK TRUE) endif() - if(SDL_THREADS) - set(SDL_THREAD_PS2 1) - sdl_glob_sources( - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysmutex.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" - "${SDL3_SOURCE_DIR}/src/thread/ps2/*.c" - ) - set(HAVE_SDL_THREADS TRUE) - endif() - if(SDL_TIMERS) - set(SDL_TIMER_PS2 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/ps2/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + + set(SDL_THREAD_PS2 1) + sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syscond.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysmutex.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" + "${SDL3_SOURCE_DIR}/src/thread/ps2/*.c" + ) + set(HAVE_SDL_THREADS TRUE) + + set(SDL_TIME_PS2 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/ps2/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_PS2 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/ps2/*.c") + set(HAVE_SDL_TIMERS TRUE) + if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_PS2 1) set(SDL_VIDEO_RENDER_PS2 1) @@ -2698,11 +2816,11 @@ elseif(N3DS) set(HAVE_SDL_AUDIO TRUE) endif() - if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_N3DS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/n3ds/*.c") - set(HAVE_SDL_FILESYSTEM TRUE) - endif() + set(SDL_FILESYSTEM_N3DS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/n3ds/*.c") + set(HAVE_SDL_FILESYSTEM TRUE) + + # !!! FIXME: do we need a FSops implementation for this? if(SDL_JOYSTICK) set(SDL_JOYSTICK_N3DS 1) @@ -2716,21 +2834,25 @@ elseif(N3DS) set(HAVE_SDL_POWER TRUE) endif() - if(SDL_THREADS) - set(SDL_THREAD_N3DS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/thread/n3ds/*.c") - sdl_sources( - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" - "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" - ) - set(HAVE_SDL_THREADS TRUE) - endif() + set(SDL_THREAD_N3DS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/thread/n3ds/*.c") + sdl_sources( + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_systls.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_sysrwlock.c" + ) + set(HAVE_SDL_THREADS TRUE) - if(SDL_TIMERS) - set(SDL_TIMER_N3DS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/n3ds/*.c") - set(HAVE_SDL_TIMERS TRUE) - endif() + set(SDL_TIME_N3DS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/n3ds/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_N3DS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/n3ds/*.c") + set(HAVE_SDL_TIMERS TRUE) + + set(SDL_FSOPS_POSIX 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/posix/SDL_sysfsops.c") + set(HAVE_SDL_FSOPS TRUE) if(SDL_SENSOR) set(SDL_SENSOR_N3DS 1) @@ -2744,24 +2866,28 @@ elseif(N3DS) set(HAVE_SDL_VIDEO TRUE) endif() - if(SDL_LOCALE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/n3ds/*.c") - set(HAVE_SDL_LOCALE TRUE) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/n3ds/*.c") + set(HAVE_SDL_LOCALE TRUE) - # Requires the n3ds file implementation - if(SDL_FILE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/n3ds/*.c") - set(HAVE_SDL_FILE TRUE) - else() - message(FATAL_ERROR "SDL_FILE must be enabled to build on N3DS") - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/n3ds/*.c") endif() -if(HAVE_VULKAN AND NOT SDL_LOADSO) - message(STATUS "Vulkan support is available, but disabled because there's no loadso.") - set(HAVE_VULKAN FALSE) - set(SDL_VIDEO_VULKAN 0) +if (SDL_DIALOG) + if(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) + set(HAVE_SDL_DIALOG TRUE) + elseif(HAIKU) + sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/haiku/SDL_haikudialog.cc) + set(HAVE_SDL_DIALOG TRUE) + elseif(WINDOWS AND NOT WINDOWS_STORE) + sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/windows/SDL_windowsdialog.c) + set(HAVE_SDL_DIALOG TRUE) + elseif(APPLE) + sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/cocoa/SDL_cocoadialog.m) + set(HAVE_SDL_DIALOG TRUE) + endif() endif() # Platform-independent options @@ -2811,6 +2937,14 @@ if(NOT HAVE_SDL_FILESYSTEM) set(SDL_FILESYSTEM_DUMMY 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/*.c") endif() +if(NOT HAVE_SDL_STORAGE) + set(SDL_STORAGE_GENERIC 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c") +endif() +if(NOT HAVE_SDL_FSOPS) + set(SDL_FSOPS_DUMMY 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/SDL_sysfsops.c") +endif() if(NOT HAVE_SDL_LOCALE) set(SDL_LOCALE_DUMMY 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/dummy/*.c") @@ -2819,6 +2953,14 @@ if(NOT HAVE_SDL_MISC) set(SDL_MISC_DUMMY 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/dummy/*.c") endif() +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_CAMERA) + set(SDL_CAMERA_DRIVER_DUMMY 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/dummy/*.c") +endif() # We always need to have threads and timers around if(NOT HAVE_SDL_THREADS) diff --git a/README.md b/README.md index 4d4741b0..c4861c70 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,8 @@ https://www.libsdl.org/ Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics -hardware via OpenGL and Direct3D. It is used by video playback software, -emulators, and popular games including Valve's award winning catalog -and many Humble Bundle games. +hardware. It is used by video playback software, emulators, and popular games +including Valve's award winning catalog and many Humble Bundle games. More extensive documentation is available in the docs directory, starting with [README.md](docs/README.md). If you are migrating to SDL 3.0 from SDL 2.0, diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index c7fa0a28..d68a2f60 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -171,7 +171,7 @@ true - $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) + $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) Building shader blobs (Xbox Series) @@ -205,7 +205,7 @@ true - $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) one + $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one Building shader blobs (Xbox One) @@ -271,7 +271,7 @@ true - $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) + $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) Building shader blobs (Xbox Series) @@ -306,7 +306,7 @@ true - $(SolutionDir)\shaders\buildshaders.bat $(SolutionDir) one + $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one Building shader blobs (Xbox One) @@ -314,6 +314,7 @@ + @@ -363,10 +364,11 @@ - + + @@ -382,6 +384,7 @@ + @@ -398,12 +401,15 @@ + + + @@ -418,11 +424,11 @@ + - @@ -499,6 +505,10 @@ $(IntDir)$(TargetName)_cpp.pch $(IntDir)$(TargetName)_cpp.pch + + + + @@ -528,7 +538,6 @@ - @@ -566,11 +575,19 @@ + + + + + + + + @@ -604,6 +621,16 @@ stdcpp17 + + true + true + + + true + true + true + true + NotUsing NotUsing @@ -618,7 +645,7 @@ - + true true @@ -636,19 +663,10 @@ stdcpp17 stdcpp17 - - stdcpp17 - stdcpp17 - stdcpp17 - stdcpp17 - CompileAsCpp - CompileAsCpp - CompileAsCpp - CompileAsCpp - + @@ -765,6 +783,9 @@ + + + NotUsing @@ -773,6 +794,8 @@ + + @@ -784,6 +807,8 @@ + + @@ -809,7 +834,6 @@ - @@ -822,10 +846,14 @@ + + - + + + @@ -834,4 +862,4 @@ - \ No newline at end of file + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 4692d468..722b2ed3 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -4,6 +4,12 @@ + + filesystem + + + filesystem\windows + @@ -43,16 +49,16 @@ - + - + @@ -146,6 +152,9 @@ + + + @@ -162,6 +171,12 @@ + + time + + + time\windows + @@ -196,6 +211,8 @@ + + @@ -254,7 +271,7 @@ - + @@ -295,6 +312,7 @@ + @@ -309,11 +327,13 @@ + + filesystem + - @@ -384,7 +404,6 @@ - @@ -422,6 +441,8 @@ + + @@ -433,4 +454,4 @@ - \ No newline at end of file + diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl deleted file mode 100644 index 47eff4cc..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_Colors.hlsl +++ /dev/null @@ -1,19 +0,0 @@ -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define ColorRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - "DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - "DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - "DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0)" - -[RootSignature(ColorRS)] -float4 main(PixelShaderInput input) : SV_TARGET0 -{ - return input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl deleted file mode 100644 index cffbc226..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureUV : register(t1); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(NVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl deleted file mode 100644 index 81d409c9..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureUV : register(t1); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(NVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl deleted file mode 100644 index 494bce51..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureUV : register(t1); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(NVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl deleted file mode 100644 index 794c7637..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureUV : register(t1); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(NVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl deleted file mode 100644 index f5b9522c..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureUV : register(t1); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(NVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl deleted file mode 100644 index 1b467b48..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG.hlsl +++ /dev/null @@ -1,43 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureUV : register(t1); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(NVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl deleted file mode 100644 index 0dcdf89c..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_Textures.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -Texture2D theTexture : register(t0); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define TextureRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(TextureRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - return theTexture.Sample(theSampler, input.tex) * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl deleted file mode 100644 index 09e58943..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601.hlsl +++ /dev/null @@ -1,46 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureU : register(t1); -Texture2D theTextureV : register(t2); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define YUVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(YUVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl deleted file mode 100644 index f5aa0cd7..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709.hlsl +++ /dev/null @@ -1,46 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureU : register(t1); -Texture2D theTextureV : register(t2); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define YUVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(YUVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl b/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl deleted file mode 100644 index 84d09b8b..00000000 --- a/VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG.hlsl +++ /dev/null @@ -1,46 +0,0 @@ -Texture2D theTextureY : register(t0); -Texture2D theTextureU : register(t1); -Texture2D theTextureV : register(t2); -SamplerState theSampler : register(s0); - -struct PixelShaderInput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define YUVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(YUVRS)] -float4 main(PixelShaderInput input) : SV_TARGET -{ - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/D3D12_VertexShader.hlsl b/VisualC-GDK/shaders/D3D12_VertexShader.hlsl deleted file mode 100644 index e10b4889..00000000 --- a/VisualC-GDK/shaders/D3D12_VertexShader.hlsl +++ /dev/null @@ -1,95 +0,0 @@ -#pragma pack_matrix( row_major ) - -struct VertexShaderConstants -{ - matrix model; - matrix projectionAndView; -}; -ConstantBuffer Constants : register(b0); - -struct VertexShaderInput -{ - float3 pos : POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -struct VertexShaderOutput -{ - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; -}; - -#define ColorRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - "DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - "DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - "DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0)" - -#define TextureRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -#define YUVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t2), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -#define NVRS \ - "RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \ - " DENY_DOMAIN_SHADER_ROOT_ACCESS |" \ - " DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \ - " DENY_HULL_SHADER_ROOT_ACCESS )," \ - "RootConstants(num32BitConstants=32, b0),"\ - "DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL ),"\ - "DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )" - -[RootSignature(ColorRS)] -VertexShaderOutput mainColor(VertexShaderInput input) -{ - VertexShaderOutput output; - float4 pos = float4(input.pos, 1.0f); - - // Transform the vertex position into projected space. - pos = mul(pos, Constants.model); - pos = mul(pos, Constants.projectionAndView); - output.pos = pos; - - // Pass through texture coordinates and color values without transformation - output.tex = input.tex; - output.color = input.color; - - return output; -} - -[RootSignature(TextureRS)] -VertexShaderOutput mainTexture(VertexShaderInput input) -{ - return mainColor(input); -} - -[RootSignature(YUVRS)] -VertexShaderOutput mainYUV(VertexShaderInput input) -{ - return mainColor(input); -} - -[RootSignature(NVRS)] -VertexShaderOutput mainNV(VertexShaderInput input) -{ - return mainColor(input); -} \ No newline at end of file diff --git a/VisualC-GDK/shaders/buildshaders.bat b/VisualC-GDK/shaders/buildshaders.bat deleted file mode 100644 index 4447b5e2..00000000 --- a/VisualC-GDK/shaders/buildshaders.bat +++ /dev/null @@ -1,35 +0,0 @@ -if %2.==one. goto setxboxone -rem Xbox Series compile -set XBOXDXC="%GameDKLatest%\GXDK\bin\Scarlett\DXC.exe" -set SUFFIX=_Series.h -goto startbuild - -:setxboxone -set XBOXDXC="%GameDKLatest%\GXDK\bin\XboxOne\DXC.exe" -set SUFFIX=_One.h - -:startbuild -echo Building with %XBOXDXC% -cd "%1\shaders" -rem Root Signatures -%XBOXDXC% -E ColorRS -T rootsig_1_1 -rootsig-define ColorRS -Fh D3D12_RootSig_Color%SUFFIX% -Vn D3D12_RootSig_Color D3D12_VertexShader.hlsl -%XBOXDXC% -E TextureRS -T rootsig_1_1 -rootsig-define TextureRS -Fh D3D12_RootSig_Texture%SUFFIX% -Vn D3D12_RootSig_Texture D3D12_VertexShader.hlsl -%XBOXDXC% -E YUVRS -T rootsig_1_1 -rootsig-define YUVRS -Fh D3D12_RootSig_YUV%SUFFIX% -Vn D3D12_RootSig_YUV D3D12_VertexShader.hlsl -%XBOXDXC% -E NVRS -T rootsig_1_1 -rootsig-define NVRS -Fh D3D12_RootSig_NV%SUFFIX% -Vn D3D12_RootSig_NV D3D12_VertexShader.hlsl -rem Vertex Shaders -%XBOXDXC% -E mainColor -T vs_6_0 -Fh D3D12_VertexShader_Color%SUFFIX% -Vn D3D12_VertexShader_Color D3D12_VertexShader.hlsl -%XBOXDXC% -E mainTexture -T vs_6_0 -Fh D3D12_VertexShader_Texture%SUFFIX% -Vn D3D12_VertexShader_Texture D3D12_VertexShader.hlsl -%XBOXDXC% -E mainNV -T vs_6_0 -Fh D3D12_VertexShader_NV%SUFFIX% -Vn D3D12_VertexShader_NV D3D12_VertexShader.hlsl -%XBOXDXC% -E mainYUV -T vs_6_0 -Fh D3D12_VertexShader_YUV%SUFFIX% -Vn D3D12_VertexShader_YUV D3D12_VertexShader.hlsl -rem Pixel Shaders -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_Colors%SUFFIX% -Vn D3D12_PixelShader_Colors D3D12_PixelShader_Colors.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_BT601%SUFFIX% -Vn D3D12_PixelShader_NV12_BT601 D3D12_PixelShader_NV12_BT601.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_BT709%SUFFIX% -Vn D3D12_PixelShader_NV12_BT709 D3D12_PixelShader_NV12_BT709.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV12_JPEG%SUFFIX% -Vn D3D12_PixelShader_NV12_JPEG D3D12_PixelShader_NV12_JPEG.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_BT601%SUFFIX% -Vn D3D12_PixelShader_NV21_BT601 D3D12_PixelShader_NV21_BT601.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_BT709%SUFFIX% -Vn D3D12_PixelShader_NV21_BT709 D3D12_PixelShader_NV21_BT709.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_NV21_JPEG%SUFFIX% -Vn D3D12_PixelShader_NV21_JPEG D3D12_PixelShader_NV21_JPEG.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_Textures%SUFFIX% -Vn D3D12_PixelShader_Textures D3D12_PixelShader_Textures.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_BT601%SUFFIX% -Vn D3D12_PixelShader_YUV_BT601 D3D12_PixelShader_YUV_BT601.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_BT709%SUFFIX% -Vn D3D12_PixelShader_YUV_BT709 D3D12_PixelShader_YUV_BT709.hlsl -%XBOXDXC% -E main -T ps_6_0 -Fh D3D12_PixelShader_YUV_JPEG%SUFFIX% -Vn D3D12_PixelShader_YUV_JPEG D3D12_PixelShader_YUV_JPEG.hlsl \ No newline at end of file diff --git a/VisualC-GDK/tests/testgdk/src/testgdk.cpp b/VisualC-GDK/tests/testgdk/src/testgdk.cpp index bc4895bd..bddecf3c 100644 --- a/VisualC-GDK/tests/testgdk/src/testgdk.cpp +++ b/VisualC-GDK/tests/testgdk/src/testgdk.cpp @@ -311,7 +311,7 @@ loop() if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat) { SDL_Log("Initial SDL_EVENT_KEY_DOWN: %s", SDL_GetScancodeName(event.key.keysym.scancode)); } -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) /* On Xbox, ignore the keydown event because the features aren't supported */ if (event.type != SDL_EVENT_KEY_DOWN) { SDLTest_CommonEvent(state, &event, &done); diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index 715c6020..ba706bb9 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -36,6 +36,7 @@ + @@ -77,19 +78,20 @@ - + + + - @@ -99,12 +101,15 @@ + + + @@ -118,11 +123,11 @@ + - @@ -190,6 +195,14 @@ + + + + + + + + @@ -252,6 +265,8 @@ true true + + @@ -321,12 +336,13 @@ $(IntDir)$(TargetName)_cpp.pch $(IntDir)$(TargetName)_cpp.pch - + + + - @@ -418,6 +434,9 @@ + + + NotUsing @@ -426,6 +445,8 @@ + + @@ -502,6 +523,8 @@ + + @@ -523,7 +546,6 @@ - @@ -614,7 +636,9 @@ $(IntDir)$(TargetName)_cpp.pch $(IntDir)$(TargetName)_cpp.pch - + + + {89e9b32e-a86a-47c3-a948-d2b1622925ce} diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters index 728fdbbc..a8da66c1 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters @@ -13,11 +13,32 @@ {0000318d975e0a2867ab1d5727bf0000} + + {00009e5236c2ac679fe0bc30beb90000} + + + {000031d805439b865ff4550d2f620000} + + + {00004389761f0ae646deb5a3d65f0000} + + + {0000bc587ef6c558d75ce2e620cb0000} + + + {0000948771d0040a6a55997a7f1e0000} + + + {0000012051ca8361c8e1013aee1d0000} + Header Files + + API Headers + Header Files @@ -132,7 +153,7 @@ Header Files - + Header Files @@ -165,8 +186,14 @@ Header Files - - Header Files + + camera + + + camera + + + filesystem Header Files @@ -216,6 +243,9 @@ Source Files + + Source Files + Source Files @@ -435,9 +465,6 @@ Source Files - - Source Files - Source Files @@ -510,6 +537,12 @@ Source Files + + camera\dummy + + + camera + Source Files @@ -564,10 +597,16 @@ Source Files + + filesystem + + + filesystem\windows + Source Files - + Source Files @@ -717,6 +756,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + Source Files @@ -753,6 +801,12 @@ Source Files + + time + + + time\windows + Source Files @@ -816,9 +870,6 @@ Source Files - - Source Files - Source Files @@ -855,9 +906,6 @@ Source Files - - Source Files - Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 0b534578..7cc84059 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -119,18 +119,17 @@ StreamingSIMDExtensions Level3 OldStyle - true OnlyExplicitInline Use SDL_internal.h true + MultiThreadedDebug _DEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows @@ -151,18 +150,17 @@ false Level3 OldStyle - true OnlyExplicitInline Use SDL_internal.h true + MultiThreadedDebug _DEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows @@ -187,18 +185,17 @@ StreamingSIMDExtensions Level3 ProgramDatabase - true OnlyExplicitInline Use SDL_internal.h true + MultiThreaded NDEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows true @@ -220,18 +217,17 @@ false Level3 ProgramDatabase - true OnlyExplicitInline Use SDL_internal.h true + MultiThreaded NDEBUG;%(PreprocessorDefinitions) setupapi.lib;winmm.lib;imm32.lib;version.lib;%(AdditionalDependencies) - true true Windows true @@ -240,6 +236,7 @@ + @@ -290,10 +287,11 @@ - + + @@ -309,6 +307,7 @@ + @@ -324,11 +323,14 @@ + + + @@ -344,11 +346,11 @@ + - @@ -390,6 +392,7 @@ + @@ -398,8 +401,15 @@ Create Create + + + + + + + @@ -426,7 +436,6 @@ - @@ -464,12 +473,20 @@ + + + + + + + + @@ -493,6 +510,7 @@ + NotUsing NotUsing @@ -509,16 +527,16 @@ - + - + @@ -612,14 +630,20 @@ + + + - + NotUsing + + + @@ -631,6 +655,8 @@ + + @@ -653,7 +679,6 @@ - @@ -665,10 +690,14 @@ + + - + + + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index e53a8eb4..77b54b84 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -88,6 +88,9 @@ {d008487d-6ed0-4251-848b-79a68e3c1459} + + {c9e8273e-13ae-47dc-bef8-8ad8e64c9a3e} + {c9e8273e-13ae-47dc-bef8-8ad8e64c9a3d} @@ -175,11 +178,32 @@ {0000ddc7911820dbe64274d3654f0000} + + {0000de1b75e1a954834693f1c81e0000} + + + {0000fc2700d453b3c8d79fe81e1c0000} + + + {0000fbfe2d21e4f451142e7d0e870000} + + + {5115ba31-20f8-4eab-a8c5-6a572ab78ff7} + + + {00003288226ff86b99eee5b443e90000} + + + {0000d7fda065b13b0ca4ab262c380000} + API Headers + + API Headers + API Headers @@ -324,7 +348,7 @@ API Headers - + API Headers @@ -393,6 +417,15 @@ API Headers + + camera + + + camera + + + filesystem + main @@ -441,6 +474,9 @@ core\windows + + cpuinfo + dynapi @@ -546,9 +582,6 @@ haptic\windows - - haptic\windows - joystick\hidapi @@ -648,6 +681,12 @@ video\windows + + video\windows + + + video\windows + video\windows @@ -771,9 +810,6 @@ video\khronos\vulkan - - video\khronos\vulkan - video\khronos\vulkan @@ -825,9 +861,34 @@ render\direct3d12 + + + + + + + + + render\vulkan + + + camera\dummy + + + camera\mediafoundation + + + camera + + + filesystem + + + filesystem\windows + main\generic @@ -894,6 +955,9 @@ cpuinfo + + dialog + dynapi @@ -927,7 +991,7 @@ events - + file @@ -1050,15 +1114,15 @@ haptic\windows - - haptic\windows - haptic\dummy joystick\dummy + + joystick\gdk + joystick\hidapi @@ -1128,6 +1192,12 @@ joystick\virtual + + time + + + time\windows + video @@ -1185,9 +1255,6 @@ video - - video - video @@ -1203,9 +1270,6 @@ video\dummy - - video\yuv2rgb - video\windows @@ -1233,6 +1297,12 @@ video\windows + + video\windows + + + video\windows + video\windows @@ -1287,6 +1357,15 @@ stdlib + + stdlib + + + stdlib + + + stdlib + stdlib @@ -1387,11 +1466,21 @@ stdlib - - stdlib - + + + + + + render\vulkan + + + render\vulkan + + + + diff --git a/VisualC/pkg-support/cmake/sdl3-config.cmake b/VisualC/pkg-support/cmake/sdl3-config.cmake index 4a9b4ac2..fda40b7d 100644 --- a/VisualC/pkg-support/cmake/sdl3-config.cmake +++ b/VisualC/pkg-support/cmake/sdl3-config.cmake @@ -1,7 +1,7 @@ # SDL CMake configuration file: # This file is meant to be placed in a cmake subfolder of SDL3-devel-3.x.y-VC -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.0...3.5) include(FeatureSummary) set_package_properties(SDL3 PROPERTIES @@ -39,20 +39,23 @@ else() return() endif() -set_and_check(_sdl3_prefix "${CMAKE_CURRENT_LIST_DIR}/..") -set(_sdl3_include_dirs "${_sdl3_prefix}/include") +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_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") + +unset(_sdl_arch_subdir) unset(_sdl3_prefix) -set(SDL3_LIBRARIES SDL3::SDL3) -set(SDL3TEST_LIBRARY SDL3::SDL3_test) - - # 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::SDL3 + set_target_properties(SDL3::Headers PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_sdl3_include_dirs}" ) @@ -60,8 +63,6 @@ endif() set(SDL3_Headers_FOUND TRUE) unset(_sdl3_include_dirs) -set(_sdl3_library "${SDL3_LIBDIR}/SDL3.lib") -set(_sdl3_dll_library "${SDL3_BINDIR}/SDL3.dll") if(EXISTS "${_sdl3_library}" AND EXISTS "${_sdl3_dll_library}") if(NOT TARGET SDL3::SDL3-shared) add_library(SDL3::SDL3-shared SHARED IMPORTED) @@ -85,7 +86,6 @@ unset(_sdl3_dll_library) set(SDL3_SDL3-static_FOUND FALSE) -set(_sdl3test_library "${SDL3_LIBDIR}/SDL3_test.lib") if(EXISTS "${_sdl3test_library}") if(NOT TARGET SDL3::SDL3_test) add_library(SDL3::SDL3_test STATIC IMPORTED) @@ -103,7 +103,7 @@ else() endif() unset(_sdl3test_library) -if(SDL3_SDL3-shared_FOUND OR SDL3_SDL3-static_FOUND) +if(SDL3_SDL3-shared_FOUND) set(SDL3_SDL3_FOUND TRUE) endif() @@ -121,9 +121,13 @@ endfunction() if(NOT TARGET SDL3::SDL3) if(TARGET SDL3::SDL3-shared) _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-shared) - else() - _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-static) 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/VisualC/tests/testautomation/testautomation.vcxproj b/VisualC/tests/testautomation/testautomation.vcxproj index dbe1f3d8..84539df4 100644 --- a/VisualC/tests/testautomation/testautomation.vcxproj +++ b/VisualC/tests/testautomation/testautomation.vcxproj @@ -206,6 +206,7 @@ + @@ -220,10 +221,11 @@ - + + diff --git a/WhatsNew.txt b/WhatsNew.txt index 1b84c49b..65499711 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -2,31 +2,32 @@ This is a list of major changes in SDL's version history. --------------------------------------------------------------------------- -3.2.0: +3.1.0: --------------------------------------------------------------------------- -General: -* SDL headers should now be included as `#include ` -* Many functions and symbols have changed since SDL 2.0, see the [migration guide](docs/README-migration.md) for details -* The preprocessor symbol __MACOSX__ has been renamed __MACOS__ -* The preprocessor symbol __IPHONEOS__ has been renamed __IOS__ -* SDL_stdinc.h no longer includes stdio.h, stdlib.h, etc., it only provides the SDL C runtime functionality -* SDL_intrin.h now includes the intrinsics headers that were in SDL_cpuinfo.h -* Added SDL_GetSystemTheme() to return whether the system is using a dark or light color theme, and SDL_EVENT_SYSTEM_THEME_CHANGED is sent when this changes -* Added SDL_GetDisplays() to return a list of connected displays -* Added SDL_GetPrimaryDisplay() to get the instance ID of the primary display -* Added SDL_GetWindowParent() to get the parent of popup windows -* Added SDL_CreateSurface() and SDL_CreateSurfaceFrom() which replace SDL_CreateRGBSurface*(), and can also be used to create YUV surfaces -* Added SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() to directly query the list of available joysticks -* Added SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() to directly query the list of available gamepads -* Added SDL_GetSensors(), SDL_GetSensorInstanceName(), SDL_GetSensorInstanceType(), and SDL_GetSensorInstanceNonPortableType() to directly query the list of available sensors -* SDL_GetTicks() now returns a 64-bit value and the tick values should be directly compared instead of using the SDL_TICKS_PASSED macro -* Added SDL_GetTicksNS() to return the number of nanoseconds since the SDL library initialized -* Added SDL_DelayNS() to specify a delay in nanoseconds, to the highest precision the system will support -* The timestamp member of the SDL_Event structure is now in nanoseconds, filled in with the time the event was generated, or the time it was queued if that's not available -* Added SDL_modf() and SDL_modff() to separate the whole and fractional portions of a floating point number -* Added SDL_aligned_alloc() and SDL_aligned_free() to allocate and free memory with a given alignment -* Added SDL_GetRenderVSync() to get vsync of the given renderer -* Added SDL_PlayAudioDevice() to start audio playback -* Added SDL_ConvertAudioSamples() to convert audio samples from one format to another -* Added the hint SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY to control re-creation of Android SDL activity. +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! diff --git a/Xcode/SDL/Info-Framework.plist b/Xcode/SDL/Info-Framework.plist index 65acdef2..e3abd182 100644 --- a/Xcode/SDL/Info-Framework.plist +++ b/Xcode/SDL/Info-Framework.plist @@ -19,10 +19,10 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.0.0 + 3.1.0 CFBundleSignature SDLX CFBundleVersion - 3.0.0 + 3.1.0 diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index c6ea6f7a..d9405dc6 100644 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -33,8 +33,15 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 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 */; }; 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */ = {isa = PBXBuildFile; fileRef = 000078E1881E857EBB6C0000 /* SDL_hashtable.c */; }; + 0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */; }; + 0000494CC93F3E624D3C0000 /* SDL_systime.c in Sources */ = {isa = PBXBuildFile; fileRef = 00003F472C51CE7DF6160000 /* SDL_systime.c */; }; + 000080903BC03006F24E0000 /* SDL_filesystem.c in Sources */ = {isa = PBXBuildFile; fileRef = 00002B010DB1A70931C20000 /* SDL_filesystem.c */; }; + 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, ); }; 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, ); }; @@ -170,14 +177,12 @@ A7D8B25A23E2514200DCD162 /* vulkan_vi.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A72F23E2513E00DCD162 /* vulkan_vi.h */; }; A7D8B26023E2514200DCD162 /* vulkan.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73023E2513E00DCD162 /* vulkan.h */; }; A7D8B26623E2514200DCD162 /* vk_platform.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73123E2513E00DCD162 /* vk_platform.h */; }; - A7D8B26C23E2514200DCD162 /* vulkan.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73223E2513E00DCD162 /* vulkan.hpp */; }; A7D8B27223E2514200DCD162 /* vulkan_fuchsia.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73323E2513E00DCD162 /* vulkan_fuchsia.h */; }; A7D8B27823E2514200DCD162 /* vulkan_wayland.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73423E2513E00DCD162 /* vulkan_wayland.h */; }; A7D8B27E23E2514200DCD162 /* vulkan_win32.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73523E2513E00DCD162 /* vulkan_win32.h */; }; A7D8B28423E2514200DCD162 /* vulkan_macos.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73623E2513E00DCD162 /* vulkan_macos.h */; }; A7D8B28A23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73723E2513E00DCD162 /* vulkan_xlib_xrandr.h */; }; A7D8B29023E2514200DCD162 /* vulkan_xcb.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73823E2513E00DCD162 /* vulkan_xcb.h */; }; - A7D8B29623E2514200DCD162 /* vulkan_mir.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73923E2513E00DCD162 /* vulkan_mir.h */; }; A7D8B29C23E2514200DCD162 /* vulkan_xlib.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73A23E2513E00DCD162 /* vulkan_xlib.h */; }; A7D8B2A223E2514200DCD162 /* vulkan_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73B23E2513E00DCD162 /* vulkan_ios.h */; }; A7D8B2A823E2514200DCD162 /* vulkan_core.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A73C23E2513E00DCD162 /* vulkan_core.h */; }; @@ -190,7 +195,6 @@ A7D8B3A423E2514200DCD162 /* SDL_fillrect.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A76823E2513E00DCD162 /* SDL_fillrect.c */; }; A7D8B3B023E2514200DCD162 /* SDL_yuv_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */; }; A7D8B3B623E2514200DCD162 /* SDL_blit.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A76B23E2513E00DCD162 /* SDL_blit.h */; }; - A7D8B3BF23E2514200DCD162 /* yuv_rgb.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A76E23E2513E00DCD162 /* yuv_rgb.c */; }; A7D8B3C823E2514200DCD162 /* yuv_rgb_sse_func.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A77023E2513E00DCD162 /* yuv_rgb_sse_func.h */; }; A7D8B3CE23E2514300DCD162 /* yuv_rgb_std_func.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A77123E2513E00DCD162 /* yuv_rgb_std_func.h */; }; A7D8B3D423E2514300DCD162 /* yuv_rgb.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A77223E2513E00DCD162 /* yuv_rgb.h */; }; @@ -222,9 +226,9 @@ A7D8B58123E2514300DCD162 /* SDL_sysjoystick.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */; }; 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_rwops.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DB23E2513F00DCD162 /* SDL_rwops.c */; }; - A7D8B5C323E2514300DCD162 /* SDL_rwopsbundlesupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7DD23E2513F00DCD162 /* SDL_rwopsbundlesupport.h */; }; - A7D8B5C923E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DE23E2513F00DCD162 /* SDL_rwopsbundlesupport.m */; }; + 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 */; }; @@ -368,11 +372,18 @@ A7D8BBE923E2574800DCD162 /* SDL_uikitvulkan.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A62523E2513D00DCD162 /* SDL_uikitvulkan.m */; }; A7D8BBEA23E2574800DCD162 /* SDL_uikitwindow.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A62723E2513D00DCD162 /* SDL_uikitwindow.h */; }; A7D8BBEB23E2574800DCD162 /* SDL_uikitwindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A61A23E2513D00DCD162 /* SDL_uikitwindow.m */; }; + E41D20152BA9577D003073FA /* SDL_storage.h in Headers */ = {isa = PBXBuildFile; fileRef = E41D20142BA9577D003073FA /* SDL_storage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E479118D2BA9555500CE3B7F /* SDL_storage.c in Sources */ = {isa = PBXBuildFile; fileRef = E47911872BA9555500CE3B7F /* SDL_storage.c */; }; + 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 */; }; 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 */; }; + 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 */; }; F31A92C828D4CB39003BFD6A /* SDL_offscreenopengles.h in Headers */ = {isa = PBXBuildFile; fileRef = F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */; }; F31A92D228D4CB39003BFD6A /* SDL_offscreenopengles.c in Sources */ = {isa = PBXBuildFile; fileRef = F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */; }; F32305FF28939F6400E66D30 /* SDL_hidapi_combined.c in Sources */ = {isa = PBXBuildFile; fileRef = F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */; }; @@ -387,9 +398,18 @@ F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */; }; F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */; }; 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 */; }; 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 */; }; + F37E184E2B8C097D0098C111 /* SDL_camera.h in Headers */ = {isa = PBXBuildFile; fileRef = 000084ED0A56E3ED52F90000 /* SDL_camera.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F37E18522BA50E760098C111 /* SDL_dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = F37E18512BA50E750098C111 /* SDL_dialog.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F37E18582BA50F3B0098C111 /* SDL_cocoadialog.m in Sources */ = {isa = PBXBuildFile; fileRef = F37E18572BA50F3B0098C111 /* SDL_cocoadialog.m */; platformFilters = (macos, ); }; + F37E185A2BA50F450098C111 /* SDL_dummydialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F37E18592BA50F450098C111 /* SDL_dummydialog.c */; platformFilters = (ios, maccatalyst, tvos, xros, ); }; + F37E185C2BAA3EF90098C111 /* SDL_time.h in Headers */ = {isa = PBXBuildFile; fileRef = F37E185B2BAA3EF90098C111 /* SDL_time.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F37E18622BAA40090098C111 /* SDL_sysfilesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = F37E18612BAA40090098C111 /* SDL_sysfilesystem.h */; }; + F37E18642BAA40670098C111 /* SDL_time_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F37E18632BAA40670098C111 /* SDL_time_c.h */; }; F3820713284F3609004DD584 /* controller_type.c in Sources */ = {isa = PBXBuildFile; fileRef = F3820712284F3609004DD584 /* controller_type.c */; }; F382071D284F362F004DD584 /* SDL_guid.c in Sources */ = {isa = PBXBuildFile; fileRef = F382071C284F362F004DD584 /* SDL_guid.c */; }; F386F6E72884663E001840AA /* SDL_log_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F386F6E42884663E001840AA /* SDL_log_c.h */; }; @@ -417,15 +437,8 @@ F3B38CDF296E2E52005DA6D3 /* SDL_intrin.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 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 */; }; - F3DDCC572AFD42B600B0842B /* SDL_surface_pixel_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */; }; - F3DDCC582AFD42B600B0842B /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DDCC4F2AFD42B500B0842B /* SDL_video_capture.c */; }; - F3DDCC592AFD42B600B0842B /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = F3DDCC502AFD42B500B0842B /* SDL_video_capture_apple.m */; }; - F3DDCC5A2AFD42B600B0842B /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC512AFD42B500B0842B /* SDL_video_capture_c.h */; }; F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; }; - F3DDCC5C2AFD42B600B0842B /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC532AFD42B600B0842B /* SDL_sysvideocapture.h */; }; F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; }; - F3DDCC5E2AFD42B600B0842B /* SDL_video_capture_v4l2.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DDCC552AFD42B600B0842B /* SDL_video_capture_v4l2.c */; }; - F3DDCC602AFD432500B0842B /* SDL_video_capture.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC5F2AFD432500B0842B /* SDL_video_capture.h */; settings = {ATTRIBUTES = (Public, ); }; }; 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 */; }; @@ -457,7 +470,7 @@ F3F7D9592933074E00816151 /* SDL_video.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C52933074B00816151 /* SDL_video.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D95D2933074E00816151 /* SDL_opengles.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C62933074B00816151 /* SDL_opengles.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9612933074E00816151 /* SDL_opengles2.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C72933074B00816151 /* SDL_opengles2.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F3F7D9652933074E00816151 /* SDL_rwops.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C82933074B00816151 /* SDL_rwops.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3F7D9652933074E00816151 /* SDL_iostream.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C82933074B00816151 /* SDL_iostream.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9692933074E00816151 /* SDL_opengles2_gl2platform.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D96D2933074E00816151 /* SDL_hidapi.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8CA2933074B00816151 /* SDL_hidapi.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9712933074E00816151 /* SDL_events.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8CB2933074B00816151 /* SDL_events.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -489,6 +502,15 @@ F3F7D9DD2933074E00816151 /* SDL_mutex.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E62933074E00816151 /* SDL_mutex.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E72933074E00816151 /* SDL_begin_code.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9E52933074E00816151 /* SDL_system.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E82933074E00816151 /* SDL_system.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3FA5A1D2B59ACE000FEAD97 /* yuv_rgb_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A142B59ACE000FEAD97 /* yuv_rgb_internal.h */; }; + F3FA5A1E2B59ACE000FEAD97 /* yuv_rgb_lsx_func.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A152B59ACE000FEAD97 /* yuv_rgb_lsx_func.h */; }; + F3FA5A1F2B59ACE000FEAD97 /* yuv_rgb_sse.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A162B59ACE000FEAD97 /* yuv_rgb_sse.h */; }; + F3FA5A202B59ACE000FEAD97 /* yuv_rgb_std.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A172B59ACE000FEAD97 /* yuv_rgb_std.h */; }; + F3FA5A212B59ACE000FEAD97 /* yuv_rgb_std.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FA5A182B59ACE000FEAD97 /* yuv_rgb_std.c */; }; + F3FA5A222B59ACE000FEAD97 /* yuv_rgb_sse.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FA5A192B59ACE000FEAD97 /* yuv_rgb_sse.c */; }; + 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 */; }; FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; /* End PBXBuildFile section */ @@ -516,11 +538,21 @@ /* End PBXCopyFilesBuildPhase section */ /* 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 = ""; }; 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 = ""; }; + 00005D3EB902478835E20000 /* SDL_syscamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_syscamera.h; sourceTree = ""; }; + 0000641A9BAC11AB3FBE0000 /* SDL_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_time.c; sourceTree = ""; }; 000078E1881E857EBB6C0000 /* SDL_hashtable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hashtable.c; sourceTree = ""; }; + 000084ED0A56E3ED52F90000 /* SDL_camera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_camera.h; path = SDL3/SDL_camera.h; sourceTree = ""; }; + 00008B79BF08CBCEAC460000 /* SDL_camera_coremedia.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_camera_coremedia.m; sourceTree = ""; }; + 00009003C7148E1126CA0000 /* SDL_camera_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_camera_c.h; sourceTree = ""; }; 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 = ""; }; + 0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysfsops.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; }; @@ -691,14 +723,12 @@ A7D8A72F23E2513E00DCD162 /* vulkan_vi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_vi.h; sourceTree = ""; }; A7D8A73023E2513E00DCD162 /* vulkan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan.h; sourceTree = ""; }; A7D8A73123E2513E00DCD162 /* vk_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vk_platform.h; sourceTree = ""; }; - A7D8A73223E2513E00DCD162 /* vulkan.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = vulkan.hpp; sourceTree = ""; }; A7D8A73323E2513E00DCD162 /* vulkan_fuchsia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_fuchsia.h; sourceTree = ""; }; A7D8A73423E2513E00DCD162 /* vulkan_wayland.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_wayland.h; sourceTree = ""; }; A7D8A73523E2513E00DCD162 /* vulkan_win32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_win32.h; sourceTree = ""; }; A7D8A73623E2513E00DCD162 /* vulkan_macos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_macos.h; sourceTree = ""; }; A7D8A73723E2513E00DCD162 /* vulkan_xlib_xrandr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_xlib_xrandr.h; sourceTree = ""; }; A7D8A73823E2513E00DCD162 /* vulkan_xcb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_xcb.h; sourceTree = ""; }; - A7D8A73923E2513E00DCD162 /* vulkan_mir.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_mir.h; sourceTree = ""; }; A7D8A73A23E2513E00DCD162 /* vulkan_xlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_xlib.h; sourceTree = ""; }; A7D8A73B23E2513E00DCD162 /* vulkan_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_ios.h; sourceTree = ""; }; A7D8A73C23E2513E00DCD162 /* vulkan_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vulkan_core.h; sourceTree = ""; }; @@ -711,7 +741,6 @@ A7D8A76823E2513E00DCD162 /* SDL_fillrect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_fillrect.c; sourceTree = ""; }; A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_yuv_c.h; sourceTree = ""; }; A7D8A76B23E2513E00DCD162 /* SDL_blit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_blit.h; sourceTree = ""; }; - A7D8A76E23E2513E00DCD162 /* yuv_rgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yuv_rgb.c; sourceTree = ""; }; A7D8A77023E2513E00DCD162 /* yuv_rgb_sse_func.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_sse_func.h; sourceTree = ""; }; A7D8A77123E2513E00DCD162 /* yuv_rgb_std_func.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_std_func.h; sourceTree = ""; }; A7D8A77223E2513E00DCD162 /* yuv_rgb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb.h; sourceTree = ""; }; @@ -745,9 +774,9 @@ A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysjoystick.h; sourceTree = ""; }; 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_rwops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rwops.c; sourceTree = ""; }; - A7D8A7DD23E2513F00DCD162 /* SDL_rwopsbundlesupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rwopsbundlesupport.h; sourceTree = ""; }; - A7D8A7DE23E2513F00DCD162 /* SDL_rwopsbundlesupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_rwopsbundlesupport.m; 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 = ""; }; @@ -867,11 +896,18 @@ BECDF66B0761BA81005FE872 /* Info-Framework.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = ""; }; BECDF66C0761BA81005FE872 /* SDL3.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL3.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E2D187D228A5673500D2B4F1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E41D20142BA9577D003073FA /* SDL_storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_storage.h; path = SDL3/SDL_storage.h; sourceTree = ""; }; + E47911872BA9555500CE3B7F /* SDL_storage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_storage.c; sourceTree = ""; }; + 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 = ""; }; 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 = ""; }; + 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 = ""; }; F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_offscreenopengles.h; sourceTree = ""; }; F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_offscreenopengles.c; sourceTree = ""; }; F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_combined.c; sourceTree = ""; }; @@ -885,6 +921,8 @@ F362B9162B3349E200D30B94 /* SDL_gamepad_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamepad_c.h; sourceTree = ""; }; F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_steam_virtual_gamepad.h; sourceTree = ""; }; 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 = ""; }; 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; }; @@ -903,6 +941,12 @@ F37A8E1928405AA100C38E95 /* CMake */ = {isa = PBXFileReference; lastKnownFileType = folder; path = CMake; sourceTree = ""; }; F37DC5F225350EBC0002E6F7 /* CoreHaptics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreHaptics.framework; path = System/Library/Frameworks/CoreHaptics.framework; sourceTree = SDKROOT; }; F37DC5F425350ECC0002E6F7 /* CoreHaptics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreHaptics.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS14.0.sdk/System/Library/Frameworks/CoreHaptics.framework; sourceTree = DEVELOPER_DIR; }; + F37E18512BA50E750098C111 /* SDL_dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dialog.h; path = SDL3/SDL_dialog.h; sourceTree = ""; }; + F37E18572BA50F3B0098C111 /* SDL_cocoadialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoadialog.m; sourceTree = ""; }; + F37E18592BA50F450098C111 /* SDL_dummydialog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummydialog.c; sourceTree = ""; }; + F37E185B2BAA3EF90098C111 /* SDL_time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_time.h; path = SDL3/SDL_time.h; sourceTree = ""; }; + F37E18612BAA40090098C111 /* SDL_sysfilesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysfilesystem.h; sourceTree = ""; }; + F37E18632BAA40670098C111 /* SDL_time_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_time_c.h; sourceTree = ""; }; F3820712284F3609004DD584 /* controller_type.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = controller_type.c; sourceTree = ""; }; F382071C284F362F004DD584 /* SDL_guid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_guid.c; sourceTree = ""; }; F382339B2738ED6600F7F527 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS15.0.sdk/System/Library/Frameworks/CoreBluetooth.framework; sourceTree = DEVELOPER_DIR; }; @@ -930,15 +974,8 @@ F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_intrin.h; path = SDL3/SDL_intrin.h; 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 = ""; }; - F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_surface_pixel_impl.h; sourceTree = ""; }; - F3DDCC4F2AFD42B500B0842B /* SDL_video_capture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_capture.c; sourceTree = ""; }; - F3DDCC502AFD42B500B0842B /* SDL_video_capture_apple.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_video_capture_apple.m; sourceTree = ""; }; - F3DDCC512AFD42B500B0842B /* SDL_video_capture_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_capture_c.h; sourceTree = ""; }; F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = ""; }; - F3DDCC532AFD42B600B0842B /* SDL_sysvideocapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysvideocapture.h; sourceTree = ""; }; F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = ""; }; - F3DDCC552AFD42B600B0842B /* SDL_video_capture_v4l2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_capture_v4l2.c; sourceTree = ""; }; - F3DDCC5F2AFD432500B0842B /* SDL_video_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_video_capture.h; path = SDL3/SDL_video_capture.h; sourceTree = ""; }; 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 = ""; }; @@ -970,7 +1007,7 @@ F3F7D8C52933074B00816151 /* SDL_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_video.h; path = SDL3/SDL_video.h; sourceTree = ""; }; F3F7D8C62933074B00816151 /* SDL_opengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles.h; path = SDL3/SDL_opengles.h; sourceTree = ""; }; F3F7D8C72933074B00816151 /* SDL_opengles2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles2.h; path = SDL3/SDL_opengles2.h; sourceTree = ""; }; - F3F7D8C82933074B00816151 /* SDL_rwops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_rwops.h; path = SDL3/SDL_rwops.h; sourceTree = ""; }; + F3F7D8C82933074B00816151 /* SDL_iostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_iostream.h; path = SDL3/SDL_iostream.h; sourceTree = ""; }; F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengles2_gl2platform.h; path = SDL3/SDL_opengles2_gl2platform.h; sourceTree = ""; }; F3F7D8CA2933074B00816151 /* SDL_hidapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_hidapi.h; path = SDL3/SDL_hidapi.h; sourceTree = ""; }; F3F7D8CB2933074B00816151 /* SDL_events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_events.h; path = SDL3/SDL_events.h; sourceTree = ""; }; @@ -1002,6 +1039,15 @@ F3F7D8E62933074E00816151 /* SDL_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_mutex.h; path = SDL3/SDL_mutex.h; sourceTree = ""; }; F3F7D8E72933074E00816151 /* SDL_begin_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_begin_code.h; path = SDL3/SDL_begin_code.h; sourceTree = ""; }; F3F7D8E82933074E00816151 /* SDL_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_system.h; path = SDL3/SDL_system.h; sourceTree = ""; }; + F3FA5A142B59ACE000FEAD97 /* yuv_rgb_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_internal.h; sourceTree = ""; }; + F3FA5A152B59ACE000FEAD97 /* yuv_rgb_lsx_func.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_lsx_func.h; sourceTree = ""; }; + F3FA5A162B59ACE000FEAD97 /* yuv_rgb_sse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_sse.h; sourceTree = ""; }; + F3FA5A172B59ACE000FEAD97 /* yuv_rgb_std.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_std.h; sourceTree = ""; }; + F3FA5A182B59ACE000FEAD97 /* yuv_rgb_std.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yuv_rgb_std.c; sourceTree = ""; }; + F3FA5A192B59ACE000FEAD97 /* yuv_rgb_sse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yuv_rgb_sse.c; sourceTree = ""; }; + 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 = ""; }; 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; }; @@ -1031,6 +1077,42 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 000004752BA2F77DECDF0000 /* unix */ = { + isa = PBXGroup; + children = ( + 00003F472C51CE7DF6160000 /* SDL_systime.c */, + ); + path = unix; + sourceTree = ""; + }; + 000023E01FD84242AF850000 /* dummy */ = { + isa = PBXGroup; + children = ( + 00005BD74B46358B33A20000 /* SDL_camera_dummy.c */, + ); + path = dummy; + sourceTree = ""; + }; + 00002EC7DF7A0A31B32A0000 /* camera */ = { + isa = PBXGroup; + children = ( + 0000DBB4B95F4CC5CAE80000 /* coremedia */, + 000023E01FD84242AF850000 /* dummy */, + 0000035D38C3899C7EFD0000 /* SDL_camera.c */, + 00009003C7148E1126CA0000 /* SDL_camera_c.h */, + 00005D3EB902478835E20000 /* SDL_syscamera.h */, + ); + path = camera; + sourceTree = ""; + }; + 000050A2BB34616138570000 /* posix */ = { + isa = PBXGroup; + children = ( + 0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */, + ); + path = posix; + sourceTree = ""; + }; 000082EF09C89B62BD840000 /* main */ = { isa = PBXGroup; children = ( @@ -1050,6 +1132,24 @@ path = ios; sourceTree = ""; }; + 0000DBB4B95F4CC5CAE80000 /* coremedia */ = { + isa = PBXGroup; + children = ( + 00008B79BF08CBCEAC460000 /* SDL_camera_coremedia.m */, + ); + path = coremedia; + sourceTree = ""; + }; + 0000F5E7419220E3A8AB0000 /* time */ = { + isa = PBXGroup; + children = ( + 000004752BA2F77DECDF0000 /* unix */, + F37E18632BAA40670098C111 /* SDL_time_c.h */, + 0000641A9BAC11AB3FBE0000 /* SDL_time.c */, + ); + path = time; + sourceTree = ""; + }; 0153844A006D81B07F000001 /* Public Headers */ = { isa = PBXGroup; children = ( @@ -1059,10 +1159,12 @@ F3F7D8E72933074E00816151 /* SDL_begin_code.h */, F3F7D8D82933074C00816151 /* SDL_bits.h */, F3F7D8CE2933074C00816151 /* SDL_blendmode.h */, + 000084ED0A56E3ED52F90000 /* SDL_camera.h */, F3F7D8D72933074C00816151 /* SDL_clipboard.h */, F3F7D8E52933074D00816151 /* SDL_close_code.h */, F3F7D8E32933074D00816151 /* SDL_copying.h */, F3F7D8DD2933074D00816151 /* SDL_cpuinfo.h */, + F37E18512BA50E750098C111 /* SDL_dialog.h */, F3F7D8B82933074A00816151 /* SDL_egl.h */, F3F7D8BE2933074A00816151 /* SDL_endian.h */, F3F7D8BC2933074A00816151 /* SDL_error.h */, @@ -1075,6 +1177,7 @@ F3F7D8B32933074900816151 /* SDL_hints.h */, F3B38CCC296E2E52005DA6D3 /* SDL_init.h */, F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */, + F3F7D8C82933074B00816151 /* SDL_iostream.h */, F3F7D8D32933074C00816151 /* SDL_joystick.h */, F3F7D8C32933074B00816151 /* SDL_keyboard.h */, F3F7D8CC2933074B00816151 /* SDL_keycode.h */, @@ -1107,17 +1210,17 @@ F3F7D8E22933074D00816151 /* SDL_rect.h */, F3F7D8DE2933074D00816151 /* SDL_render.h */, F3F7D8B42933074900816151 /* SDL_revision.h */, - F3F7D8C82933074B00816151 /* SDL_rwops.h */, F3F7D8C12933074B00816151 /* SDL_scancode.h */, F3F7D8C22933074B00816151 /* SDL_sensor.h */, F3F7D8AC2933074900816151 /* SDL_stdinc.h */, + E41D20142BA9577D003073FA /* SDL_storage.h */, F3F7D8BB2933074A00816151 /* SDL_surface.h */, F3F7D8E82933074E00816151 /* SDL_system.h */, F3F7D8CD2933074C00816151 /* SDL_thread.h */, + F37E185B2BAA3EF90098C111 /* SDL_time.h */, F3F7D8B22933074900816151 /* SDL_timer.h */, F3F7D8AF2933074900816151 /* SDL_touch.h */, F3F7D8E42933074D00816151 /* SDL_version.h */, - F3DDCC5F2AFD432500B0842B /* SDL_video_capture.h */, F3F7D8C52933074B00816151 /* SDL_video.h */, F3F7D8D42933074C00816151 /* SDL_vulkan.h */, F3F7D8CF2933074C00816151 /* SDL.h */, @@ -1158,8 +1261,10 @@ children = ( A7D8A57223E2513D00DCD162 /* atomic */, A7D8A86423E2513F00DCD162 /* audio */, + 00002EC7DF7A0A31B32A0000 /* camera */, F36C7ACF294B9F5E004D61C3 /* core */, A7D8A77423E2513E00DCD162 /* cpuinfo */, + F37E18542BA50EB40098C111 /* dialog */, A7D8A5D723E2513D00DCD162 /* dynapi */, A7D8A92923E2514000DCD162 /* events */, A7D8A7DA23E2513E00DCD162 /* file */, @@ -1176,7 +1281,9 @@ A7D8A8DA23E2514000DCD162 /* render */, A7D8A57623E2513D00DCD162 /* sensor */, A7D8A8D223E2514000DCD162 /* stdlib */, + E47911832BA9555500CE3B7F /* storage */, A7D8A77623E2513E00DCD162 /* thread */, + 0000F5E7419220E3A8AB0000 /* time */, A7D8A5DE23E2513D00DCD162 /* timer */, A7D8A5EB23E2513D00DCD162 /* video */, A7D8A7F523E2513F00DCD162 /* SDL_assert_c.h */, @@ -1436,15 +1543,9 @@ A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */, A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */, A7D8A60323E2513D00DCD162 /* SDL_stretch.c */, - F3DDCC4E2AFD42B500B0842B /* SDL_surface_pixel_impl.h */, A7D8A61423E2513D00DCD162 /* SDL_surface.c */, A7D8A61723E2513D00DCD162 /* SDL_sysvideo.h */, - F3DDCC532AFD42B600B0842B /* SDL_sysvideocapture.h */, F3DDCC522AFD42B600B0842B /* SDL_video_c.h */, - F3DDCC502AFD42B500B0842B /* SDL_video_capture_apple.m */, - F3DDCC512AFD42B500B0842B /* SDL_video_capture_c.h */, - F3DDCC552AFD42B600B0842B /* SDL_video_capture_v4l2.c */, - F3DDCC4F2AFD42B500B0842B /* SDL_video_capture.c */, E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */, A7D8A60E23E2513D00DCD162 /* SDL_video.c */, A7D8A63E23E2513D00DCD162 /* SDL_vulkan_internal.h */, @@ -1539,6 +1640,8 @@ A7D8A67F23E2513E00DCD162 /* SDL_cocoaopengl.m */, A7D8A69023E2513E00DCD162 /* SDL_cocoaopengles.h */, A7D8A68223E2513E00DCD162 /* SDL_cocoaopengles.m */, + F3681E7F2B7AA6240002C6FD /* SDL_cocoashape.h */, + F3681E7E2B7AA6240002C6FD /* SDL_cocoashape.m */, A7D8A69323E2513E00DCD162 /* SDL_cocoavideo.h */, A7D8A68523E2513E00DCD162 /* SDL_cocoavideo.m */, A7D8A68F23E2513E00DCD162 /* SDL_cocoavulkan.h */, @@ -1600,7 +1703,6 @@ A7D8A73323E2513E00DCD162 /* vulkan_fuchsia.h */, A7D8A73B23E2513E00DCD162 /* vulkan_ios.h */, A7D8A73623E2513E00DCD162 /* vulkan_macos.h */, - A7D8A73923E2513E00DCD162 /* vulkan_mir.h */, A7D8A72F23E2513E00DCD162 /* vulkan_vi.h */, A7D8A73423E2513E00DCD162 /* vulkan_wayland.h */, A7D8A73523E2513E00DCD162 /* vulkan_win32.h */, @@ -1608,7 +1710,6 @@ A7D8A73723E2513E00DCD162 /* vulkan_xlib_xrandr.h */, A7D8A73A23E2513E00DCD162 /* vulkan_xlib.h */, A7D8A73023E2513E00DCD162 /* vulkan.h */, - A7D8A73223E2513E00DCD162 /* vulkan.hpp */, ); path = vulkan; sourceTree = ""; @@ -1616,9 +1717,17 @@ A7D8A76C23E2513E00DCD162 /* yuv2rgb */ = { isa = PBXGroup; children = ( + F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */, + F3FA5A142B59ACE000FEAD97 /* yuv_rgb_internal.h */, + F3FA5A152B59ACE000FEAD97 /* yuv_rgb_lsx_func.h */, + F3FA5A1A2B59ACE000FEAD97 /* yuv_rgb_lsx.c */, + F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */, A7D8A77023E2513E00DCD162 /* yuv_rgb_sse_func.h */, + F3FA5A192B59ACE000FEAD97 /* yuv_rgb_sse.c */, + F3FA5A162B59ACE000FEAD97 /* yuv_rgb_sse.h */, A7D8A77123E2513E00DCD162 /* yuv_rgb_std_func.h */, - A7D8A76E23E2513E00DCD162 /* yuv_rgb.c */, + F3FA5A182B59ACE000FEAD97 /* yuv_rgb_std.c */, + F3FA5A172B59ACE000FEAD97 /* yuv_rgb_std.h */, A7D8A77223E2513E00DCD162 /* yuv_rgb.h */, ); path = yuv2rgb; @@ -1748,7 +1857,7 @@ isa = PBXGroup; children = ( A7D8A7DC23E2513F00DCD162 /* cocoa */, - A7D8A7DB23E2513F00DCD162 /* SDL_rwops.c */, + A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */, ); path = file; sourceTree = ""; @@ -1756,8 +1865,8 @@ A7D8A7DC23E2513F00DCD162 /* cocoa */ = { isa = PBXGroup; children = ( - A7D8A7DD23E2513F00DCD162 /* SDL_rwopsbundlesupport.h */, - A7D8A7DE23E2513F00DCD162 /* SDL_rwopsbundlesupport.m */, + A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */, + A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */, ); path = cocoa; sourceTree = ""; @@ -1795,6 +1904,9 @@ children = ( A7D8A7FD23E2513F00DCD162 /* cocoa */, A7D8A7F723E2513F00DCD162 /* dummy */, + 00002B010DB1A70931C20000 /* SDL_filesystem.c */, + F37E18612BAA40090098C111 /* SDL_sysfilesystem.h */, + 000050A2BB34616138570000 /* posix */, ); path = filesystem; sourceTree = ""; @@ -1920,6 +2032,9 @@ A7D8A8D423E2514000DCD162 /* SDL_getenv.c */, A7D8A8D323E2514000DCD162 /* SDL_iconv.c */, A7D8A8D923E2514000DCD162 /* SDL_malloc.c */, + F316ABD72B5C3185002EF551 /* SDL_memcpy.c */, + F316ABDA2B5CA721002EF551 /* SDL_memmove.c */, + F316ABD62B5C3185002EF551 /* SDL_memset.c */, A7D8A8D723E2514000DCD162 /* SDL_qsort.c */, A7D8A8D823E2514000DCD162 /* SDL_stdlib.c */, A7D8A8D523E2514000DCD162 /* SDL_string.c */, @@ -2074,6 +2189,24 @@ path = SDL3; sourceTree = ""; }; + E47911832BA9555500CE3B7F /* storage */ = { + isa = PBXGroup; + children = ( + E47911872BA9555500CE3B7F /* SDL_storage.c */, + E47911882BA9555500CE3B7F /* SDL_sysstorage.h */, + E47911892BA9555500CE3B7F /* generic */, + ); + path = storage; + sourceTree = ""; + }; + E47911892BA9555500CE3B7F /* generic */ = { + isa = PBXGroup; + children = ( + E479118A2BA9555500CE3B7F /* SDL_genericstorage.c */, + ); + path = generic; + sourceTree = ""; + }; E4A568B42AF763940062EEC4 /* generic */ = { isa = PBXGroup; children = ( @@ -2091,6 +2224,31 @@ path = core; sourceTree = ""; }; + F37E18542BA50EB40098C111 /* dialog */ = { + isa = PBXGroup; + children = ( + F37E18552BA50ED50098C111 /* cocoa */, + F37E18562BA50F2A0098C111 /* dummy */, + ); + path = dialog; + sourceTree = ""; + }; + F37E18552BA50ED50098C111 /* cocoa */ = { + isa = PBXGroup; + children = ( + F37E18572BA50F3B0098C111 /* SDL_cocoadialog.m */, + ); + path = cocoa; + sourceTree = ""; + }; + F37E18562BA50F2A0098C111 /* dummy */ = { + isa = PBXGroup; + children = ( + F37E18592BA50F450098C111 /* SDL_dummydialog.c */, + ); + path = dummy; + sourceTree = ""; + }; F3ADAB8C2576F08500A6B1D9 /* ios */ = { isa = PBXGroup; children = ( @@ -2131,10 +2289,12 @@ A7D8B61723E2514300DCD162 /* SDL_assert_c.h in Headers */, F3F7D9292933074E00816151 /* SDL_atomic.h in Headers */, F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */, - F3DDCC602AFD432500B0842B /* SDL_video_capture.h in Headers */, A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */, - F3DDCC5A2AFD42B600B0842B /* SDL_video_capture_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 */, F3F7D9E12933074E00816151 /* SDL_begin_code.h in Headers */, F3F7D9A52933074E00816151 /* SDL_bits.h in Headers */, A7D8BA0123E2514400DCD162 /* SDL_blendfillrect.h in Headers */, @@ -2145,11 +2305,12 @@ A7D8B2BA23E2514200DCD162 /* SDL_blit_auto.h in Headers */, A7D8B39823E2514200DCD162 /* SDL_blit_copy.h in Headers */, A7D8ADEC23E2514100DCD162 /* SDL_blit_slow.h in Headers */, + F37E184E2B8C097D0098C111 /* SDL_camera.h in Headers */, F3F7D9A12933074E00816151 /* SDL_clipboard.h in Headers */, + F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */, A7D8BB6F23E2514500DCD162 /* SDL_clipboardevents_c.h in Headers */, F3F7D9D92933074E00816151 /* SDL_close_code.h in Headers */, A7D8AECA23E2514100DCD162 /* SDL_cocoaclipboard.h in Headers */, - F3DDCC5C2AFD42B600B0842B /* SDL_sysvideocapture.h in Headers */, A7D8AF1223E2514100DCD162 /* SDL_cocoaevents.h in Headers */, A7D8AE8E23E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */, A7D8AF0623E2514100DCD162 /* SDL_cocoamessagebox.h in Headers */, @@ -2158,31 +2319,29 @@ A7D8AF1E23E2514100DCD162 /* SDL_cocoamouse.h in Headers */, A7D8AEDC23E2514100DCD162 /* SDL_cocoaopengl.h in Headers */, A7D8AEEE23E2514100DCD162 /* SDL_cocoaopengles.h in Headers */, + F3681E812B7AA6240002C6FD /* SDL_cocoashape.h in Headers */, A7D8AF0023E2514100DCD162 /* SDL_cocoavideo.h in Headers */, A7D8AEE823E2514100DCD162 /* SDL_cocoavulkan.h in Headers */, A7D8AEFA23E2514100DCD162 /* SDL_cocoawindow.h in Headers */, - F32DDACF2AB795A30041EAA5 /* SDL_audio_channel_converters.h in Headers */, F3F7D9D12933074E00816151 /* SDL_copying.h in Headers */, A7D8B8CC23E2514400DCD162 /* SDL_coreaudio.h in Headers */, A7D8A96F23E2514000DCD162 /* SDL_coremotionsensor.h in Headers */, F3F7D9B92933074E00816151 /* SDL_cpuinfo.h in Headers */, - F3990E062A788303000D8759 /* SDL_hidapi_ios.h in Headers */, A7D8B98023E2514400DCD162 /* SDL_d3dmath.h in Headers */, - F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */, A7D8B8A223E2514400DCD162 /* SDL_diskaudio.h in Headers */, A7D8BB3F23E2514500DCD162 /* SDL_displayevents_c.h in Headers */, A7D8BA1923E2514400DCD162 /* SDL_draw.h in Headers */, + E479118E2BA9555500CE3B7F /* SDL_sysstorage.h in Headers */, A7D8BA0723E2514400DCD162 /* SDL_drawline.h in Headers */, A7D8B9EF23E2514400DCD162 /* SDL_drawpoint.h in Headers */, A7D8BB2D23E2514500DCD162 /* SDL_dropevents_c.h in Headers */, A7D8B79423E2514400DCD162 /* SDL_dummyaudio.h in Headers */, A7D8A96323E2514000DCD162 /* SDL_dummysensor.h in Headers */, A7D8AB0A23E2514100DCD162 /* SDL_dynapi.h in Headers */, - F32DDAD02AB795A30041EAA5 /* SDL_audioresample.h in Headers */, A7D8AB1023E2514100DCD162 /* SDL_dynapi_overrides.h in Headers */, A7D8AB1C23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */, + E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */, F3F7D9252933074E00816151 /* SDL_egl.h in Headers */, - F362B9192B3349E200D30B94 /* controller_list.h in Headers */, A7D8ABD923E2514100DCD162 /* SDL_egl_c.h in Headers */, F3F7D93D2933074E00816151 /* SDL_endian.h in Headers */, F3F7D9352933074E00816151 /* SDL_error.h in Headers */, @@ -2191,6 +2350,7 @@ A7D8BBA523E2514500DCD162 /* SDL_events_c.h in Headers */, F3F7D99D2933074E00816151 /* SDL_filesystem.h in Headers */, F3F7D9852933074E00816151 /* SDL_gamepad.h in Headers */, + F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */, A7D8B4AC23E2514300DCD162 /* SDL_gamepad_db.h in Headers */, A7D8BA5523E2514400DCD162 /* SDL_gles2funcs.h in Headers */, A7D8BA7923E2514400DCD162 /* SDL_glfuncs.h in Headers */, @@ -2198,6 +2358,9 @@ F3F7D8F92933074E00816151 /* SDL_haptic.h in Headers */, A7D8AABC23E2514100DCD162 /* SDL_haptic_c.h in Headers */, F3F7D96D2933074E00816151 /* SDL_hidapi.h in Headers */, + F3990E042A788303000D8759 /* SDL_hidapi_c.h in Headers */, + F3990E062A788303000D8759 /* SDL_hidapi_ios.h in Headers */, + F3990E052A788303000D8759 /* SDL_hidapi_mac.h in Headers */, A75FDBC523EA380300529352 /* SDL_hidapi_rumble.h in Headers */, A7D8B55723E2514300DCD162 /* SDL_hidapijoystick_c.h in Headers */, F3F7D9112933074E00816151 /* SDL_hints.h in Headers */, @@ -2206,7 +2369,6 @@ A7D8A99923E2514000DCD162 /* SDL_internal.h in Headers */, F3B38CDF296E2E52005DA6D3 /* SDL_intrin.h in Headers */, F395C1932569C68F00942BFF /* SDL_iokitjoystick_c.h in Headers */, - F3990E052A788303000D8759 /* SDL_hidapi_mac.h in Headers */, F3F7D9912933074E00816151 /* SDL_joystick.h in Headers */, A7D8B58723E2514300DCD162 /* SDL_joystick_c.h in Headers */, F3F7D9512933074E00816151 /* SDL_keyboard.h in Headers */, @@ -2222,7 +2384,6 @@ F3F7D91D2933074E00816151 /* SDL_messagebox.h in Headers */, F3F7D98D2933074E00816151 /* SDL_metal.h in Headers */, F395C1BA2569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */, - F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */, F3F7D9992933074E00816151 /* SDL_misc.h in Headers */, F3F7D9AD2933074E00816151 /* SDL_mouse.h in Headers */, A7D8BB1B23E2514500DCD162 /* SDL_mouse_c.h in Headers */, @@ -2235,32 +2396,35 @@ F31A92C828D4CB39003BFD6A /* SDL_offscreenopengles.h in Headers */, A7D8AB6D23E2514100DCD162 /* SDL_offscreenvideo.h in Headers */, A7D8AB8523E2514100DCD162 /* SDL_offscreenwindow.h in Headers */, + F37E18642BAA40670098C111 /* SDL_time_c.h in Headers */, F3B38CDB296E2E52005DA6D3 /* SDL_oldnames.h in Headers */, F3F7D9C92933074E00816151 /* SDL_opengl.h in Headers */, F3F7D9452933074E00816151 /* SDL_opengl_glext.h in Headers */, - F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */, - E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */, F3F7D95D2933074E00816151 /* SDL_opengles.h in Headers */, F3F7D9612933074E00816151 /* SDL_opengles2.h in Headers */, F3F7D8FD2933074E00816151 /* SDL_opengles2_gl2.h in Headers */, F3F7D9392933074E00816151 /* SDL_opengles2_gl2ext.h in Headers */, F3F7D9692933074E00816151 /* SDL_opengles2_gl2platform.h in Headers */, F3F7D9092933074E00816151 /* SDL_opengles2_khrplatform.h in Headers */, - F32DDAD22AB795A30041EAA5 /* SDL_audio_resampler_filter.h in Headers */, + 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */, + 63134A252A7902FD0021E9A6 /* SDL_pen_c.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 */, F3F7D9152933074E00816151 /* SDL_revision.h in Headers */, A7D8BA3123E2514400DCD162 /* SDL_rotate.h in Headers */, - F3F7D9652933074E00816151 /* SDL_rwops.h in Headers */, - A7D8B5C323E2514300DCD162 /* SDL_rwopsbundlesupport.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 */, @@ -2270,6 +2434,7 @@ A7D8B99B23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */, A7D8B9A123E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */, F3F7D8F52933074E00816151 /* SDL_stdinc.h in Headers */, + F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */, A7D8BBC723E2561500DCD162 /* SDL_steamcontroller.h in Headers */, F3F7D9312933074E00816151 /* SDL_surface.h in Headers */, A7D8B85A23E2514400DCD162 /* SDL_sysaudio.h in Headers */, @@ -2294,13 +2459,12 @@ F3F7D9012933074E00816151 /* SDL_touch.h in Headers */, A7D8BB6323E2514500DCD162 /* SDL_touch_c.h in Headers */, A1626A522617008D003F1973 /* SDL_triangle.h in Headers */, - F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */, A7D8BBD223E2574800DCD162 /* SDL_uikitappdelegate.h in Headers */, A7D8BBD423E2574800DCD162 /* SDL_uikitclipboard.h in Headers */, A7D8BBD623E2574800DCD162 /* SDL_uikitevents.h in Headers */, + F37E185C2BAA3EF90098C111 /* SDL_time.h in Headers */, A7D8BBD823E2574800DCD162 /* SDL_uikitmessagebox.h in Headers */, A7D8BBDA23E2574800DCD162 /* SDL_uikitmetalview.h in Headers */, - F3990E042A788303000D8759 /* SDL_hidapi_c.h in Headers */, A7D8BBDC23E2574800DCD162 /* SDL_uikitmodes.h in Headers */, A7D8BBDE23E2574800DCD162 /* SDL_uikitopengles.h in Headers */, A7D8BBE023E2574800DCD162 /* SDL_uikitopenglview.h in Headers */, @@ -2309,11 +2473,11 @@ A7D8BBE623E2574800DCD162 /* SDL_uikitviewcontroller.h in Headers */, A7D8BBE823E2574800DCD162 /* SDL_uikitvulkan.h in Headers */, A7D8BBEA23E2574800DCD162 /* SDL_uikitwindow.h in Headers */, - F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */, F386F6F02884663E001840AA /* SDL_utils_c.h in Headers */, F3973FA228A59BDD00B84553 /* SDL_vacopy.h in Headers */, F3F7D9D52933074E00816151 /* SDL_version.h in Headers */, F3F7D9592933074E00816151 /* SDL_video.h in Headers */, + F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */, 75E09163241EA924004729E1 /* SDL_virtualjoystick_c.h in Headers */, F3F7D9952933074E00816151 /* SDL_vulkan.h in Headers */, A7D8AD1D23E2514100DCD162 /* SDL_vulkan_internal.h in Headers */, @@ -2322,6 +2486,7 @@ A7D8B3B023E2514200DCD162 /* SDL_yuv_c.h in Headers */, A7D8B9CB23E2514400DCD162 /* SDL_yuv_sw_c.h in Headers */, A7D8BB4523E2514500DCD162 /* blank_cursor.h in Headers */, + F362B9192B3349E200D30B94 /* controller_list.h in Headers */, A7D8B5B723E2514300DCD162 /* controller_type.h in Headers */, A7D8BB4B23E2514500DCD162 /* default_cursor.h in Headers */, A7D8B23C23E2514200DCD162 /* egl.h in Headers */, @@ -2341,30 +2506,31 @@ A7D8B56F23E2514300DCD162 /* usb_ids.h in Headers */, A7D8B25423E2514200DCD162 /* vk_icd.h in Headers */, A7D8B24E23E2514200DCD162 /* vk_layer.h in Headers */, - F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */, A7D8B26623E2514200DCD162 /* vk_platform.h in Headers */, A7D8B2AE23E2514200DCD162 /* vk_sdk_platform.h in Headers */, A7D8B26023E2514200DCD162 /* vulkan.h in Headers */, - A7D8B26C23E2514200DCD162 /* vulkan.hpp in Headers */, A7D8B2B423E2514200DCD162 /* vulkan_android.h in Headers */, A7D8B2A823E2514200DCD162 /* vulkan_core.h in Headers */, + E41D20152BA9577D003073FA /* SDL_storage.h in Headers */, + F37E18522BA50E760098C111 /* SDL_dialog.h in Headers */, A7D8B27223E2514200DCD162 /* vulkan_fuchsia.h in Headers */, A7D8B2A223E2514200DCD162 /* vulkan_ios.h in Headers */, A7D8B28423E2514200DCD162 /* vulkan_macos.h in Headers */, - A7D8B29623E2514200DCD162 /* vulkan_mir.h in Headers */, A7D8B25A23E2514200DCD162 /* vulkan_vi.h in Headers */, - F32DDAD32AB795A30041EAA5 /* SDL_audioqueue.h in Headers */, A7D8B27823E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27E23E2514200DCD162 /* vulkan_win32.h in Headers */, A7D8B29023E2514200DCD162 /* vulkan_xcb.h in Headers */, - F3DDCC572AFD42B600B0842B /* SDL_surface_pixel_impl.h in Headers */, A7D8B29C23E2514200DCD162 /* vulkan_xlib.h in Headers */, A7D8B28A23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */, A7D8B3D423E2514300DCD162 /* yuv_rgb.h in Headers */, + F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */, + F3FA5A1D2B59ACE000FEAD97 /* yuv_rgb_internal.h in Headers */, + F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */, + F3FA5A1E2B59ACE000FEAD97 /* yuv_rgb_lsx_func.h in Headers */, + F3FA5A1F2B59ACE000FEAD97 /* yuv_rgb_sse.h in Headers */, A7D8B3C823E2514200DCD162 /* yuv_rgb_sse_func.h in Headers */, + F3FA5A202B59ACE000FEAD97 /* yuv_rgb_std.h in Headers */, A7D8B3CE23E2514300DCD162 /* yuv_rgb_std_func.h in Headers */, - 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */, - 63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2459,7 +2625,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "mkdir -p build/dmg-tmp\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\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 = "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"; }; F3B38CF0296F63D1005DA6D3 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -2494,6 +2660,7 @@ 9846B07C287A9020000C35C8 /* SDL_hidapi_shield.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 */, A7D8A95123E2514000DCD162 /* SDL_spinlock.c in Sources */, F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */, @@ -2504,9 +2671,9 @@ A7D8B98623E2514400DCD162 /* SDL_render_metal.m in Sources */, A7D8AE7623E2514100DCD162 /* SDL_clipboard.c in Sources */, A7D8AEC423E2514100DCD162 /* SDL_cocoaevents.m in Sources */, + E479118F2BA9555500CE3B7F /* SDL_genericstorage.c in Sources */, A7D8B86623E2514400DCD162 /* SDL_audiocvt.c in Sources */, A7D8B9F523E2514400DCD162 /* SDL_rotate.c in Sources */, - F3DDCC5E2AFD42B600B0842B /* SDL_video_capture_v4l2.c in Sources */, A7D8BBE323E2574800DCD162 /* SDL_uikitvideo.m in Sources */, 5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */, A7D8A97523E2514000DCD162 /* SDL_coremotionsensor.m in Sources */, @@ -2522,9 +2689,8 @@ A7D8AB2523E2514100DCD162 /* SDL_log.c in Sources */, A7D8AE8823E2514100DCD162 /* SDL_cocoaopengl.m in Sources */, A7D8AB7323E2514100DCD162 /* SDL_offscreenframebuffer.c in Sources */, - A7D8B3BF23E2514200DCD162 /* yuv_rgb.c in Sources */, + F37E18582BA50F3B0098C111 /* SDL_cocoadialog.m in Sources */, A7D8B43423E2514300DCD162 /* SDL_systhread.c in Sources */, - F3DDCC592AFD42B600B0842B /* SDL_video_capture_apple.m in Sources */, A7D8BB3323E2514500DCD162 /* SDL_windowevents.c in Sources */, A7D8BABB23E2514400DCD162 /* s_scalbn.c in Sources */, F3973FAB28A59BDD00B84553 /* SDL_crc16.c in Sources */, @@ -2533,6 +2699,7 @@ A7D8B9DD23E2514400DCD162 /* SDL_blendpoint.c in Sources */, A7D8B4EE23E2514300DCD162 /* SDL_gamepad.c in Sources */, E4A568B62AF763940062EEC4 /* SDL_sysmain_callbacks.c in Sources */, + F316ABD82B5C3185002EF551 /* SDL_memset.c in Sources */, A7D8BA1323E2514400DCD162 /* SDL_render_sw.c in Sources */, A7D8B42223E2514300DCD162 /* SDL_syssem.c in Sources */, A7D8B53923E2514300DCD162 /* SDL_hidapi_xbox360.c in Sources */, @@ -2548,6 +2715,7 @@ A7D8AB6723E2514100DCD162 /* SDL_offscreenevents.c in Sources */, A7D8ABF123E2514100DCD162 /* SDL_nullevents.c in Sources */, A7D8B81823E2514400DCD162 /* SDL_audiodev.c in Sources */, + E479118D2BA9555500CE3B7F /* SDL_storage.c in Sources */, A7D8AF0C23E2514100DCD162 /* SDL_cocoaclipboard.m in Sources */, A7D8BBE523E2574800DCD162 /* SDL_uikitview.m in Sources */, A7D8BBE923E2574800DCD162 /* SDL_uikitvulkan.m in Sources */, @@ -2559,7 +2727,6 @@ A7D8B86023E2514400DCD162 /* SDL_audiotypecvt.c in Sources */, A7D8BBC523E2561500DCD162 /* SDL_steamcontroller.c in Sources */, A7D8AD3223E2514100DCD162 /* SDL_blit_N.c in Sources */, - F3DDCC582AFD42B600B0842B /* SDL_video_capture.c in Sources */, A7D8BB7B23E2514500DCD162 /* SDL_dropevents.c in Sources */, A7D8BACD23E2514500DCD162 /* e_atan2.c in Sources */, A7D8BA8B23E2514400DCD162 /* s_sin.c in Sources */, @@ -2578,12 +2745,13 @@ F32DDAD12AB795A30041EAA5 /* SDL_audioqueue.c in Sources */, A7D8B8E423E2514400DCD162 /* SDL_error.c in Sources */, A7D8AD6823E2514100DCD162 /* SDL_blit.c in Sources */, - A7D8B5BD23E2514300DCD162 /* SDL_rwops.c in Sources */, + A7D8B5BD23E2514300DCD162 /* SDL_iostream.c in Sources */, A7D8BA9123E2514400DCD162 /* s_cos.c in Sources */, A7D8B9D123E2514400DCD162 /* SDL_yuv_sw.c in Sources */, A7D8B76A23E2514300DCD162 /* SDL_wave.c in Sources */, 5616CA4C252BB2A6005D5928 /* SDL_url.c in Sources */, A7D8BAD323E2514500DCD162 /* s_tan.c in Sources */, + F316ABDB2B5CA721002EF551 /* SDL_memmove.c in Sources */, A7D8AA6523E2514000DCD162 /* SDL_hints.c in Sources */, A7D8B53F23E2514300DCD162 /* SDL_hidapi_ps4.c in Sources */, F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */, @@ -2597,6 +2765,7 @@ F395C1B12569C6A000942BFF /* SDL_mfijoystick.m in Sources */, A7D8B99223E2514400DCD162 /* SDL_shaders_metal.metal in Sources */, F3990DF52A787C10000D8759 /* SDL_sysurl.m in Sources */, + F316ABD92B5C3185002EF551 /* SDL_memcpy.c in Sources */, A7D8B97A23E2514400DCD162 /* SDL_render.c in Sources */, A7D8ABD323E2514100DCD162 /* SDL_stretch.c in Sources */, A7D8BAFD23E2514500DCD162 /* s_floor.c in Sources */, @@ -2639,6 +2808,7 @@ A7D8ACE723E2514100DCD162 /* SDL_rect.c in Sources */, A7D8AE9A23E2514100DCD162 /* SDL_cocoaopengles.m in Sources */, A7D8B96823E2514400DCD162 /* SDL_qsort.c in Sources */, + F3FA5A222B59ACE000FEAD97 /* yuv_rgb_sse.c in Sources */, A7D8B55123E2514300DCD162 /* SDL_hidapi_switch.c in Sources */, A7D8B96223E2514400DCD162 /* SDL_strtokr.c in Sources */, A7D8BB7523E2514500DCD162 /* SDL_clipboardevents.c in Sources */, @@ -2655,12 +2825,13 @@ A7D8AADA23E2514100DCD162 /* SDL_syshaptic.c in Sources */, A7D8BAE523E2514500DCD162 /* e_exp.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 */, F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */, A7D8BBD523E2574800DCD162 /* SDL_uikitclipboard.m in Sources */, - A7D8B5C923E2514300DCD162 /* SDL_rwopsbundlesupport.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 */, @@ -2675,7 +2846,9 @@ A7D8A99323E2514000DCD162 /* SDL_sensor.c in Sources */, A7D8BAA923E2514400DCD162 /* k_sin.c in Sources */, A7D8AB4923E2514100DCD162 /* SDL_systimer.c in Sources */, + F37E185A2BA50F450098C111 /* SDL_dummydialog.c in Sources */, A7D8BA2523E2514400DCD162 /* SDL_drawpoint.c in Sources */, + F3681E802B7AA6240002C6FD /* SDL_cocoashape.m in Sources */, F388C95528B5F6F700661ECF /* SDL_hidapi_ps3.c in Sources */, A7D8BAF723E2514500DCD162 /* e_sqrt.c in Sources */, F36C7AD1294BA009004D61C3 /* SDL_runapp.c in Sources */, @@ -2688,6 +2861,13 @@ 000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */, 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */, 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */, + 000098E9DAA43EF6FF7F0000 /* SDL_camera.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 */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2709,8 +2889,8 @@ CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; DEPLOYMENT_POSTPROCESSING = YES; - DYLIB_COMPATIBILITY_VERSION = 1.0.0; - DYLIB_CURRENT_VERSION = 1.0.0; + DYLIB_COMPATIBILITY_VERSION = 101.0.0; + DYLIB_CURRENT_VERSION = 101.0.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_ALTIVEC_EXTENSIONS = YES; @@ -2740,13 +2920,14 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3; PRODUCT_NAME = SDL3; STRIP_STYLE = "non-global"; - SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos"; + SUPPORTED_PLATFORMS = "xrsimulator xros macosx iphonesimulator iphoneos appletvsimulator appletvos"; SUPPORTS_MACCATALYST = YES; TVOS_DEPLOYMENT_TARGET = 9.0; + XROS_DEPLOYMENT_TARGET = 1.0; }; name = Release; }; @@ -2765,8 +2946,8 @@ ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; - DYLIB_COMPATIBILITY_VERSION = 1.0.0; - DYLIB_CURRENT_VERSION = 1.0.0; + DYLIB_COMPATIBILITY_VERSION = 101.0.0; + DYLIB_CURRENT_VERSION = 101.0.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -2796,14 +2977,15 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.1.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3; PRODUCT_NAME = SDL3; STRIP_INSTALLED_PRODUCT = NO; - SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos"; + SUPPORTED_PLATFORMS = "xrsimulator xros macosx iphonesimulator iphoneos appletvsimulator appletvos"; SUPPORTS_MACCATALYST = YES; TVOS_DEPLOYMENT_TARGET = 9.0; + XROS_DEPLOYMENT_TARGET = 1.0; }; name = Debug; }; diff --git a/Xcode/SDL/pkg-support/SDL.info b/Xcode/SDL/pkg-support/SDL.info index 66ba1703..326d112d 100644 --- a/Xcode/SDL/pkg-support/SDL.info +++ b/Xcode/SDL/pkg-support/SDL.info @@ -1,4 +1,4 @@ -Title SDL 3.0.0 +Title SDL 3.1.0 Version 1 Description SDL Library for macOS (http://www.libsdl.org) DefaultLocation /Library/Frameworks diff --git a/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake b/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake index 6dbcf129..21d6f7d7 100644 --- a/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake +++ b/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake @@ -1,14 +1,31 @@ # 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 Resources/CMake of a SDL3 framework +# This file 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 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") return() endif() -file(READ "${CMAKE_CURRENT_LIST_DIR}/../../Headers/SDL_version.h" _sdl_version_h) +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}") @@ -22,6 +39,13 @@ else() return() endif() +unset(_sdl_major_re) +unset(_sdl_major) +unset(_sdl_minor_re) +unset(_sdl_minor) +unset(_sdl_patch_re) +unset(_sdl_patch) + 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) @@ -42,7 +66,11 @@ else() endif() endif() -# if the using project doesn't have CMAKE_SIZEOF_VOID_P set, fail. -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") +# 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/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake b/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake index 5a4e7b43..1e5151bd 100644 --- a/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake +++ b/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 Resources/CMake of a SDL3 framework +# 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) @@ -31,15 +31,50 @@ endmacro() set(SDL3_FOUND TRUE) -# Compute the installation prefix relative to this file. -get_filename_component(_sdl3_framework_path "${CMAKE_CURRENT_LIST_FILE}" PATH) # /SDL3.framework/Resources/CMake/ -get_filename_component(_sdl3_framework_path "${_IMPORT_PREFIX}" PATH) # /SDL3.framework/Resources/ -get_filename_component(_sdl3_framework_path "${_IMPORT_PREFIX}" PATH) # /SDL3.framework/ -get_filename_component(_sdl3_framework_parent_path "${_sdl3_framework_path}" PATH) # / +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_LIBRARIES "SDL3::SDL3") # 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. @@ -53,16 +88,26 @@ if(NOT TARGET SDL3::Headers) ) endif() set(SDL3_Headers_FOUND TRUE) -unset(_sdl3_include_dirs) 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" - INTERFACE_LINK_LIBRARIES "SDL3::Headers" - IMPORTED_LOCATION "${_sdl3_framework_path}/SDL3" - IMPORTED_SONAME "${_sdl3_framework_path}/SDL3" COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" INTERFACE_SDL3_SHARED "ON" COMPATIBLE_INTERFACE_STRING "SDL_VERSION" @@ -75,10 +120,13 @@ 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 OR SDL3_SDL3-static_FOUND) +if(SDL3_SDL3-shared_FOUND) set(SDL3_SDL3_FOUND TRUE) endif() @@ -96,9 +144,13 @@ endfunction() if(NOT TARGET SDL3::SDL3) if(TARGET SDL3::SDL3-shared) _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-shared) - else() - _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-static) 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/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj b/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj index f188f537..2069c222 100644 --- a/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj +++ b/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj @@ -137,7 +137,7 @@ F35E56CF2983130F00A43A5F /* testautomation_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B62983130A00A43A5F /* testautomation_main.c */; }; F35E56D02983130F00A43A5F /* testautomation_hints.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B72983130A00A43A5F /* testautomation_hints.c */; }; F35E56D12983130F00A43A5F /* testautomation_render.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B82983130A00A43A5F /* testautomation_render.c */; }; - F35E56D22983130F00A43A5F /* testautomation_rwops.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B92983130B00A43A5F /* testautomation_rwops.c */; }; + F35E56D22983130F00A43A5F /* testautomation_iostream.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B92983130B00A43A5F /* testautomation_iostream.c */; }; F35E56D32983130F00A43A5F /* testautomation_math.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56BA2983130B00A43A5F /* testautomation_math.c */; }; F35E56D42983130F00A43A5F /* testautomation_events.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56BB2983130B00A43A5F /* testautomation_events.c */; }; F35E56D52983130F00A43A5F /* testautomation_clipboard.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56BC2983130B00A43A5F /* testautomation_clipboard.c */; }; @@ -1312,7 +1312,7 @@ F35E56B62983130A00A43A5F /* testautomation_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_main.c; sourceTree = ""; }; F35E56B72983130A00A43A5F /* testautomation_hints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_hints.c; sourceTree = ""; }; F35E56B82983130A00A43A5F /* testautomation_render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_render.c; sourceTree = ""; }; - F35E56B92983130B00A43A5F /* testautomation_rwops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_rwops.c; sourceTree = ""; }; + F35E56B92983130B00A43A5F /* testautomation_iostream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_iostream.c; sourceTree = ""; }; F35E56BA2983130B00A43A5F /* testautomation_math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_math.c; sourceTree = ""; }; F35E56BB2983130B00A43A5F /* testautomation_events.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_events.c; sourceTree = ""; }; F35E56BC2983130B00A43A5F /* testautomation_clipboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_clipboard.c; sourceTree = ""; }; @@ -1774,7 +1774,7 @@ F35E56C32983130D00A43A5F /* testautomation_platform.c */, F35E56C52983130D00A43A5F /* testautomation_rect.c */, F35E56B82983130A00A43A5F /* testautomation_render.c */, - F35E56B92983130B00A43A5F /* testautomation_rwops.c */, + F35E56B92983130B00A43A5F /* testautomation_iostream.c */, F35E56C82983130E00A43A5F /* testautomation_sdltest.c */, F35E56BE2983130C00A43A5F /* testautomation_stdlib.c */, F35E56CB2983130F00A43A5F /* testautomation_surface.c */, @@ -3355,7 +3355,7 @@ files = ( F35E56D12983130F00A43A5F /* testautomation_render.c in Sources */, F399C6512A7892D800C86979 /* testautomation_intrinsics.c in Sources */, - F35E56D22983130F00A43A5F /* testautomation_rwops.c in Sources */, + F35E56D22983130F00A43A5F /* testautomation_iostream.c in Sources */, F35E56E32983130F00A43A5F /* testautomation_surface.c in Sources */, F35E56DB2983130F00A43A5F /* testautomation_platform.c in Sources */, F35E56DD2983130F00A43A5F /* testautomation_rect.c in Sources */, diff --git a/android-project/app/build.gradle b/android-project/app/build.gradle index a158bbff..8dac6e00 100644 --- a/android-project/app/build.gradle +++ b/android-project/app/build.gradle @@ -52,7 +52,7 @@ android { // path 'jni/CMakeLists.txt' // } } - + } lint { abortOnError false diff --git a/android-project/app/proguard-rules.pro b/android-project/app/proguard-rules.pro index eaf0e916..0cb79dc8 100644 --- a/android-project/app/proguard-rules.pro +++ b/android-project/app/proguard-rules.pro @@ -15,3 +15,71 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} + +-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); + 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(); + 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); + boolean setCustomCursor(int); + 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); +} + +-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager { + boolean initialize(boolean, boolean); + boolean openDevice(int); + int writeReport(int, byte[], boolean); + boolean readReport(int, byte[], boolean); + void closeDevice(int); +} + +-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 hapticStop(int); +} diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml index e0d03341..9b0a816d 100644 --- a/android-project/app/src/main/AndroidManifest.xml +++ b/android-project/app/src/main/AndroidManifest.xml @@ -37,6 +37,13 @@ android:name="android.hardware.microphone" android:required="false" /> --> + + + + @@ -53,7 +60,7 @@ - + = Build.VERSION_CODES.TIRAMISU) { + mContext.registerReceiver(mUsbBroadcast, filter, Context.RECEIVER_EXPORTED); + } else { + mContext.registerReceiver(mUsbBroadcast, filter); + } for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { handleUsbDeviceAttached(usbDevice); @@ -403,7 +407,11 @@ public class HIDDeviceManager { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); - mContext.registerReceiver(mBluetoothBroadcast, filter); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + mContext.registerReceiver(mBluetoothBroadcast, filter, Context.RECEIVER_EXPORTED); + } else { + mContext.registerReceiver(mBluetoothBroadcast, filter); + } if (mIsChromebook) { mHandler = new Handler(Looper.getMainLooper()); diff --git a/android-project/app/src/main/java/org/libsdl/app/SDL.java b/android-project/app/src/main/java/org/libsdl/app/SDL.java index 44c21c1c..3e3ec94e 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDL.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDL.java @@ -44,13 +44,13 @@ public class SDL { } try { - // Let's see if we have ReLinker available in the project. This is necessary for - // some projects that have huge numbers of local libraries bundled, and thus may + // Let's see if we have ReLinker available in the project. This is necessary for + // some projects that have huge numbers of local libraries bundled, and thus may // trip a bug in Android's native library loader which ReLinker works around. (If // loadLibrary works properly, ReLinker will simply use the normal Android method // internally.) // - // To use ReLinker, just add it as a dependency. For more information, see + // To use ReLinker, just add it as a dependency. For more information, see // https://github.com/KeepSafe/ReLinker for ReLinker's repository. // Class relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker"); @@ -58,7 +58,7 @@ public class SDL { Class contextClass = mContext.getClassLoader().loadClass("android.content.Context"); Class stringClass = mContext.getClassLoader().loadClass("java.lang.String"); - // Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if + // Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if // they've changed during updates. Method forceMethod = relinkClass.getDeclaredMethod("force"); Object relinkInstance = forceMethod.invoke(null); diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 0d2aeebf..a560662a 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -54,7 +54,7 @@ import java.util.Locale; public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener { private static final String TAG = "SDL"; private static final int SDL_MAJOR_VERSION = 3; - private static final int SDL_MINOR_VERSION = 0; + private static final int SDL_MINOR_VERSION = 1; private static final int SDL_MICRO_VERSION = 0; /* // Display InputType.SOURCE/CLASS of events and devices @@ -1465,17 +1465,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh if (device != null && ((device.getSources() & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN || device.isVirtual())) { - int touchDevId = device.getId(); - /* - * Prevent id to be -1, since it's used in SDL internal for synthetic events - * Appears when using Android emulator, eg: - * adb shell input mouse tap 100 100 - * adb shell input touchscreen tap 100 100 - */ - if (touchDevId < 0) { - touchDevId -= 1; - } - nativeAddTouch(touchDevId, device.getName()); + nativeAddTouch(device.getId(), device.getName()); } } } diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java index 8e5345b8..f0e5540d 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java @@ -23,7 +23,7 @@ public class SDLControllerManager public static native int nativeAddJoystick(int device_id, String name, String desc, int vendor_id, int product_id, - boolean is_accelerometer, int button_mask, + int button_mask, int naxes, int axis_mask, int nhats); public static native int nativeRemoveJoystick(int device_id); public static native int nativeAddHaptic(int device_id, String name); @@ -235,7 +235,7 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler { mJoysticks.add(joystick); SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc, - getVendorId(joystickDevice), getProductId(joystickDevice), false, + getVendorId(joystickDevice), getProductId(joystickDevice), getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2); } } @@ -546,13 +546,15 @@ class SDLHapticHandler { if (haptic == null) { InputDevice device = InputDevice.getDevice(deviceIds[i]); Vibrator vib = device.getVibrator(); - if (vib.hasVibrator()) { - haptic = new SDLHaptic(); - haptic.device_id = deviceIds[i]; - haptic.name = device.getName(); - haptic.vib = vib; - mHaptics.add(haptic); - SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name); + if (vib != null) { + if (vib.hasVibrator()) { + haptic = new SDLHaptic(); + haptic.device_id = deviceIds[i]; + haptic.name = device.getName(); + haptic.vib = vib; + mHaptics.add(haptic); + SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name); + } } } } diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java index 6cd26865..74ecaf5b 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java @@ -222,16 +222,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, int i = -1; float x,y,p; - /* - * Prevent id to be -1, since it's used in SDL internal for synthetic events - * Appears when using Android emulator, eg: - * adb shell input mouse tap 100 100 - * adb shell input touchscreen tap 100 100 - */ - if (touchDevId < 0) { - touchDevId -= 1; - } - // 12290 = Samsung DeX mode desktop mouse // 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN // 0x2 = SOURCE_CLASS_POINTER diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci index 6cb692f3..ca06ac65 100644 --- a/build-scripts/SDL_migration.cocci +++ b/build-scripts/SDL_migration.cocci @@ -1051,7 +1051,7 @@ typedef SDL_GameController, SDL_Gamepad; @@ @@ - SDL_GameControllerAddMappingsFromRW -+ SDL_AddGamepadMappingsFromRW ++ SDL_AddGamepadMappingsFromIO (...) @@ typedef SDL_GameControllerAxis, SDL_GamepadAxis; @@ -1205,21 +1205,6 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; (...) @@ @@ -- SDL_GameControllerHasLED -+ SDL_GamepadHasLED - (...) -@@ -@@ -- SDL_GameControllerHasRumble -+ SDL_GamepadHasRumble - (...) -@@ -@@ -- SDL_GameControllerHasRumbleTriggers -+ SDL_GamepadHasRumbleTriggers - (...) -@@ -@@ - SDL_GameControllerHasSensor + SDL_GamepadHasSensor (...) @@ -1819,25 +1804,15 @@ expression e2; @@ @@ - RW_SEEK_CUR -+ SDL_RW_SEEK_CUR ++ SDL_IO_SEEK_CUR @@ @@ - RW_SEEK_END -+ SDL_RW_SEEK_END ++ SDL_IO_SEEK_END @@ @@ - RW_SEEK_SET -+ SDL_RW_SEEK_SET -@@ -@@ -- SDL_AllocRW -+ SDL_CreateRW - (...) -@@ -@@ -- SDL_FreeRW -+ SDL_DestroyRW - (...) ++ SDL_IO_SEEK_SET @@ @@ - SDL_SensorClose @@ -2168,6 +2143,10 @@ expression e; + SDL_EVENT_JOYSTICK_AXIS_MOTION @@ @@ +- SDL_JOYBALLMOTION ++ SDL_EVENT_JOYSTICK_BALL_MOTION +@@ +@@ - SDL_JOYHATMOTION + SDL_EVENT_JOYSTICK_HAT_MOTION @@ @@ -2428,21 +2407,41 @@ SDL_Event e1; - e1.caxis + e1.gaxis @@ +SDL_Event *e1; +@@ +- e1->caxis ++ e1->gaxis +@@ SDL_Event e1; @@ - e1.cbutton + e1.gbutton @@ +SDL_Event *e1; +@@ +- e1->cbutton ++ e1->gbutton +@@ SDL_Event e1; @@ - e1.cdevice + e1.gdevice @@ +SDL_Event *e1; +@@ +- e1->cdevice ++ e1->gdevice +@@ SDL_Event e1; @@ - e1.ctouchpad + e1.gtouchpad @@ +SDL_Event *e1; +@@ +- e1->ctouchpad ++ e1->gtouchpad +@@ SDL_Event e1; @@ - e1.csensor @@ -2450,29 +2449,49 @@ SDL_Event e1; @@ SDL_Event *e1; @@ -- e1->caxis -+ e1->gaxis -@@ -SDL_Event *e1; -@@ -- e1->cbutton -+ e1->gbutton -@@ -SDL_Event *e1; -@@ -- e1->cdevice -+ e1->gdevice -@@ -SDL_Event *e1; -@@ -- e1->ctouchpad -+ e1->gtouchpad -@@ -SDL_Event *e1; -@@ - e1->csensor + e1->gsensor @@ +SDL_Event e1; +@@ +- e1.wheel.mouseX ++ e1.wheel.mouse_x +@@ +SDL_Event *e1; +@@ +- e1->wheel.mouseX ++ e1->wheel.mouse_x +@@ +SDL_Event e1; +@@ +- e1.wheel.mouseY ++ e1.wheel.mouse_y +@@ +SDL_Event *e1; +@@ +- e1->wheel.mouseY ++ e1->wheel.mouse_y +@@ +SDL_Event e1; +@@ +- e1.tfinger.touchId ++ e1.tfinger.touchID +@@ +SDL_Event *e1; +@@ +- e1->tfinger.touchId ++ e1->tfinger.touchID +@@ +SDL_Event e1; +@@ +- e1.tfinger.fingerId ++ e1.tfinger.fingerID +@@ +SDL_Event *e1; +@@ +- e1->tfinger.fingerId ++ e1->tfinger.fingerID +@@ expression e1, e2, e3, e4; @@ - SDL_CreateWindow(e1, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, e2, e3, e4) @@ -2764,3 +2783,339 @@ expression e1, e2, e3, e4; @@ - SDL_SoftStretchLinear(e1, e2, e3, e4) + SDL_SoftStretch(e1, e2, e3, e4, SDL_SCALEMODE_LINEAR) +@@ +@@ +- SDL_HapticClose ++ SDL_CloseHaptic + (...) +@@ +@@ +- SDL_HapticOpen ++ SDL_OpenHaptic + (...) +@@ +@@ +- SDL_HapticOpenFromMouse ++ SDL_OpenHapticFromMouse + (...) +@@ +@@ +- SDL_HapticOpenFromJoystick ++ SDL_OpenHapticFromJoystick + (...) +@@ +@@ +- SDL_MouseIsHaptic ++ SDL_IsMouseHaptic + (...) +@@ +@@ +- SDL_JoystickIsHaptic ++ SDL_IsJoystickHaptic + (...) +@@ +@@ +- SDL_HapticNumEffects ++ SDL_GetMaxHapticEffects + (...) +@@ +@@ +- SDL_HapticNumEffectsPlaying ++ SDL_GetMaxHapticEffectsPlaying + (...) +@@ +@@ +- SDL_HapticQuery ++ SDL_GetHapticFeatures + (...) +@@ +@@ +- SDL_HapticNumAxes ++ SDL_GetNumHapticAxes + (...) +@@ +@@ +- SDL_HapticNewEffect ++ SDL_CreateHapticEffect + (...) +@@ +@@ +- SDL_HapticUpdateEffect ++ SDL_UpdateHapticEffect + (...) +@@ +@@ +- SDL_HapticRunEffect ++ SDL_RunHapticEffect + (...) +@@ +@@ +- SDL_HapticStopEffect ++ SDL_StopHapticEffect + (...) +@@ +@@ +- SDL_HapticDestroyEffect ++ SDL_DestroyHapticEffect + (...) +@@ +@@ +- SDL_HapticGetEffectStatus ++ SDL_GetHapticEffectStatus + (...) +@@ +@@ +- SDL_HapticSetGain ++ SDL_SetHapticGain + (...) +@@ +@@ +- SDL_HapticSetAutocenter ++ SDL_SetHapticAutocenter + (...) +@@ +@@ +- SDL_HapticPause ++ SDL_PauseHaptic + (...) +@@ +@@ +- SDL_HapticUnpause ++ SDL_ResumeHaptic + (...) +@@ +@@ +- SDL_HapticStopAll ++ SDL_StopHapticEffects + (...) +@@ +@@ +- SDL_HapticRumbleInit ++ SDL_InitHapticRumble + (...) +@@ +@@ +- SDL_HapticRumblePlay ++ SDL_PlayHapticRumble + (...) +@@ +@@ +- SDL_HapticRumbleStop ++ SDL_StopHapticRumble + (...) +@@ +@@ +- SDL_AtomicTryLock ++ SDL_TryLockSpinlock + (...) +@@ +@@ +- SDL_AtomicLock ++ SDL_LockSpinlock + (...) +@@ +@@ +- SDL_AtomicUnlock ++ SDL_UnlockSpinlock + (...) +@@ +@@ +- SDL_AtomicCAS ++ SDL_AtomicCompareAndSwap + (...) +@@ +@@ +- SDL_AtomicCASPtr ++ SDL_AtomicCompareAndSwapPointer + (...) +@@ +@@ +- SDL_ThreadID ++ SDL_GetCurrentThreadID + (...) +@@ +@@ +- SDL_threadID ++ SDL_ThreadID + (...) +@@ +@@ +- SDL_HasWindowSurface ++ SDL_WindowHasSurface + (...) +@@ +SDL_PixelFormat e1; +@@ +- e1.BitsPerPixel ++ e1.bits_per_pixel +@@ +SDL_PixelFormat *e1; +@@ +- e1->BitsPerPixel ++ e1->bits_per_pixel +@@ +SDL_PixelFormat e1; +@@ +- e1.BytesPerPixel ++ e1.bytes_per_pixel +@@ +SDL_PixelFormat *e1; +@@ +- e1->BytesPerPixel ++ e1->bytes_per_pixel +@@ +SDL_MessageBoxButtonData e1; +@@ +- e1.buttonid ++ e1.buttonID +@@ +SDL_MessageBoxButtonData *e1; +@@ +- e1->buttonid ++ e1->buttonID +@@ +SDL_GamepadBinding e1; +@@ +- e1.inputType ++ e1.input_type +@@ +SDL_GamepadBinding *e1; +@@ +- e1->inputType ++ e1->input_type +@@ +SDL_GamepadBinding e1; +@@ +- e1.outputType ++ e1.output_type +@@ +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 +@@ +@@ +- SDL_HINT_DIRECTINPUT_ENABLED ++ SDL_HINT_JOYSTICK_DIRECTINPUT +@@ +@@ +- SDL_HINT_GDK_TEXTINPUT_DEFAULT ++ SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT +@@ +@@ +- SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE ++ SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE +@@ +@@ +- SDL_HINT_LINUX_DIGITAL_HATS ++ SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS +@@ +@@ +- SDL_HINT_LINUX_HAT_DEADZONES ++ SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES +@@ +@@ +- SDL_HINT_LINUX_JOYSTICK_CLASSIC ++ SDL_HINT_JOYSTICK_LINUX_CLASSIC +@@ +@@ +- SDL_HINT_LINUX_JOYSTICK_DEADZONES ++ SDL_HINT_JOYSTICK_LINUX_DEADZONES +@@ +@@ +- SDL_HINT_PS2_DYNAMIC_VSYNC ++ SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC +@@ +@@ +- SDL_JoystickNumBalls ++ SDL_GetNumJoystickBalls + (...) +@@ +@@ +- SDL_JoystickGetBall ++ SDL_GetJoystickBall + (...) +@@ +@@ +- SDL_RWclose ++ SDL_CloseIO + (...) +@@ +@@ +- SDL_RWread ++ SDL_ReadIO + (...) +@@ +@@ +- SDL_RWwrite ++ SDL_WriteIO + (...) +@@ +@@ +- SDL_RWtell ++ SDL_TellIO + (...) +@@ +@@ +- SDL_RWsize ++ SDL_SizeIO + (...) +@@ +@@ +- SDL_RWseek ++ SDL_SeekIO + (...) +@@ +@@ +- SDL_LoadBMP_RW ++ SDL_LoadBMP_IO + (...) +@@ +@@ +- SDL_LoadWAV_RW ++ SDL_LoadWAV_IO + (...) +@@ +@@ +- SDL_SaveBMP_RW ++ SDL_SaveBMP_IO + (...) +@@ +@@ +- SDL_RWFromFile ++ SDL_IOFromFile + (...) +@@ +@@ +- SDL_RWFromMem ++ SDL_IOFromMem + (...) +@@ +@@ +- SDL_RWFromConstMem ++ SDL_IOFromConstMem + (...) +@@ +typedef SDL_RWops, SDL_IOStream; +@@ +- SDL_RWops ++ SDL_IOStream +@@ +@@ +- SDL_LogGetOutputFunction ++ SDL_GetLogOutputFunction + (...) +@@ +@@ +- SDL_LogSetOutputFunction ++ SDL_SetLogOutputFunction + (...) diff --git a/build-scripts/androidbuild.sh b/build-scripts/androidbuild.sh index 81457818..1a107e27 100755 --- a/build-scripts/androidbuild.sh +++ b/build-scripts/androidbuild.sh @@ -80,7 +80,8 @@ do cd $folder done -ACTIVITY="${folder}Activity" +# 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 diff --git a/build-scripts/build-release.py b/build-scripts/build-release.py new file mode 100755 index 00000000..b85b0635 --- /dev/null +++ b/build-scripts/build-release.py @@ -0,0 +1,641 @@ +#!/usr/bin/env python + +import argparse +import collections +import contextlib +import datetime +import io +import json +import logging +import os +from pathlib import Path +import platform +import re +import shutil +import subprocess +import sys +import tarfile +import tempfile +import textwrap +import typing +import zipfile + +logger = logging.getLogger(__name__) + + +VcArchDevel = collections.namedtuple("VcArchDevel", ("dll", "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) + + +class Executer: + def __init__(self, root: Path, dry: bool=False): + self.root = root + self.dry = dry + + def run(self, cmd, stdout=False, dry_out=None, force=False): + sys.stdout.flush() + logger.info("Executing args=%r", cmd) + if self.dry and not force: + if stdout: + return subprocess.run(["echo", "-E", dry_out or ""], stdout=subprocess.PIPE if stdout else None, text=True, check=True, cwd=self.root) + else: + return subprocess.run(cmd, stdout=subprocess.PIPE if stdout else None, text=True, check=True, cwd=self.root) + + +class SectionPrinter: + @contextlib.contextmanager + def group(self, title: str): + print(f"{title}:") + yield + + +class GitHubSectionPrinter(SectionPrinter): + def __init__(self): + super().__init__() + self.in_group = False + + @contextlib.contextmanager + def group(self, title: str): + print(f"::group::{title}") + assert not self.in_group, "Can enter a group only once" + self.in_group = True + yield + self.in_group = False + print("::endgroup::") + + +class VisualStudio: + def __init__(self, executer: Executer, year: typing.Optional[str]=None): + self.executer = executer + self.vsdevcmd = self.find_vsdevcmd(year) + self.msbuild = self.find_msbuild() + + @property + def dry(self): + return self.executer.dry + + VS_YEAR_TO_VERSION = { + "2022": 17, + "2019": 16, + "2017": 15, + "2015": 14, + "2013": 12, + } + + 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] + except KeyError: + logger.error("Invalid Visual Studio year") + return None + vswhere_spec.extend(["-version", f"[{version},{version+1})"]) + vswhere_cmd = ["vswhere"] + vswhere_spec + ["-property", "installationPath"] + vs_install_path = Path(self.executer.run(vswhere_cmd, stdout=True, dry_out="/tmp").stdout.strip()) + logger.info("VS install_path = %s", vs_install_path) + assert vs_install_path.is_dir(), "VS installation path does not exist" + vsdevcmd_path = vs_install_path / "Common7/Tools/vsdevcmd.bat" + logger.info("vsdevcmd path = %s", vsdevcmd_path) + if self.dry: + vsdevcmd_path.parent.mkdir(parents=True, exist_ok=True) + vsdevcmd_path.touch(exist_ok=True) + assert vsdevcmd_path.is_file(), "vsdevcmd.bat batch file does not exist" + return vsdevcmd_path + + def find_msbuild(self) -> typing.Optional[Path]: + vswhere_cmd = ["vswhere", "-latest", "-requires", "Microsoft.Component.MSBuild", "-find", "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: + msbuild_path.parent.mkdir(parents=True, exist_ok=True) + msbuild_path.touch(exist_ok=True) + assert msbuild_path.is_file(), "MSBuild.exe does not exist" + return msbuild_path + + def build(self, arch: str, platform: str, configuration: str, projects: list[Path]): + assert projects, "Need at least one project to build" + + vsdev_cmd_str = f"\"{self.vsdevcmd}\" -arch={arch}" + msbuild_cmd_str = " && ".join([f"\"{self.msbuild}\" \"{project}\" /m /p:BuildInParallel=true /p:Platform={platform} /p:Configuration={configuration}" for project in projects]) + bat_contents = f"{vsdev_cmd_str} && {msbuild_cmd_str}\n" + bat_path = Path(tempfile.gettempdir()) / "cmd.bat" + with bat_path.open("w") as f: + f.write(bat_contents) + + logger.info("Running cmd.exe script (%s): %s", bat_path, bat_contents) + cmd = ["cmd.exe", "/D", "/E:ON", "/V:OFF", "/S", "/C", f"CALL {str(bat_path)}"] + self.executer.run(cmd) + + +class Releaser: + def __init__(self, project: str, commit: str, root: Path, dist_path: Path, section_printer: SectionPrinter, executer: Executer, cmake_generator: str): + self.project = project + self.version = self.extract_sdl_version(root=root, project=project) + self.root = root + self.commit = commit + self.dist_path = dist_path + self.section_printer = section_printer + self.executer = executer + self.cmake_generator = cmake_generator + + self.artifacts = {} + + @property + def dry(self): + 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]: + 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) + current_time = None + tree_paths = {item.path for item in tree_items.values()} + path_times = {} + 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) + 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 + return path_times + + @staticmethod + def _path_filter(path: str): + if path.startswith(".git"): + 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)} + return git_contents + + def create_source_archives(self): + archive_base = f"{self.project}-{self.version}" + + git_contents = self._get_git_contents() + git_files = list(git_contents.values()) + assert len(git_contents) == len(git_files) + + latest_mod_time = max(item.time for item in git_files) + + git_files.append(self.TreeItem(path="VERSION.txt", data=f"{self.version}\n".encode(), mode=0o100644, time=latest_mod_time)) + git_files.append(self.TreeItem(path=GIT_HASH_FILENAME, data=f"{self.commit}\n".encode(), mode=0o100644, time=latest_mod_time)) + + git_files.sort(key=lambda v: v.time) + + zip_path = self.dist_path / f"{archive_base}.zip" + logger.info("Creating .zip source archive (%s)...", zip_path) + if self.dry: + zip_path.touch() + else: + with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zip_object: + for git_file in git_files: + file_data_time = (git_file.time.year, git_file.time.month, git_file.time.day, git_file.time.hour, git_file.time.minute, git_file.time.second) + zip_info = zipfile.ZipInfo(filename=f"{archive_base}/{git_file.path}", date_time=file_data_time) + zip_info.external_attr = git_file.mode << 16 + zip_info.compress_type = zipfile.ZIP_DEFLATED + zip_object.writestr(zip_info, data=git_file.data) + self.artifacts["src-zip"] = zip_path + + tar_types = ( + (".tar.gz", "gz"), + (".tar.xz", "xz"), + ) + for ext, comp in tar_types: + tar_path = self.dist_path / f"{archive_base}{ext}" + logger.info("Creating %s source archive (%s)...", ext, tar_path) + if self.dry: + tar_path.touch() + else: + with tarfile.open(tar_path, f"w:{comp}") as tar_object: + for git_file in git_files: + tar_info = tarfile.TarInfo(f"{archive_base}/{git_file.path}") + tar_info.mode = git_file.mode + tar_info.size = len(git_file.data) + tar_info.mtime = git_file.time.timestamp() + tar_object.addfile(tar_info, fileobj=io.BytesIO(git_file.data)) + + if tar_path.suffix == ".gz": + # Zero the embedded timestamp in the gzip'ed tarball + with open(tar_path, "r+b") as f: + f.seek(4, 0) + f.write(b"\x00\x00\x00\x00") + + 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" + dmg_in.unlink(missing_ok=True) + self.executer.run(["xcodebuild", "-project", 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() + + assert dmg_in.is_file(), "SDL3.dmg was not created by xcodebuild" + + dmg_out = self.dist_path / f"{self.project}-{self.version}.dmg" + shutil.copy(dmg_in, dmg_out) + self.artifacts["dmg"] = dmg_out + + @property + def git_hash_data(self): + 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): + if not time: + time = datetime.datetime(year=2024, month=4, day=1) + path = GIT_HASH_FILENAME + if root: + path = f"{root}/{path}" + + tar_info = tarfile.TarInfo(path) + tar_info.mode = 0o100644 + tar_info.size = len(self.git_hash_data) + tar_info.mtime = 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): + if not time: + time = datetime.datetime(year=2024, month=4, day=1) + path = GIT_HASH_FILENAME + if root: + path = f"{root}/{path}" + + file_data_time = (time.year, time.month, time.day, time.hour, time.minute, time.second) + zip_info = zipfile.ZipInfo(filename=path, date_time=file_data_time) + zip_info.external_attr = 0o100644 << 16 + zip_info.compress_type = zipfile.ZIP_DEFLATED + zip_file.writestr(zip_info, data=self.git_hash_data) + + def create_mingw_archives(self): + build_type = "Release" + mingw_archs = ("i686", "x86_64") + build_parent_dir = self.root / "build-mingw" + + zip_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.zip" + tar_exts = ("gz", "xz") + tar_paths = { ext: self.dist_path / f"{self.project}-devel-{self.version}-mingw.tar.{ext}" for ext in tar_exts} + + arch_install_paths = {} + arch_files = {} + + for arch in mingw_archs: + build_path = build_parent_dir / f"build-{arch}" + install_path = build_parent_dir / f"install-{arch}" + arch_install_paths[arch] = install_path + shutil.rmtree(install_path, ignore_errors=True) + build_path.mkdir(parents=True, exist_ok=True) + with self.section_printer.group(f"Configuring MinGW {arch}"): + self.executer.run([ + "cmake", "-S", str(self.root), "-B", str(build_path), + "--fresh", + "-DSDL_SHARED=ON", + "-DSDL_STATIC=ON", + "-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_TOOLCHAIN_FILE={self.root}/build-scripts/cmake-toolchain-mingw64-{arch}.cmake", + f"-G{self.cmake_generator}", + f"-DCMAKE_INSTALL_PREFIX={install_path}", + ]) + with self.section_printer.group(f"Build MinGW {arch}"): + self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type]) + with self.section_printer.group(f"Install MinGW {arch}"): + 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/"), + ("BUGS.txt", ""), + ("CREDITS.md", ""), + ("README-SDL.txt", ""), + ("WhatsNew.txt", ""), + ("LICENSE.txt", ""), + ("README.md", ""), + ] + 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 + # objcopy --only-keep-debug SDL3.dll SDL3.debug.dll + # objcopy --add-gnu-debuglink=SDL3.debug.dll SDL3.dll + # objcopy --strip-debug SDL3.dll + + for comp in tar_exts: + 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: + 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 arch in mingw_archs: + install_path = arch_install_paths[arch] + arcname_parent = f"{arc_root}/{arch}-w64-mingw32" + for file in arch_files[arch]: + arcname = os.path.join(arcname_parent, file.relative_to(install_path)) + tar_object.add(file, arcname=arcname) + for test_file in test_files: + arcname = f"{arc_root}/test/{test_file.relative_to(self.root/'test')}" + tar_object.add(test_file, arcname=arcname) + self._tar_add_git_hash(tar_object=tar_object, root=arc_root) + + self.artifacts[f"mingw-devel-tar-{comp}"] = tar_paths[comp] + + def build_vs(self, arch: str, platform: str, vs: VisualStudio, configuration: str="Release"): + dll_path = self.root / f"VisualC/SDL/{platform}/{configuration}/{self.project}.dll" + 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) + imp_path.unlink(missing_ok=True) + test_path.unlink(missing_ok=True) + + projects = [ + self.root / "VisualC/SDL/SDL.vcxproj", + self.root / "VisualC/SDL_test/SDL_test.vcxproj", + ] + + 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() + 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 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, imp=imp_path, test=test_path) + + def build_vs_devel(self, arch_vc: dict[str, VcArchDevel]): + zip_path = self.dist_path / f"{self.project}-devel-{self.version}-VC.zip" + archive_prefix = f"{self.project}-{self.version}" + + def zip_file(zf: zipfile.ZipFile, path: Path, arcrelpath: str): + arcname = f"{archive_prefix}/{arcrelpath}" + logger.debug("Adding %s to %s", path, arcname) + zf.write(path, arcname=arcname) + + def zip_directory(zf: zipfile.ZipFile, directory: Path, arcrelpath: str): + for f in directory.iterdir(): + if f.is_file(): + arcname = f"{archive_prefix}/{arcrelpath}/{f.name}" + logger.debug("Adding %s to %s", f, arcname) + zf.write(f, arcname=arcname) + + with zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED) as zf: + 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.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") + + for txt in ("BUGS.txt", "README-SDL.txt", "WhatsNew.txt"): + zip_file(zf, path=self.root / txt, arcrelpath=txt) + zip_file(zf, path=self.root / "LICENSE.txt", arcrelpath="COPYING.txt") + zip_file(zf, path=self.root / "README.md", arcrelpath="README.txt") + + self._zip_add_git_hash(zip_file=zf, root=archive_prefix) + self.artifacts["VC-devel"] = zip_path + + @classmethod + def extract_sdl_version(cls, root: Path, project: 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}" + + +def main(argv=None): + 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("--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.set_defaults(loglevel=logging.INFO) + parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year") + 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") + parser.add_argument('--force', action='store_true', dest="force", help="Ignore a non-clean git tree") + + 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() + if args.dry: + args.dist_path = args.dist_path / "dry" + + if args.github: + section_printer = GitHubSectionPrinter() + else: + section_printer = SectionPrinter() + + executer = Executer(root=args.root, dry=args.dry) + + root_git_hash_path = args.root / GIT_HASH_FILENAME + root_is_maybe_archive = root_git_hash_path.is_file() + if root_is_maybe_archive: + 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) + args.commit = archive_commit + else: + args.commit = executer.run(["git", "rev-parse", args.commit], stdout=True, dry_out="e5812a9fd2cda317b503325a702ba3c1c37861d9").stdout.strip() + logger.info("Using commit %s", args.commit) + + releaser = Releaser( + project=args.project, + commit=args.commit, + root=args.root, + dist_path=args.dist_path, + executer=executer, + section_printer=section_printer, + cmake_generator=args.cmake_generator, + ) + + if root_is_maybe_archive: + logger.warn("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: + print(porcelain_status) + logger.warning("The tree is dirty! Do not publish any generated artifacts!") + if not args.force: + 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}") + + releaser.prepare() + + if "source" in args.actions: + if root_is_maybe_archive: + raise Exception("Cannot build source archive from source archive") + with section_printer.group("Create source archives"): + releaser.create_source_archives() + + if "xcframework" in args.actions: + if platform.system() != "Darwin" and not args.dry: + parser.error("xcframework artifact(s) can only be built on Darwin") + + releaser.create_xcframework() + + if "win32" in args.actions: + if platform.system() != "Windows" and not args.dry: + 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) + with section_printer.group("Create SDL VC development zip"): + arch_vc = { + "x86": x86, + "x64": x64, + } + releaser.build_vs_devel(arch_vc) + + if "mingw" in args.actions: + releaser.create_mingw_archives() + + with section_printer.group("Summary"): + print(f"artifacts = {releaser.artifacts}") + + if args.github: + if args.dry: + os.environ["GITHUB_OUTPUT"] = "/tmp/github_output.txt" + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"project={releaser.project}\n") + f.write(f"version={releaser.version}\n") + for k, v in releaser.artifacts.items(): + f.write(f"{k}={v.name}\n") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/build-scripts/check_stdlib_usage.py b/build-scripts/check_stdlib_usage.py index 5e62ff18..8dea74e1 100755 --- a/build-scripts/check_stdlib_usage.py +++ b/build-scripts/check_stdlib_usage.py @@ -42,6 +42,7 @@ words = [ 'atanf', 'atof', 'atoi', + 'bsearch', 'calloc', 'ceil', 'ceilf', @@ -90,6 +91,8 @@ words = [ 'pow', 'powf', 'qsort', + 'qsort_r', + 'qsort_s', 'realloc', 'round', 'roundf', diff --git a/build-scripts/cmake-toolchain-mingw64-i686.cmake b/build-scripts/cmake-toolchain-mingw64-i686.cmake index 22260e1f..8be7b3a8 100644 --- a/build-scripts/cmake-toolchain-mingw64-i686.cmake +++ b/build-scripts/cmake-toolchain-mingw64-i686.cmake @@ -3,6 +3,7 @@ set(CMAKE_SYSTEM_PROCESSOR x86) find_program(CMAKE_C_COMPILER NAMES i686-w64-mingw32-gcc) find_program(CMAKE_CXX_COMPILER NAMES i686-w64-mingw32-g++) +find_program(CMAKE_RC_COMPILER NAMES i686-w64-mingw32-windres windres) if(NOT CMAKE_C_COMPILER) message(FATAL_ERROR "Failed to find CMAKE_C_COMPILER.") @@ -11,3 +12,7 @@ endif() if(NOT CMAKE_CXX_COMPILER) message(FATAL_ERROR "Failed to find CMAKE_CXX_COMPILER.") endif() + +if(NOT CMAKE_RC_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_RC_COMPILER.") +endif() diff --git a/build-scripts/cmake-toolchain-mingw64-x86_64.cmake b/build-scripts/cmake-toolchain-mingw64-x86_64.cmake index c8135ba9..8bf43669 100644 --- a/build-scripts/cmake-toolchain-mingw64-x86_64.cmake +++ b/build-scripts/cmake-toolchain-mingw64-x86_64.cmake @@ -3,6 +3,7 @@ set(CMAKE_SYSTEM_PROCESSOR x86_64) find_program(CMAKE_C_COMPILER NAMES x86_64-w64-mingw32-gcc) find_program(CMAKE_CXX_COMPILER NAMES x86_64-w64-mingw32-g++) +find_program(CMAKE_RC_COMPILER NAMES x86_64-w64-mingw32-windres windres) if(NOT CMAKE_C_COMPILER) message(FATAL_ERROR "Failed to find CMAKE_C_COMPILER.") @@ -11,3 +12,7 @@ endif() if(NOT CMAKE_CXX_COMPILER) message(FATAL_ERROR "Failed to find CMAKE_CXX_COMPILER.") endif() + +if(NOT CMAKE_RC_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_RC_COMPILER.") +endif() diff --git a/build-scripts/create-release.sh b/build-scripts/create-release.sh new file mode 100755 index 00000000..927cadcf --- /dev/null +++ b/build-scripts/create-release.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +commit=$(git rev-parse HEAD) +echo "Creating release workflow for commit $commit" +gh workflow run release.yml --ref main -f commit=$commit + diff --git a/build-scripts/rename_headers.py b/build-scripts/rename_headers.py index e09d8dad..b61e4773 100755 --- a/build-scripts/rename_headers.py +++ b/build-scripts/rename_headers.py @@ -7,17 +7,22 @@ import pathlib import re -def main(): +def do_include_replacements(paths): replacements = [ + ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_image.h(?:[\">])"), r"" ), + ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_mixer.h(?:[\">])"), r"" ), + ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_net.h(?:[\">])"), r"" ), + ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_rtf.h(?:[\">])"), r"" ), + ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_ttf.h(?:[\">])"), r"" ), ( re.compile(r"(?:[\"<])(?:SDL2/)?SDL_gamecontroller.h(?:[\">])"), r"" ), ( re.compile(r"(?:[\"<])(?:SDL2/)?begin_code.h(?:[\">])"), r"" ), ( re.compile(r"(?:[\"<])(?:SDL2/)?close_code.h(?:[\">])"), r"" ), ( re.compile(r"(?:[\"<])(?:SDL2/)?(SDL[_a-z0-9]*\.h)(?:[\">])"), r"" ) ] - for entry in args.args: + for entry in paths: path = pathlib.Path(entry) if not path.exists(): - print("%s doesn't exist, skipping" % entry) + print("{} does not exist, skipping".format(entry)) continue replace_headers_in_path(path, replacements) @@ -55,17 +60,16 @@ def replace_headers_in_path(path, replacements): replace_headers_in_file(path, replacements) -if __name__ == "__main__": - - parser = argparse.ArgumentParser(fromfile_prefix_chars='@') - parser.add_argument("args", nargs="*") +def main(): + parser = argparse.ArgumentParser(fromfile_prefix_chars='@', description="Rename #include's for SDL3.") + parser.add_argument("args", metavar="PATH", nargs="*", help="Input source file") args = parser.parse_args() try: - main() + do_include_replacements(args.args) except Exception as e: print(e) - exit(-1) - - exit(0) + return 1 +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/build-scripts/rename_macros.py b/build-scripts/rename_macros.py new file mode 100755 index 00000000..913b10e5 --- /dev/null +++ b/build-scripts/rename_macros.py @@ -0,0 +1,383 @@ +#!/usr/bin/env python3 +# +# This script renames SDL macros in the specified paths + +import argparse +import pathlib +import re + + +class TextReplacer: + def __init__(self, macros, repl_format): + if isinstance(macros, dict): + macros_keys = macros.keys() + else: + macros_keys = macros + self.macros = macros + self.re_macros = re.compile(r"\W(" + "|".join(macros_keys) + r")(?:\W|$)") + self.repl_format = repl_format + + def apply(self, contents): + def cb(m): + macro = m.group(1) + original = m.group(0) + match_start, _ = m.span(0) + platform_start, platform_end = m.span(1) + if isinstance(self.macros, dict): + repl_args = (macro, self.macros[macro]) + else: + repl_args = macro, + new_text = self.repl_format.format(*repl_args) + r = original[:(platform_start-match_start)] + new_text + original[platform_end-match_start:] + return r + contents, _ = self.re_macros.subn(cb, contents) + + return contents + + +class MacrosCheck: + def __init__(self): + self.renamed_platform_macros = TextReplacer(RENAMED_MACROS, "{1}") + self.deprecated_platform_macros = TextReplacer(DEPRECATED_PLATFORM_MACROS, "{0} /* {0} has been removed in SDL3 */") + + def run(self, contents): + contents = self.renamed_platform_macros.apply(contents) + contents = self.deprecated_platform_macros.apply(contents) + return contents + + +def apply_checks(paths): + checks = ( + MacrosCheck(), + ) + + for entry in paths: + path = pathlib.Path(entry) + if not path.exists(): + print("{} does not exist, skipping".format(entry)) + continue + apply_checks_in_path(path, checks) + + +def apply_checks_in_file(file, checks): + try: + with file.open("r", encoding="UTF-8", newline="") as rfp: + original = rfp.read() + contents = original + for check in checks: + contents = check.run(contents) + 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 apply_checks_in_dir(path, checks): + for entry in path.glob("*"): + if entry.is_dir(): + apply_checks_in_dir(entry, checks) + else: + print("Processing %s" % entry) + apply_checks_in_file(entry, checks) + + +def apply_checks_in_path(path, checks): + if path.is_dir(): + apply_checks_in_dir(path, checks) + else: + apply_checks_in_file(path, checks) + + +def main(): + parser = argparse.ArgumentParser(fromfile_prefix_chars='@', description="Rename macros for SDL3") + parser.add_argument("args", nargs="*", help="Input source files") + args = parser.parse_args() + + try: + apply_checks(args.args) + except Exception as e: + print(e) + return 1 + + +RENAMED_MACROS = { + "__AIX__": "SDL_PLATFORM_AIX", + "__HAIKU__": "SDL_PLATFORM_HAIKU", + "__BSDI__": "SDL_PLATFORM_BSDI", + "__FREEBSD__": "SDL_PLATFORM_FREEBSD", + "__HPUX__": "SDL_PLATFORM_HPUX", + "__IRIX__": "SDL_PLATFORM_IRIX", + "__LINUX__": "SDL_PLATFORM_LINUX", + "__OS2__": "SDL_PLATFORM_OS2", + # "__ANDROID__": "SDL_PLATFORM_ANDROID, + "__NGAGE__": "SDL_PLATFORM_NGAGE", + "__APPLE__": "SDL_PLATFORM_APPLE", + "__TVOS__": "SDL_PLATFORM_TVOS", + "__IPHONEOS__": "SDL_PLATFORM_IOS", + "__MACOSX__": "SDL_PLATFORM_MACOS", + "__NETBSD__": "SDL_PLATFORM_NETBSD", + "__OPENBSD__": "SDL_PLATFORM_OPENBSD", + "__OSF__": "SDL_PLATFORM_OSF", + "__QNXNTO__": "SDL_PLATFORM_QNXNTO", + "__RISCOS__": "SDL_PLATFORM_RISCOS", + "__SOLARIS__": "SDL_PLATFORM_SOLARIS", + "__PSP__": "SDL_PLATFORM_PSP", + "__PS2__": "SDL_PLATFORM_PS2", + "__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", + "__WIN32__": "SDL_PLATFORM_WIN32", + # "__CYGWIN_": "SDL_PLATFORM_CYGWIN", + "__WINGDK__": "SDL_PLATFORM_WINGDK", + "__GDK__": "SDL_PLATFORM_GDK", + # "__EMSCRIPTEN__": "SDL_PLATFORM_EMSCRIPTEN", +} + +DEPRECATED_PLATFORM_MACROS = { + "__DREAMCAST__", + "__NACL__", + "__PNACL__", + "__WINDOWS__", + "SDL_ALTIVEC_BLITTERS", + "SDL_ARM_NEON_BLITTERS", + "SDL_ARM_SIMD_BLITTERS", + "SDL_ATOMIC_DISABLED", + "SDL_AUDIO_DISABLED", + "SDL_AUDIO_DRIVER_AAUDIO", + "SDL_AUDIO_DRIVER_ALSA", + "SDL_AUDIO_DRIVER_ALSA_DYNAMIC", + "SDL_AUDIO_DRIVER_ANDROID", + "SDL_AUDIO_DRIVER_ARTS", + "SDL_AUDIO_DRIVER_ARTS_DYNAMIC", + "SDL_AUDIO_DRIVER_COREAUDIO", + "SDL_AUDIO_DRIVER_DISK", + "SDL_AUDIO_DRIVER_DSOUND", + "SDL_AUDIO_DRIVER_DUMMY", + "SDL_AUDIO_DRIVER_EMSCRIPTEN", + "SDL_AUDIO_DRIVER_ESD", + "SDL_AUDIO_DRIVER_ESD_DYNAMIC", + "SDL_AUDIO_DRIVER_FUSIONSOUND", + "SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC", + "SDL_AUDIO_DRIVER_HAIKU", + "SDL_AUDIO_DRIVER_JACK", + "SDL_AUDIO_DRIVER_JACK_DYNAMIC", + "SDL_AUDIO_DRIVER_N3DS", + "SDL_AUDIO_DRIVER_NAS", + "SDL_AUDIO_DRIVER_NAS_DYNAMIC", + "SDL_AUDIO_DRIVER_NETBSD", + "SDL_AUDIO_DRIVER_OPENSLES", + "SDL_AUDIO_DRIVER_OS2", + "SDL_AUDIO_DRIVER_OSS", + "SDL_AUDIO_DRIVER_PAUDIO", + "SDL_AUDIO_DRIVER_PIPEWIRE", + "SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC", + "SDL_AUDIO_DRIVER_PS2", + "SDL_AUDIO_DRIVER_PSP", + "SDL_AUDIO_DRIVER_PULSEAUDIO", + "SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC", + "SDL_AUDIO_DRIVER_QSA", + "SDL_AUDIO_DRIVER_SNDIO", + "SDL_AUDIO_DRIVER_SNDIO_DYNAMIC", + "SDL_AUDIO_DRIVER_SUNAUDIO", + "SDL_AUDIO_DRIVER_VITA", + "SDL_AUDIO_DRIVER_WASAPI", + "SDL_AUDIO_DRIVER_WINMM", + "SDL_CPUINFO_DISABLED", + "SDL_DEFAULT_ASSERT_LEVEL", + "SDL_EVENTS_DISABLED", + "SDL_FILESYSTEM_ANDROID", + "SDL_FILESYSTEM_COCOA", + "SDL_FILESYSTEM_DISABLED", + "SDL_FILESYSTEM_DUMMY", + "SDL_FILESYSTEM_EMSCRIPTEN", + "SDL_FILESYSTEM_HAIKU", + "SDL_FILESYSTEM_N3DS", + "SDL_FILESYSTEM_OS2", + "SDL_FILESYSTEM_PS2", + "SDL_FILESYSTEM_PSP", + "SDL_FILESYSTEM_RISCOS", + "SDL_FILESYSTEM_UNIX", + "SDL_FILESYSTEM_VITA", + "SDL_FILESYSTEM_WINDOWS", + "SDL_FILE_DISABLED", + "SDL_HAPTIC_ANDROID", + "SDL_HAPTIC_DINPUT", + "SDL_HAPTIC_DISABLED", + "SDL_HAPTIC_DUMMY", + "SDL_HAPTIC_IOKIT", + "SDL_HAPTIC_LINUX", + "SDL_HAPTIC_XINPUT", + "SDL_HAVE_LIBDECOR_GET_MIN_MAX", + "SDL_HAVE_MACHINE_JOYSTICK_H", + "SDL_HIDAPI_DISABLED", + "SDL_INPUT_FBSDKBIO", + "SDL_INPUT_LINUXEV", + "SDL_INPUT_LINUXKD", + "SDL_INPUT_WSCONS", + "SDL_IPHONE_KEYBOARD", + "SDL_IPHONE_LAUNCHSCREEN", + "SDL_JOYSTICK_ANDROID", + "SDL_JOYSTICK_DINPUT", + "SDL_JOYSTICK_DISABLED", + "SDL_JOYSTICK_DUMMY", + "SDL_JOYSTICK_EMSCRIPTEN", + "SDL_JOYSTICK_HAIKU", + "SDL_JOYSTICK_HIDAPI", + "SDL_JOYSTICK_IOKIT", + "SDL_JOYSTICK_LINUX", + "SDL_JOYSTICK_MFI", + "SDL_JOYSTICK_N3DS", + "SDL_JOYSTICK_OS2", + "SDL_JOYSTICK_PS2", + "SDL_JOYSTICK_PSP", + "SDL_JOYSTICK_RAWINPUT", + "SDL_JOYSTICK_USBHID", + "SDL_JOYSTICK_VIRTUAL", + "SDL_JOYSTICK_VITA", + "SDL_JOYSTICK_WGI", + "SDL_JOYSTICK_XINPUT", + "SDL_LIBSAMPLERATE_DYNAMIC", + "SDL_LIBUSB_DYNAMIC", + "SDL_LOADSO_DISABLED", + "SDL_LOADSO_DLOPEN", + "SDL_LOADSO_DUMMY", + "SDL_LOADSO_LDG", + "SDL_LOADSO_OS2", + "SDL_LOADSO_WINDOWS", + "SDL_LOCALE_DISABLED", + "SDL_LOCALE_DUMMY", + "SDL_MISC_DISABLED", + "SDL_MISC_DUMMY", + "SDL_POWER_ANDROID", + "SDL_POWER_DISABLED", + "SDL_POWER_EMSCRIPTEN", + "SDL_POWER_HAIKU", + "SDL_POWER_HARDWIRED", + "SDL_POWER_LINUX", + "SDL_POWER_MACOSX", + "SDL_POWER_N3DS", + "SDL_POWER_PSP", + "SDL_POWER_UIKIT", + "SDL_POWER_VITA", + "SDL_POWER_WINDOWS", + "SDL_POWER_WINRT", + "SDL_RENDER_DISABLED", + "SDL_SENSOR_ANDROID", + "SDL_SENSOR_COREMOTION", + "SDL_SENSOR_DISABLED", + "SDL_SENSOR_DUMMY", + "SDL_SENSOR_N3DS", + "SDL_SENSOR_VITA", + "SDL_SENSOR_WINDOWS", + "SDL_THREADS_DISABLED", + "SDL_THREAD_GENERIC_COND_SUFFIX", + "SDL_THREAD_N3DS", + "SDL_THREAD_OS2", + "SDL_THREAD_PS2", + "SDL_THREAD_PSP", + "SDL_THREAD_PTHREAD", + "SDL_THREAD_PTHREAD_RECURSIVE_MUTEX", + "SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP", + "SDL_THREAD_VITA", + "SDL_THREAD_WINDOWS", + "SDL_TIMERS_DISABLED", + "SDL_TIMER_DUMMY", + "SDL_TIMER_HAIKU", + "SDL_TIMER_N3DS", + "SDL_TIMER_OS2", + "SDL_TIMER_PS2", + "SDL_TIMER_PSP", + "SDL_TIMER_UNIX", + "SDL_TIMER_VITA", + "SDL_TIMER_WINDOWS", + "SDL_UDEV_DYNAMIC", + "SDL_USE_IME", + "SDL_USE_LIBICONV", + "SDL_VIDEO_DISABLED", + "SDL_VIDEO_DRIVER_ANDROID", + "SDL_VIDEO_DRIVER_COCOA", + "SDL_VIDEO_DRIVER_DIRECTFB", + "SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC", + "SDL_VIDEO_DRIVER_DUMMY", + "SDL_VIDEO_DRIVER_EMSCRIPTEN", + "SDL_VIDEO_DRIVER_HAIKU", + "SDL_VIDEO_DRIVER_KMSDRM", + "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC", + "SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM", + "SDL_VIDEO_DRIVER_N3DS", + "SDL_VIDEO_DRIVER_OFFSCREEN", + "SDL_VIDEO_DRIVER_OS2", + "SDL_VIDEO_DRIVER_PS2", + "SDL_VIDEO_DRIVER_PSP", + "SDL_VIDEO_DRIVER_QNX", + "SDL_VIDEO_DRIVER_RISCOS", + "SDL_VIDEO_DRIVER_RPI", + "SDL_VIDEO_DRIVER_UIKIT", + "SDL_VIDEO_DRIVER_VITA", + "SDL_VIDEO_DRIVER_VIVANTE", + "SDL_VIDEO_DRIVER_VIVANTE_VDK", + "SDL_VIDEO_DRIVER_WAYLAND", + "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC", + "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR", + "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL", + "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR", + "SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON", + "SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH", + "SDL_VIDEO_DRIVER_WINDOWS", + "SDL_VIDEO_DRIVER_WINRT", + "SDL_VIDEO_DRIVER_X11", + "SDL_VIDEO_DRIVER_X11_DYNAMIC", + "SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR", + "SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT", + "SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES", + "SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2", + "SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR", + "SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS", + "SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM", + "SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS", + "SDL_VIDEO_DRIVER_X11_XCURSOR", + "SDL_VIDEO_DRIVER_X11_XDBE", + "SDL_VIDEO_DRIVER_X11_XFIXES", + "SDL_VIDEO_DRIVER_X11_XINPUT2", + "SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH", + "SDL_VIDEO_DRIVER_X11_XRANDR", + "SDL_VIDEO_DRIVER_X11_XSCRNSAVER", + "SDL_VIDEO_DRIVER_X11_XSHAPE", + "SDL_VIDEO_METAL", + "SDL_VIDEO_OPENGL", + "SDL_VIDEO_OPENGL_BGL", + "SDL_VIDEO_OPENGL_CGL", + "SDL_VIDEO_OPENGL_EGL", + "SDL_VIDEO_OPENGL_ES", + "SDL_VIDEO_OPENGL_ES2", + "SDL_VIDEO_OPENGL_GLX", + "SDL_VIDEO_OPENGL_OSMESA", + "SDL_VIDEO_OPENGL_OSMESA_DYNAMIC", + "SDL_VIDEO_OPENGL_WGL", + "SDL_VIDEO_RENDER_D3D", + "SDL_VIDEO_RENDER_D3D11", + "SDL_VIDEO_RENDER_D3D12", + "SDL_VIDEO_RENDER_DIRECTFB", + "SDL_VIDEO_RENDER_METAL", + "SDL_VIDEO_RENDER_OGL", + "SDL_VIDEO_RENDER_OGL_ES", + "SDL_VIDEO_RENDER_OGL_ES2", + "SDL_VIDEO_RENDER_PS2", + "SDL_VIDEO_RENDER_PSP", + "SDL_VIDEO_RENDER_VITA_GXM", + "SDL_VIDEO_VITA_PIB", + "SDL_VIDEO_VITA_PVR", + "SDL_VIDEO_VITA_PVR_OGL", + "SDL_VIDEO_VULKAN", +} + +if __name__ == "__main__": + raise SystemExit(main()) + diff --git a/build-scripts/test-versioning.sh b/build-scripts/test-versioning.sh index 9dd9b18a..a887a9cc 100755 --- a/build-scripts/test-versioning.sh +++ b/build-scripts/test-versioning.sh @@ -25,7 +25,7 @@ not_ok () { failed=1 } -version=$(sed -Ene 's/^project\(SDL[0-9]+ LANGUAGES C CXX VERSION "([0-9.]*)"\)$/\1/p' CMakeLists.txt) +version=$(sed -Ene 's/^project\(SDL[0-9]+ LANGUAGES C VERSION "([0-9.]*)"\)$/\1/p' CMakeLists.txt) if [ "$ref_version" = "$version" ]; then ok "CMakeLists.txt $version" diff --git a/cmake/FindLibUSB.cmake b/cmake/FindLibUSB.cmake new file mode 100644 index 00000000..24887350 --- /dev/null +++ b/cmake/FindLibUSB.cmake @@ -0,0 +1,73 @@ +include(FindPackageHandleStandardArgs) + +set(LibUSB_PKG_CONFIG_SPEC libusb-1.0>=1.0.16) +set(LibUSB_MIN_API_VERSION 0x01000102) + +find_package(PkgConfig QUIET) + +if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_LibUSB ${LibUSB_PKG_CONFIG_SPEC}) +endif() + +find_library(LibUSB_LIBRARY + NAMES usb-1.0 libusb-1.0 + HINTS ${PC_LibUSB_LIBRARY_DIRS} +) + +find_path(LibUSB_INCLUDE_PATH + NAMES libusb.h + PATH_SUFFIXES libusb-1.0 + HINTS ${PC_LibUSB_INCLUDE_DIRS} +) + +set(LibUSB_API_VERSION "LibUSB_API_VERSION-NOTFOUND") +if(LibUSB_INCLUDE_PATH AND EXISTS "${LibUSB_INCLUDE_PATH}/libusb.h") + file(READ "${LibUSB_INCLUDE_PATH}/libusb.h" LIBUSB_H_TEXT) + if("${LIBUSB_H_TEXT}" MATCHES "#define[ \t]+LIBUSBX?_API_VERSION[ \t]+(0x[0-9a-fA-F]+)" ) + set(LibUSB_API_VERSION "${CMAKE_MATCH_1}") + endif() +endif() + +if(LibUSB_API_VERSION) + math(EXPR LibUSB_MIN_API_VERSION_decimal "${LibUSB_MIN_API_VERSION}") + math(EXPR LibUSB_API_VERSION_decimal "${LibUSB_API_VERSION}") + if(NOT LibUSB_MIN_API_VERSION_decimal LESS_EQUAL LibUSB_API_VERSION_decimal) + set(LibUSB_LIBRARY "LibUSB_LIBRARY-NOTFOUND") + endif() +else() + set(LibUSB_LIBRARY "LibUSB_LIBRARY-NOTFOUND") +endif() + +set(LibUSB_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of LibUSB") + +set(LibUSB_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of LibUSB") + +set(LibUSB_LINK_FLAGS "" CACHE STRING "Extra link flags of LibUSB") + +if(LibUSB_LIBRARY AND LibUSB_INCLUDE_PATH) + if(PC_LibUSB_FOUND) + set(LibUSB_VERSION "${PC_LibUSB_VERSION}") + else() + set(LibUSB_VERSION "1.0.16-or-higher") + endif() +else() + set(LibUSB_VERSION "LibUSB_VERSION-NOTFOUND") +endif() + +find_package_handle_standard_args(LibUSB + VERSION_VAR LibUSB_VERSION + REQUIRED_VARS LibUSB_LIBRARY LibUSB_INCLUDE_PATH +) + +if(LibUSB_FOUND AND NOT TARGET LibUSB::LibUSB) + add_library(LibUSB::LibUSB IMPORTED UNKNOWN) + set_target_properties(LibUSB::LibUSB + PROPERTIES + IMPORTED_LOCATION "${LibUSB_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${LibUSB_INCLUDE_PATH}" + INTERFACE_COMPILE_OPTIONS "${LibUSB_COMPILE_OPTIONS}" + INTERFACE_LINK_LIBRARIES "${LibUSB_LINK_LIBRARIES}" + INTERFACE_LINK_OPTIONS "${LibUSB_LINK_OPTIONS}" + ) +endif() + diff --git a/cmake/macros.cmake b/cmake/macros.cmake index c04c760a..656f4e09 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -100,6 +100,199 @@ function(SDL_detect_linker) endif() endfunction() +function(read_absolute_symlink DEST PATH) + file(READ_SYMLINK "${PATH}" p) + if(NOT IS_ABSOLUTE "${p}") + get_filename_component(pdir "${PATH}" DIRECTORY) + set(p "${pdir}/${p}") + endif() + get_filename_component(p "${p}" ABSOLUTE) + set("${DEST}" "${p}" PARENT_SCOPE) +endfunction() + +function(win32_implib_identify_dll DEST IMPLIB) + cmake_parse_arguments(ARGS "NOTFATAL" "" "" ${ARGN}) + if(CMAKE_DLLTOOL) + execute_process( + COMMAND "${CMAKE_DLLTOOL}" --identify "${IMPLIB}" + RESULT_VARIABLE retcode + OUTPUT_VARIABLE stdout + ERROR_VARIABLE stderr) + if(NOT retcode EQUAL 0) + if(NOT ARGS_NOTFATAL) + message(FATAL_ERROR "${CMAKE_DLLTOOL} failed.") + else() + set("${DEST}" "${DEST}-NOTFOUND" PARENT_SCOPE) + return() + endif() + endif() + string(STRIP "${stdout}" result) + set(${DEST} "${result}" PARENT_SCOPE) + elseif(MSVC) + get_filename_component(CMAKE_C_COMPILER_DIRECTORY "${CMAKE_C_COMPILER}" DIRECTORY CACHE) + find_program(CMAKE_DUMPBIN NAMES dumpbin PATHS "${CMAKE_C_COMPILER_DIRECTORY}") + if(CMAKE_DUMPBIN) + execute_process( + COMMAND "${CMAKE_DUMPBIN}" "-headers" "${IMPLIB}" + RESULT_VARIABLE retcode + OUTPUT_VARIABLE stdout + ERROR_VARIABLE stderr) + if(NOT retcode EQUAL 0) + if(NOT ARGS_NOTFATAL) + message(FATAL_ERROR "dumpbin failed.") + else() + set(${DEST} "${DEST}-NOTFOUND" PARENT_SCOPE) + return() + endif() + endif() + string(REGEX MATCH "DLL name[ ]+:[ ]+([^\n]+)\n" match "${stdout}") + if(NOT match) + if(NOT ARGS_NOTFATAL) + message(FATAL_ERROR "dumpbin did not find any associated dll for ${IMPLIB}.") + else() + set(${DEST} "${DEST}-NOTFOUND" PARENT_SCOPE) + return() + endif() + endif() + set(result "${CMAKE_MATCH_1}") + set(${DEST} "${result}" PARENT_SCOPE) + else() + message(FATAL_ERROR "Cannot find dumpbin, please set CMAKE_DUMPBIN cmake variable") + endif() + else() + if(NOT ARGS_NOTFATAL) + message(FATAL_ERROR "Don't know how to identify dll from import library. Set CMAKE_DLLTOOL (for mingw) or CMAKE_DUMPBIN (for MSVC)") + else() + set(${DEST} "${DEST}-NOTFOUND") + endif() + endif() +endfunction() + +function(get_actual_target) + set(dst "${ARGV0}") + set(target "${${dst}}") + set(input "${target}") + get_target_property(alias "${target}" ALIASED_TARGET) + while(alias) + set(target "${alias}") + get_target_property(alias "${target}" ALIASED_TARGET) + endwhile() + message(DEBUG "get_actual_target(\"${input}\") -> \"${target}\"") + set("${dst}" "${target}" PARENT_SCOPE) +endfunction() + +function(target_get_dynamic_library DEST TARGET) + set(result) + get_actual_target(TARGET) + if(WIN32) + # Use the target dll of the import library + set(props_to_check IMPORTED_IMPLIB) + if(CMAKE_BUILD_TYPE) + list(APPEND props_to_check IMPORTED_IMPLIB_${CMAKE_BUILD_TYPE}) + endif() + list(APPEND props_to_check IMPORTED_LOCATION) + if(CMAKE_BUILD_TYPE) + list(APPEND props_to_check IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) + endif() + foreach (config_type ${CMAKE_CONFIGURATION_TYPES} RELEASE DEBUG RELWITHDEBINFO MINSIZEREL) + list(APPEND props_to_check IMPORTED_IMPLIB_${config_type}) + list(APPEND props_to_check IMPORTED_LOCATION_${config_type}) + endforeach() + + foreach(prop_to_check ${props_to_check}) + if(NOT result) + get_target_property(propvalue "${TARGET}" ${prop_to_check}) + if(propvalue AND EXISTS "${propvalue}") + win32_implib_identify_dll(result "${propvalue}" NOTFATAL) + endif() + endif() + 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 + set(location_properties IMPORTED_LOCATION) + if(CMAKE_BUILD_TYPE) + list(APPEND location_properties IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) + endif() + foreach (config_type ${CMAKE_CONFIGURATION_TYPES} RELEASE DEBUG RELWITHDEBINFO MINSIZEREL) + list(APPEND location_properties IMPORTED_LOCATION_${config_type}) + endforeach() + if(APPLE) + set(valid_shared_library_regex "\\.[0-9]+\\.dylib$") + else() + set(valid_shared_library_regex "\\.so\\.([0-9.]+)?[0-9]") + endif() + 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}") + if(EXISTS "${library_path}") + get_filename_component(library_path "${library_path}" ABSOLUTE) + while (IS_SYMLINK "${library_path}") + read_absolute_symlink(library_path "${library_path}") + endwhile() + message(DEBUG "${TARGET} -> ${library_path}") + get_filename_component(libdir "${library_path}" DIRECTORY) + file(GLOB subfiles "${libdir}/*") + set(similar_files "${library_path}") + foreach(subfile ${subfiles}) + if(IS_SYMLINK "${subfile}") + read_absolute_symlink(subfile_target "${subfile}") + while(IS_SYMLINK "${subfile_target}") + read_absolute_symlink(subfile_target "${subfile_target}") + endwhile() + get_filename_component(subfile_target "${subfile_target}" ABSOLUTE) + if(subfile_target STREQUAL library_path AND subfile MATCHES "${valid_shared_library_regex}") + list(APPEND similar_files "${subfile}") + endif() + endif() + endforeach() + list(SORT similar_files) + message(DEBUG "files that are similar to \"${library_path}\"=${similar_files}") + if(APPLE) + list(REVERSE similar_files) + endif() + list(GET similar_files 0 item) + get_filename_component(result "${item}" NAME) + endif() + endif() + endforeach() + endif() + if(result) + string(TOLOWER "${result}" result_lower) + if(WIN32 OR OS2) + if(NOT result_lower MATCHES ".*dll") + message(FATAL_ERROR "\"${result}\" is not a .dll library") + endif() + elseif(APPLE) + if(NOT result_lower MATCHES ".*dylib.*") + message(FATAL_ERROR "\"${result}\" is not a .dylib shared library") + endif() + else() + if(NOT result_lower MATCHES ".*so.*") + message(FATAL_ERROR "\"${result}\" is not a .so shared library") + endif() + endif() + else() + get_target_property(target_type ${TARGET} TYPE) + if(target_type MATCHES "SHARED_LIBRARY|MODULE_LIBRARY") + # OK + elseif(target_type MATCHES "STATIC_LIBRARY|OBJECT_LIBRARY|INTERFACE_LIBRARY|EXECUTABLE") + message(SEND_ERROR "${TARGET} is not a shared library, but has type=${target_type}") + else() + message(WARNING "Unable to extract dynamic library from target=${TARGET}, type=${target_type}.") + endif() + # TARGET_SONAME_FILE is not allowed for DLL target platforms. + if(WIN32) + set(result "$") + else() + set(result "$") + endif() + endif() + set(${DEST} ${result} PARENT_SCOPE) +endfunction() + function(check_linker_supports_version_file VAR) SDL_detect_linker() if(CMAKE_C_COMPILER_LINKER_ID MATCHES "^(MSVC)$") diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 6a0be91b..6a12b304 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -557,9 +557,20 @@ macro(CheckWayland) set(LibDecor_PKG_CONFIG_SPEC libdecor-0) pkg_check_modules(PC_LIBDECOR IMPORTED_TARGET ${LibDecor_PKG_CONFIG_SPEC}) if(PC_LIBDECOR_FOUND) - # Version 0.2.0 or higher is needed for suspended window state and statically linked min/max getters. + + # Libdecor doesn't provide internal version defines, so generate them here. + if (PC_LIBDECOR_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") + set(SDL_LIBDECOR_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(SDL_LIBDECOR_VERSION_MINOR ${CMAKE_MATCH_2}) + set(SDL_LIBDECOR_VERSION_PATCH ${CMAKE_MATCH_3}) + else() + message(WARNING "Failed to parse libdecor version; defaulting to lowest supported (0.1.0)") + set(SDL_LIBDECOR_VERSION_MAJOR 0) + set(SDL_LIBDECOR_VERSION_MINOR 1) + set(SDL_LIBDECOR_VERSION_PATCH 0) + endif() + if(PC_LIBDECOR_VERSION VERSION_GREATER_EQUAL "0.2.0") - set(SDL_HAVE_LIBDECOR_VER_0_2_0 1) set(LibDecor_PKG_CONFIG_SPEC "libdecor-0>=0.2.0") endif() set(HAVE_WAYLAND_LIBDECOR TRUE) @@ -652,6 +663,7 @@ macro(CheckEGL) cmake_push_check_state() find_package(OpenGL MODULE) list(APPEND CMAKE_REQUIRED_INCLUDES ${OPENGL_EGL_INCLUDE_DIRS}) + list(APPEND CMAKE_REQUIRED_INCLUDES "${SDL3_SOURCE_DIR}/src/video/khronos") check_c_source_compiles(" #define EGL_API_FB #define MESA_EGL_NO_X11_HEADERS @@ -686,18 +698,21 @@ endmacro() # - nada macro(CheckOpenGLES) if(SDL_OPENGLES) + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_INCLUDES "${SDL3_SOURCE_DIR}/src/video/khronos") check_c_source_compiles(" #include #include int main (int argc, char** argv) { return 0; }" HAVE_OPENGLES_V1) - if(HAVE_OPENGLES_V1) - set(HAVE_OPENGLES TRUE) - set(SDL_VIDEO_OPENGL_ES 1) - endif() check_c_source_compiles(" #include #include int main (int argc, char** argv) { return 0; }" HAVE_OPENGLES_V2) + cmake_pop_check_state() + if(HAVE_OPENGLES_V1) + set(HAVE_OPENGLES TRUE) + set(SDL_VIDEO_OPENGL_ES 1) + endif() if(HAVE_OPENGLES_V2) set(HAVE_OPENGLES TRUE) set(SDL_VIDEO_OPENGL_ES2 1) @@ -710,6 +725,10 @@ macro(CheckVulkan) if(SDL_VULKAN) 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() endmacro() @@ -737,7 +756,7 @@ endmacro() # PTHREAD_LIBS macro(CheckPTHREAD) cmake_push_check_state() - if(SDL_THREADS AND SDL_PTHREADS) + if(SDL_PTHREADS) if(ANDROID) # the android libc provides built-in support for pthreads, so no # additional linking or compile flags are necessary @@ -1020,13 +1039,10 @@ macro(CheckHIDAPI) set(HAVE_HIDAPI ON) if(SDL_HIDAPI_LIBUSB) set(HAVE_LIBUSB FALSE) - - set(LibUSB_PKG_CONFIG_SPEC libusb-1.0>=1.0.16) - pkg_check_modules(PC_LIBUSB IMPORTED_TARGET ${LibUSB_PKG_CONFIG_SPEC}) - if(PC_LIBUSB_FOUND) + find_package(LibUSB) + if(LibUSB_FOUND) cmake_push_check_state() - list(APPEND CMAKE_REQUIRED_INCLUDES ${PC_LIBUSB_INCLUDE_DIRS}) - list(APPEND CMAKE_REQUIRED_LIBRARIES PkgConfig::PC_LIBUSB) + list(APPEND CMAKE_REQUIRED_LIBRARIES LibUSB::LibUSB) check_c_source_compiles(" #include #include @@ -1037,13 +1053,13 @@ macro(CheckHIDAPI) cmake_pop_check_state() if(HAVE_LIBUSB_H) set(HAVE_LIBUSB TRUE) - FindLibraryAndSONAME("usb-1.0" LIBDIRS ${PC_LIBUSB_LIBRARY_DIRS}) - if(SDL_HIDAPI_LIBUSB_SHARED AND USB_1.0_LIB_SONAME) + target_get_dynamic_library(dynamic_libusb LibUSB::LibUSB) + if(SDL_HIDAPI_LIBUSB_SHARED AND dynamic_libusb) set(HAVE_HIDAPI_LIBUSB_SHARED ON) - set(SDL_LIBUSB_DYNAMIC "\"${USB_1.0_LIB_SONAME}\"") - sdl_link_dependency(hidapi INCLUDES $) + set(SDL_LIBUSB_DYNAMIC "\"${dynamic_libusb}\"") + sdl_link_dependency(hidapi INCLUDES $) else() - sdl_link_dependency(hidapi LIBS PkgConfig::PC_LIBUSB PKG_CONFIG_PREFIX PC_LIBUSB PKG_CONFIG_SPECS ${LibUSB_PKG_CONFIG_SPEC}) + sdl_link_dependency(hidapi LIBS LibUSB::LibUSB PKG_CONFIG_SPECS "${LibUSB_PKG_CONFIG_SPEC}" CMAKE_MODULE LibUSB) endif() endif() endif() @@ -1052,6 +1068,7 @@ macro(CheckHIDAPI) if(HAVE_HIDAPI) if(ANDROID) + enable_language(CXX) sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp") endif() if(IOS OR TVOS) diff --git a/cmake/sdlcompilers.cmake b/cmake/sdlcompilers.cmake index 5fd3081b..5138fdd0 100644 --- a/cmake/sdlcompilers.cmake +++ b/cmake/sdlcompilers.cmake @@ -19,6 +19,13 @@ macro(SDL_DetectCompiler) endif() endmacro() +function(sdl_target_compile_option_all_languages TARGET OPTION) + target_compile_options(${TARGET} PRIVATE "$<$:${OPTION}>") + if(CMAKE_OBJC_COMPILER) + target_compile_options(${TARGET} PRIVATE "$<$:${OPTION}>") + endif() +endfunction() + function(SDL_AddCommonCompilerFlags TARGET) option(SDL_WERROR "Enable -Werror" OFF) @@ -41,20 +48,20 @@ function(SDL_AddCommonCompilerFlags TARGET) if(MSVC_CLANG) target_compile_options(${TARGET} PRIVATE "/W3") elseif(HAVE_GCC_WALL) - target_compile_options(${TARGET} PRIVATE "-Wall") + sdl_target_compile_option_all_languages(${TARGET} "-Wall") if(HAIKU) - target_compile_options(${TARGET} PRIVATE "-Wno-multichar") + sdl_target_compile_option_all_languages(${TARGET} "-Wno-multichar") endif() endif() check_c_compiler_flag(-Wundef HAVE_GCC_WUNDEF) if(HAVE_GCC_WUNDEF) - target_compile_options(${TARGET} PRIVATE "$<$:-Wundef>") + sdl_target_compile_option_all_languages(${TARGET} "-Wundef") endif() check_c_compiler_flag(-fno-strict-aliasing HAVE_GCC_NO_STRICT_ALIASING) if(HAVE_GCC_NO_STRICT_ALIASING) - target_compile_options(${TARGET} PRIVATE "$<$:-fno-strict-aliasing>") + sdl_target_compile_option_all_languages(${TARGET} "-fno-strict-aliasing") endif() check_c_compiler_flag(-Wdocumentation HAVE_GCC_WDOCUMENTATION) @@ -62,10 +69,10 @@ function(SDL_AddCommonCompilerFlags TARGET) if(SDL_WERROR) check_c_compiler_flag(-Werror=documentation HAVE_GCC_WERROR_DOCUMENTATION) if(HAVE_GCC_WERROR_DOCUMENTATION) - target_compile_options(${TARGET} PRIVATE "$<$:-Werror=documentation>") + sdl_target_compile_option_all_languages(${TARGET} "-Werror=documentation") endif() endif() - target_compile_options(${TARGET} PRIVATE "$<$:-Wdocumentation>") + sdl_target_compile_option_all_languages(${TARGET} "-Wdocumentation") endif() check_c_compiler_flag(-Wdocumentation-unknown-command HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND) @@ -73,30 +80,35 @@ function(SDL_AddCommonCompilerFlags TARGET) if(SDL_WERROR) check_c_compiler_flag(-Werror=documentation-unknown-command HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND) if(HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND) - target_compile_options(${TARGET} PRIVATE "$<$:-Werror=documentation-unknown-command>") + sdl_target_compile_option_all_languages(${TARGET} "-Werror=documentation-unknown-command") endif() endif() - target_compile_options(${TARGET} PRIVATE "$<$:-Wdocumentation-unknown-command>") + sdl_target_compile_option_all_languages(${TARGET} "-Wdocumentation-unknown-command") endif() check_c_compiler_flag(-fcomment-block-commands=threadsafety HAVE_GCC_COMMENT_BLOCK_COMMANDS) if(HAVE_GCC_COMMENT_BLOCK_COMMANDS) - target_compile_options(${TARGET} PRIVATE "$<$:-fcomment-block-commands=threadsafety>") + sdl_target_compile_option_all_languages(${TARGET} "-fcomment-block-commands=threadsafety") else() check_c_compiler_flag(/clang:-fcomment-block-commands=threadsafety HAVE_CLANG_COMMENT_BLOCK_COMMANDS) if(HAVE_CLANG_COMMENT_BLOCK_COMMANDS) - target_compile_options(${TARGET} PRIVATE "$<$:/clang:-fcomment-block-commands=threadsafety>") + sdl_target_compile_option_all_languages(${TARGET} "/clang:-fcomment-block-commands=threadsafety") endif() endif() check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW) if(HAVE_GCC_WSHADOW) - target_compile_options(${TARGET} PRIVATE "$<$:-Wshadow>") + sdl_target_compile_option_all_languages(${TARGET} "-Wshadow") endif() check_c_compiler_flag(-Wunused-local-typedefs HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS) if(HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS) - target_compile_options(${TARGET} PRIVATE "$<$:-Wno-unused-local-typedefs>") + sdl_target_compile_option_all_languages(${TARGET} "-Wno-unused-local-typedefs") + endif() + + check_c_compiler_flag(-Wimplicit-fallthrough HAVE_GCC_WIMPLICIT_FALLTHROUGH) + if(HAVE_GCC_WIMPLICIT_FALLTHROUGH) + sdl_target_compile_option_all_languages(${TARGET} "-Wimplicit-fallthrough") endif() endif() @@ -109,7 +121,7 @@ function(SDL_AddCommonCompilerFlags TARGET) elseif(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QNX) check_c_compiler_flag(-Werror HAVE_WERROR) if(HAVE_WERROR) - target_compile_options(${TARGET} PRIVATE "$<$:-Werror>") + sdl_target_compile_option_all_languages(${TARGET} "-Werror") endif() endif() endif() @@ -117,12 +129,12 @@ function(SDL_AddCommonCompilerFlags TARGET) if(USE_CLANG) check_c_compiler_flag("-fcolor-diagnostics" COMPILER_SUPPORTS_FCOLOR_DIAGNOSTICS) if(COMPILER_SUPPORTS_FCOLOR_DIAGNOSTICS) - target_compile_options(${TARGET} PRIVATE "$<$:-fcolor-diagnostics>") + sdl_target_compile_option_all_languages(${TARGET} "-fcolor-diagnostics") endif() else() check_c_compiler_flag("-fdiagnostics-color=always" COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS) if(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS) - target_compile_options(${TARGET} PRIVATE "$<$:-fdiagnostics-color=always>") + sdl_target_compile_option_all_languages(${TARGET} "-fdiagnostics-color=always") endif() endif() endfunction() diff --git a/cmake/test/CMakeLists.txt b/cmake/test/CMakeLists.txt index f03590f2..d3fd8a09 100644 --- a/cmake/test/CMakeLists.txt +++ b/cmake/test/CMakeLists.txt @@ -1,4 +1,4 @@ -# This cmake build script is meant for verifying the various CMake configuration script. +# This cmake build script is meant for verifying the various CMake configuration scripts. cmake_minimum_required(VERSION 3.12) project(sdl_test LANGUAGES C) @@ -35,9 +35,14 @@ add_feature_info("TEST_STATIC" TEST_STATIC "Test linking with static library") option(TEST_TEST "Test linking to SDL3_test library" ON) add_feature_info("TEST_TEST" TEST_STATIC "Test linking to SDL test library") +option(TEST_FULL "Run complete SDL test suite" OFF) +add_feature_info("TEST_FULL" TEST_FULL "Build full SDL testsuite") + find_package(SDL3 REQUIRED CONFIG COMPONENTS Headers) -add_library(headers_test OBJECT inc_sdl_slash.c inc_sdl_noslash.c) -target_link_libraries(headers_test PRIVATE SDL3::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) @@ -93,6 +98,15 @@ find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3) add_executable(gui-whatever WIN32 main_gui.c) target_link_libraries(gui-whatever PRIVATE SDL3::SDL3) +if(TEST_FULL) + enable_testing() + set(SDL_TESTS_TIMEOUT_MULTIPLIER "1" CACHE STRING "Test timeout multiplier") + set(SDL_TESTS_LINK_SHARED ${TEST_SHARED}) + + add_definitions(-DNO_BUILD_CONFIG) + add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../test" SDL_test) +endif() + if(ANDROID) find_package(SDL3 REQUIRED CONFIG COMPONENTS Jar) endif() diff --git a/cmake/test/inc_sdl_noslash.c b/cmake/test/inc_sdl_noslash.c index f9912925..600329ca 100644 --- a/cmake/test/inc_sdl_noslash.c +++ b/cmake/test/inc_sdl_noslash.c @@ -3,6 +3,6 @@ void inc_sdl_noslash(void) { SDL_SetMainReady(); - SDL_Init(SDL_INIT_EVERYTHING); + SDL_Init(0); SDL_Quit(); } diff --git a/cmake/test/inc_sdl_slash.c b/cmake/test/inc_sdl_slash.c index e3674993..7acca152 100644 --- a/cmake/test/inc_sdl_slash.c +++ b/cmake/test/inc_sdl_slash.c @@ -3,6 +3,6 @@ void inc_sdl_slash(void) { SDL_SetMainReady(); - SDL_Init(SDL_INIT_EVERYTHING); + SDL_Init(0); SDL_Quit(); } diff --git a/docs/README-android.md b/docs/README-android.md index 588b43d0..94260dab 100644 --- a/docs/README-android.md +++ b/docs/README-android.md @@ -165,7 +165,7 @@ Loading assets Any files you put in the "app/src/main/assets" directory of your project directory will get bundled into the application package and you can load -them using the standard functions in SDL_rwops.h. +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: diff --git a/docs/README-cmake.md b/docs/README-cmake.md index 337a41ab..73f80f21 100644 --- a/docs/README-cmake.md +++ b/docs/README-cmake.md @@ -8,14 +8,15 @@ The CMake build system is supported on the following platforms: * Linux * Microsoft Visual C * MinGW and Msys -* macOS, iOS, and tvOS, with support for XCode +* macOS, iOS, tvOS, and visionOS with support for XCode * Android * Emscripten -* FreeBSD +* NetBSD * Haiku * Nintendo 3DS -* Playstation 2 -* Playstation Vita +* PlayStation 2 +* PlayStation Portable +* PlayStation Vita * QNX 7.x/8.x * RiscOS @@ -136,27 +137,88 @@ flags to the compiler. cmake .. -DCMAKE_C_FLAGS="/ARCH:AVX2" -DCMAKE_CXX_FLAGS="/ARCH:AVX2" ``` -### iOS/tvOS +### Apple -CMake 3.14+ natively includes support for iOS and tvOS. SDL binaries may be built -using Xcode or Make, possibly among other build-systems. +CMake documentation for cross building for Apple: +[link](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-ios-tvos-visionos-or-watchos) -When using a recent version of CMake (3.14+), it should be possible to: +#### iOS/tvOS/visionOS -- build SDL for iOS, both static and dynamic -- build SDL test apps (as iOS/tvOS .app bundles) -- generate a working SDL_build_config.h for iOS (using SDL_build_config.h.cmake as a basis) +CMake 3.14+ natively includes support for iOS, tvOS and watchOS. visionOS requires CMake 3.28+. +SDL binaries may be built using Xcode or Make, possibly among other build-systems. -To use, set the following CMake variables when running CMake's configuration stage: +When using a compatible version of CMake, it should be possible to: -- `CMAKE_SYSTEM_NAME=` (either `iOS` or `tvOS`) -- `CMAKE_OSX_SYSROOT=` (examples: `iphoneos`, `iphonesimulator`, `iphoneos12.4`, `/full/path/to/iPhoneOS.sdk`, - `appletvos`, `appletvsimulator`, `appletvos12.4`, `/full/path/to/AppleTVOS.sdk`, etc.) -- `CMAKE_OSX_ARCHITECTURES=` (example: "arm64;armv7s;x86_64") +- build SDL dylibs, both static and dynamic dylibs +- build SDL frameworks, only shared +- build SDL test apps +#### Frameworks + +Configure with `-DSDL_FRAMEWORK=ON` to build a SDL framework instead of a dylib shared library. +Only shared frameworks are supported, no static ones. + +#### Platforms + +Use `-DCMAKE_PLATFORM_NAME=` to configure the platform. CMake can target only one platform at a time. + +| Apple platform | `CMAKE_SYSTEM_NAME` value | +|-----------------|---------------------------| +| macOS (MacOS X) | `Darwin` | +| iOS | `iOS` | +| tvOS | `tvOS` | +| visionOS | `visionOS` | +| watchOS | `watchOS` | + +#### Universal binaries + +A universal binaries, can be built by configuring CMake with +`-DCMAKE_OSX_ARCHITECTURES=`. + +For example `-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"` will build binaries that run on both Intel cpus and Apple silicon. + +SDL supports following Apple architectures: + +| Platform | `CMAKE_OSX_ARCHITECTURES` value | +|----------------------------|---------------------------------| +| 64-bit ARM (Apple Silicon) | `arm64` | +| x86_64 | `x86_64` | +| 32-bit ARM | `armv7s` | + +CMake documentation: [link](https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html) + +#### Simulators and/or non-default maxOS platform SDK + +Use `-DCMAKE_OSX_SYSROOT=` to configure a different platform SDK. +The value can be either the name of the SDK, or a full path to the sdk (e.g. `/full/path/to/iPhoneOS.sdk`). + +| SDK | `CMAKE_OSX_SYSROOT` value | +|----------------------|---------------------------| +| iphone | `iphoneos` | +| iphonesimulator | `iphonesimulator` | +| appleTV | `appletvos` | +| appleTV simulator | `appletvsimulator` | +| visionOS | `xr` | +| visionOS simulator | `xrsimulator` | +| watchOS | `watchos` | +| watchOS simulator | `watchsimulator` | + +Append with a version number to target a specific SDK revision: e.g. `iphoneos12.4`, `appletvos12.4`. + +CMake documentation: [link](https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_SYSROOT.html) #### Examples +- for macOS, building a dylib and/or static library for x86_64 and arm64: + + ```bash + cmake ~/sdl -DCMAKE_SYSTEM_NAME=Darwin -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" + +- for macOS, building an universal framework for x86_64 and arm64: + + ```bash + cmake ~/sdl -DSDL_FRAMEWORK=ON -DCMAKE_SYSTEM_NAME=Darwin -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" + - for iOS-Simulator, using the latest, installed SDK: ```bash @@ -275,9 +337,15 @@ file(WRITE main.c [===========================================[ /* START of source modifications */ #include +/* + * SDL3/SDL_main.h is explicitly not included such that a terminal window would appear on Windows. + */ int main(int argc, char *argv[]) { - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { + (void)argc; + (void)argv; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { SDL_Log("SDL_Init failed (%s)", SDL_GetError()); return 1; } @@ -314,6 +382,7 @@ int main(int argc, char *argv[]) { SDL_DestroyWindow(window); SDL_Quit(); + return 0; } /* END of source modifications */ diff --git a/docs/README-dynapi.md b/docs/README-dynapi.md index 665b7c65..967f1bdf 100644 --- a/docs/README-dynapi.md +++ b/docs/README-dynapi.md @@ -35,7 +35,7 @@ SDL now has, internally, a table of function pointers. So, this is what SDL_Init now looks like: ```c -UInt32 SDL_Init(Uint32 flags) +Uint32 SDL_Init(Uint32 flags) { return jump_table.SDL_Init(flags); } @@ -100,7 +100,7 @@ a shared library of its own). If so, it loads that library and looks for and calls a single function: ```c -SInt32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize); +Sint32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize); ``` That function takes a version number (more on that in a moment), the address of diff --git a/docs/README-emscripten.md b/docs/README-emscripten.md index 31553e06..6a445bd4 100644 --- a/docs/README-emscripten.md +++ b/docs/README-emscripten.md @@ -301,7 +301,7 @@ Your game probably has data files. Here's how to access them. Filesystem access works like a Unix filesystem; you have a single directory tree, possibly interpolated from several mounted locations, no drive letters, '/' for a path separator. You can access them with standard file APIs like -open() or fopen() or SDL_RWops. You can read or write from the filesystem. +open() or fopen() or SDL_IOStream. You can read or write from the filesystem. By default, you probably have a "MEMFS" filesystem (all files are stored in memory, but access to them is immediate and doesn't need to block). There are diff --git a/docs/README-gdk.md b/docs/README-gdk.md index 9a948583..7c447039 100644 --- a/docs/README-gdk.md +++ b/docs/README-gdk.md @@ -21,7 +21,7 @@ Windows GDK Status The Windows GDK port supports the full set of Win32 APIs, renderers, controllers, input devices, etc., as the normal Windows x64 build of SDL. * Additionally, the GDK port adds the following: - * Compile-time platform detection for SDL programs. The `__GDK__` is `#define`d on every GDK platform, and the `__WINGDK__` is `#define`d on Windows GDK, specifically. (This distinction exists because other GDK platforms support a smaller subset of functionality. This allows you to mark code for "any" GDK separate from Windows GDK.) + * Compile-time platform detection for SDL programs. The `SDL_PLATFORM_GDK` is `#define`d on every GDK platform, and the `SDL_PLATFORM_WINGDK` is `#define`d on Windows GDK, specifically. (This distinction exists because other GDK platforms support a smaller subset of functionality. This allows you to mark code for "any" GDK separate from Windows GDK.) * GDK-specific setup: * Initializing/uninitializing the game runtime, and initializing Xbox Live services * Creating a global task queue and setting it as the default for the process. When running any async operations, passing in `NULL` as the task queue will make the task get added to the global task queue. @@ -149,7 +149,7 @@ Xbox GDKX Setup In general, the same process in the Windows GDK instructions work. There are just a few additional notes: * For Xbox One consoles, use the Gaming.Xbox.XboxOne.x64 target * For Xbox Series consoles, use the Gaming.Xbox.Scarlett.x64 target -* The Xbox One target sets the `__XBOXONE__` define and the Xbox Series target sets the `__XBOXSERIES__` define +* The Xbox One target sets the `SDL_PLATFORM_XBOXONE` define and the Xbox Series target sets the `SDL_PLATFORM_XBOXSERIES` define * You don't need to link against the Xbox.Services Thunks lib nor include that dll in your package (it doesn't exist for Xbox) * The shader blobs for Xbox are created in a pre-build step for the Xbox targets, rather than included in the source (due to NDA and version compatability reasons) * To create a package, use: diff --git a/docs/README-ios.md b/docs/README-ios.md index 221cb27d..ff991ad0 100644 --- a/docs/README-ios.md +++ b/docs/README-ios.md @@ -238,7 +238,7 @@ e.g. { ... initialize game ... - #ifdef __IOS__ + #ifdef SDL_PLATFORM_IOS // Initialize the Game Center for scoring and matchmaking InitGameCenter(); diff --git a/docs/README-main-functions.md b/docs/README-main-functions.md index a9d8fca5..b9d9caa5 100644 --- a/docs/README-main-functions.md +++ b/docs/README-main-functions.md @@ -137,7 +137,7 @@ functions: First: ```c -int SDL_AppInit(int argc, char **argv); +int SDL_AppInit(void **appstate, int argc, char **argv); ``` This will be called _once_ before anything else. argc/argv work like they @@ -148,10 +148,17 @@ an exit code that reports success to the platform. This function should not go into an infinite mainloop; it should do any one-time startup it requires and then return. +If you want to, you can assign a pointer to `*appstate`, and this pointer +will be made available to you in later functions calls in their `appstate` +parameter. This allows you to avoid global variables, but is totally +optional. If you don't set this, the pointer will be NULL in later function +calls. + + Then: ```c -int SDL_AppIterate(void); +int SDL_AppIterate(void *appstate); ``` This is called over and over, possibly at the refresh rate of the display or @@ -171,7 +178,7 @@ as fast as possible. You do not check the event queue in this function Next: ```c -int SDL_AppEvent(const SDL_Event *event); +int SDL_AppEvent(void *appstate, const SDL_Event *event); ``` This will be called whenever an SDL event arrives, on the thread that runs @@ -183,7 +190,7 @@ SDL_AppIterate(), so you can terminate in response to SDL_EVENT_QUIT, etc. Finally: ```c -void SDL_AppQuit(void); +void SDL_AppQuit(void *appstate); ``` This is called once before terminating the app--assuming the app isn't being @@ -192,3 +199,5 @@ SDL will call SDL_Quit so the app doesn't have to (but it's safe for the app to call it, too). Process termination proceeds as if the app returned normally from main(), so atexit handles will run, if your platform supports that. +If you set `*appstate` during SDL_AppInit, this is where you should free that +data, as this pointer will not be provided to your app again. diff --git a/docs/README-migration.md b/docs/README-migration.md index 959fd0de..a531c939 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -13,11 +13,17 @@ rename_symbols.py --all-symbols source_code_path It's also possible to apply a semantic patch to migrate more easily to SDL3: [SDL_migration.cocci](https://github.com/libsdl-org/SDL/blob/main/build-scripts/SDL_migration.cocci) -SDL headers should now be included as `#include `. Typically that's the only header you'll need in your application unless you are using OpenGL or Vulkan functionality. We have provided a handy Python script [rename_headers.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_headers.py) to rename SDL2 headers to their SDL3 counterparts: +SDL headers should now be included as `#include `. Typically that's the only SDL header you'll need in your application unless you are using OpenGL or Vulkan functionality. SDL_image, SDL_mixer, SDL_net, SDL_ttf and SDL_rtf have also their preferred include path changed: for SDL_image, it becomes `#include `. We have provided a handy Python script [rename_headers.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_headers.py) to rename SDL2 headers to their SDL3 counterparts: ```sh rename_headers.py source_code_path ``` +Some macros are renamed and/or removed in SDL3. We have provided a handy Python script [rename_macros.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_macros.py) to replace these, and also add fixme comments on how to further improve the code: +```sh +rename_macros.py source_code_path +``` + + CMake users should use this snippet to include SDL support in their project: ``` find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) @@ -47,6 +53,13 @@ The vi format comments have been removed from source code. Vim users can use the The following structures have been renamed: - SDL_atomic_t => SDL_AtomicInt +The following functions have been renamed: +* SDL_AtomicCAS() => SDL_AtomicCompareAndSwap() +* SDL_AtomicCASPtr() => SDL_AtomicCompareAndSwapPointer() +* SDL_AtomicLock() => SDL_LockSpinlock() +* SDL_AtomicTryLock() => SDL_TryLockSpinlock() +* SDL_AtomicUnlock() => SDL_UnlockSpinlock() + ## SDL_audio.h The audio subsystem in SDL3 is dramatically different than SDL2. The primary way to play audio is no longer an audio callback; instead you bind SDL_AudioStreams to devices; however, there is still a callback method available if needed. @@ -178,7 +191,7 @@ SDL_FreeWAV has been removed and calls can be replaced with SDL_free. SDL_LoadWAV() is a proper function now and no longer a macro (but offers the same functionality otherwise). -SDL_LoadWAV_RW() and SDL_LoadWAV() return an int now: zero on success, -1 on error, like most of SDL. They no longer return a pointer to an SDL_AudioSpec. +SDL_LoadWAV_IO() and SDL_LoadWAV() return an int now: zero on success, -1 on error, like most of SDL. They no longer return a pointer to an SDL_AudioSpec. SDL_AudioCVT interface has been removed, the SDL_AudioStream interface (for audio supplied in pieces) or the new SDL_ConvertAudioSamples() function (for converting a complete audio buffer in one call) can be used instead. @@ -240,6 +253,7 @@ The following functions have been renamed: * SDL_AudioStreamGet() => SDL_GetAudioStreamData() * SDL_AudioStreamPut() => SDL_PutAudioStreamData() * SDL_FreeAudioStream() => SDL_DestroyAudioStream() +* SDL_LoadWAV_RW() => SDL_LoadWAV_IO() * SDL_NewAudioStream() => SDL_CreateAudioStream() @@ -303,7 +317,7 @@ The timestamp_us member of the sensor events has been renamed sensor_timestamp a You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS(). -Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. +Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed. Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling. @@ -317,10 +331,16 @@ The SDL_EVENT_WINDOW_SIZE_CHANGED event has been removed, and you can use SDL_EV The gamepad event structures caxis, cbutton, cdevice, ctouchpad, and csensor have been renamed gaxis, gbutton, gdevice, gtouchpad, and gsensor. +The mouseX and mouseY fields of SDL_MouseWheelEvent have been renamed mouse_x and mouse_y. + +The touchId and fingerId fields of SDL_TouchFingerEvent have been renamed touchID and fingerID. + SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state. SDL_AddEventWatch() now returns -1 if it fails because it ran out of memory and couldn't add the event watch callback. +SDL_RegisterEvents() now returns 0 if it couldn't allocate any user events. + The following symbols have been renamed: * SDL_APP_DIDENTERBACKGROUND => SDL_EVENT_DID_ENTER_BACKGROUND * SDL_APP_DIDENTERFOREGROUND => SDL_EVENT_DID_ENTER_FOREGROUND @@ -351,6 +371,7 @@ The following symbols have been renamed: * SDL_FINGERUP => SDL_EVENT_FINGER_UP * SDL_FIRSTEVENT => SDL_EVENT_FIRST * SDL_JOYAXISMOTION => SDL_EVENT_JOYSTICK_AXIS_MOTION +* SDL_JOYBALLMOTION => SDL_EVENT_JOYSTICK_BALL_MOTION * SDL_JOYBATTERYUPDATED => SDL_EVENT_JOYSTICK_BATTERY_UPDATED * SDL_JOYBUTTONDOWN => SDL_EVENT_JOYSTICK_BUTTON_DOWN * SDL_JOYBUTTONUP => SDL_EVENT_JOYSTICK_BUTTON_UP @@ -371,12 +392,14 @@ The following symbols have been renamed: * SDL_RENDER_DEVICE_RESET => SDL_EVENT_RENDER_DEVICE_RESET * SDL_RENDER_TARGETS_RESET => SDL_EVENT_RENDER_TARGETS_RESET * SDL_SENSORUPDATE => SDL_EVENT_SENSOR_UPDATE -* SDL_SYSWMEVENT => SDL_EVENT_SYSWM * SDL_TEXTEDITING => SDL_EVENT_TEXT_EDITING * SDL_TEXTEDITING_EXT => SDL_EVENT_TEXT_EDITING_EXT * SDL_TEXTINPUT => SDL_EVENT_TEXT_INPUT * SDL_USEREVENT => SDL_EVENT_USER +The following symbols have been removed: +* SDL_SYSWMEVENT - you can use SDL_SetWindowsMessageHook() and SDL_SetX11EventHook() to watch and modify system events before SDL sees them. + The following structures have been renamed: * SDL_ControllerAxisEvent => SDL_GamepadAxisEvent * SDL_ControllerButtonEvent => SDL_GamepadButtonEvent @@ -491,6 +514,8 @@ SDL_bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 product_i } ``` +The inputType and outputType fields of SDL_GamepadBinding have been renamed input_type and output_type. + The following enums have been renamed: * SDL_GameControllerAxis => SDL_GamepadAxis * SDL_GameControllerBindType => SDL_GamepadBindingType @@ -503,7 +528,7 @@ The following structures have been renamed: The following functions have been renamed: * SDL_GameControllerAddMapping() => SDL_AddGamepadMapping() * SDL_GameControllerAddMappingsFromFile() => SDL_AddGamepadMappingsFromFile() -* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromRW() +* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromIO() * SDL_GameControllerClose() => SDL_CloseGamepad() * SDL_GameControllerFromInstanceID() => SDL_GetGamepadFromInstanceID() * SDL_GameControllerFromPlayerIndex() => SDL_GetGamepadFromPlayerIndex() @@ -532,9 +557,6 @@ The following functions have been renamed: * SDL_GameControllerGetVendor() => SDL_GetGamepadVendor() * SDL_GameControllerHasAxis() => SDL_GamepadHasAxis() * SDL_GameControllerHasButton() => SDL_GamepadHasButton() -* SDL_GameControllerHasLED() => SDL_GamepadHasLED() -* SDL_GameControllerHasRumble() => SDL_GamepadHasRumble() -* SDL_GameControllerHasRumbleTriggers() => SDL_GamepadHasRumbleTriggers() * SDL_GameControllerHasSensor() => SDL_GamepadHasSensor() * SDL_GameControllerIsSensorEnabled() => SDL_GamepadSensorEnabled() * SDL_GameControllerMapping() => SDL_GetGamepadMapping() @@ -555,12 +577,15 @@ The following functions have been removed: * SDL_GameControllerEventState() - replaced with SDL_SetGamepadEventsEnabled() and SDL_GamepadEventsEnabled() * SDL_GameControllerGetBindForAxis() - replaced with SDL_GetGamepadBindings() * SDL_GameControllerGetBindForButton() - replaced with SDL_GetGamepadBindings() +* SDL_GameControllerHasLED() - replaced with SDL_PROP_GAMEPAD_CAP_RGB_LED_BOOLEAN +* SDL_GameControllerHasRumble() - replaced with SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN +* SDL_GameControllerHasRumbleTriggers() - replaced with SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN * SDL_GameControllerMappingForDeviceIndex() - replaced with SDL_GetGamepadInstanceMapping() +* SDL_GameControllerMappingForIndex() - replaced with SDL_GetGamepadMappings() * SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadInstanceName() +* SDL_GameControllerNumMappings() - replaced with SDL_GetGamepadMappings() * SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadInstancePath() * SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadInstanceType() -* SDL_GameControllerNumMappings() - replaced with SDL_GetGamepadMappings() -* SDL_GameControllerMappingForIndex() - replaced with SDL_GetGamepadMappings() The following symbols have been renamed: * SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID @@ -618,6 +643,65 @@ be dropped into an SDL3 or SDL2 program, to continue to provide this functionality to your app and aid migration. That is located in the [SDL_gesture GitHub repository](https://github.com/libsdl-org/SDL_gesture). +## SDL_haptic.h + +Gamepads with simple rumble capability no longer show up in the SDL haptics interface, instead you should use SDL_RumbleGamepad(). + +Rather than iterating over haptic devices using device index, there is a new function SDL_GetHaptics() to get the current list of haptic devices, and new functions to get information about haptic devices from their instance ID: +```c +{ + if (SDL_InitSubSystem(SDL_INIT_HAPTIC) == 0) { + int i, num_haptics; + SDL_HapticID *haptics = SDL_GetHaptics(&num_haptics); + if (haptics) { + for (i = 0; i < num_haptics; ++i) { + SDL_HapticID instance_id = haptics[i]; + const char *name = SDL_GetHapticInstanceName(instance_id); + + SDL_Log("Haptic %" SDL_PRIu32 ": %s\n", + instance_id, name ? name : "Unknown"); + } + SDL_free(haptics); + } + SDL_QuitSubSystem(SDL_INIT_HAPTIC); + } +} +``` + +SDL_HapticEffectSupported(), SDL_HapticRumbleSupported(), and SDL_IsJoystickHaptic() now return SDL_bool instead of an optional negative error code. + +The following functions have been renamed: +* SDL_HapticClose() => SDL_CloseHaptic() +* SDL_HapticDestroyEffect() => SDL_DestroyHapticEffect() +* SDL_HapticGetEffectStatus() => SDL_GetHapticEffectStatus() +* SDL_HapticNewEffect() => SDL_CreateHapticEffect() +* SDL_HapticNumAxes() => SDL_GetNumHapticAxes() +* SDL_HapticNumEffects() => SDL_GetMaxHapticEffects() +* SDL_HapticNumEffectsPlaying() => SDL_GetMaxHapticEffectsPlaying() +* SDL_HapticOpen() => SDL_OpenHaptic() +* SDL_HapticOpenFromJoystick() => SDL_OpenHapticFromJoystick() +* SDL_HapticOpenFromMouse() => SDL_OpenHapticFromMouse() +* SDL_HapticPause() => SDL_PauseHaptic() +* SDL_HapticQuery() => SDL_GetHapticFeatures() +* SDL_HapticRumbleInit() => SDL_InitHapticRumble() +* SDL_HapticRumblePlay() => SDL_PlayHapticRumble() +* SDL_HapticRumbleStop() => SDL_StopHapticRumble() +* SDL_HapticRunEffect() => SDL_RunHapticEffect() +* SDL_HapticSetAutocenter() => SDL_SetHapticAutocenter() +* SDL_HapticSetGain() => SDL_SetHapticGain() +* SDL_HapticStopAll() => SDL_StopHapticEffects() +* SDL_HapticStopEffect() => SDL_StopHapticEffect() +* SDL_HapticUnpause() => SDL_ResumeHaptic() +* SDL_HapticUpdateEffect() => SDL_UpdateHapticEffect() +* SDL_JoystickIsHaptic() => SDL_IsJoystickHaptic() +* SDL_MouseIsHaptic() => SDL_IsMouseHaptic() + +The following functions have been removed: +* SDL_HapticIndex() - replaced with SDL_GetHapticInstanceID() +* SDL_HapticName() - replaced with SDL_GetHapticInstanceName() +* SDL_HapticOpened() - replaced with SDL_GetHapticFromInstanceID() +* SDL_NumHaptics() - replaced with SDL_GetHaptics() + ## SDL_hints.h SDL_AddHintCallback() now returns a standard int result instead of void, returning 0 if the function succeeds or a negative error code if there was an error. @@ -625,24 +709,47 @@ SDL_AddHintCallback() now returns a standard int result instead of void, returni Calling SDL_GetHint() with the name of the hint being changed from within a hint callback will now return the new value rather than the old value. The old value is still passed as a parameter to the hint callback. The following hints have been removed: +* SDL_HINT_ACCELEROMETER_AS_JOYSTICK * SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional -* SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver instead +* SDL_HINT_GRAB_KEYBOARD - use SDL_SetWindowKeyboardGrab() instead +* SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver() instead * SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer -* SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() * SDL_HINT_RENDER_BATCHING - Render batching is always enabled, apps should call SDL_FlushRenderer() before calling into a lower-level graphics API. -* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with the "opengl" property in SDL_CreateWindowWithProperties() -* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with the "vulkan" property in SDL_CreateWindowWithProperties() +* SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation() +* SDL_HINT_RENDER_OPENGL_SHADERS - shaders are always used if they are available +* SDL_HINT_RENDER_SCALE_QUALITY - textures now default to linear filtering, use SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST) if you want nearest pixel mode instead +* SDL_HINT_VIDEO_EXTERNAL_CONTEXT - replaced with SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN in SDL_CreateWindowWithProperties() +* SDL_HINT_THREAD_STACK_SIZE - the stack size can be specified using SDL_CreateThreadWithStackSize() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with SDL_PROP_WINDOW_CREATE_VULKAN_BOOLEAN in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled -* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with the "win32.pixel_format_hwnd" in SDL_CreateWindowWithProperties() +* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER in SDL_CreateWindowWithProperties() * SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead * SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend * SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend +* SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING - SDL now properly handles the 0x406D1388 Exception if no debugger intercepts it, preventing its propagation. +* SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 - replaced with SDL_HINT_WINDOWS_CLOSE_ON_ALT_F4, defaulting to SDL_TRUE +* SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING * Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER * Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER * The environment variables SDL_VIDEO_X11_WMCLASS and SDL_VIDEO_WAYLAND_WMCLASS have been removed and replaced with the unified hint SDL_HINT_APP_ID +The following hints have been renamed: +* SDL_HINT_ALLOW_TOPMOST => SDL_HINT_WINDOW_ALLOW_TOPMOST +* SDL_HINT_DIRECTINPUT_ENABLED => SDL_HINT_JOYSTICK_DIRECTINPUT +* SDL_HINT_GDK_TEXTINPUT_DEFAULT => SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT +* SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE => SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE +* SDL_HINT_LINUX_DIGITAL_HATS => SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS +* SDL_HINT_LINUX_HAT_DEADZONES => SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES +* SDL_HINT_LINUX_JOYSTICK_CLASSIC => SDL_HINT_JOYSTICK_LINUX_CLASSIC +* SDL_HINT_LINUX_JOYSTICK_DEADZONES => SDL_HINT_JOYSTICK_LINUX_DEADZONES +* SDL_HINT_PS2_DYNAMIC_VSYNC => SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC + +The following functions have been removed: +* SDL_ClearHints() - replaced with SDL_ResetHints() + ## SDL_init.h The following symbols have been renamed: @@ -650,6 +757,7 @@ The following symbols have been renamed: The following symbols have been removed: * SDL_INIT_NOPARACHUTE +* SDL_INIT_EVERYTHING - you should only initialize the subsystems you are using ## SDL_joystick.h @@ -694,6 +802,7 @@ The following functions have been renamed: * SDL_JoystickGetAttached() => SDL_JoystickConnected() * SDL_JoystickGetAxis() => SDL_GetJoystickAxis() * SDL_JoystickGetAxisInitialState() => SDL_GetJoystickAxisInitialState() +* SDL_JoystickGetBall() => SDL_GetJoystickBall() * SDL_JoystickGetButton() => SDL_GetJoystickButton() * SDL_JoystickGetFirmwareVersion() => SDL_GetJoystickFirmwareVersion() * SDL_JoystickGetGUID() => SDL_GetJoystickGUID() @@ -710,6 +819,7 @@ The following functions have been renamed: * SDL_JoystickIsVirtual() => SDL_IsJoystickVirtual() * SDL_JoystickName() => SDL_GetJoystickName() * SDL_JoystickNumAxes() => SDL_GetNumJoystickAxes() +* SDL_JoystickNumBalls() => SDL_GetNumJoystickBalls() * SDL_JoystickNumButtons() => SDL_GetNumJoystickButtons() * SDL_JoystickNumHats() => SDL_GetNumJoystickHats() * SDL_JoystickOpen() => SDL_OpenJoystick() @@ -736,8 +846,10 @@ The following functions have been removed: * SDL_JoystickGetDeviceProductVersion() - replaced with SDL_GetJoystickInstanceProductVersion() * SDL_JoystickGetDeviceType() - replaced with SDL_GetJoystickInstanceType() * SDL_JoystickGetDeviceVendor() - replaced with SDL_GetJoystickInstanceVendor() +* SDL_JoystickHasLED() - replaced with SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN +* SDL_JoystickHasRumble() - replaced with SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN +* SDL_JoystickHasRumbleTriggers() - replaced with SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN * SDL_JoystickNameForIndex() - replaced with SDL_GetJoystickInstanceName() -* SDL_JoystickNumBalls() - API has been removed, see https://github.com/libsdl-org/SDL/issues/6766 * SDL_JoystickPathForIndex() - replaced with SDL_GetJoystickInstancePath() * SDL_NumJoysticks() - replaced with SDL_GetJoysticks() @@ -746,13 +858,19 @@ The following symbols have been removed: ## SDL_keyboard.h +Text input is no longer automatically enabled when initializing video, you should call SDL_StartTextInput() when you want to receive text input and call SDL_StopTextInput() when you are done. Starting text input may shown an input method editor (IME) and cause key up/down events to be skipped, so should only be enabled when the application wants text input. + The following functions have been renamed: * SDL_IsScreenKeyboardShown() => SDL_ScreenKeyboardShown() * SDL_IsTextInputActive() => SDL_TextInputActive() -* SDL_IsTextInputShown() => SDL_TextInputShown() + +The following functions have been removed: +* SDL_IsTextInputShown() ## SDL_keycode.h +SDL_Keycode is now an enum instead of Sint32. + The following symbols have been renamed: * KMOD_ALT => SDL_KMOD_ALT * KMOD_CAPS => SDL_KMOD_CAPS @@ -777,13 +895,31 @@ The following symbols have been renamed: SDL_LoadFunction() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior. +## SDL_log.h + +The following functions have been renamed: +* SDL_LogGetOutputFunction() => SDL_GetLogOutputFunction() +* SDL_LogSetOutputFunction() => SDL_SetLogOutputFunction() + ## SDL_main.h SDL3 doesn't have a static libSDLmain to link against anymore. Instead SDL_main.h is now a header-only library **and not included by SDL.h anymore**. Using it is really simple: Just `#include ` in the source file with your standard -`int main(int argc, char* argv[])` function. +`int main(int argc, char* argv[])` function. See docs/README-main-functions.md for details. + +Several platform-specific entry point functions have been removed as unnecessary. If for some reason you explicitly need them, here are easy replacements: + +```c +#define SDL_WinRTRunApp(MAIN_FUNC, RESERVED) SDL_RunApp(0, NULL, MAIN_FUNC, RESERVED) +#define SDL_UIKitRunApp(ARGC, ARGV, MAIN_FUNC) SDL_RunApp(ARGC, ARGV, MAIN_FUNC, NULL) +#define SDL_GDKRunApp(MAIN_FUNC, RESERVED) SDL_RunApp(0, NULL, MAIN_FUNC, RESERVED) +``` + +## SDL_messagebox.h + +The buttonid field of SDL_MessageBoxButtonData has been renamed buttonID. ## SDL_metal.h @@ -826,6 +962,10 @@ The following symbols have been renamed: SDL_CalculateGammaRamp has been removed, because SDL_SetWindowGammaRamp has been removed as well due to poor support in modern operating systems (see [SDL_video.h](#sdl_videoh)). +The BitsPerPixel and BytesPerPixel fields of SDL_PixelFormat have been renamed bits_per_pixel and bytes_per_pixel. + +SDL_PixelFormatEnum is used instead of Uint32 for API functions that refer to pixel format by enumerated value. + The following functions have been renamed: * SDL_AllocFormat() => SDL_CreatePixelFormat() * SDL_AllocPalette() => SDL_CreatePalette() @@ -860,7 +1000,53 @@ The following symbols have been renamed: ## SDL_platform.h -The preprocessor symbol `__MACOSX__` has been renamed `__MACOS__`, and `__IPHONEOS__` has been renamed `__IOS__` +The following platform preprocessor macros have been renamed: + +| SDL2 | SDL3 | +|-------------------|---------------------------| +| `__3DS__` | `SDL_PLATFORM_3DS` | +| `__AIX__` | `SDL_PLATFORM_AIX` | +| `__ANDROID__` | `SDL_PLATFORM_ANDROID` | +| `__APPLE__` | `SDL_PLATFORM_APPLE` | +| `__BSDI__` | `SDL_PLATFORM_BSDI` | +| `__CYGWIN_` | `SDL_PLATFORM_CYGWIN` | +| `__EMSCRIPTEN__` | `SDL_PLATFORM_EMSCRIPTEN` | +| `__FREEBSD__` | `SDL_PLATFORM_FREEBSD` | +| `__GDK__` | `SDL_PLATFORM_GDK` | +| `__HAIKU__` | `SDL_PLATFORM_HAIKU` | +| `__HPUX__` | `SDL_PLATFORM_HPUX` | +| `__IPHONEOS__` | `SDL_PLATFORM_IOS` | +| `__IRIX__` | `SDL_PLATFORM_IRIX` | +| `__LINUX__` | `SDL_PLATFORM_LINUX` | +| `__MACOSX__` | `SDL_PLATFORM_MACOS` | +| `__NETBSD__` | `SDL_PLATFORM_NETBSD` | +| `__NGAGE__` | `SDL_PLATFORM_NGAGE` | +| `__OPENBSD__` | `SDL_PLATFORM_OPENBSD` | +| `__OS2__` | `SDL_PLATFORM_OS2` | +| `__OSF__` | `SDL_PLATFORM_OSF` | +| `__PS2__` | `SDL_PLATFORM_PS2` | +| `__PSP__` | `SDL_PLATFORM_PSP` | +| `__QNXNTO__` | `SDL_PLATFORM_QNXNTO` | +| `__RISCOS__` | `SDL_PLATFORM_RISCOS` | +| `__SOLARIS__` | `SDL_PLATFORM_SOLARIS` | +| `__TVOS__` | `SDL_PLATFORM_TVOS` | +| `__unix__` | `SDL_PLATFORM_UNI` | +| `__VITA__` | `SDL_PLATFORM_VITA` | +| `__WIN32__` | `SDL_PLATFORM_WIN32` | +| `__WINGDK__` | `SDL_PLATFORM_WINGDK` | +| `__WINRT__` | `SDL_PLATFORM_WINRT` | +| `__XBOXONE__` | `SDL_PLATFORM_XBOXONE` | +| `__XBOXSERIES__` | `SDL_PLATFORM_XBOXSERIES` | + +You can use the Python script [rename_macros.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_macros.py) to automatically rename these in your source code. + +A new macro `SDL_PLATFORM_WINDOWS` has been added that is true for all Windows platforms, including Xbox, GDK, etc. + +The following platform preprocessor macros have been removed: +* `__DREAMCAST__` +* `__NACL__` +* `__PNACL__` +* `__WINDOWS__` ## SDL_rect.h @@ -904,13 +1090,6 @@ to decide for you. The SDL_RENDERER_TARGETTEXTURE flag has been removed, all current renderers support target texture functionality. -When a renderer is created, it will automatically set the logical size to the size of -the window in points. For high DPI displays, this will set up scaling from points to -pixels. You can disable this scaling with: -```c - SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST); -``` - Mouse and touch events are no longer filtered to change their coordinates, instead you can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into the rendering viewport. @@ -919,6 +1098,10 @@ SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SD The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active. +SDL_Vertex has been changed to use floating point colors, in the range of [0..1] for SDR content. + +SDL_RenderReadPixels() returns a surface instead of filling in preallocated memory. + The following functions have been renamed: * SDL_GetRendererOutputSize() => SDL_GetCurrentRenderOutputSize() * SDL_RenderCopy() => SDL_RenderTexture() @@ -951,7 +1134,6 @@ The following functions have been renamed: * SDL_RenderIsClipEnabled() => SDL_RenderClipEnabled() * SDL_RenderLogicalToWindow() => SDL_RenderCoordinatesToWindow() * SDL_RenderSetClipRect() => SDL_SetRenderClipRect() -* SDL_RenderSetIntegerScale() => SDL_SetRenderIntegerScale() * SDL_RenderSetLogicalSize() => SDL_SetRenderLogicalPresentation() * SDL_RenderSetScale() => SDL_SetRenderScale() * SDL_RenderSetVSync() => SDL_SetRenderVSync() @@ -968,6 +1150,7 @@ The following functions have been removed: * SDL_SetTextureUserData() - use SDL_GetTextureProperties() instead The following symbols have been renamed: +* SDL_RendererFlip => SDL_FlipMode * SDL_ScaleModeBest => SDL_SCALEMODE_BEST * SDL_ScaleModeLinear => SDL_SCALEMODE_LINEAR * SDL_ScaleModeNearest => SDL_SCALEMODE_NEAREST @@ -975,11 +1158,19 @@ The following symbols have been renamed: ## SDL_rwops.h The following symbols have been renamed: -* RW_SEEK_CUR => SDL_RW_SEEK_CUR -* RW_SEEK_END => SDL_RW_SEEK_END -* RW_SEEK_SET => SDL_RW_SEEK_SET +* RW_SEEK_CUR => SDL_IO_SEEK_CUR +* RW_SEEK_END => SDL_IO_SEEK_END +* RW_SEEK_SET => SDL_IO_SEEK_SET -SDL_RWread and SDL_RWwrite (and SDL_RWops::read, SDL_RWops::write) have a different function signature in SDL3. +SDL_rwops.h is now named SDL_iostream.h + +SDL_RWops is now an opaque structure, and has been renamed to SDL_IOStream. The SDL3 APIs to create an SDL_IOStream (SDL_IOFromFile, etc) are renamed but otherwise still function as they did in SDL2. However, to make a custom SDL_IOStream with app-provided function pointers, call SDL_OpenIO and provide the function pointers through there. To call into an SDL_IOStream's functionality, use the standard APIs (SDL_ReadIO, etc), as the function pointers are internal. + +SDL_IOStream is not to be confused with the unrelated standard C++ iostream class! + +The RWops function pointers are now in a separate structure called SDL_IOStreamInterface, which is provided to SDL_OpenIO when creating a custom SDL_IOStream implementation. All the functions now take a `void *` userdata argument for their first parameter instead of an SDL_IOStream, since that's now an opaque structure. + +SDL_RWread and SDL_RWwrite (and the read and write function pointers) have a different function signature in SDL3, in addition to being renamed. Previously they looked more like stdio: @@ -991,55 +1182,67 @@ size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxn But now they look more like POSIX: ```c -size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size); -size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size); +size_t SDL_ReadIO(void *userdata, void *ptr, size_t size); +size_t SDL_WriteIO(void *userdata, const void *ptr, size_t size); ``` Code that used to look like this: -``` +```c size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream) { return SDL_RWread(stream, ptr, size, nitems); } ``` should be changed to: -``` -size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream) +```c +size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_IOStream *stream) { if (size > 0 && nitems > 0) { - return SDL_RWread(stream, ptr, size * nitems) / size; + return SDL_ReadIO(stream, ptr, size * nitems) / size; } return 0; } ``` +SDL_RWops::type was removed; it wasn't meaningful for app-provided implementations at all, and wasn't much use for SDL's internal implementations, either. If you _have_ to identify the type, you can examine the SDL_IOStream's properties to detect built-in implementations. + +SDL_IOStreamInterface::close implementations should clean up their own userdata, but not call SDL_CloseIO on themselves; now the contract is always that SDL_CloseIO is called, which calls `->close` before freeing the opaque object. + +SDL_AllocRW(), SDL_FreeRW(), SDL_RWclose() and direct access to the `->close` function pointer have been removed from the API, so there's only one path to manage RWops lifetimes now: SDL_OpenIO() and SDL_CloseIO(). + SDL_RWFromFP has been removed from the API, due to issues when the SDL library uses a different C runtime from the application. You can implement this in your own code easily: ```c #include - -static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence) +typedef struct IOStreamStdioFPData { + FILE *fp; + SDL_bool autoclose; +} IOStreamStdioFPData; + +static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence) +{ + FILE *fp = ((IOStreamStdioFPData *) userdata)->fp; int stdiowhence; switch (whence) { - case SDL_RW_SEEK_SET: + case SDL_IO_SEEK_SET: stdiowhence = SEEK_SET; break; - case SDL_RW_SEEK_CUR: + case SDL_IO_SEEK_CUR: stdiowhence = SEEK_CUR; break; - case SDL_RW_SEEK_END: + case SDL_IO_SEEK_END: stdiowhence = SEEK_END; break; default: return SDL_SetError("Unknown value for 'whence'"); } - if (fseek((FILE *)context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) { - Sint64 pos = ftell((FILE *)context->hidden.stdio.fp); + if (fseek(fp, (fseek_off_t)offset, stdiowhence) == 0) { + const Sint64 pos = ftell(fp); if (pos < 0) { return SDL_SetError("Couldn't get stream offset"); } @@ -1048,63 +1251,82 @@ static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence) return SDL_Error(SDL_EFSEEK); } -static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size) +static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) { - size_t bytes; - - bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp); - if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { + FILE *fp = ((IOStreamStdioFPData *) userdata)->fp; + const size_t bytes = fread(ptr, 1, size, fp); + if (bytes == 0 && ferror(fp)) { SDL_Error(SDL_EFREAD); } return bytes; } -static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size) +static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) { - size_t bytes; - - bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp); - if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { + FILE *fp = ((IOStreamStdioFPData *) userdata)->fp; + const size_t bytes = fwrite(ptr, 1, size, fp); + if (bytes == 0 && ferror(fp)) { SDL_Error(SDL_EFWRITE); } return bytes; } -static int SDLCALL stdio_close(SDL_RWops *context) +static int SDLCALL stdio_close(void *userdata) { + IOStreamStdioData *rwopsdata = (IOStreamStdioData *) userdata; int status = 0; - if (context->hidden.stdio.autoclose) { - if (fclose((FILE *)context->hidden.stdio.fp) != 0) { + if (rwopsdata->autoclose) { + if (fclose(rwopsdata->fp) != 0) { status = SDL_Error(SDL_EFWRITE); } } - SDL_DestroyRW(context); return status; } -SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose) +SDL_IOStream *SDL_RWFromFP(FILE *fp, SDL_bool autoclose) { - SDL_RWops *rwops = NULL; + SDL_IOStreamInterface iface; + IOStreamStdioFPData *rwopsdata; + SDL_IOStream *rwops; - rwops = SDL_CreateRW(); - if (rwops != NULL) { - rwops->seek = stdio_seek; - rwops->read = stdio_read; - rwops->write = stdio_write; - rwops->close = stdio_close; - rwops->hidden.stdio.fp = fp; - rwops->hidden.stdio.autoclose = autoclose; - rwops->type = SDL_RWOPS_STDFILE; + rwopsdata = (IOStreamStdioFPData *) SDL_malloc(sizeof (*rwopsdata)); + if (!rwopsdata) { + return NULL; + } + + SDL_zero(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.close = stdio_close; + + rwopsdata->fp = fp; + rwopsdata->autoclose = autoclose; + + rwops = SDL_OpenIO(&iface, rwopsdata); + if (!rwops) { + iface.close(rwopsdata); } return rwops; } ``` +The internal `FILE *` is available through a standard SDL_IOStream property, for streams made through SDL_IOFromFile() that use stdio behind the scenes; apps use this pointer at their own risk and should make sure that SDL and the app are using the same C runtime. + + The functions SDL_ReadU8(), SDL_ReadU16LE(), SDL_ReadU16BE(), SDL_ReadU32LE(), SDL_ReadU32BE(), SDL_ReadU64LE(), and SDL_ReadU64BE() now return SDL_TRUE if the read succeeded and SDL_FALSE if it didn't, and store the data in a pointer passed in as a parameter. The following functions have been renamed: -* SDL_AllocRW() => SDL_CreateRW() -* SDL_FreeRW() => SDL_DestroyRW() +* SDL_RWFromConstMem() => SDL_IOFromConstMem() +* SDL_RWFromFile() => SDL_IOFromFile() +* SDL_RWFromMem() => SDL_IOFromMem() +* SDL_RWclose() => SDL_CloseIO() +* SDL_RWread() => SDL_ReadIO() +* SDL_RWseek() => SDL_SeekIO() +* SDL_RWsize() => SDL_GetIOSize() +* SDL_RWtell() => SDL_TellIO() +* SDL_RWwrite() => SDL_WriteIO() * SDL_ReadBE16() => SDL_ReadU16BE() * SDL_ReadBE32() => SDL_ReadU32BE() * SDL_ReadBE64() => SDL_ReadU64BE() @@ -1118,6 +1340,10 @@ The following functions have been renamed: * SDL_WriteLE32() => SDL_WriteU32LE() * SDL_WriteLE64() => SDL_WriteU64LE() + +The following structures have been renamed: +* SDL_RWops => SDL_IOStream + ## SDL_sensor.h SDL_SensorID has changed from Sint32 to Uint32, with an invalid ID being 0. @@ -1168,7 +1394,7 @@ The following functions have been removed: ## SDL_shape.h -This header has been removed. You can create a window with the SDL_WINDOW_TRANSPARENT flag and then render using the alpha channel to achieve a similar effect. You can see an example of this in test/testshape.c +This header has been removed and a simplified version of this API has been added as SDL_SetWindowShape() in SDL_video.h. See test/testshape.c for an example. ## SDL_stdinc.h @@ -1179,6 +1405,9 @@ M_PI is no longer defined in SDL_stdinc.h, you can use the new symbols SDL_PI_D The following functions have been renamed: * SDL_strtokr() => SDL_strtok_r() +The following functions have been removed: +* SDL_memcpy4() + ## SDL_surface.h The userdata member of SDL_Surface has been replaced with a more general properties interface, which can be queried with SDL_GetSurfaceProperties() @@ -1228,6 +1457,8 @@ SDL_BlitSurfaceScaled() and SDL_BlitSurfaceUncheckedScaled() now take a scale pa SDL_SoftStretch() now takes a scale paramater. +SDL_PixelFormatEnum is used instead of Uint32 for API functions that refer to pixel format by enumerated value. + The following functions have been renamed: * SDL_FillRect() => SDL_FillSurfaceRect() * SDL_FillRects() => SDL_FillSurfaceRects() @@ -1236,14 +1467,19 @@ The following functions have been renamed: * SDL_GetColorKey() => SDL_GetSurfaceColorKey() * SDL_HasColorKey() => SDL_SurfaceHasColorKey() * SDL_HasSurfaceRLE() => SDL_SurfaceHasRLE() +* SDL_LoadBMP_RW() => SDL_LoadBMP_IO() * SDL_LowerBlit() => SDL_BlitSurfaceUnchecked() * SDL_LowerBlitScaled() => SDL_BlitSurfaceUncheckedScaled() +* SDL_SaveBMP_RW() => SDL_SaveBMP_IO() * SDL_SetClipRect() => SDL_SetSurfaceClipRect() * SDL_SetColorKey() => SDL_SetSurfaceColorKey() * SDL_UpperBlit() => SDL_BlitSurface() * SDL_UpperBlitScaled() => SDL_BlitSurfaceScaled() The following functions have been removed: +* SDL_GetYUVConversionMode() +* SDL_GetYUVConversionModeForResolution() +* SDL_SetYUVConversionMode() - use SDL_SetSurfaceColorspace() to set the surface colorspace and SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER with SDL_CreateTextureWithProperties() to set the texture colorspace. The default colorspace for YUV pixel formats is SDL_COLORSPACE_JPEG. * SDL_SoftStretchLinear() - use SDL_SoftStretch() with SDL_SCALEMODE_LINEAR ## SDL_system.h @@ -1252,6 +1488,8 @@ SDL_WindowsMessageHook has changed signatures so the message may be modified and SDL_AndroidGetExternalStorageState() takes the state as an output parameter and returns 0 if the function succeeds or a negative error code if there was an error. +SDL_AndroidRequestPermission is no longer a blocking call; the caller now provides a callback function that fires when a response is available. + The following functions have been removed: * SDL_RenderGetD3D11Device() - replaced with the "SDL.renderer.d3d11.device" property * SDL_RenderGetD3D12Device() - replaced with the "SDL.renderer.d3d12.device" property @@ -1284,7 +1522,7 @@ The information previously available in SDL_GetWindowWMInfo() is now available a if (nswindow) { ... } -#elif defined(__LINUX__) +#elif defined(SDL_PLATFORM_LINUX) if (SDL_GetWindowWMInfo(window, &info)) { if (info.subsystem == SDL_SYSWM_X11) { Display *xdisplay = info.info.x11.display; @@ -1304,26 +1542,26 @@ The information previously available in SDL_GetWindowWMInfo() is now available a ``` becomes: ```c -#if defined(__WIN32__) - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); +#if defined(SDL_PLATFORM_WIN32) + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); if (hwnd) { ... } -#elif defined(__MACOS__) - NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER, NULL); +#elif defined(SDL_PLATFORM_MACOS) + NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL); if (nswindow) { ... } -#elif defined(__LINUX__) +#elif defined(SDL_PLATFORM_LINUX) if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { - Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, NULL); - Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, 0); + Display *xdisplay = (Display *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); + Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); if (xdisplay && xwindow) { ... } } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { - struct wl_display *display = (struct wl_display *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER, NULL); - struct wl_surface *surface = (struct wl_surface *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER, NULL); + struct wl_display *display = (struct wl_display *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, NULL); + struct wl_surface *surface = (struct wl_surface *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL); if (display && surface) { ... } @@ -1338,6 +1576,10 @@ The following functions have been renamed: * SDL_TLSCreate() => SDL_CreateTLS() * SDL_TLSGet() => SDL_GetTLS() * SDL_TLSSet() => SDL_SetTLS() +* SDL_ThreadID() => SDL_GetCurrentThreadID() + +The following symbols have been renamed: +* SDL_threadID => SDL_ThreadID ## SDL_timer.h @@ -1369,6 +1611,8 @@ SDL_GetNumTouchFingers() returns a negative error code if there was an error. SDL_GetTouchName is replaced with SDL_GetTouchDeviceName(), which takes an SDL_TouchID instead of an index. +SDL_TouchID and SDL_FingerID are now Uint64 with 0 being an invalid value. + The following functions have been removed: * SDL_GetNumTouchDevices() - replaced with SDL_GetTouchDevices() * SDL_GetTouchDevice() - replaced with SDL_GetTouchDevices() @@ -1379,8 +1623,13 @@ The following functions have been removed: SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0. +The following structures have been renamed: +* SDL_version => SDL_Version + ## SDL_video.h +Several video backends have had their names lower-cased ("kmsdrm", "rpi", "android", "psp", "ps2", "vita"). SDL already does a case-insensitive compare for SDL_HINT_VIDEO_DRIVER tests, but if your app is calling SDL_GetVideoDriver() or SDL_GetCurrentVideoDriver() and doing case-sensitive compares on those strings, please update your code. + SDL_VideoInit() and SDL_VideoQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_VIDEO, which will properly refcount the subsystems. You can choose a specific video driver using SDL_VIDEO_DRIVER hint. Rather than iterating over displays using display index, there is a new function SDL_GetDisplays() to get the current list of displays, and functions which used to take a display index now take SDL_DisplayID, with an invalid ID being 0. @@ -1406,11 +1655,11 @@ Rather than iterating over displays using display index, there is a new function SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it, e.g. ```c SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetStringProperty(props, SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING, title); - SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_X_NUMBER, x); - SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER, y); - SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, width); - SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, height); + SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height); SDL_SetNumberProperty(props, "flags", flags); pWindow = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); @@ -1450,7 +1699,7 @@ SDL_GetDesktopDisplayMode() and SDL_GetCurrentDisplayMode() return pointers to d Windows now have an explicit fullscreen mode that is set, using SDL_SetWindowFullscreenMode(). The fullscreen mode for a window can be queried with SDL_GetWindowFullscreenMode(), which returns a pointer to the mode, or NULL if the window will be fullscreen desktop. SDL_SetWindowFullscreen() just takes a boolean value, setting the correct fullscreen state based on the selected mode. -SDL_WINDOW_FULLSCREEN_DESKTOP has been removed, and you can call SDL_GetWindowFullscreenMode() to see whether an exclusive fullscreen mode will be used or the fullscreen desktop mode will be used when the window is fullscreen. +SDL_WINDOW_FULLSCREEN_DESKTOP has been removed, and you can call SDL_GetWindowFullscreenMode() to see whether an exclusive fullscreen mode will be used or the borderless fullscreen desktop mode will be used when the window is fullscreen. SDL_SetWindowBrightness and SDL_SetWindowGammaRamp have been removed from the API, because they interact poorly with modern operating systems and aren't able to limit their effects to the SDL window. @@ -1466,8 +1715,13 @@ SDL_GL_GetSwapInterval() takes the interval as an output parameter and returns 0 SDL_GL_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place. +SDL_SetWindowGrab() and SDL_GetWindowGrab() have been removed. Use SDL_SetWindowMouseGrab()/SDL_GetWindowMouseGrab() or SDL_SetWindowKeyboardGrab()/SDL_GetWindowKeyboardGrab() for grabbing mouse and/or keyboard input respectively. + The SDL_WINDOW_TOOLTIP and SDL_WINDOW_POPUP_MENU window flags are now supported on Windows, Mac (Cocoa), X11, and Wayland. Creating windows with these flags must happen via the `SDL_CreatePopupWindow()` function. This function requires passing in the handle to a valid parent window for the popup, and the popup window is positioned relative to the parent. + +SDL_WindowFlags is used instead of Uint32 for API functions that refer to window flags. + The following functions have been renamed: * SDL_GetClosestDisplayMode() => SDL_GetClosestFullscreenDisplayMode() * SDL_GetDisplayOrientation() => SDL_GetCurrentDisplayOrientation() @@ -1475,12 +1729,13 @@ The following functions have been renamed: * SDL_GetRectDisplayIndex() => SDL_GetDisplayForRect() * SDL_GetWindowDisplayIndex() => SDL_GetDisplayForWindow() * SDL_GetWindowDisplayMode() => SDL_GetWindowFullscreenMode() +* SDL_HasWindowSurface() => SDL_WindowHasSurface() * SDL_IsScreenSaverEnabled() => SDL_ScreenSaverEnabled() * SDL_SetWindowDisplayMode() => SDL_SetWindowFullscreenMode() The following functions have been removed: * SDL_GetClosestFullscreenDisplayMode() -* SDL_GetDisplayDPI() - not reliable across platforms, approximately replaced by multiplying `display_scale` in the structure returned by SDL_GetDesktopDisplayMode() times 160 on iPhone and Android, and 96 on other platforms. +* SDL_GetDisplayDPI() - not reliable across platforms, approximately replaced by multiplying SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms. * SDL_GetDisplayMode() * SDL_GetNumDisplayModes() - replaced with SDL_GetFullscreenDisplayModes() * SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays() @@ -1489,7 +1744,6 @@ The following functions have been removed: * SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with the properties that allow you to wrap an existing window The SDL_Window id type is named SDL_WindowID -The SDL_WindowFlags enum should be replaced with Uint32 The following symbols have been renamed: * SDL_WINDOW_ALLOW_HIGHDPI => SDL_WINDOW_HIGH_PIXEL_DENSITY diff --git a/docs/README-ps2.md b/docs/README-ps2.md index ade0b6d8..cc9d245a 100644 --- a/docs/README-ps2.md +++ b/docs/README-ps2.md @@ -17,7 +17,7 @@ cmake --install build ``` ## Hints -The PS2 port has a special Hint for having a dynamic VSYNC. The Hint is `SDL_HINT_PS2_DYNAMIC_VSYNC`. +The PS2 port has a special Hint for having a dynamic VSYNC. The Hint is `SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC`. If you enabled the dynamic vsync having as well `SDL_RENDERER_PRESENTVSYNC` enabled, then if the app is not able to run at 60 FPS, automatically the `vsync` will be disabled having a better performance, instead of dropping FPS to 30. ## Notes diff --git a/docs/README-wayland.md b/docs/README-wayland.md index efa52a95..6b4aa6ce 100644 --- a/docs/README-wayland.md +++ b/docs/README-wayland.md @@ -6,6 +6,14 @@ encounter limitations or behavior that is different from other windowing systems ## Common issues: +### Legacy, DPI-unaware applications are blurry + +- Wayland handles high-DPI displays by scaling the desktop, which causes applications that are not designed to be + DPI-aware to be automatically scaled by the window manager, which results in them being blurry. SDL can _attempt_ to + scale these applications such that they will be output with a 1:1 pixel aspect, however this may be buggy, especially + with odd-sized windows and/or scale factors that aren't quarter-increments (125%, 150%, etc...). To enable this, set + the environment variable `SDL_VIDEO_WAYLAND_SCALE_TO_DISPLAY=1` + ### Window decorations are missing, or the decorations look strange - On some desktops (i.e. GNOME), Wayland applications use a library @@ -52,15 +60,15 @@ having SDL handle input and rendering, it needs to create a custom, roleless sur toplevel window. This is done by using `SDL_CreateWindowWithProperties()` and setting the -`SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` property to `SDL_TRUE`. Once the window has been +`SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` property to `SDL_TRUE`. Once the window has been successfully created, the `wl_display` and `wl_surface` objects can then be retrieved from the -`SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER` and `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER` properties respectively. +`SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER` and `SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER` properties respectively. Surfaces don't receive any size change notifications, so if an application changes the window size, it must inform SDL that the surface size has changed by calling SDL_SetWindowSize() with the new dimensions. Custom surfaces will automatically handle scaling internally if the window was created with the -`SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` property set to `SDL_TRUE`. In this case, applications should +`SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` property set to `SDL_TRUE`. In this case, applications should not manually attach viewports or change the surface scale value, as SDL will handle this internally. Calls to `SDL_SetWindowSize()` should use the logical size of the window, and `SDL_GetWindowSizeInPixels()` should be used to query the size of the backbuffer surface in pixels. If this property is not set or is `SDL_FALSE`, applications can @@ -77,7 +85,7 @@ and attach it to an application-managed toplevel window. Wayland windows and surfaces are more intrinsically tied to the client library than other windowing systems, therefore, when importing surfaces, it is necessary for both SDL and the application or toolkit to use the same `wl_display` -object. This can be set/queried via the global `SDL_PROPERTY_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER` property. To +object. This can be set/queried via the global `SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER` property. To import an external `wl_display`, set this property before initializing the SDL video subsystem, and read the value to export the internal `wl_display` after the video subsystem has been initialized. Setting this property after the video subsystem has been initialized has no effect, and reading it when the video subsystem is uninitialized will either @@ -85,14 +93,14 @@ return the user provided value, if one was set while in the uninitialized state, Once this is done, and the application has created or obtained the `wl_surface` to be wrapped in an `SDL_Window`, the window is created with `SDL_CreateWindowWithProperties()` with the -`SDL_PROPERTY_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER` property to set to the `wl_surface` object that is to be +`SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER` property to set to the `wl_surface` object that is to be imported by SDL. SDL receives no notification regarding size changes on external surfaces or toplevel windows, so if the external surface needs to be resized, SDL must be informed by calling SDL_SetWindowSize() with the new dimensions. If desired, SDL can automatically handle the scaling for the surface by setting the -`SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` property to `SDL_TRUE`, however, if the surface being imported +`SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN` property to `SDL_TRUE`, however, if the surface being imported already has, or will have, a viewport/fractional scale manager attached to it by the application or an external toolkit, a protocol violation will result. Avoid setting this property if importing surfaces from toolkits such as Qt or GTK. @@ -144,7 +152,7 @@ int main(int argc, char *argv[]) } /* Set SDL to use the existing wl_display object from Qt and initialize. */ - SDL_SetProperty(SDL_GetGlobalProperties(), SDL_PROPERTY_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER, display); + SDL_SetProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER, display); SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); /* Create a basic, frameless QWindow */ @@ -166,10 +174,10 @@ int main(int argc, char *argv[]) * Qt objects should not be flagged as DPI-aware or protocol violations will result. */ props = SDL_CreateProperties(); - SDL_SetProperty(props, SDL_PROPERTY_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER, surface); - SDL_SetBooleanProperty(props, SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN, SDL_TRUE); - SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER, 640); - SDL_SetNumberProperty(props, SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER, 480); + SDL_SetProperty(props, SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER, surface); + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, SDL_TRUE); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, 640); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, 480); sdlWindow = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); if (!sdlWindow) { diff --git a/docs/README-winrt.md b/docs/README-winrt.md index a41b21eb..7ef21be6 100644 --- a/docs/README-winrt.md +++ b/docs/README-winrt.md @@ -33,7 +33,7 @@ Here is a rough list of what works, and what doesn't: * What works: * compilation via Visual C++ 2019. * compile-time platform detection for SDL programs. The C/C++ #define, - `__WINRT__`, will be set to 1 (by SDL) when compiling for WinRT. + `SDL_PLATFORM_WINRT`, will be set to 1 (by SDL) when compiling for WinRT. * GPU-accelerated 2D rendering, via SDL_Renderer. * OpenGL ES 2, via the ANGLE library (included separately from SDL) * software rendering, via either SDL_Surface (optionally in conjunction with @@ -42,7 +42,7 @@ Here is a rough list of what works, and what doesn't: * threads * timers (via SDL_GetTicks(), SDL_AddTimer(), SDL_GetPerformanceCounter(), SDL_GetPerformanceFrequency(), etc.) - * file I/O via SDL_RWops + * file I/O via SDL_IOStream * mouse input (unsupported on Windows Phone) * audio, via SDL's WASAPI backend (if you want to record, your app must have "Microphone" capabilities enabled in its manifest, and the user must diff --git a/docs/README.md b/docs/README.md index 469a8394..a94fdd3c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,9 +4,8 @@ https://www.libsdl.org/ Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics -hardware via OpenGL and Direct3D. It is used by video playback software, -emulators, and popular games including Valve's award winning catalog -and many Humble Bundle games. +hardware. It is used by video playback software, emulators, and popular games +including Valve's award winning catalog and many Humble Bundle games. SDL officially supports Windows, macOS, Linux, iOS, and Android. Support for other platforms may be found in the source code. @@ -17,32 +16,40 @@ available for several other languages, including C# and Python. This library is distributed under the zlib license, which can be found in the file "LICENSE.txt". +Information on building SDL with CMake is available in [README-cmake.md](README-cmake.md) + The best way to learn how to use SDL is to check out the header files in the "include" subdirectory and the programs in the "test" subdirectory. The header files and test programs are well commented and always up to date. +Information on reporting bugs and contributing is available in [README-contributing.md](README-contributing.md) + More documentation and FAQs are available online at [the wiki](http://wiki.libsdl.org/) -- [Android](README-android.md) -- [CMake](README-cmake.md) -- [DynAPI](README-dynapi.md) -- [Emscripten](README-emscripten.md) -- [GDK](README-gdk.md) -- [Git](README-git.md) -- [iOS](README-ios.md) -- [Linux](README-linux.md) -- [macOS](README-macos.md) -- [Supported Platforms](README-platforms.md) +- [High DPI Support](README-highdpi.md) +- [main()](README-main-functions.md) - [Porting information](README-porting.md) -- [PSP](README-psp.md) -- [PS2](README-ps2.md) -- [Raspberry Pi](README-raspberrypi.md) +- [Migrating from SDL 2.0](README-migration.md) +- [Supported Platforms](README-platforms.md) - [Touch](README-touch.md) - [Versions](README-versions.md) -- [Windows](README-windows.md) -- [WinRT](README-winrt.md) +- [Visual Studio](README-visualc.md) + +- [Android](README-android.md) +- [Emscripten](README-emscripten.md) +- [iOS](README-ios.md) +- [KMSDRM support on BSD](README-kmsbsd.md) +- [Linux](README-linux.md) +- [macOS](README-macos.md) +- [Nintendo 3DS](README-n3ds.md) +- [PS2](README-ps2.md) +- [PSP](README-psp.md) - [PSVita](README-vita.md) -- [Nokia N-Gage](README-ngage.md) +- [Raspberry Pi](README-raspberrypi.md) +- [RISC OS](README-riscos.md) +- [Windows GDK](README-gdk.md) +- [Windows UWP](README-winrt.md) +- [Windows](README-windows.md) If you need help with the library, or just want to discuss SDL related issues, you can join the [SDL Discourse](https://discourse.libsdl.org/), diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h index a0a77e53..8dac3e9f 100644 --- a/include/SDL3/SDL.h +++ b/include/SDL3/SDL.h @@ -35,8 +35,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -66,17 +68,18 @@ #include #include #include -#include +#include #include #include +#include #include #include #include +#include #include #include #include #include -#include "SDL3/SDL_video_capture.h" #include #endif /* SDL_h_ */ diff --git a/include/SDL3/SDL_assert.h b/include/SDL3/SDL_assert.h index e4f553e4..c2ecadbc 100644 --- a/include/SDL3/SDL_assert.h +++ b/include/SDL3/SDL_assert.h @@ -66,9 +66,9 @@ assert can have unique static variables associated with it. #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" ) #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv) #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" ) -#elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */ +#elif ( defined(SDL_PLATFORM_APPLE) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" ) -#elif defined(__APPLE__) && defined(__arm__) +#elif defined(SDL_PLATFORM_APPLE) && defined(__arm__) #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" ) #elif defined(__386__) && defined(__WATCOMC__) #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } @@ -167,7 +167,7 @@ extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *data #ifndef SDL_AssertBreakpoint #if defined(ANDROID) && defined(assert) /* Define this as empty in case assert() is defined as SDL_assert */ -#define SDL_AssertBreakpoint() +#define SDL_AssertBreakpoint() #else #define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() #endif diff --git a/include/SDL3/SDL_atomic.h b/include/SDL3/SDL_atomic.h index 25541723..b5ebe007 100644 --- a/include/SDL3/SDL_atomic.h +++ b/include/SDL3/SDL_atomic.h @@ -31,8 +31,8 @@ * with full mutexes. * * The list of "safe" functions to use are: - * SDL_AtomicLock() - * SDL_AtomicUnlock() + * SDL_LockSpinlock() + * SDL_UnlockSpinlock() * SDL_AtomicIncRef() * SDL_AtomicDecRef() * @@ -105,10 +105,10 @@ typedef int SDL_SpinLock; * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicLock - * \sa SDL_AtomicUnlock + * \sa SDL_LockSpinlock + * \sa SDL_UnlockSpinlock */ -extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock); +extern DECLSPEC SDL_bool SDLCALL SDL_TryLockSpinlock(SDL_SpinLock *lock); /** * Lock a spin lock by setting it to a non-zero value. @@ -120,10 +120,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicTryLock - * \sa SDL_AtomicUnlock + * \sa SDL_TryLockSpinlock + * \sa SDL_UnlockSpinlock */ -extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock); +extern DECLSPEC void SDLCALL SDL_LockSpinlock(SDL_SpinLock *lock); /** * Unlock a spin lock by setting it to 0. @@ -137,10 +137,10 @@ extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicLock - * \sa SDL_AtomicTryLock + * \sa SDL_LockSpinlock + * \sa SDL_TryLockSpinlock */ -extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock); +extern DECLSPEC void SDLCALL SDL_UnlockSpinlock(SDL_SpinLock *lock); /* @} *//* SDL AtomicLock */ @@ -153,7 +153,7 @@ extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock); void _ReadWriteBarrier(void); #pragma intrinsic(_ReadWriteBarrier) #define SDL_CompilerBarrier() _ReadWriteBarrier() -#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) +#elif (defined(__GNUC__) && !defined(SDL_PLATFORM_EMSCRIPTEN)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) /* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */ #define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory") #elif defined(__WATCOMC__) @@ -161,7 +161,7 @@ extern __inline void SDL_CompilerBarrier(void); #pragma aux SDL_CompilerBarrier = "" parm [] modify exact []; #else #define SDL_CompilerBarrier() \ -{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); } +{ SDL_SpinLock _tmp = 0; SDL_LockSpinlock(&_tmp); SDL_UnlockSpinlock(&_tmp); } #endif /** @@ -199,7 +199,7 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__GNUC__) && defined(__arm__) -#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */ +#if 0 /* defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID) */ /* Information from: https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19 @@ -226,7 +226,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); #else #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") -#endif /* __LINUX__ || __ANDROID__ */ +#endif /* SDL_PLATFORM_LINUX || SDL_PLATFORM_ANDROID */ #endif /* __GNUC__ && __arm__ */ #else #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) @@ -267,7 +267,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); * * It is a struct so people don't accidentally use numeric operations on it. */ -typedef struct { int value; } SDL_AtomicInt; +typedef struct SDL_AtomicInt { int value; } SDL_AtomicInt; /** * Set an atomic variable to a new value if it is currently an old value. @@ -282,11 +282,9 @@ typedef struct { int value; } SDL_AtomicInt; * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicCASPtr - * \sa SDL_AtomicGet - * \sa SDL_AtomicSet + * \sa SDL_AtomicCompareAndSwapPointer */ -extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_AtomicInt *a, int oldval, int newval); +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareAndSwap(SDL_AtomicInt *a, int oldval, int newval); /** * Set an atomic variable to a value. @@ -370,11 +368,11 @@ extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_AtomicInt *a, int v); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicCAS + * \sa SDL_AtomicCompareAndSwap * \sa SDL_AtomicGetPtr * \sa SDL_AtomicSetPtr */ -extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval); +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareAndSwapPointer(void **a, void *oldval, void *newval); /** * Set a pointer to a value atomically. @@ -388,7 +386,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void * * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicCASPtr + * \sa SDL_AtomicCompareAndSwapPointer * \sa SDL_AtomicGetPtr */ extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v); @@ -404,7 +402,7 @@ extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AtomicCASPtr + * \sa SDL_AtomicCompareAndSwapPointer * \sa SDL_AtomicSetPtr */ extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a); diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 1dbfcb11..feac79c5 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -561,7 +561,6 @@ extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid); * \since This function is available since SDL 3.0.0. * * \sa SDL_BindAudioStreams - * \sa SDL_UnbindAudioStreams * \sa SDL_UnbindAudioStream * \sa SDL_GetAudioStreamDevice */ @@ -583,7 +582,6 @@ extern DECLSPEC int SDLCALL SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_Au * \since This function is available since SDL 3.0.0. * * \sa SDL_BindAudioStreams - * \sa SDL_UnbindAudioStreams * \sa SDL_UnbindAudioStream * \sa SDL_GetAudioStreamDevice */ @@ -607,9 +605,6 @@ extern DECLSPEC int SDLCALL SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_Aud * \since This function is available since SDL 3.0.0. * * \sa SDL_BindAudioStreams - * \sa SDL_BindAudioStream - * \sa SDL_UnbindAudioStream - * \sa SDL_GetAudioStreamDevice */ extern DECLSPEC void SDLCALL SDL_UnbindAudioStreams(SDL_AudioStream **streams, int num_streams); @@ -626,9 +621,6 @@ extern DECLSPEC void SDLCALL SDL_UnbindAudioStreams(SDL_AudioStream **streams, i * \since This function is available since SDL 3.0.0. * * \sa SDL_BindAudioStream - * \sa SDL_BindAudioStreams - * \sa SDL_UnbindAudioStreams - * \sa SDL_GetAudioStreamDevice */ extern DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream); @@ -649,8 +641,6 @@ extern DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream); * * \sa SDL_BindAudioStream * \sa SDL_BindAudioStreams - * \sa SDL_UnbindAudioStream - * \sa SDL_UnbindAudioStreams */ extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_GetAudioStreamDevice(SDL_AudioStream *stream); @@ -727,9 +717,6 @@ extern DECLSPEC int SDLCALL SDL_GetAudioStreamFormat(SDL_AudioStream *stream, * \since This function is available since SDL 3.0.0. * * \sa SDL_GetAudioStreamFormat - * \sa SDL_PutAudioStreamData - * \sa SDL_GetAudioStreamData - * \sa SDL_GetAudioStreamAvailable * \sa SDL_SetAudioStreamFrequencyRatio */ extern DECLSPEC int SDLCALL SDL_SetAudioStreamFormat(SDL_AudioStream *stream, @@ -801,12 +788,10 @@ extern DECLSPEC int SDLCALL SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *st * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateAudioStream - * \sa SDL_GetAudioStreamData - * \sa SDL_GetAudioStreamAvailable - * \sa SDL_FlushAudioStream * \sa SDL_ClearAudioStream - * \sa SDL_DestroyAudioStream + * \sa SDL_FlushAudioStream + * \sa SDL_GetAudioStreamData + * \sa SDL_GetAudioStreamQueued */ extern DECLSPEC int SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len); @@ -833,13 +818,9 @@ extern DECLSPEC int SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream, cons * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateAudioStream - * \sa SDL_PutAudioStreamData - * \sa SDL_GetAudioStreamAvailable - * \sa SDL_SetAudioStreamFormat - * \sa SDL_FlushAudioStream * \sa SDL_ClearAudioStream - * \sa SDL_DestroyAudioStream + * \sa SDL_GetAudioStreamAvailable + * \sa SDL_PutAudioStreamData */ extern DECLSPEC int SDLCALL SDL_GetAudioStreamData(SDL_AudioStream *stream, void *buf, int len); @@ -863,12 +844,8 @@ extern DECLSPEC int SDLCALL SDL_GetAudioStreamData(SDL_AudioStream *stream, void * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateAudioStream - * \sa SDL_PutAudioStreamData * \sa SDL_GetAudioStreamData - * \sa SDL_FlushAudioStream - * \sa SDL_ClearAudioStream - * \sa SDL_DestroyAudioStream + * \sa SDL_PutAudioStreamData */ extern DECLSPEC int SDLCALL SDL_GetAudioStreamAvailable(SDL_AudioStream *stream); @@ -900,7 +877,6 @@ extern DECLSPEC int SDLCALL SDL_GetAudioStreamAvailable(SDL_AudioStream *stream) * \since This function is available since SDL 3.0.0. * * \sa SDL_PutAudioStreamData - * \sa SDL_GetAudioStreamData * \sa SDL_ClearAudioStream */ extern DECLSPEC int SDLCALL SDL_GetAudioStreamQueued(SDL_AudioStream *stream); @@ -922,12 +898,7 @@ extern DECLSPEC int SDLCALL SDL_GetAudioStreamQueued(SDL_AudioStream *stream); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateAudioStream * \sa SDL_PutAudioStreamData - * \sa SDL_GetAudioStreamData - * \sa SDL_GetAudioStreamAvailable - * \sa SDL_ClearAudioStream - * \sa SDL_DestroyAudioStream */ extern DECLSPEC int SDLCALL SDL_FlushAudioStream(SDL_AudioStream *stream); @@ -942,12 +913,10 @@ extern DECLSPEC int SDLCALL SDL_FlushAudioStream(SDL_AudioStream *stream); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateAudioStream - * \sa SDL_PutAudioStreamData - * \sa SDL_GetAudioStreamData * \sa SDL_GetAudioStreamAvailable - * \sa SDL_FlushAudioStream - * \sa SDL_DestroyAudioStream + * \sa SDL_GetAudioStreamData + * \sa SDL_GetAudioStreamQueued + * \sa SDL_PutAudioStreamData */ extern DECLSPEC int SDLCALL SDL_ClearAudioStream(SDL_AudioStream *stream); @@ -976,8 +945,6 @@ extern DECLSPEC int SDLCALL SDL_ClearAudioStream(SDL_AudioStream *stream); * \since This function is available since SDL 3.0.0. * * \sa SDL_UnlockAudioStream - * \sa SDL_SetAudioStreamPutCallback - * \sa SDL_SetAudioStreamGetCallback */ extern DECLSPEC int SDLCALL SDL_LockAudioStream(SDL_AudioStream *stream); @@ -997,8 +964,6 @@ extern DECLSPEC int SDLCALL SDL_LockAudioStream(SDL_AudioStream *stream); * \since This function is available since SDL 3.0.0. * * \sa SDL_LockAudioStream - * \sa SDL_SetAudioStreamPutCallback - * \sa SDL_SetAudioStreamGetCallback */ extern DECLSPEC int SDLCALL SDL_UnlockAudioStream(SDL_AudioStream *stream); @@ -1134,11 +1099,6 @@ extern DECLSPEC int SDLCALL SDL_SetAudioStreamPutCallback(SDL_AudioStream *strea * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateAudioStream - * \sa SDL_PutAudioStreamData - * \sa SDL_GetAudioStreamData - * \sa SDL_GetAudioStreamAvailable - * \sa SDL_FlushAudioStream - * \sa SDL_ClearAudioStream */ extern DECLSPEC void SDLCALL SDL_DestroyAudioStream(SDL_AudioStream *stream); @@ -1306,7 +1266,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, * Example: * * ```c - * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, &spec, &buf, &len); + * SDL_LoadWAV_IO(SDL_IOFromFile("sample.wav", "rb"), 1, &spec, &buf, &len); * ``` * * Note that the SDL_LoadWAV function does this same thing for you, but in a @@ -1317,7 +1277,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, * ``` * * \param src The data source for the WAVE data - * \param freesrc If SDL_TRUE, calls SDL_RWclose() on `src` before returning, + * \param closeio If SDL_TRUE, calls SDL_CloseIO() on `src` before returning, * even in the case of an error * \param spec A pointer to an SDL_AudioSpec that will be set to the WAVE * data's format details on successful return @@ -1344,7 +1304,7 @@ extern DECLSPEC int SDLCALL SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, * \sa SDL_free * \sa SDL_LoadWAV */ -extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, SDL_bool freesrc, +extern DECLSPEC int SDLCALL SDL_LoadWAV_IO(SDL_IOStream * src, SDL_bool closeio, SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len); @@ -1354,7 +1314,7 @@ extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, SDL_bool freesrc, * This is a convenience function that is effectively the same as: * * ```c - * SDL_LoadWAV_RW(SDL_RWFromFile(path, "rb"), 1, spec, audio_buf, audio_len); + * SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len); * ``` * * Note that in SDL2, this was a preprocessor macro and not a real function. @@ -1383,7 +1343,7 @@ extern DECLSPEC int SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, SDL_bool freesrc, * \since This function is available since SDL 3.0.0. * * \sa SDL_free - * \sa SDL_LoadWAV_RW + * \sa SDL_LoadWAV_IO */ extern DECLSPEC int SDLCALL SDL_LoadWAV(const char *path, SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len); @@ -1458,8 +1418,6 @@ extern DECLSPEC int SDLCALL SDL_MixAudioFormat(Uint8 * dst, * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateAudioStream */ extern DECLSPEC int SDLCALL SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, diff --git a/include/SDL3/SDL_begin_code.h b/include/SDL3/SDL_begin_code.h index 12803825..c53ad79e 100644 --- a/include/SDL3/SDL_begin_code.h +++ b/include/SDL3/SDL_begin_code.h @@ -53,7 +53,7 @@ /* Some compilers use a special export keyword */ #ifndef DECLSPEC -# if defined(__WIN32__) || defined(__WINRT__) || defined(__CYGWIN__) || defined(__GDK__) +# if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_CYGWIN) || defined(SDL_PLATFORM_GDK) # ifdef DLL_EXPORT # define DECLSPEC __declspec(dllexport) # else @@ -70,7 +70,7 @@ /* By default SDL uses the C calling convention */ #ifndef SDLCALL -#if (defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)) && !defined(__GNUC__) +#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK)) && !defined(__GNUC__) #define SDLCALL __cdecl #else #define SDLCALL diff --git a/include/SDL3/SDL_blendmode.h b/include/SDL3/SDL_blendmode.h index 4b1b4ee4..8b3667c1 100644 --- a/include/SDL3/SDL_blendmode.h +++ b/include/SDL3/SDL_blendmode.h @@ -65,8 +65,8 @@ typedef enum typedef enum { SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */ - SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ - SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */ } SDL_BlendOperation; diff --git a/include/SDL3/SDL_camera.h b/include/SDL3/SDL_camera.h new file mode 100644 index 00000000..717de3c7 --- /dev/null +++ b/include/SDL3/SDL_camera.h @@ -0,0 +1,478 @@ +/* + 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_camera.h + * + * Video Capture for the SDL library. + */ + +#ifndef SDL_camera_h_ +#define SDL_camera_h_ + +#include + +#include +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This is a unique ID for a camera device for the time it is connected to the system, + * and is never reused for the lifetime of the application. If the device is + * disconnected and reconnected, it will get a new ID. + * + * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. + * + * \sa SDL_GetCameraDevices + */ +typedef Uint32 SDL_CameraDeviceID; + + +/** + * The structure used to identify an opened SDL camera + */ +struct SDL_Camera; +typedef struct SDL_Camera SDL_Camera; + +/** + * SDL_CameraSpec structure + * + * \sa SDL_GetCameraDeviceSupportedFormats + * \sa SDL_GetCameraFormat + * + */ +typedef struct SDL_CameraSpec +{ + SDL_PixelFormatEnum format; /**< Frame format */ + int width; /**< Frame width */ + int height; /**< Frame height */ + int interval_numerator; /**< Frame rate numerator ((dom / num) == fps, (num / dom) == duration) */ + int interval_denominator; /**< Frame rate demoninator ((dom / num) == fps, (num / dom) == duration) */ +} SDL_CameraSpec; + +/** + * The position of camera in relation to system device. + * + * \sa SDL_GetCameraDevicePosition + */ +typedef enum SDL_CameraPosition +{ + SDL_CAMERA_POSITION_UNKNOWN, + SDL_CAMERA_POSITION_FRONT_FACING, + SDL_CAMERA_POSITION_BACK_FACING +} SDL_CameraPosition; + + +/** + * Use this function to get the number of built-in camera drivers. + * + * This function returns a hardcoded number. This never returns a negative + * value; if there are no drivers compiled into this build of SDL, this + * function returns zero. The presence of a driver in this list does not mean + * it will function, it just means SDL is capable of interacting with that + * interface. For example, a build of SDL might have v4l2 support, but if + * there's no kernel support available, SDL's v4l2 driver would fail if used. + * + * By default, SDL tries all drivers, in its preferred order, until one is + * found to be usable. + * + * \returns the number of built-in camera drivers. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetCameraDriver + */ +extern DECLSPEC int SDLCALL SDL_GetNumCameraDrivers(void); + +/** + * Use this function to get the name of a built in camera driver. + * + * The list of camera drivers is given in the order that they are normally + * initialized by default; the drivers that seem more reasonable to choose + * first (as far as the SDL developers believe) are earlier in the list. + * + * The names of drivers are all simple, low-ASCII identifiers, like "v4l2", + * "coremedia" or "android". These never have Unicode characters, and are not + * meant to be proper names. + * + * \param index the index of the camera driver; the value ranges from 0 to + * SDL_GetNumCameraDrivers() - 1 + * \returns the name of the camera 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_GetNumCameraDrivers + */ +extern DECLSPEC const char *SDLCALL SDL_GetCameraDriver(int index); + +/** + * Get the name of the current camera driver. + * + * The returned string points to internal static memory and thus never becomes + * invalid, even if you quit the camera subsystem and initialize a new driver + * (although such a case would return a different static string from another + * call to this function, of course). As such, you should not modify or free + * the returned string. + * + * \returns the name of the current camera driver or NULL if no driver has + * been initialized. + * + * \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_GetCurrentCameraDriver(void); + +/** + * Get a list of currently connected camera devices. + * + * \param count a pointer filled in with the number of camera devices. Can be + * NULL. + * \returns a 0 terminated array of camera instance IDs which should be freed + * with SDL_free(), or NULL on error; call SDL_GetError() for more + * details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenCamera + */ +extern DECLSPEC SDL_CameraDeviceID *SDLCALL SDL_GetCameraDevices(int *count); + +/** + * Get the list of native formats/sizes a camera supports. + * + * This returns a list of all formats and frame sizes that a specific camera + * can offer. This is useful if your app can accept a variety of image formats + * and sizes and so want to find the optimal spec that doesn't require + * conversion. + * + * This function isn't strictly required; if you call SDL_OpenCameraDevice + * with a NULL spec, SDL will choose a native format for you, and if you + * instead specify a desired format, it will transparently convert to the + * requested format on your behalf. + * + * If `count` is not NULL, it will be filled with the number of elements in + * the returned array. Additionally, the last element of the array has all + * fields set to zero (this element is not included in `count`). + * + * The returned list is owned by the caller, and should be released with + * SDL_free() when no longer needed. + * + * Note that it's legal for a camera to supply a list with only the zeroed + * final element and `*count` set to zero; this is what will happen on + * Emscripten builds, since that platform won't tell _anything_ about + * available cameras until you've opened one, and won't even tell if there + * _is_ a camera until the user has given you permission to check through a + * scary warning popup. + * + * \param devid the camera device instance ID to query. + * \param count a pointer filled in with the number of elements in the list. + * Can be NULL. + * \returns a 0 terminated array of SDL_CameraSpecs, which should be freed + * with SDL_free(), or NULL on error; call SDL_GetError() for more + * details. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetCameraDevices + * \sa SDL_OpenCameraDevice + */ +extern DECLSPEC SDL_CameraSpec *SDLCALL SDL_GetCameraDeviceSupportedFormats(SDL_CameraDeviceID devid, int *count); + +/** + * Get human-readable device name for a camera. + * + * The returned string is owned by the caller; please release it with + * SDL_free() when done with it. + * + * \param instance_id the camera device instance ID + * \returns Human-readable device name, or NULL on error; 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_GetCameraDevices + */ +extern DECLSPEC char * SDLCALL SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id); + +/** + * Get the position of the camera in relation to the system. + * + * Most platforms will report UNKNOWN, but mobile devices, like phones, can + * often make a distiction between cameras on the front of the device (that + * points towards the user, for taking "selfies") and cameras on the back (for + * filming in the direction the user is facing). + * + * \param instance_id the camera device instance ID + * \returns The position of the camera on the system hardware. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetCameraDevices + */ +extern DECLSPEC SDL_CameraPosition SDLCALL SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id); + +/** + * Open a video capture device (a "camera"). + * + * You can open the device with any reasonable spec, and if the hardware can't + * directly support it, it will convert data seamlessly to the requested + * format. This might incur overhead, including scaling of image data. + * + * If you would rather accept whatever format the device offers, you can pass + * a NULL spec here and it will choose one for you (and you can use + * SDL_Surface's conversion/scaling functions directly if necessary). + * + * You can call SDL_GetCameraFormat() to get the actual data format if passing + * a NULL spec here. You can see the exact specs a device can support without + * conversion with SDL_GetCameraSupportedSpecs(). + * + * SDL will not attempt to emulate framerate; it will try to set the hardware + * to the rate closest to the requested speed, but it won't attempt to limit + * or duplicate frames artificially; call SDL_GetCameraFormat() to see the + * actual framerate of the opened the device, and check your timestamps if + * this is crucial to your app! + * + * Note that the camera is not usable until the user approves its use! On some + * platforms, the operating system will prompt the user to permit access to + * the camera, and they can choose Yes or No at that point. Until they do, the + * camera will not be usable. The app should either wait for an + * SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event, + * or poll SDL_IsCameraApproved() occasionally until it returns non-zero. On + * platforms that don't require explicit user approval (and perhaps in places + * where the user previously permitted access), the approval event might come + * immediately, but it might come seconds, minutes, or hours later! + * + * \param instance_id the camera device instance ID + * \param spec The desired format for data the device will provide. Can be + * NULL. + * \returns device, 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_GetCameraDevices + * \sa SDL_GetCameraFormat + */ +extern DECLSPEC SDL_Camera *SDLCALL SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_CameraSpec *spec); + +/** + * Query if camera access has been approved by the user. + * + * Cameras will not function between when the device is opened by the app and + * when the user permits access to the hardware. On some platforms, this + * presents as a popup dialog where the user has to explicitly approve access; + * on others the approval might be implicit and not alert the user at all. + * + * This function can be used to check the status of that approval. It will + * return 0 if still waiting for user response, 1 if the camera is approved + * for use, and -1 if the user denied access. + * + * Instead of polling with this function, you can wait for a + * SDL_EVENT_CAMERA_DEVICE_APPROVED (or SDL_EVENT_CAMERA_DEVICE_DENIED) event + * in the standard SDL event loop, which is guaranteed to be sent once when + * permission to use the camera is decided. + * + * If a camera is declined, there's nothing to be done but call + * SDL_CloseCamera() to dispose of it. + * + * \param camera the opened camera device to query + * \returns -1 if user denied access to the camera, 1 if user approved access, + * 0 if no decision has been made yet. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenCameraDevice + * \sa SDL_CloseCamera + */ +extern DECLSPEC int SDLCALL SDL_GetCameraPermissionState(SDL_Camera *camera); + +/** + * Get the instance ID of an opened camera. + * + * \param camera an SDL_Camera to query + * \returns the instance ID of the specified camera 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_OpenCameraDevice + */ +extern DECLSPEC SDL_CameraDeviceID SDLCALL SDL_GetCameraInstanceID(SDL_Camera *camera); + +/** + * Get the properties associated with an opened camera. + * + * \param camera the SDL_Camera obtained from SDL_OpenCameraDevice() + * \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_GetProperty + * \sa SDL_SetProperty + */ +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetCameraProperties(SDL_Camera *camera); + +/** + * Get the spec that a camera is using when generating images. + * + * Note that this might not be the native format of the hardware, as SDL might + * be converting to this format behind the scenes. + * + * If the system is waiting for the user to approve access to the camera, as + * some platforms require, this will return -1, but this isn't necessarily a + * fatal error; you should either wait for an SDL_EVENT_CAMERA_DEVICE_APPROVED + * (or SDL_EVENT_CAMERA_DEVICE_DENIED) event, or poll SDL_IsCameraApproved() + * occasionally until it returns non-zero. + * + * \param camera opened camera device + * \param spec The SDL_CameraSpec to be initialized by this 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_OpenCameraDevice + */ +extern DECLSPEC int SDLCALL SDL_GetCameraFormat(SDL_Camera *camera, SDL_CameraSpec *spec); + +/** + * Acquire a frame. + * + * The frame is a memory pointer to the image data, whose size and format are + * given by the spec requested when opening the device. + * + * This is a non blocking API. If there is a frame available, a non-NULL + * surface is returned, and timestampNS will be filled with a non-zero value. + * + * Note that an error case can also return NULL, but a NULL by itself is + * normal and just signifies that a new frame is not yet available. Note that + * even if a camera device fails outright (a USB camera is unplugged while in + * use, etc), SDL will send an event separately to notify the app, but + * continue to provide blank frames at ongoing intervals until + * SDL_CloseCamera() is called, so real failure here is almost always an out + * of memory condition. + * + * After use, the frame should be released with SDL_ReleaseCameraFrame(). If + * you don't do this, the system may stop providing more video! + * + * Do not call SDL_FreeSurface() on the returned surface! It must be given + * back to the camera subsystem with SDL_ReleaseCameraFrame! + * + * If the system is waiting for the user to approve access to the camera, as + * some platforms require, this will return NULL (no frames available); you + * should either wait for an SDL_EVENT_CAMERA_DEVICE_APPROVED (or + * SDL_EVENT_CAMERA_DEVICE_DENIED) event, or poll SDL_IsCameraApproved() + * occasionally until it returns non-zero. + * + * \param camera opened camera device + * \param timestampNS a pointer filled in with the frame's timestamp, or 0 on + * error. Can be NULL. + * \returns A new frame of video on success, NULL if none is currently + * available. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ReleaseCameraFrame + */ +extern DECLSPEC SDL_Surface * SDLCALL SDL_AcquireCameraFrame(SDL_Camera *camera, Uint64 *timestampNS); + +/** + * Release a frame of video acquired from a camera. + * + * Let the back-end re-use the internal buffer for camera. + * + * This function _must_ be called only on surface objects returned by + * SDL_AcquireCameraFrame(). This function should be called as quickly as + * possible after acquisition, as SDL keeps a small FIFO queue of surfaces for + * video frames; if surfaces aren't released in a timely manner, SDL may drop + * upcoming video frames from the camera. + * + * If the app needs to keep the surface for a significant time, they should + * make a copy of it and release the original. + * + * The app should not use the surface again after calling this function; + * assume the surface is freed and the pointer is invalid. + * + * \param camera opened camera device + * \param frame The video frame surface to release. + * \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_AcquireCameraFrame + */ +extern DECLSPEC int SDLCALL SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame); + +/** + * Use this function to shut down camera processing and close the camera + * device. + * + * \param camera opened camera device + * + * \threadsafety It is safe to call this function from any thread, but no + * thread may reference `device` once this function is called. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenCameraWithSpec + * \sa SDL_OpenCamera + */ +extern DECLSPEC void SDLCALL SDL_CloseCamera(SDL_Camera *camera); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_camera_h_ */ diff --git a/include/SDL3/SDL_clipboard.h b/include/SDL3/SDL_clipboard.h index 84317613..7e2d3aba 100644 --- a/include/SDL3/SDL_clipboard.h +++ b/include/SDL3/SDL_clipboard.h @@ -187,8 +187,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_ClipboardDataCallback - * \sa SDL_SetClipboardData + * \sa SDL_ClearClipboardData * \sa SDL_GetClipboardData * \sa SDL_HasClipboardData */ diff --git a/include/SDL3/SDL_cpuinfo.h b/include/SDL3/SDL_cpuinfo.h index c4b3d398..59a4b325 100644 --- a/include/SDL3/SDL_cpuinfo.h +++ b/include/SDL3/SDL_cpuinfo.h @@ -75,16 +75,6 @@ extern DECLSPEC int SDLCALL SDL_GetCPUCacheLineSize(void); * \returns SDL_TRUE if the CPU has AltiVec features or SDL_FALSE if not. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasMMX - * \sa SDL_HasSSE - * \sa SDL_HasSSE2 - * \sa SDL_HasSSE3 - * \sa SDL_HasSSE41 - * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void); @@ -96,16 +86,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void); * \returns SDL_TRUE if the CPU has MMX features or SDL_FALSE if not. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_HasAltiVec - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasSSE - * \sa SDL_HasSSE2 - * \sa SDL_HasSSE3 - * \sa SDL_HasSSE41 - * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void); @@ -118,11 +98,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasMMX * \sa SDL_HasSSE2 * \sa SDL_HasSSE3 * \sa SDL_HasSSE41 @@ -139,11 +114,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasMMX * \sa SDL_HasSSE * \sa SDL_HasSSE3 * \sa SDL_HasSSE41 @@ -160,11 +130,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasMMX * \sa SDL_HasSSE * \sa SDL_HasSSE2 * \sa SDL_HasSSE41 @@ -181,11 +146,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE3(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasMMX * \sa SDL_HasSSE * \sa SDL_HasSSE2 * \sa SDL_HasSSE3 @@ -202,11 +162,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec - * \sa SDL_HasAVX - * \sa SDL_HasAVX2 - * \sa SDL_HasAVX512F - * \sa SDL_HasMMX * \sa SDL_HasSSE * \sa SDL_HasSSE2 * \sa SDL_HasSSE3 @@ -223,15 +178,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec * \sa SDL_HasAVX2 * \sa SDL_HasAVX512F - * \sa SDL_HasMMX - * \sa SDL_HasSSE - * \sa SDL_HasSSE2 - * \sa SDL_HasSSE3 - * \sa SDL_HasSSE41 - * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void); @@ -244,15 +192,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec * \sa SDL_HasAVX * \sa SDL_HasAVX512F - * \sa SDL_HasMMX - * \sa SDL_HasSSE - * \sa SDL_HasSSE2 - * \sa SDL_HasSSE3 - * \sa SDL_HasSSE41 - * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void); @@ -265,15 +206,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HasAltiVec * \sa SDL_HasAVX * \sa SDL_HasAVX2 - * \sa SDL_HasMMX - * \sa SDL_HasSSE - * \sa SDL_HasSSE2 - * \sa SDL_HasSSE3 - * \sa SDL_HasSSE41 - * \sa SDL_HasSSE42 */ extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void); diff --git a/include/SDL3/SDL_dialog.h b/include/SDL3/SDL_dialog.h new file mode 100644 index 00000000..4af592e5 --- /dev/null +++ b/include/SDL3/SDL_dialog.h @@ -0,0 +1,213 @@ +/* + 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_dialog_h_ +#define SDL_dialog_h_ + +#include + +#include +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * An entry for filters for file dialogs. + * + * `name` is a user-readable label for the filter (for example, "Office document"). + * + * `pattern` is a semicolon-separated list of file extensions (for example, + * "doc;docx"). + * + * \sa SDL_DialogFileCallback + * \sa SDL_ShowOpenFileDialog + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + */ +typedef struct +{ + const char *name; + const char *pattern; +} SDL_DialogFileFilter; + +/** + * Callback used by file dialog functions. + * + * The specific usage is described in each function. + * + * If filelist is... + * - `NULL`, an error occured. Details can be obtained with SDL_GetError(). + * - A pointer to `NULL`, the user either didn't choose any file or canceled + * the dialog. + * - A pointer to non-`NULL`, the user chose one or more files. The argument is + * a null-terminated list of pointers to C strings, each containing a path. + * + * The filelist argument does not need to be freed; it will automatically be + * freed when the callback returns. + * + * The filter argument is the index of the filter that was selected, or one + * more than the size of the list (therefore the index of the terminating NULL + * entry) if no filter was selected, or -1 if the platform or method doesn't + * support fetching the selected filter or if an error occured. + * + * \sa SDL_DialogFileFilter + * \sa SDL_ShowOpenFileDialog + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + */ +typedef void(SDLCALL *SDL_DialogFileCallback)(void *userdata, const char * const *filelist, int filter); + +/** + * Displays a dialog that lets the user select a file on their filesystem. + * + * This function should only be invoked from the main thread. + * + * This is an asynchronous function; it will return immediately, and the + * result will be passed to the callback. + * + * The callback will be invoked with a null-terminated list of files the user + * chose. The list will be empty if the user canceled the dialog, and it will + * be NULL if an error occured. + * + * Note that the callback may be called from a different thread than the one + * the function was invoked on. + * + * Depending on the platform, the user may be allowed to input paths that + * don't yet exist. + * + * \param callback The function to be invoked when the user selects a file and + * accepts, or the user cancels the dialog, or an error + * occurs. The first argument is a null-terminated list of C + * strings, representing the paths chosen by the user. The + * list will be empty if the user canceled the dialog, and it + * will be NULL if an error occured. If an error occured, it + * can be fetched with SDL_GetError(). The second argument is + * the userdata pointer passed to the function. + * \param userdata An optional pointer to pass extra data to the callback when + * it will be invoked. + * \param window The window that the dialog should be modal for. May be NULL. + * Not all platforms support this option. + * \param filters A null-terminated list of SDL_DialogFileFilter's. May be + * NULL. Not all platforms support this option, and platforms + * that do support it may allow the user to ignore the filters. + * \param default_location The default folder or file to start the dialog at. + * May be NULL. Not all platforms support this option. + * \param allow_many If non-zero, the user will be allowed to select multiple + * entries. Not all platforms support this option. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ShowSaveFileDialog + * \sa SDL_ShowOpenFolderDialog + */ +extern DECLSPEC void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location, SDL_bool allow_many); + +/** + * Displays a dialog that lets the user choose a new or existing file on their + * filesystem. + * + * This function should only be invoked from the main thread. + * + * This is an asynchronous function; it will return immediately, and the + * result will be passed to the callback. + * + * The callback will be invoked with a null-terminated list of files the user + * chose. The list will be empty if the user canceled the dialog, and it will + * be NULL if an error occured. + * + * Note that the callback may be called from a different thread than the one + * the function was invoked on. + * + * The chosen file may or may not already exist. + * + * \param callback The function to be invoked when the user selects a file and + * accepts, or the user cancels the dialog, or an error + * occurs. The first argument is a null-terminated list of C + * strings, representing the paths chosen by the user. The + * list will be empty if the user canceled the dialog, and it + * will be NULL if an error occured. If an error occured, it + * can be fetched with SDL_GetError(). The second argument is + * the userdata pointer passed to the function. + * \param userdata An optional pointer to pass extra data to the callback when + * it will be invoked. + * \param window The window that the dialog should be modal for. May be NULL. + * Not all platforms support this option. + * \param filters A null-terminated list of SDL_DialogFileFilter's. May be + * NULL. Not all platforms support this option, and platforms + * that do support it may allow the user to ignore the filters. + * \param default_location The default folder or file to start the dialog at. + * May be NULL. Not all platforms support this option. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ShowOpenFileDialog + */ +extern DECLSPEC void SDLCALL SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location); + +/** + * Displays a dialog that lets the user select a folder on their filesystem. + * + * This function should only be invoked from the main thread. + * + * This is an asynchronous function; it will return immediately, and the + * result will be passed to the callback. + * + * The callback will be invoked with a null-terminated list of files the user + * chose. The list will be empty if the user canceled the dialog, and it will + * be NULL if an error occured. + * + * Note that the callback may be called from a different thread than the one + * the function was invoked on. + * + * Depending on the platform, the user may be allowed to input paths that + * don't yet exist. + * + * \param callback The function to be invoked when the user selects a folder + * and accepts, or the user cancels the dialog, or an error + * occurs. The first argument is a null-terminated list of C + * strings, representing the paths chosen by the user. The + * list will be empty if the user canceled the dialog, and it + * will be NULL if an error occured. If an error occured, it + * can be fetched with SDL_GetError(). The second argument is + * the userdata pointer passed to the function. + * \param userdata An optional pointer to pass extra data to the callback when + * it will be invoked. + * \param window The window that the dialog should be modal for. May be NULL. + * Not all platforms support this option. + * \param default_location The default folder or file to start the dialog at. + * May be NULL. Not all platforms support this option. + * \param allow_many If non-zero, the user will be allowed to select multiple + * entries. Not all platforms support this option. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ShowOpenFileDialog + */ +extern DECLSPEC void SDLCALL SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, SDL_bool allow_many); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_joystick_h_ */ diff --git a/include/SDL3/SDL_egl.h b/include/SDL3/SDL_egl.h index 1945a8fd..6234a74a 100644 --- a/include/SDL3/SDL_egl.h +++ b/include/SDL3/SDL_egl.h @@ -25,9 +25,11 @@ * This is a simple file to encapsulate the EGL API headers. */ -#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) +#include -#if defined(__vita__) || defined(__psp2__) +#if !defined(_MSC_VER) && !defined(SDL_PLATFORM_ANDROID) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) + +#if defined(SDL_PLATFORM_VITA) #include #include #include @@ -419,7 +421,7 @@ typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; typedef HWND EGLNativeWindowType; -#elif defined(__EMSCRIPTEN__) +#elif defined(SDL_PLATFORM_EMSCRIPTEN) typedef int EGLNativeDisplayType; typedef int EGLNativePixmapType; diff --git a/include/SDL3/SDL_endian.h b/include/SDL3/SDL_endian.h index 480fe5ff..b787ea83 100644 --- a/include/SDL3/SDL_endian.h +++ b/include/SDL3/SDL_endian.h @@ -56,13 +56,13 @@ _m_prefetch(void *__P) /* @} */ #ifndef SDL_BYTEORDER -#ifdef __linux__ +#ifdef SDL_PLATFORM_LINUX #include #define SDL_BYTEORDER __BYTE_ORDER -#elif defined(__OpenBSD__) || defined(__DragonFly__) +#elif defined(SDL_PLATFORM_OPENBSD) || defined(__DragonFly__) #include #define SDL_BYTEORDER BYTE_ORDER -#elif defined(__FreeBSD__) || defined(__NetBSD__) +#elif defined(SDL_PLATFORM_FREEBSD) || defined(SDL_PLATFORM_NETBSD) #include #define SDL_BYTEORDER BYTE_ORDER /* predefs from newer gcc and clang versions: */ @@ -84,7 +84,7 @@ _m_prefetch(void *__P) #else #define SDL_BYTEORDER SDL_LIL_ENDIAN #endif -#endif /* __linux__ */ +#endif /* SDL_PLATFORM_LINUX */ #endif /* !SDL_BYTEORDER */ #ifndef SDL_FLOATWORDORDER diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 32655f7c..4c96cbe1 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -39,6 +39,7 @@ #include #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -97,8 +98,9 @@ typedef enum SDL_EVENT_DISPLAY_REMOVED, /**< Display has been removed from the system */ SDL_EVENT_DISPLAY_MOVED, /**< Display has changed position */ SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */ + SDL_EVENT_DISPLAY_HDR_STATE_CHANGED, /**< Display HDR properties have changed */ SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION, - SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, + SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_HDR_STATE_CHANGED, /* Window events */ /* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */ @@ -141,20 +143,25 @@ typedef enum SDL_EVENT_TEXT_INPUT, /**< Keyboard text input */ SDL_EVENT_KEYMAP_CHANGED, /**< Keymap changed due to a system event such as an input language or keyboard layout change. */ + SDL_EVENT_KEYBOARD_ADDED, /**< A new keyboard has been inserted into the system */ + SDL_EVENT_KEYBOARD_REMOVED, /**< A keyboard has been removed */ /* Mouse events */ SDL_EVENT_MOUSE_MOTION = 0x400, /**< Mouse moved */ SDL_EVENT_MOUSE_BUTTON_DOWN, /**< Mouse button pressed */ SDL_EVENT_MOUSE_BUTTON_UP, /**< Mouse button released */ SDL_EVENT_MOUSE_WHEEL, /**< Mouse wheel motion */ + SDL_EVENT_MOUSE_ADDED, /**< A new mouse has been inserted into the system */ + SDL_EVENT_MOUSE_REMOVED, /**< A mouse has been removed */ /* Joystick events */ SDL_EVENT_JOYSTICK_AXIS_MOTION = 0x600, /**< Joystick axis motion */ - SDL_EVENT_JOYSTICK_HAT_MOTION = 0x602, /**< Joystick hat position change */ + SDL_EVENT_JOYSTICK_BALL_MOTION, /**< Joystick trackball motion */ + SDL_EVENT_JOYSTICK_HAT_MOTION, /**< Joystick hat position change */ SDL_EVENT_JOYSTICK_BUTTON_DOWN, /**< Joystick button pressed */ SDL_EVENT_JOYSTICK_BUTTON_UP, /**< Joystick button released */ - SDL_EVENT_JOYSTICK_ADDED, /**< A new joystick has been inserted into the system */ - SDL_EVENT_JOYSTICK_REMOVED, /**< An opened joystick has been removed */ + SDL_EVENT_JOYSTICK_ADDED, /**< A new joystick has been inserted into the system */ + SDL_EVENT_JOYSTICK_REMOVED, /**< An opened joystick has been removed */ SDL_EVENT_JOYSTICK_BATTERY_UPDATED, /**< Joystick battery level change */ SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, /**< Joystick update is complete */ @@ -204,6 +211,12 @@ typedef enum SDL_EVENT_PEN_BUTTON_DOWN, /**< Pressure-sensitive pen button pressed */ SDL_EVENT_PEN_BUTTON_UP, /**< Pressure-sensitive pen button released */ + /* Camera hotplug events */ + SDL_EVENT_CAMERA_DEVICE_ADDED = 0x1400, /**< A new camera device is available */ + SDL_EVENT_CAMERA_DEVICE_REMOVED, /**< A camera device has been removed. */ + SDL_EVENT_CAMERA_DEVICE_APPROVED, /**< A camera device has been approved for use by the user. */ + SDL_EVENT_CAMERA_DEVICE_DENIED, /**< A camera device has been denied for use by the user. */ + /* Render events */ SDL_EVENT_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */ SDL_EVENT_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */ @@ -219,7 +232,11 @@ typedef enum /** * This last event is only for bounding internal arrays */ - SDL_EVENT_LAST = 0xFFFF + SDL_EVENT_LAST = 0xFFFF, + + /* This just makes sure the enum is the size of Uint32 */ + SDL_EVENT_ENUM_PADDING = 0x7FFFFFFF + } SDL_EventType; /** @@ -227,7 +244,8 @@ typedef enum */ typedef struct SDL_CommonEvent { - Uint32 type; + Uint32 type; /**< Event type, shared with all events, Uint32 to cover user events which are not in the SDL_EventType enumeration */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_CommonEvent; @@ -236,7 +254,8 @@ typedef struct SDL_CommonEvent */ typedef struct SDL_DisplayEvent { - Uint32 type; /**< ::SDL_DISPLAYEVENT_* */ + SDL_EventType type; /**< ::SDL_DISPLAYEVENT_* */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_DisplayID displayID;/**< The associated display */ Sint32 data1; /**< event dependent data */ @@ -247,21 +266,35 @@ typedef struct SDL_DisplayEvent */ typedef struct SDL_WindowEvent { - Uint32 type; /**< ::SDL_WINDOWEVENT_* */ + SDL_EventType type; /**< ::SDL_WINDOWEVENT_* */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The associated window */ Sint32 data1; /**< event dependent data */ Sint32 data2; /**< event dependent data */ } SDL_WindowEvent; +/** + * Keyboard device event structure (event.kdevice.*) + */ +typedef struct SDL_KeyboardDeviceEvent +{ + SDL_EventType type; /**< ::SDL_EVENT_KEYBOARD_ADDED or ::SDL_EVENT_KEYBOARD_REMOVED */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_KeyboardID which; /**< The keyboard instance id */ +} SDL_KeyboardDeviceEvent; + /** * Keyboard button event structure (event.key.*) */ typedef struct SDL_KeyboardEvent { - Uint32 type; /**< ::SDL_EVENT_KEY_DOWN or ::SDL_EVENT_KEY_UP */ + SDL_EventType type; /**< ::SDL_EVENT_KEY_DOWN or ::SDL_EVENT_KEY_UP */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ + SDL_KeyboardID which; /**< The keyboard instance id, or 0 if unknown or virtual */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 repeat; /**< Non-zero if this is a key repeat */ Uint8 padding2; @@ -278,7 +311,8 @@ typedef struct SDL_KeyboardEvent */ typedef struct SDL_TextEditingEvent { - Uint32 type; /**< ::SDL_EVENT_TEXT_EDITING */ + SDL_EventType type; /**< ::SDL_EVENT_TEXT_EDITING */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ char *text; /**< The editing text */ @@ -286,7 +320,6 @@ typedef struct SDL_TextEditingEvent Sint32 length; /**< The length of selected editing text */ } SDL_TextEditingEvent; -#define SDL_TEXTINPUTEVENT_TEXT_SIZE 64 /** * Keyboard text input event structure (event.text.*) * @@ -295,18 +328,31 @@ typedef struct SDL_TextEditingEvent */ typedef struct SDL_TextInputEvent { - Uint32 type; /**< ::SDL_EVENT_TEXT_INPUT */ + SDL_EventType type; /**< ::SDL_EVENT_TEXT_INPUT */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with keyboard focus, if any */ char *text; /**< The input text */ } SDL_TextInputEvent; +/** + * Mouse device event structure (event.mdevice.*) + */ +typedef struct SDL_MouseDeviceEvent +{ + SDL_EventType type; /**< ::SDL_EVENT_MOUSE_ADDED or ::SDL_EVENT_MOUSE_REMOVED */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_MouseID which; /**< The mouse instance id */ +} SDL_MouseDeviceEvent; + /** * Mouse motion event structure (event.motion.*) */ typedef struct SDL_MouseMotionEvent { - Uint32 type; /**< ::SDL_EVENT_MOUSE_MOTION */ + SDL_EventType type; /**< ::SDL_EVENT_MOUSE_MOTION */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with mouse focus, if any */ SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */ @@ -322,7 +368,8 @@ typedef struct SDL_MouseMotionEvent */ typedef struct SDL_MouseButtonEvent { - Uint32 type; /**< ::SDL_EVENT_MOUSE_BUTTON_DOWN or ::SDL_EVENT_MOUSE_BUTTON_UP */ + SDL_EventType type; /**< ::SDL_EVENT_MOUSE_BUTTON_DOWN or ::SDL_EVENT_MOUSE_BUTTON_UP */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with mouse focus, if any */ SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */ @@ -339,15 +386,16 @@ typedef struct SDL_MouseButtonEvent */ typedef struct SDL_MouseWheelEvent { - Uint32 type; /**< ::SDL_EVENT_MOUSE_WHEEL */ + SDL_EventType type; /**< ::SDL_EVENT_MOUSE_WHEEL */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window with mouse focus, if any */ SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */ float x; /**< The amount scrolled horizontally, positive to the right and negative to the left */ float y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */ - Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */ - float mouseX; /**< X coordinate, relative to window */ - float mouseY; /**< Y coordinate, relative to window */ + SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */ + float mouse_x; /**< X coordinate, relative to window */ + float mouse_y; /**< Y coordinate, relative to window */ } SDL_MouseWheelEvent; /** @@ -355,7 +403,8 @@ typedef struct SDL_MouseWheelEvent */ typedef struct SDL_JoyAxisEvent { - Uint32 type; /**< ::SDL_EVENT_JOYSTICK_AXIS_MOTION */ + SDL_EventType type; /**< ::SDL_EVENT_JOYSTICK_AXIS_MOTION */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 axis; /**< The joystick axis index */ @@ -366,12 +415,30 @@ typedef struct SDL_JoyAxisEvent Uint16 padding4; } SDL_JoyAxisEvent; +/** + * \brief Joystick trackball motion event structure (event.jball.*) + */ +typedef struct SDL_JoyBallEvent +{ + Uint32 type; /**< ::SDL_JOYBALLMOTION */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_JoystickID which; /**< The joystick instance id */ + Uint8 ball; /**< The joystick trackball index */ + Uint8 padding1; + Uint8 padding2; + Uint8 padding3; + Sint16 xrel; /**< The relative motion in the X direction */ + Sint16 yrel; /**< The relative motion in the Y direction */ +} SDL_JoyBallEvent; + /** * Joystick hat position change event structure (event.jhat.*) */ typedef struct SDL_JoyHatEvent { - Uint32 type; /**< ::SDL_EVENT_JOYSTICK_HAT_MOTION */ + SDL_EventType type; /**< ::SDL_EVENT_JOYSTICK_HAT_MOTION */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 hat; /**< The joystick hat index */ @@ -391,7 +458,8 @@ typedef struct SDL_JoyHatEvent */ typedef struct SDL_JoyButtonEvent { - Uint32 type; /**< ::SDL_EVENT_JOYSTICK_BUTTON_DOWN or ::SDL_EVENT_JOYSTICK_BUTTON_UP */ + SDL_EventType type; /**< ::SDL_EVENT_JOYSTICK_BUTTON_DOWN or ::SDL_EVENT_JOYSTICK_BUTTON_UP */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 button; /**< The joystick button index */ @@ -405,7 +473,8 @@ typedef struct SDL_JoyButtonEvent */ typedef struct SDL_JoyDeviceEvent { - Uint32 type; /**< ::SDL_EVENT_JOYSTICK_ADDED or ::SDL_EVENT_JOYSTICK_REMOVED or ::SDL_EVENT_JOYSTICK_UPDATE_COMPLETE */ + SDL_EventType type; /**< ::SDL_EVENT_JOYSTICK_ADDED or ::SDL_EVENT_JOYSTICK_REMOVED or ::SDL_EVENT_JOYSTICK_UPDATE_COMPLETE */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ } SDL_JoyDeviceEvent; @@ -415,7 +484,8 @@ typedef struct SDL_JoyDeviceEvent */ typedef struct SDL_JoyBatteryEvent { - Uint32 type; /**< ::SDL_EVENT_JOYSTICK_BATTERY_UPDATED */ + SDL_EventType type; /**< ::SDL_EVENT_JOYSTICK_BATTERY_UPDATED */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ SDL_JoystickPowerLevel level; /**< The joystick battery level */ @@ -426,7 +496,8 @@ typedef struct SDL_JoyBatteryEvent */ typedef struct SDL_GamepadAxisEvent { - Uint32 type; /**< ::SDL_EVENT_GAMEPAD_AXIS_MOTION */ + SDL_EventType type; /**< ::SDL_EVENT_GAMEPAD_AXIS_MOTION */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 axis; /**< The gamepad axis (SDL_GamepadAxis) */ @@ -443,7 +514,8 @@ typedef struct SDL_GamepadAxisEvent */ typedef struct SDL_GamepadButtonEvent { - Uint32 type; /**< ::SDL_EVENT_GAMEPAD_BUTTON_DOWN or ::SDL_EVENT_GAMEPAD_BUTTON_UP */ + SDL_EventType type; /**< ::SDL_EVENT_GAMEPAD_BUTTON_DOWN or ::SDL_EVENT_GAMEPAD_BUTTON_UP */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Uint8 button; /**< The gamepad button (SDL_GamepadButton) */ @@ -458,7 +530,8 @@ typedef struct SDL_GamepadButtonEvent */ typedef struct SDL_GamepadDeviceEvent { - Uint32 type; /**< ::SDL_EVENT_GAMEPAD_ADDED, ::SDL_EVENT_GAMEPAD_REMOVED, or ::SDL_EVENT_GAMEPAD_REMAPPED, ::SDL_EVENT_GAMEPAD_UPDATE_COMPLETE or ::SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED */ + SDL_EventType type; /**< ::SDL_EVENT_GAMEPAD_ADDED, ::SDL_EVENT_GAMEPAD_REMOVED, or ::SDL_EVENT_GAMEPAD_REMAPPED, ::SDL_EVENT_GAMEPAD_UPDATE_COMPLETE or ::SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ } SDL_GamepadDeviceEvent; @@ -468,7 +541,8 @@ typedef struct SDL_GamepadDeviceEvent */ typedef struct SDL_GamepadTouchpadEvent { - Uint32 type; /**< ::SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN or ::SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION or ::SDL_EVENT_GAMEPAD_TOUCHPAD_UP */ + SDL_EventType type; /**< ::SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN or ::SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION or ::SDL_EVENT_GAMEPAD_TOUCHPAD_UP */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Sint32 touchpad; /**< The index of the touchpad */ @@ -483,7 +557,8 @@ typedef struct SDL_GamepadTouchpadEvent */ typedef struct SDL_GamepadSensorEvent { - Uint32 type; /**< ::SDL_EVENT_GAMEPAD_SENSOR_UPDATE */ + SDL_EventType type; /**< ::SDL_EVENT_GAMEPAD_SENSOR_UPDATE */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_JoystickID which; /**< The joystick instance id */ Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */ @@ -496,7 +571,8 @@ typedef struct SDL_GamepadSensorEvent */ typedef struct SDL_AudioDeviceEvent { - Uint32 type; /**< ::SDL_EVENT_AUDIO_DEVICE_ADDED, or ::SDL_EVENT_AUDIO_DEVICE_REMOVED, or ::SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED */ + SDL_EventType type; /**< ::SDL_EVENT_AUDIO_DEVICE_ADDED, or ::SDL_EVENT_AUDIO_DEVICE_REMOVED, or ::SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_AudioDeviceID which; /**< SDL_AudioDeviceID for the device being added or removed or changing */ Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */ @@ -505,16 +581,30 @@ typedef struct SDL_AudioDeviceEvent Uint8 padding3; } SDL_AudioDeviceEvent; +/** + * Camera device event structure (event.cdevice.*) + */ +typedef struct SDL_CameraDeviceEvent +{ + SDL_EventType type; /**< ::SDL_EVENT_CAMERA_DEVICE_ADDED, ::SDL_EVENT_CAMERA_DEVICE_REMOVED, ::SDL_EVENT_CAMERA_DEVICE_APPROVED, ::SDL_EVENT_CAMERA_DEVICE_DENIED */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_CameraDeviceID which; /**< SDL_CameraDeviceID for the device being added or removed or changing */ + Uint8 padding1; + Uint8 padding2; + Uint8 padding3; +} SDL_CameraDeviceEvent; /** * Touch finger event structure (event.tfinger.*) */ typedef struct SDL_TouchFingerEvent { - Uint32 type; /**< ::SDL_EVENT_FINGER_MOTION or ::SDL_EVENT_FINGER_DOWN or ::SDL_EVENT_FINGER_UP */ + SDL_EventType type; /**< ::SDL_EVENT_FINGER_MOTION or ::SDL_EVENT_FINGER_DOWN or ::SDL_EVENT_FINGER_UP */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - SDL_TouchID touchId; /**< The touch device id */ - SDL_FingerID fingerId; + SDL_TouchID touchID; /**< The touch device id */ + SDL_FingerID fingerID; float x; /**< Normalized in the range 0...1 */ float y; /**< Normalized in the range 0...1 */ float dx; /**< Normalized in the range -1...1 */ @@ -530,17 +620,16 @@ typedef struct SDL_TouchFingerEvent */ typedef struct SDL_PenTipEvent { - Uint32 type; /**< ::SDL_EVENT_PEN_DOWN or ::SDL_EVENT_PEN_UP */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - Uint32 windowID; /**< The window with pen focus, if any */ - SDL_PenID which; /**< The pen instance id */ - Uint8 tip; /**< ::SDL_PEN_TIP_INK when using a regular pen tip, or ::SDL_PEN_TIP_ERASER if the pen is being used as an eraser (e.g., flipped to use the eraser tip) */ - Uint8 state; /**< ::SDL_PRESSED on ::SDL_EVENT_PEN_DOWN and ::SDL_RELEASED on ::SDL_EVENT_PEN_UP */ - Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), - ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and - ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ - float x; /**< X coordinate, relative to window */ - float y; /**< Y coordinate, relative to window */ + SDL_EventType type; /**< ::SDL_EVENT_PEN_DOWN or ::SDL_EVENT_PEN_UP */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_WindowID windowID; /**< The window with pen focus, if any */ + SDL_PenID which; /**< The pen instance id */ + Uint8 tip; /**< ::SDL_PEN_TIP_INK when using a regular pen tip, or ::SDL_PEN_TIP_ERASER if the pen is being used as an eraser (e.g., flipped to use the eraser tip) */ + Uint8 state; /**< ::SDL_PRESSED on ::SDL_EVENT_PEN_DOWN and ::SDL_RELEASED on ::SDL_EVENT_PEN_UP */ + Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ + float x; /**< X coordinate, relative to window */ + float y; /**< Y coordinate, relative to window */ float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */ } SDL_PenTipEvent; @@ -549,17 +638,16 @@ typedef struct SDL_PenTipEvent */ typedef struct SDL_PenMotionEvent { - Uint32 type; /**< ::SDL_EVENT_PEN_MOTION */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - Uint32 windowID; /**< The window with pen focus, if any */ - SDL_PenID which; /**< The pen instance id */ + SDL_EventType type; /**< ::SDL_EVENT_PEN_MOTION */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_WindowID windowID; /**< The window with pen focus, if any */ + SDL_PenID which; /**< The pen instance id */ Uint8 padding1; Uint8 padding2; - Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), - ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and - ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ - float x; /**< X coordinate, relative to window */ - float y; /**< Y coordinate, relative to window */ + Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ + float x; /**< X coordinate, relative to window */ + float y; /**< Y coordinate, relative to window */ float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */ } SDL_PenMotionEvent; @@ -568,17 +656,16 @@ typedef struct SDL_PenMotionEvent */ typedef struct SDL_PenButtonEvent { - Uint32 type; /**< ::SDL_EVENT_PEN_BUTTON_DOWN or ::SDL_EVENT_PEN_BUTTON_UP */ - Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ - Uint32 windowID; /**< The window with pen focus, if any */ - SDL_PenID which; /**< The pen instance id */ - Uint8 button; /**< The pen button index (1 represents the pen tip for compatibility with mouse events) */ - Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ - Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), - ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and - ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ - float x; /**< X coordinate, relative to window */ - float y; /**< Y coordinate, relative to window */ + SDL_EventType type; /**< ::SDL_EVENT_PEN_BUTTON_DOWN or ::SDL_EVENT_PEN_BUTTON_UP */ + Uint32 reserved; + Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ + SDL_WindowID windowID; /**< The window with pen focus, if any */ + SDL_PenID which; /**< The pen instance id */ + Uint8 button; /**< The pen button index (1 represents the pen tip for compatibility with mouse events) */ + Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ + Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), ::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and ::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */ + float x; /**< X coordinate, relative to window */ + float y; /**< Y coordinate, relative to window */ float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */ } SDL_PenButtonEvent; @@ -590,7 +677,8 @@ typedef struct SDL_PenButtonEvent */ typedef struct SDL_DropEvent { - Uint32 type; /**< ::SDL_EVENT_DROP_BEGIN or ::SDL_EVENT_DROP_FILE or ::SDL_EVENT_DROP_TEXT or ::SDL_EVENT_DROP_COMPLETE or ::SDL_EVENT_DROP_POSITION */ + SDL_EventType type; /**< ::SDL_EVENT_DROP_BEGIN or ::SDL_EVENT_DROP_FILE or ::SDL_EVENT_DROP_TEXT or ::SDL_EVENT_DROP_COMPLETE or ::SDL_EVENT_DROP_POSITION */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The window that was dropped on, if any */ float x; /**< X coordinate, relative to window (not on begin) */ @@ -604,7 +692,8 @@ typedef struct SDL_DropEvent */ typedef struct SDL_ClipboardEvent { - Uint32 type; /**< ::SDL_EVENT_CLIPBOARD_UPDATE */ + SDL_EventType type; /**< ::SDL_EVENT_CLIPBOARD_UPDATE */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_ClipboardEvent; @@ -613,7 +702,8 @@ typedef struct SDL_ClipboardEvent */ typedef struct SDL_SensorEvent { - Uint32 type; /**< ::SDL_EVENT_SENSOR_UPDATE */ + SDL_EventType type; /**< ::SDL_EVENT_SENSOR_UPDATE */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_SensorID which; /**< The instance ID of the sensor */ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_GetSensorData() */ @@ -625,7 +715,8 @@ typedef struct SDL_SensorEvent */ typedef struct SDL_QuitEvent { - Uint32 type; /**< ::SDL_EVENT_QUIT */ + SDL_EventType type; /**< ::SDL_EVENT_QUIT */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ } SDL_QuitEvent; @@ -634,7 +725,8 @@ typedef struct SDL_QuitEvent */ typedef struct SDL_UserEvent { - Uint32 type; /**< ::SDL_EVENT_USER through ::SDL_EVENT_LAST-1 */ + Uint32 type; /**< ::SDL_EVENT_USER through ::SDL_EVENT_LAST-1, Uint32 because these are not in the SDL_EventType enumeration */ + Uint32 reserved; Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */ SDL_WindowID windowID; /**< The associated window if any */ Sint32 code; /**< User defined event code */ @@ -648,27 +740,31 @@ typedef struct SDL_UserEvent */ typedef union SDL_Event { - Uint32 type; /**< Event type, shared with all events */ + Uint32 type; /**< Event type, shared with all events, Uint32 to cover user events which are not in the SDL_EventType enumeration */ SDL_CommonEvent common; /**< Common event data */ SDL_DisplayEvent display; /**< Display event data */ SDL_WindowEvent window; /**< Window event data */ + SDL_KeyboardDeviceEvent kdevice; /**< Keyboard device change event data */ SDL_KeyboardEvent key; /**< Keyboard event data */ SDL_TextEditingEvent edit; /**< Text editing event data */ SDL_TextInputEvent text; /**< Text input event data */ + SDL_MouseDeviceEvent mdevice; /**< Mouse device change event data */ SDL_MouseMotionEvent motion; /**< Mouse motion event data */ SDL_MouseButtonEvent button; /**< Mouse button event data */ SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */ + SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */ SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */ + SDL_JoyBallEvent jball; /**< Joystick ball event data */ SDL_JoyHatEvent jhat; /**< Joystick hat event data */ SDL_JoyButtonEvent jbutton; /**< Joystick button event data */ - SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */ SDL_JoyBatteryEvent jbattery; /**< Joystick battery event data */ + SDL_GamepadDeviceEvent gdevice; /**< Gamepad device event data */ SDL_GamepadAxisEvent gaxis; /**< Gamepad axis event data */ SDL_GamepadButtonEvent gbutton; /**< Gamepad button event data */ - SDL_GamepadDeviceEvent gdevice; /**< Gamepad device event data */ SDL_GamepadTouchpadEvent gtouchpad; /**< Gamepad touchpad event data */ SDL_GamepadSensorEvent gsensor; /**< Gamepad sensor event data */ SDL_AudioDeviceEvent adevice; /**< Audio device event data */ + SDL_CameraDeviceEvent cdevice; /**< Camera device event data */ SDL_SensorEvent sensor; /**< Sensor event data */ SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ @@ -823,6 +919,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasEvents(Uint32 minType, Uint32 maxType); * sure that all pending OS events are flushed, you can call SDL_PumpEvents() * on the main thread immediately before the flush call. * + * If you have user events with custom data that needs to be freed, you should + * use SDL_PeepEvents() to remove and clean up those events before calling + * this function. + * * \param type the type of event to be cleared; see SDL_EventType for details * * \since This function is available since SDL 3.0.0. @@ -1151,15 +1251,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_EventEnabled(Uint32 type); * Allocate a set of user-defined events, and return the beginning event * number for that set of events. * - * Calling this function with `numevents` <= 0 is an error and will return - * (Uint32)-1. - * - * Note, (Uint32)-1 means the maximum unsigned 32-bit integer value (or - * 0xFFFFFFFF), but is clearer to write. - * * \param numevents the number of events to be allocated - * \returns the beginning event number, or (Uint32)-1 if there are not enough - * user-defined events left. + * \returns the beginning event number, or 0 if numevents is invalid or if + * there are not enough user-defined events left. * * \since This function is available since SDL 3.0.0. * diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index 8ee4d2c2..239a6513 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -206,8 +206,8 @@ typedef enum } SDL_Folder; /** - * Finds the most suitable user folder for @p purpose, and returns its path in - * OS-specific notation. + * Finds the most suitable user folder for the specified purpose, and returns + * its path in OS-specific notation. * * Many OSes provide certain standard folders for certain purposes, such as * storing pictures, music or videos for a certain user. This function gives @@ -231,11 +231,92 @@ typedef enum * folder, or NULL if an error happened. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_Folder */ extern DECLSPEC char *SDLCALL SDL_GetUserFolder(SDL_Folder folder); + +/* Abstract filesystem interface */ + +typedef enum SDL_PathType +{ + SDL_PATHTYPE_NONE, /**< path does not exist */ + SDL_PATHTYPE_FILE, /**< a normal file */ + SDL_PATHTYPE_DIRECTORY, /**< a directory */ + SDL_PATHTYPE_OTHER /**< something completely different like a device node (not a symlink, those are always followed) */ +} SDL_PathType; + +typedef struct SDL_PathInfo +{ + SDL_PathType type; /* the path type */ + Uint64 size; /* the file size in bytes */ + SDL_Time create_time; /* the time when the path was created */ + SDL_Time modify_time; /* the last time the path was modified */ + SDL_Time access_time; /* the last time the path was read */ +} SDL_PathInfo; + +/** + * Create a directory. + * + * \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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_CreateDirectory(const char *path); + +/* Callback for directory enumeration. Return 1 to keep enumerating, 0 to stop enumerating (no error), -1 to stop enumerating and report an error. `dirname` is the directory being enumerated, `fname` is the enumerated entry. */ +typedef int (SDLCALL *SDL_EnumerateDirectoryCallback)(void *userdata, const char *dirname, const char *fname); + +/** + * Enumerate a directory. + * + * \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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata); + +/** + * Remove a file or an empty directory. + * + * \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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_RemovePath(const char *path); + +/** + * Rename a file or directory. + * + * \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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_RenamePath(const char *oldpath, const char *newpath); + +/** + * Get information about a filesystem path. + * + * \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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_GetPathInfo(const char *path, SDL_PathInfo *info); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 98af9a17..7a9b7e82 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include @@ -113,12 +113,17 @@ typedef enum SDL_GAMEPAD_BUTTON_DPAD_DOWN, SDL_GAMEPAD_BUTTON_DPAD_LEFT, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - SDL_GAMEPAD_BUTTON_MISC1, /* Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button) */ + SDL_GAMEPAD_BUTTON_MISC1, /* Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button, Google Stadia capture button) */ SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, /* Upper or primary paddle, under your right hand (e.g. Xbox Elite paddle P1) */ SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, /* Upper or primary paddle, under your left hand (e.g. Xbox Elite paddle P3) */ SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, /* Lower or secondary paddle, under your right hand (e.g. Xbox Elite paddle P2) */ SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, /* Lower or secondary paddle, under your left hand (e.g. Xbox Elite paddle P4) */ SDL_GAMEPAD_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */ + SDL_GAMEPAD_BUTTON_MISC2, /* Additional button */ + SDL_GAMEPAD_BUTTON_MISC3, /* Additional button */ + SDL_GAMEPAD_BUTTON_MISC4, /* Additional button */ + SDL_GAMEPAD_BUTTON_MISC5, /* Additional button */ + SDL_GAMEPAD_BUTTON_MISC6, /* Additional button */ SDL_GAMEPAD_BUTTON_MAX } SDL_GamepadButton; @@ -173,9 +178,9 @@ typedef enum SDL_GAMEPAD_BINDTYPE_HAT } SDL_GamepadBindingType; -typedef struct +typedef struct SDL_GamepadBinding { - SDL_GamepadBindingType inputType; + SDL_GamepadBindingType input_type; union { int button; @@ -195,7 +200,7 @@ typedef struct } input; - SDL_GamepadBindingType outputType; + SDL_GamepadBindingType output_type; union { SDL_GamepadButton button; @@ -246,7 +251,7 @@ typedef struct extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping); /** - * Load a set of gamepad mappings from a seekable SDL data stream. + * Load a set of gamepad mappings from an SDL_IOStream. * * You can call this function several times, if needed, to load different * database files. @@ -263,7 +268,7 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping); * constrained environment. * * \param src the data stream for the mappings to be added - * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning, + * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `src` before returning, * even in the case of an error * \returns the number of mappings added or -1 on error; call SDL_GetError() * for more information. @@ -272,9 +277,10 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMapping(const char *mapping); * * \sa SDL_AddGamepadMapping * \sa SDL_AddGamepadMappingsFromFile + * \sa SDL_GetGamepadMapping * \sa SDL_GetGamepadMappingForGUID */ -extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc); +extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromIO(SDL_IOStream *src, SDL_bool closeio); /** * Load a set of gamepad mappings from a file. @@ -296,7 +302,8 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_boo * \since This function is available since SDL 3.0.0. * * \sa SDL_AddGamepadMapping - * \sa SDL_AddGamepadMappingsFromRW + * \sa SDL_AddGamepadMappingsFromIO + * \sa SDL_GetGamepadMapping * \sa SDL_GetGamepadMappingForGUID */ extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromFile(const char *file); @@ -314,7 +321,7 @@ extern DECLSPEC int SDLCALL SDL_AddGamepadMappingsFromFile(const char *file); extern DECLSPEC int SDLCALL SDL_ReloadGamepadMappings(void); /** - * Get the mapping at a particular index. + * Get the current gamepad mappings. * * You must free the returned pointer with SDL_free() when you are done with * it, but you do _not_ free each string in the array. @@ -358,6 +365,7 @@ extern DECLSPEC char * SDLCALL SDL_GetGamepadMappingForGUID(SDL_JoystickGUID gui * \since This function is available since SDL 3.0.0. * * \sa SDL_AddGamepadMapping + * \sa SDL_GetGamepadInstanceMapping * \sa SDL_GetGamepadMappingForGUID * \sa SDL_SetGamepadMapping */ @@ -381,6 +389,17 @@ extern DECLSPEC char * SDLCALL SDL_GetGamepadMapping(SDL_Gamepad *gamepad); */ extern DECLSPEC int SDLCALL SDL_SetGamepadMapping(SDL_JoystickID instance_id, const char *mapping); +/** + * Return whether a gamepad is currently connected. + * + * \returns SDL_TRUE if a gamepad is connected, SDL_FALSE otherwise. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepads + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasGamepad(void); + /** * Get a list of currently connected gamepads. * @@ -391,6 +410,7 @@ extern DECLSPEC int SDLCALL SDL_SetGamepadMapping(SDL_JoystickID instance_id, co * * \since This function is available since SDL 3.0.0. * + * \sa SDL_HasGamepad * \sa SDL_OpenGamepad */ extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetGamepads(int *count); @@ -404,6 +424,7 @@ extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetGamepads(int *count); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetJoysticks * \sa SDL_OpenGamepad */ extern DECLSPEC SDL_bool SDLCALL SDL_IsGamepad(SDL_JoystickID instance_id); @@ -420,7 +441,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsGamepad(SDL_JoystickID instance_id); * \since This function is available since SDL 3.0.0. * * \sa SDL_GetGamepadName - * \sa SDL_OpenGamepad + * \sa SDL_GetGamepads */ extern DECLSPEC const char *SDLCALL SDL_GetGamepadInstanceName(SDL_JoystickID instance_id); @@ -436,7 +457,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetGamepadInstanceName(SDL_JoystickID in * \since This function is available since SDL 3.0.0. * * \sa SDL_GetGamepadPath - * \sa SDL_OpenGamepad + * \sa SDL_GetGamepads */ extern DECLSPEC const char *SDLCALL SDL_GetGamepadInstancePath(SDL_JoystickID instance_id); @@ -451,7 +472,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetGamepadInstancePath(SDL_JoystickID in * \since This function is available since SDL 3.0.0. * * \sa SDL_GetGamepadPlayerIndex - * \sa SDL_OpenGamepad + * \sa SDL_GetGamepads */ extern DECLSPEC int SDLCALL SDL_GetGamepadInstancePlayerIndex(SDL_JoystickID instance_id); @@ -468,6 +489,7 @@ extern DECLSPEC int SDLCALL SDL_GetGamepadInstancePlayerIndex(SDL_JoystickID ins * * \sa SDL_GetGamepadGUID * \sa SDL_GetGamepadGUIDString + * \sa SDL_GetGamepads */ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetGamepadInstanceGUID(SDL_JoystickID instance_id); @@ -482,6 +504,9 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetGamepadInstanceGUID(SDL_Joystick * index, this function returns zero * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadVendor + * \sa SDL_GetGamepads */ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceVendor(SDL_JoystickID instance_id); @@ -496,6 +521,9 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceVendor(SDL_JoystickID insta * invalid index, this function returns zero * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadProduct + * \sa SDL_GetGamepads */ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProduct(SDL_JoystickID instance_id); @@ -510,6 +538,9 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProduct(SDL_JoystickID inst * invalid index, this function returns zero * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadProductVersion + * \sa SDL_GetGamepads */ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProductVersion(SDL_JoystickID instance_id); @@ -522,6 +553,10 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadInstanceProductVersion(SDL_Joystick * \returns the gamepad type. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadType + * \sa SDL_GetGamepads + * \sa SDL_GetRealGamepadInstanceType */ extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadInstanceType(SDL_JoystickID instance_id); @@ -534,6 +569,10 @@ extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadInstanceType(SDL_JoystickI * \returns the gamepad type. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadInstanceType + * \sa SDL_GetGamepads + * \sa SDL_GetRealGamepadType */ extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadInstanceType(SDL_JoystickID instance_id); @@ -547,6 +586,9 @@ extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadInstanceType(SDL_Joyst * no mapping is available. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepads + * \sa SDL_GetGamepadMapping */ extern DECLSPEC char *SDLCALL SDL_GetGamepadInstanceMapping(SDL_JoystickID instance_id); @@ -594,6 +636,19 @@ extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromPlayerIndex(int player_in * * These properties are shared with the underlying joystick object. * + * The following read-only properties are provided by SDL: + * + * - `SDL_PROP_GAMEPAD_CAP_MONO_LED_BOOLEAN`: true if this gamepad has an LED + * that has adjustable brightness + * - `SDL_PROP_GAMEPAD_CAP_RGB_LED_BOOLEAN`: true if this gamepad has an LED + * that has adjustable color + * - `SDL_PROP_GAMEPAD_CAP_PLAYER_LED_BOOLEAN`: true if this gamepad has a + * player LED + * - `SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN`: true if this gamepad has + * left/right rumble + * - `SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN`: true if this gamepad has + * simple trigger rumble + * * \param gamepad a gamepad identifier previously returned by * SDL_OpenGamepad() * \returns a valid property ID on success or 0 on failure; call @@ -606,6 +661,12 @@ extern DECLSPEC SDL_Gamepad *SDLCALL SDL_GetGamepadFromPlayerIndex(int player_in */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGamepadProperties(SDL_Gamepad *gamepad); +#define SDL_PROP_GAMEPAD_CAP_MONO_LED_BOOLEAN SDL_PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN +#define SDL_PROP_GAMEPAD_CAP_RGB_LED_BOOLEAN SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN +#define SDL_PROP_GAMEPAD_CAP_PLAYER_LED_BOOLEAN SDL_PROP_JOYSTICK_CAP_PLAYER_LED_BOOLEAN +#define SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN +#define SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN + /** * Get the instance ID of an opened gamepad. * @@ -615,8 +676,6 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGamepadProperties(SDL_Gamepad *g * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_OpenGamepad */ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetGamepadInstanceID(SDL_Gamepad *gamepad); @@ -631,7 +690,6 @@ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetGamepadInstanceID(SDL_Gamepad *gam * \since This function is available since SDL 3.0.0. * * \sa SDL_GetGamepadInstanceName - * \sa SDL_OpenGamepad */ extern DECLSPEC const char *SDLCALL SDL_GetGamepadName(SDL_Gamepad *gamepad); @@ -684,6 +742,8 @@ extern DECLSPEC SDL_GamepadType SDLCALL SDL_GetRealGamepadType(SDL_Gamepad *game * \returns the player index for gamepad, or -1 if it's not available. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetGamepadPlayerIndex */ extern DECLSPEC int SDLCALL SDL_GetGamepadPlayerIndex(SDL_Gamepad *gamepad); @@ -697,6 +757,8 @@ extern DECLSPEC int SDLCALL SDL_GetGamepadPlayerIndex(SDL_Gamepad *gamepad); * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadPlayerIndex */ extern DECLSPEC int SDLCALL SDL_SetGamepadPlayerIndex(SDL_Gamepad *gamepad, int player_index); @@ -709,6 +771,8 @@ extern DECLSPEC int SDLCALL SDL_SetGamepadPlayerIndex(SDL_Gamepad *gamepad, int * \returns the USB vendor ID, or zero if unavailable. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadInstanceVendor */ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadVendor(SDL_Gamepad *gamepad); @@ -721,6 +785,8 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadVendor(SDL_Gamepad *gamepad); * \returns the USB product ID, or zero if unavailable. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadInstanceProduct */ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadProduct(SDL_Gamepad *gamepad); @@ -733,6 +799,8 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadProduct(SDL_Gamepad *gamepad); * \returns the USB product version, or zero if unavailable. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadInstanceProductVersion */ extern DECLSPEC Uint16 SDLCALL SDL_GetGamepadProductVersion(SDL_Gamepad *gamepad); @@ -794,9 +862,6 @@ extern DECLSPEC SDL_JoystickPowerLevel SDLCALL SDL_GetGamepadPowerLevel(SDL_Game * connected, or SDL_FALSE if not. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CloseGamepad - * \sa SDL_OpenGamepad */ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadConnected(SDL_Gamepad *gamepad); @@ -830,6 +895,7 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetGamepadJoystick(SDL_Gamepad *gamepa * \since This function is available since SDL 3.0.0. * * \sa SDL_GamepadEventsEnabled + * \sa SDL_UpdateGamepads */ extern DECLSPEC void SDLCALL SDL_SetGamepadEventsEnabled(SDL_bool enabled); @@ -942,7 +1008,7 @@ extern DECLSPEC SDL_GamepadAxis SDLCALL SDL_GetGamepadAxisFromString(const char * * \sa SDL_GetGamepadAxisFromString */ -extern DECLSPEC const char* SDLCALL SDL_GetGamepadStringForAxis(SDL_GamepadAxis axis); +extern DECLSPEC const char * SDLCALL SDL_GetGamepadStringForAxis(SDL_GamepadAxis axis); /** * Query whether a gamepad has a given axis. @@ -955,6 +1021,9 @@ extern DECLSPEC const char* SDLCALL SDL_GetGamepadStringForAxis(SDL_GamepadAxis * \returns SDL_TRUE if the gamepad has this axis, SDL_FALSE otherwise. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GamepadHasButton + * \sa SDL_GetGamepadAxis */ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis); @@ -977,6 +1046,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_Ga * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GamepadHasAxis * \sa SDL_GetGamepadButton */ extern DECLSPEC Sint16 SDLCALL SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis); @@ -994,6 +1064,8 @@ extern DECLSPEC Sint16 SDLCALL SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_Game * `SDL_GAMEPAD_BUTTON_INVALID` if no match was found. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadStringForButton */ extern DECLSPEC SDL_GamepadButton SDLCALL SDL_GetGamepadButtonFromString(const char *str); @@ -1024,6 +1096,8 @@ extern DECLSPEC const char* SDLCALL SDL_GetGamepadStringForButton(SDL_GamepadBut * \returns SDL_TRUE if the gamepad has this button, SDL_FALSE otherwise. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GamepadHasAxis */ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_GamepadButton button); @@ -1037,6 +1111,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_ * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GamepadHasButton * \sa SDL_GetGamepadAxis */ extern DECLSPEC Uint8 SDLCALL SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button); @@ -1074,6 +1149,8 @@ extern DECLSPEC SDL_GamepadButtonLabel SDLCALL SDL_GetGamepadButtonLabel(SDL_Gam * \returns number of touchpads * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetNumGamepadTouchpadFingers */ extern DECLSPEC int SDLCALL SDL_GetNumGamepadTouchpads(SDL_Gamepad *gamepad); @@ -1086,6 +1163,9 @@ extern DECLSPEC int SDLCALL SDL_GetNumGamepadTouchpads(SDL_Gamepad *gamepad); * \returns number of supported simultaneous fingers * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadTouchpadFinger + * \sa SDL_GetNumGamepadTouchpads */ extern DECLSPEC int SDLCALL SDL_GetNumGamepadTouchpadFingers(SDL_Gamepad *gamepad, int touchpad); @@ -1103,6 +1183,8 @@ extern DECLSPEC int SDLCALL SDL_GetNumGamepadTouchpadFingers(SDL_Gamepad *gamepa * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetNumGamepadTouchpadFingers */ extern DECLSPEC int SDLCALL SDL_GetGamepadTouchpadFinger(SDL_Gamepad *gamepad, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure); @@ -1114,6 +1196,10 @@ extern DECLSPEC int SDLCALL SDL_GetGamepadTouchpadFinger(SDL_Gamepad *gamepad, i * \returns SDL_TRUE if the sensor exists, SDL_FALSE otherwise. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetGamepadSensorData + * \sa SDL_GetGamepadSensorDataRate + * \sa SDL_SetGamepadSensorEnabled */ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasSensor(SDL_Gamepad *gamepad, SDL_SensorType type); @@ -1127,6 +1213,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasSensor(SDL_Gamepad *gamepad, SDL_ * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GamepadHasSensor + * \sa SDL_GamepadSensorEnabled */ extern DECLSPEC int SDLCALL SDL_SetGamepadSensorEnabled(SDL_Gamepad *gamepad, SDL_SensorType type, SDL_bool enabled); @@ -1138,6 +1227,8 @@ extern DECLSPEC int SDLCALL SDL_SetGamepadSensorEnabled(SDL_Gamepad *gamepad, SD * \returns SDL_TRUE if the sensor is enabled, SDL_FALSE otherwise. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetGamepadSensorEnabled */ extern DECLSPEC SDL_bool SDLCALL SDL_GamepadSensorEnabled(SDL_Gamepad *gamepad, SDL_SensorType type); @@ -1175,6 +1266,9 @@ extern DECLSPEC int SDLCALL SDL_GetGamepadSensorData(SDL_Gamepad *gamepad, SDL_S * Each call to this function cancels any previous rumble effect, and calling * it with 0 intensity stops any rumbling. * + * This function requires you to process SDL events or call + * SDL_UpdateJoysticks() to update rumble state. + * * \param gamepad The gamepad to vibrate * \param low_frequency_rumble The intensity of the low frequency (left) * rumble motor, from 0 to 0xFFFF @@ -1184,8 +1278,6 @@ extern DECLSPEC int SDLCALL SDL_GetGamepadSensorData(SDL_Gamepad *gamepad, SDL_S * \returns 0, or -1 if rumble isn't supported on this gamepad * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GamepadHasRumble */ extern DECLSPEC int SDLCALL SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); @@ -1199,6 +1291,9 @@ extern DECLSPEC int SDLCALL SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 low_f * whole. This is currently only supported on Xbox One gamepads. If you want * the (more common) whole-gamepad rumble, use SDL_RumbleGamepad() instead. * + * This function requires you to process SDL events or call + * SDL_UpdateJoysticks() to update rumble state. + * * \param gamepad The gamepad to vibrate * \param left_rumble The intensity of the left trigger rumble motor, from 0 * to 0xFFFF @@ -1210,50 +1305,19 @@ extern DECLSPEC int SDLCALL SDL_RumbleGamepad(SDL_Gamepad *gamepad, Uint16 low_f * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GamepadHasRumbleTriggers + * \sa SDL_RumbleGamepad */ extern DECLSPEC int SDLCALL SDL_RumbleGamepadTriggers(SDL_Gamepad *gamepad, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); -/** - * Query whether a gamepad has an LED. - * - * \param gamepad The gamepad to query - * \returns SDL_TRUE, or SDL_FALSE if this gamepad does not have a modifiable - * LED - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasLED(SDL_Gamepad *gamepad); - -/** - * Query whether a gamepad has rumble support. - * - * \param gamepad The gamepad to query - * \returns SDL_TRUE, or SDL_FALSE if this gamepad does not have rumble - * support - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_RumbleGamepad - */ -extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasRumble(SDL_Gamepad *gamepad); - -/** - * Query whether a gamepad has rumble support on triggers. - * - * \param gamepad The gamepad to query - * \returns SDL_TRUE, or SDL_FALSE if this gamepad does not have trigger - * rumble support - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_RumbleGamepadTriggers - */ -extern DECLSPEC SDL_bool SDLCALL SDL_GamepadHasRumbleTriggers(SDL_Gamepad *gamepad); - /** * Update a gamepad's LED color. * + * An example of a joystick LED is the light on the back of a PlayStation 4's + * DualShock 4 controller. + * + * For gamepads with a single color LED, the maximum of the RGB values will be + * used as the LED brightness. + * * \param gamepad The gamepad to update * \param red The intensity of the red LED * \param green The intensity of the green LED diff --git a/include/SDL3/SDL_guid.h b/include/SDL3/SDL_guid.h index accb4d9a..30abc274 100644 --- a/include/SDL3/SDL_guid.h +++ b/include/SDL3/SDL_guid.h @@ -52,7 +52,7 @@ extern "C" { * GUIDs may be platform-dependent (i.e., the same device may report * different GUIDs on different operating systems). */ -typedef struct { +typedef struct SDL_GUID { Uint8 data[16]; } SDL_GUID; diff --git a/include/SDL3/SDL_haptic.h b/include/SDL3/SDL_haptic.h index 75709944..3bc17b8a 100644 --- a/include/SDL3/SDL_haptic.h +++ b/include/SDL3/SDL_haptic.h @@ -27,55 +27,60 @@ * The basic usage is as follows: * - Initialize the subsystem (::SDL_INIT_HAPTIC). * - Open a haptic device. - * - SDL_HapticOpen() to open from index. - * - SDL_HapticOpenFromJoystick() to open from an existing joystick. + * - SDL_OpenHaptic() to open from index. + * - SDL_OpenHapticFromJoystick() to open from an existing joystick. * - Create an effect (::SDL_HapticEffect). - * - Upload the effect with SDL_HapticNewEffect(). - * - Run the effect with SDL_HapticRunEffect(). - * - (optional) Free the effect with SDL_HapticDestroyEffect(). - * - Close the haptic device with SDL_HapticClose(). + * - Upload the effect with SDL_CreateHapticEffect(). + * - Run the effect with SDL_RunHapticEffect(). + * - (optional) Free the effect with SDL_DestroyHapticEffect(). + * - Close the haptic device with SDL_CloseHaptic(). * * \par Simple rumble example: * \code - * SDL_Haptic *haptic; + * SDL_Haptic *haptic = NULL; * * // Open the device - * haptic = SDL_HapticOpen( 0 ); + * SDL_HapticID *haptics = SDL_GetHaptics(NULL); + * if (haptics) { + * haptic = SDL_OpenHaptic(haptics[0]); + * SDL_free(haptics); + * } * if (haptic == NULL) * return -1; * * // Initialize simple rumble - * if (SDL_HapticRumbleInit( haptic ) != 0) + * if (SDL_InitHapticRumble(haptic) != 0) * return -1; * * // Play effect at 50% strength for 2 seconds - * if (SDL_HapticRumblePlay( haptic, 0.5, 2000 ) != 0) + * if (SDL_PlayHapticRumble(haptic, 0.5, 2000) != 0) * return -1; - * SDL_Delay( 2000 ); + * SDL_Delay(2000); * * // Clean up - * SDL_HapticClose( haptic ); + * SDL_CloseHaptic(haptic); * \endcode * * \par Complete example: * \code - * int test_haptic( SDL_Joystick * joystick ) { + * int test_haptic(SDL_Joystick *joystick) + * { * SDL_Haptic *haptic; * SDL_HapticEffect effect; * int effect_id; * * // Open the device - * haptic = SDL_HapticOpenFromJoystick( joystick ); + * haptic = SDL_OpenHapticFromJoystick(joystick); * if (haptic == NULL) return -1; // Most likely joystick isn't haptic * * // See if it can do sine waves - * if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_SINE)==0) { - * SDL_HapticClose(haptic); // No sine effect + * if ((SDL_GetHapticFeatures(haptic) & SDL_HAPTIC_SINE)==0) { + * SDL_CloseHaptic(haptic); // No sine effect * return -1; * } * * // Create the effect - * SDL_memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default + * SDL_memset(&effect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default * effect.type = SDL_HAPTIC_SINE; * effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates * effect.periodic.direction.dir[0] = 18000; // Force comes from south @@ -86,21 +91,23 @@ * effect.periodic.fade_length = 1000; // Takes 1 second to fade away * * // Upload the effect - * effect_id = SDL_HapticNewEffect( haptic, &effect ); + * effect_id = SDL_CreateHapticEffect(haptic, &effect); * * // Test the effect - * SDL_HapticRunEffect( haptic, effect_id, 1 ); - * SDL_Delay( 5000); // Wait for the effect to finish + * SDL_RunHapticEffect(haptic, effect_id, 1); + * SDL_Delay(5000); // Wait for the effect to finish * * // We destroy the effect, although closing the device also does this - * SDL_HapticDestroyEffect( haptic, effect_id ); + * SDL_DestroyHapticEffect(haptic, effect_id); * * // Close the device - * SDL_HapticClose(haptic); + * SDL_CloseHaptic(haptic); * * return 0; // Success * } * \endcode + * + * Note that the SDL haptic subsystem is not thread-safe. */ #ifndef SDL_haptic_h_ @@ -132,9 +139,9 @@ extern "C" { * * The haptic structure used to identify an SDL haptic. * - * \sa SDL_HapticOpen - * \sa SDL_HapticOpenFromJoystick - * \sa SDL_HapticClose + * \sa SDL_OpenHaptic + * \sa SDL_OpenHapticFromJoystick + * \sa SDL_CloseHaptic */ struct SDL_Haptic; typedef struct SDL_Haptic SDL_Haptic; @@ -159,7 +166,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_CONSTANT (1u<<0) +#define SDL_HAPTIC_CONSTANT (1u<<0) /** * Sine wave effect supported. @@ -168,21 +175,16 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_SINE (1u<<1) +#define SDL_HAPTIC_SINE (1u<<1) /** - * Left/Right effect supported. + * Square wave effect supported. * - * Haptic effect for direct control over high/low frequency motors. + * Periodic haptic effect that simulates square waves. * - * \sa SDL_HapticLeftRight - * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry, - * we ran out of bits, and this is important for XInput devices. + * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_LEFTRIGHT (1u<<2) - -/* !!! FIXME: put this back when we have more bits in 2.1 */ -/* #define SDL_HAPTIC_SQUARE (1<<2) */ +#define SDL_HAPTIC_SQUARE (1<<2) /** * Triangle wave effect supported. @@ -191,7 +193,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_TRIANGLE (1u<<3) +#define SDL_HAPTIC_TRIANGLE (1u<<3) /** * Sawtoothup wave effect supported. @@ -200,7 +202,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticPeriodic */ -#define SDL_HAPTIC_SAWTOOTHUP (1u<<4) +#define SDL_HAPTIC_SAWTOOTHUP (1u<<4) /** * Sawtoothdown wave effect supported. @@ -218,7 +220,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticRamp */ -#define SDL_HAPTIC_RAMP (1u<<6) +#define SDL_HAPTIC_RAMP (1u<<6) /** * Spring effect supported - uses axes position. @@ -228,7 +230,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_SPRING (1u<<7) +#define SDL_HAPTIC_SPRING (1u<<7) /** * Damper effect supported - uses axes velocity. @@ -238,7 +240,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_DAMPER (1u<<8) +#define SDL_HAPTIC_DAMPER (1u<<8) /** * Inertia effect supported - uses axes acceleration. @@ -248,7 +250,7 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_INERTIA (1u<<9) +#define SDL_HAPTIC_INERTIA (1u<<9) /** * Friction effect supported - uses axes movement. @@ -258,14 +260,30 @@ typedef struct SDL_Haptic SDL_Haptic; * * \sa SDL_HapticCondition */ -#define SDL_HAPTIC_FRICTION (1u<<10) +#define SDL_HAPTIC_FRICTION (1u<<10) + +/** + * Left/Right effect supported. + * + * Haptic effect for direct control over high/low frequency motors. + * + * \sa SDL_HapticLeftRight + */ +#define SDL_HAPTIC_LEFTRIGHT (1u<<11) + +/** + * Reserved for future use + */ +#define SDL_HAPTIC_RESERVED1 (1u<<12) +#define SDL_HAPTIC_RESERVED2 (1u<<13) +#define SDL_HAPTIC_RESERVED3 (1u<<14) /** * Custom effect is supported. * * User defined custom haptic effect. */ -#define SDL_HAPTIC_CUSTOM (1u<<11) +#define SDL_HAPTIC_CUSTOM (1u<<15) /* @} *//* Haptic effects */ @@ -276,37 +294,37 @@ typedef struct SDL_Haptic SDL_Haptic; * * Device supports setting the global gain. * - * \sa SDL_HapticSetGain + * \sa SDL_SetHapticGain */ -#define SDL_HAPTIC_GAIN (1u<<12) +#define SDL_HAPTIC_GAIN (1u<<16) /** * Device can set autocenter. * * Device supports setting autocenter. * - * \sa SDL_HapticSetAutocenter + * \sa SDL_SetHapticAutocenter */ -#define SDL_HAPTIC_AUTOCENTER (1u<<13) +#define SDL_HAPTIC_AUTOCENTER (1u<<17) /** * Device can be queried for effect status. * * Device supports querying effect status. * - * \sa SDL_HapticGetEffectStatus + * \sa SDL_GetHapticEffectStatus */ -#define SDL_HAPTIC_STATUS (1u<<14) +#define SDL_HAPTIC_STATUS (1u<<18) /** * Device can be paused. * * Devices supports being paused. * - * \sa SDL_HapticPause - * \sa SDL_HapticUnpause + * \sa SDL_PauseHaptic + * \sa SDL_ResumeHaptic */ -#define SDL_HAPTIC_PAUSE (1u<<15) +#define SDL_HAPTIC_PAUSE (1u<<19) /** @@ -356,7 +374,7 @@ typedef struct SDL_Haptic SDL_Haptic; /** * Used to play a device an infinite number of times. * - * \sa SDL_HapticRunEffect + * \sa SDL_RunHapticEffect */ #define SDL_HAPTIC_INFINITY 4294967295U @@ -455,7 +473,7 @@ typedef struct SDL_Haptic SDL_Haptic; * \sa SDL_HAPTIC_SPHERICAL * \sa SDL_HAPTIC_STEERING_AXIS * \sa SDL_HapticEffect - * \sa SDL_HapticNumAxes + * \sa SDL_GetNumHapticAxes */ typedef struct SDL_HapticDirection { @@ -504,7 +522,7 @@ typedef struct SDL_HapticConstant * * The struct handles the following effects: * - ::SDL_HAPTIC_SINE - * - ::SDL_HAPTIC_LEFTRIGHT + * - ::SDL_HAPTIC_SQUARE * - ::SDL_HAPTIC_TRIANGLE * - ::SDL_HAPTIC_SAWTOOTHUP * - ::SDL_HAPTIC_SAWTOOTHDOWN @@ -550,7 +568,7 @@ typedef struct SDL_HapticConstant \endverbatim * * \sa SDL_HAPTIC_SINE - * \sa SDL_HAPTIC_LEFTRIGHT + * \sa SDL_HAPTIC_SQUARE * \sa SDL_HAPTIC_TRIANGLE * \sa SDL_HAPTIC_SAWTOOTHUP * \sa SDL_HAPTIC_SAWTOOTHDOWN @@ -559,7 +577,7 @@ typedef struct SDL_HapticConstant typedef struct SDL_HapticPeriodic { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT, + 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. */ @@ -819,36 +837,46 @@ typedef union SDL_HapticEffect SDL_HapticCustom custom; /**< Custom effect. */ } 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. + * + * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. + */ +typedef Uint32 SDL_HapticID; + /* Function prototypes */ /** - * Count the number of haptic devices attached to the system. + * Get a list of currently connected haptic devices. * - * \returns the number of haptic devices detected on the system or a negative - * error code on failure; call SDL_GetError() for more information. + * \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. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticName + * \sa SDL_OpenHaptic */ -extern DECLSPEC int SDLCALL SDL_NumHaptics(void); +extern DECLSPEC SDL_HapticID *SDLCALL SDL_GetHaptics(int *count); /** * Get the implementation dependent name of a haptic device. * - * This can be called before any joysticks are opened. If no name can be - * found, this function returns NULL. + * This can be called before any haptic devices are opened. * - * \param device_index index of the device to query. - * \returns the name of the device or NULL on failure; call SDL_GetError() for - * more information. + * \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. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_NumHaptics + * \sa SDL_GetHapticName + * \sa SDL_OpenHaptic */ -extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index); +extern DECLSPEC const char *SDLCALL SDL_GetHapticInstanceName(SDL_HapticID instance_id); /** * Open a haptic device for use. @@ -857,53 +885,60 @@ extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index); * system. * * When opening a haptic device, its gain will be set to maximum and - * autocenter will be disabled. To modify these values use SDL_HapticSetGain() - * and SDL_HapticSetAutocenter(). + * autocenter will be disabled. To modify these values use SDL_SetHapticGain() + * and SDL_SetHapticAutocenter(). * - * \param device_index index of the device to open + * \param instance_id the haptic device instance ID * \returns the device identifier or NULL on failure; call SDL_GetError() for * more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticClose - * \sa SDL_HapticIndex - * \sa SDL_HapticOpenFromJoystick - * \sa SDL_HapticOpenFromMouse - * \sa SDL_HapticPause - * \sa SDL_HapticSetAutocenter - * \sa SDL_HapticSetGain - * \sa SDL_HapticStopAll + * \sa SDL_CloseHaptic + * \sa SDL_GetHaptics + * \sa SDL_OpenHapticFromJoystick + * \sa SDL_OpenHapticFromMouse + * \sa SDL_SetHapticAutocenter + * \sa SDL_SetHapticGain */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpen(int device_index); +extern DECLSPEC SDL_Haptic *SDLCALL SDL_OpenHaptic(SDL_HapticID instance_id); + /** - * Check if the haptic device at the designated index has been opened. + * Get the SDL_Haptic associated with an instance ID, if it has been opened. * - * \param device_index the index of the device to query - * \returns 1 if it has been opened, 0 if it hasn't or on failure; call - * SDL_GetError() for more information. + * \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. - * - * \sa SDL_HapticIndex - * \sa SDL_HapticOpen */ -extern DECLSPEC int SDLCALL SDL_HapticOpened(int device_index); +extern DECLSPEC SDL_Haptic *SDLCALL SDL_GetHapticFromInstanceID(SDL_HapticID instance_id); /** - * Get the index of a haptic device. + * Get the instance ID of an opened haptic device. * * \param haptic the SDL_Haptic device to query - * \returns the index of the specified haptic device or a negative error code - * on failure; call SDL_GetError() for more information. + * \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); + +/** + * Get the implementation dependent name of a haptic device. + * + * \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_HapticOpen - * \sa SDL_HapticOpened + * \sa SDL_GetHapticInstanceName */ -extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic); +extern DECLSPEC const char *SDLCALL SDL_GetHapticName(SDL_Haptic *haptic); /** * Query whether or not the current mouse has haptic capabilities. @@ -912,9 +947,9 @@ extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticOpenFromMouse + * \sa SDL_OpenHapticFromMouse */ -extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void); +extern DECLSPEC SDL_bool SDLCALL SDL_IsMouseHaptic(void); /** * Try to open a haptic device from the current mouse. @@ -924,24 +959,22 @@ extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticOpen - * \sa SDL_MouseIsHaptic + * \sa SDL_CloseHaptic + * \sa SDL_IsMouseHaptic */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromMouse(void); +extern 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, SDL_FALSE if it isn't, or a - * negative error code on failure; call SDL_GetError() for more - * information. + * \returns SDL_TRUE if the joystick is haptic or SDL_FALSE if it isn't. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticOpenFromJoystick + * \sa SDL_OpenHapticFromJoystick */ -extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick); +extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickHaptic(SDL_Joystick *joystick); /** * Open a haptic device for use from a joystick device. @@ -960,30 +993,28 @@ extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticClose - * \sa SDL_HapticOpen - * \sa SDL_JoystickIsHaptic + * \sa SDL_CloseHaptic + * \sa SDL_IsJoystickHaptic */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromJoystick(SDL_Joystick * - joystick); +extern DECLSPEC SDL_Haptic *SDLCALL SDL_OpenHapticFromJoystick(SDL_Joystick *joystick); /** - * Close a haptic device previously opened with SDL_HapticOpen(). + * Close a haptic device previously opened with SDL_OpenHaptic(). * * \param haptic the SDL_Haptic device to close * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticOpen + * \sa SDL_OpenHaptic */ -extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic); +extern DECLSPEC void SDLCALL SDL_CloseHaptic(SDL_Haptic *haptic); /** * Get the number of effects a haptic device can store. * * On some platforms this isn't fully supported, and therefore is an * approximation. Always check to see if your created effect was actually - * created and do not rely solely on SDL_HapticNumEffects(). + * created and do not rely solely on SDL_GetMaxHapticEffects(). * * \param haptic the SDL_Haptic device to query * \returns the number of effects the haptic device can store or a negative @@ -991,10 +1022,10 @@ extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticNumEffectsPlaying - * \sa SDL_HapticQuery + * \sa SDL_GetMaxHapticEffectsPlaying + * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_GetMaxHapticEffects(SDL_Haptic *haptic); /** * Get the number of effects a haptic device can play at the same time. @@ -1008,10 +1039,10 @@ extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticNumEffects - * \sa SDL_HapticQuery + * \sa SDL_GetMaxHapticEffects + * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_GetMaxHapticEffectsPlaying(SDL_Haptic *haptic); /** * Get the haptic device's supported features in bitwise manner. @@ -1023,9 +1054,9 @@ extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic); * \since This function is available since SDL 3.0.0. * * \sa SDL_HapticEffectSupported - * \sa SDL_HapticNumEffects + * \sa SDL_GetMaxHapticEffects */ -extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic); +extern DECLSPEC Uint32 SDLCALL SDL_GetHapticFeatures(SDL_Haptic *haptic); /** @@ -1040,25 +1071,21 @@ extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_HapticNumAxes(SDL_Haptic * haptic); +extern 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 effect is supported, SDL_FALSE if it isn't, or a - * negative error code on failure; call SDL_GetError() for more - * information. + * \returns SDL_TRUE if the effect is supported or SDL_FALSE if it isn't. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticNewEffect - * \sa SDL_HapticQuery + * \sa SDL_CreateHapticEffect + * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic, - SDL_HapticEffect * - effect); +extern DECLSPEC SDL_bool SDLCALL SDL_HapticEffectSupported(SDL_Haptic *haptic, const SDL_HapticEffect *effect); /** * Create a new haptic effect on a specified device. @@ -1071,12 +1098,11 @@ extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticDestroyEffect - * \sa SDL_HapticRunEffect - * \sa SDL_HapticUpdateEffect + * \sa SDL_DestroyHapticEffect + * \sa SDL_RunHapticEffect + * \sa SDL_UpdateHapticEffect */ -extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic, - SDL_HapticEffect * effect); +extern DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect); /** * Update the properties of an effect. @@ -1084,7 +1110,7 @@ extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic, * Can be used dynamically, although behavior when dynamically changing * direction may be strange. Specifically the effect may re-upload itself and * start playing from the start. You also cannot change the type either when - * running SDL_HapticUpdateEffect(). + * running SDL_UpdateHapticEffect(). * * \param haptic the SDL_Haptic device that has the effect * \param effect the identifier of the effect to update @@ -1095,13 +1121,10 @@ extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticDestroyEffect - * \sa SDL_HapticNewEffect - * \sa SDL_HapticRunEffect + * \sa SDL_CreateHapticEffect + * \sa SDL_RunHapticEffect */ -extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic, - int effect, - SDL_HapticEffect * data); +extern DECLSPEC int SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, const SDL_HapticEffect *data); /** * Run the haptic effect on its associated haptic device. @@ -1121,13 +1144,11 @@ extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticDestroyEffect - * \sa SDL_HapticGetEffectStatus - * \sa SDL_HapticStopEffect + * \sa SDL_GetHapticEffectStatus + * \sa SDL_StopHapticEffect + * \sa SDL_StopHapticEffects */ -extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic, - int effect, - Uint32 iterations); +extern DECLSPEC int SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations); /** * Stop the haptic effect on its associated haptic device. @@ -1141,11 +1162,10 @@ extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticDestroyEffect - * \sa SDL_HapticRunEffect + * \sa SDL_RunHapticEffect + * \sa SDL_StopHapticEffects */ -extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic, - int effect); +extern DECLSPEC int SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int effect); /** * Destroy a haptic effect on the device. @@ -1158,10 +1178,9 @@ extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticNewEffect + * \sa SDL_CreateHapticEffect */ -extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic, - int effect); +extern DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect); /** * Get the status of the current effect on the specified haptic device. @@ -1174,12 +1193,8 @@ extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic, * code on failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_HapticRunEffect - * \sa SDL_HapticStopEffect */ -extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic, - int effect); +extern DECLSPEC int SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect); /** * Set the global gain of the specified haptic device. @@ -1188,7 +1203,7 @@ extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic, * * The user may specify the maximum gain by setting the environment variable * `SDL_HAPTIC_GAIN_MAX` which should be between 0 and 100. All calls to - * SDL_HapticSetGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the + * SDL_SetHapticGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the * maximum. * * \param haptic the SDL_Haptic device to set the gain on @@ -1198,9 +1213,9 @@ extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticQuery + * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain); +extern DECLSPEC int SDLCALL SDL_SetHapticGain(SDL_Haptic *haptic, int gain); /** * Set the global autocenter of the device. @@ -1217,16 +1232,15 @@ extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticQuery + * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic, - int autocenter); +extern DECLSPEC int SDLCALL SDL_SetHapticAutocenter(SDL_Haptic *haptic, int autocenter); /** * Pause a haptic device. * - * Device must support the `SDL_HAPTIC_PAUSE` feature. Call - * SDL_HapticUnpause() to resume playback. + * Device must support the `SDL_HAPTIC_PAUSE` feature. Call SDL_ResumeHaptic() + * to resume playback. * * Do not modify the effects nor add new ones while the device is paused. That * can cause all sorts of weird errors. @@ -1237,14 +1251,14 @@ extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticUnpause + * \sa SDL_ResumeHaptic */ -extern DECLSPEC int SDLCALL SDL_HapticPause(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_PauseHaptic(SDL_Haptic *haptic); /** - * Unpause a haptic device. + * Resume a haptic device. * - * Call to unpause after SDL_HapticPause(). + * 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 @@ -1252,9 +1266,9 @@ extern DECLSPEC int SDLCALL SDL_HapticPause(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticPause + * \sa SDL_PauseHaptic */ -extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_ResumeHaptic(SDL_Haptic *haptic); /** * Stop all the currently playing effects on a haptic device. @@ -1264,24 +1278,23 @@ extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic); * 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_HapticStopAll(SDL_Haptic * haptic); +extern DECLSPEC int 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 effect is supported, SDL_FALSE if it isn't, or a - * negative error code on failure; call SDL_GetError() for more - * information. + * \returns SDL_TRUE if the effect is supported or SDL_FALSE if it isn't. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticRumbleInit - * \sa SDL_HapticRumblePlay - * \sa SDL_HapticRumbleStop + * \sa SDL_InitHapticRumble */ -extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic); +extern DECLSPEC SDL_bool SDLCALL SDL_HapticRumbleSupported(SDL_Haptic *haptic); /** * Initialize a haptic device for simple rumble playback. @@ -1292,12 +1305,11 @@ extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticOpen - * \sa SDL_HapticRumblePlay - * \sa SDL_HapticRumbleStop + * \sa SDL_PlayHapticRumble + * \sa SDL_StopHapticRumble * \sa SDL_HapticRumbleSupported */ -extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_InitHapticRumble(SDL_Haptic *haptic); /** * Run a simple rumble effect on a haptic device. @@ -1310,11 +1322,10 @@ extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticRumbleInit - * \sa SDL_HapticRumbleStop - * \sa SDL_HapticRumbleSupported + * \sa SDL_InitHapticRumble + * \sa SDL_StopHapticRumble */ -extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length ); +extern DECLSPEC int SDLCALL SDL_PlayHapticRumble(SDL_Haptic *haptic, float strength, Uint32 length); /** * Stop the simple rumble on a haptic device. @@ -1325,11 +1336,9 @@ extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float stre * * \since This function is available since SDL 3.0.0. * - * \sa SDL_HapticRumbleInit - * \sa SDL_HapticRumblePlay - * \sa SDL_HapticRumbleSupported + * \sa SDL_PlayHapticRumble */ -extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic); +extern DECLSPEC int SDLCALL SDL_StopHapticRumble(SDL_Haptic *haptic); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 3319a149..065b1b31 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -47,15 +47,6 @@ extern "C" { #endif -/** - * Set if Android/iOS accelerometers should be listed as joystick devices. - * - * This variable can be set to the following values: - * "0" - The accelerometer is not listed as a joystick - * "1" - The accelerometer is available as a 3 axis joystick (the default). - */ -#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK" - /** * Specify the behavior of Alt+Tab while the keyboard is grabbed. * @@ -64,21 +55,25 @@ extern "C" { * 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. + * "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. + */ #define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED" /** - * If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it. - * This is a debugging aid for developers and not expected to be used by end users. The default is "1" + * A variable to control whether the SDL activity is allowed to be re-created. * - * This variable can be set to the following values: - * "0" - don't allow topmost - * "1" - allow topmost + * 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. + * + * This hint can be set anytime. */ -#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST" +#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. @@ -87,28 +82,25 @@ extern "C" { * "0" - Non blocking. * "1" - Blocking. (default) * - * The value should be set before SDL is initialized. + * 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 - * (Requires SDL_ANDROID_BLOCK_ON_PAUSE as "Non blocking") + * A variable to control whether SDL will pause audio in background. * * The variable can be set to the following values: - * "0" - Non paused. + * "0" - Not paused, requires that SDL_HINT_ANDROID_BLOCK_ON_PAUSE be set to "0" * "1" - Paused. (default) * - * The value should be set before SDL is initialized. + * This hint should be set before SDL is initialized. */ #define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO" /** * 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 set to 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) @@ -116,78 +108,50 @@ extern "C" { * manually. (This will also let right mouse click work on systems * where the right mouse button functions as back.) * - * The value of this hint is used at runtime, so it can be changed at any time. + * This hint can be set anytime. */ #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" /** - * A variable to control whether SDL activity is allowed to be re-created. - * If so, java static datas and static datas from native libraries remain with their current values. - * When not allowed, the activity terminates with exit(0) to be fully re-initialized afterward. + * A variable setting the app ID string. * - * The variable can be set to the following values: - * "0" - Not allowed. (default) - * "1" - Allowed. + * This string is used by desktop compositors to identify and group windows together, as well as match applications with associated desktop settings and icons. * - * The value of this hint is used at runtime, so it can be changed at any time. - */ -#define SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY "SDL_ANDROID_ALLOW_RECREATE_ACTIVITY" - -/** - * 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. + * 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. * - * 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: * - * 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. * - * - 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. * - * - 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 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. * - * - The entire ID must be less than 255 characters in length. + * Examples of valid app ID strings: * - * Examples of valid app ID strings: + * - org.MyOrg.MyApp + * - com.your_company.your_app * - * - 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'). * - * 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 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. * - * 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. - * - * On targets where this is not supported, this hint does nothing. + * This hint should be set before SDL is initialized. */ #define SDL_HINT_APP_ID "SDL_APP_ID" /** - * Specify an application name. + * Specify an 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") + * 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 @@ -196,13 +160,12 @@ extern "C" { * Note that, for audio streams, this can be overridden with * SDL_HINT_AUDIO_DEVICE_APP_NAME. * - * On targets where this is not supported, this hint does nothing. + * This hint should be set before SDL is initialized. */ #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 @@ -212,37 +175,41 @@ extern "C" { * can be found here: * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/ * - * This variable can be set to the following values: - * "0" - Controller input does not generate UI events (the default). - * "1" - Controller input generates UI events. + * The variable can be set to the following values: + * "0" - Controller input does not generate UI events. (default) + * "1" - Controller input generates UI events. + * + * This hint can be set anytime. */ #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. * - * This variable can be set to the following values: - * "0" - Remote orientation does not affect joystick axes (the default). - * "1" - Joystick axes are based on the orientation 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. + * + * This hint can be set anytime. */ #define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION" /** - * A variable controlling the audio category on iOS and macOS + * A variable controlling the audio category on iOS and macOS. * - * This 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 + * 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 + * + * This hint should be set before an audio device is opened. */ #define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" /** - * Specify an application name for an audio device. + * Specify an application name for an audio device. * * Some audio backends (such as PulseAudio) allow you to describe your audio * stream. Among other things, this description might show up in a system @@ -258,12 +225,32 @@ extern "C" { * set. Otherwise, it'll probably the application's name or "SDL Application" * if SDL doesn't have any better information. * - * On targets where this is not supported, this hint does nothing. + * This hint should be set before an audio device is opened. */ #define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME" /** - * Specify an application name for an audio device. + * 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). + * + * 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. + * + * 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. + * + * This hint should be set before an audio device is opened. + */ +#define SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES "SDL_AUDIO_DEVICE_SAMPLE_FRAMES" + +/** + * Specify an audio stream name for an audio device. * * Some audio backends (such as PulseAudio) allow you to describe your audio * stream. Among other things, this description might show up in a system @@ -279,12 +266,12 @@ extern "C" { * Setting this to "" or leaving it unset will have SDL use a reasonable * default: "audio stream" or something similar. * - * On targets where this is not supported, this hint does nothing. + * This hint should be set before an audio device is opened. */ #define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME" /** - * Specify an application role for an audio device. + * 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 @@ -299,36 +286,58 @@ extern "C" { * Setting this to "" or leaving it unset will have SDL use a reasonable * default: "Game" or something similar. * - * On targets where this is not supported, this hint does nothing. + * This hint should be set before an audio device is opened. */ #define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE" /** - * A variable controlling whether SDL updates joystick state when getting input events + * A variable that specifies an audio backend to use. * - * This variable can be set to the following values: + * 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. * - * "0" - You'll call SDL_UpdateJoysticks() manually - * "1" - SDL will automatically call SDL_UpdateJoysticks() (default) + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_AUDIO_DRIVER "SDL_AUDIO_DRIVER" + +/** + * A variable that causes SDL to not ignore audio "monitors" * - * This hint can be toggled on and off at runtime. + * 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. + * + * 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. + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS" + +/** + * 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) + * + * This hint can be set anytime. */ #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 * - * This variable can be set to the following values: + * 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 toggled on and off at runtime. + * This hint can be set anytime. */ #define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS" /** - * Prevent SDL from using version 4 of the bitmap header when saving BMPs. + * 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 @@ -337,252 +346,337 @@ extern "C" { * 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. + * 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. * - * The default value is "0". + * This hint can be set anytime. */ #define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT" /** - * Override for SDL_GetDisplayUsableBounds() + * A variable that decides what camera backend to use. * - * 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. + * 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 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 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. + */ +#define SDL_HINT_CAMERA_DRIVER "SDL_CAMERA_DRIVER" + +/** + * 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. + * + * 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: + * "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. + * + * 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 + * + * The variable can be set to the following values: + * "0" - Disable DirectInput detection. + * "1" - Enable DirectInput detection. (default) + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_JOYSTICK_DIRECTINPUT "SDL_JOYSTICK_DIRECTINPUT" + +/** + * 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. + * + * 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. */ #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 + * 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 (the 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. */ #define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY" /** - * Specify the CSS selector used for the "default" window/canvas + * Specify the CSS selector used for the "default" window/canvas. * - * This hint only applies to the emscripten platform + * This hint only applies to the emscripten platform. * * The default value is "#canvas" + * + * This hint should be set before creating a window. */ #define SDL_HINT_EMSCRIPTEN_CANVAS_SELECTOR "SDL_EMSCRIPTEN_CANVAS_SELECTOR" /** - * override the binding element for keyboard inputs for Emscripten builds + * Override the binding element for keyboard inputs for Emscripten builds. * - * This hint only applies to the emscripten platform + * This hint only applies to the emscripten platform. * * The variable can be one of - * "#window" - The javascript window object (this is the default) + * "#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. */ #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: - * "0" - Do not show the on-screen keyboard - * "1" - Show the on-screen keyboard + * 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. * - * The default value is "1". This hint must be set before text input is activated. + * This hint must be set before SDL_StartTextInput() is called */ #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 controlling verbosity of the logging of SDL events pushed onto the internal queue. * - * This variable can be set to the following values, from least to most verbose: + * 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. * - * "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 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_LogSetOutputFunction(), etc. - * - * This hint can be toggled on and off at runtime, if you only need to log - * events for a small subset of program execution. + * This hint can be set anytime. */ #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. * - * This variable can be set to the following values: - * "0" - No forcing (the default) - * "1" - Extra level of forcing + * 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. + * 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. */ #define SDL_HINT_FORCE_RAISEWINDOW "SDL_HINT_FORCE_RAISEWINDOW" /** -* A variable controlling whether the window is activated when the SDL_RaiseWindow function is called -* -* This 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 -* -* By default SDL will activate the window when the SDL_RaiseWindow function is called. -* At present this is only available for MS Windows. -*/ -#define SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED "SDL_WINDOW_ACTIVATE_WHEN_RAISED" - -/** - * 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. * - * This variable can be set to the following values: - * "0" - Disable 3D acceleration - * "1" - Enable 3D acceleration, using the default renderer. - * "X" - Enable 3D acceleration, using X where X is one of the valid rendering drivers. (e.g. "direct3d", "opengl", etc.) + * 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.) * - * By default SDL tries to make a best guess for each platform whether - * to use acceleration or not. + * This hint should be set before calling SDL_GetWindowSurface() */ #define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION" /** - * A variable that lets you manually hint extra gamecontroller db entries. + * 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 * - * This hint must be set before calling SDL_Init(SDL_INIT_GAMEPAD) - * You can update mappings after the system 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. */ #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 * - * This hint must be set before calling SDL_Init(SDL_INIT_GAMEPAD) - * You can update mappings after the system 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. */ #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 + * The variable should be comma separated entries, in the form: VID/PID=type * - * The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd + * The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd * - * The type should be one of: - * Xbox360 - * XboxOne - * PS3 - * PS4 - * PS5 - * SwitchPro + * This hint affects what low level protocol is used with the HIDAPI driver. * - * This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMEPAD) + * The variable can be set to the following values: + * "Xbox360" + * "XboxOne" + * "PS3" + * "PS4" + * "PS5" + * "SwitchPro" + * + * This hint should be set before SDL is initialized. */ #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. */ #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. */ #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT" /** - * 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 + * 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. + * Or the variable can be 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 is checked when a gamepad is opened. + * This hint should be set before a gamepad is opened. */ #define SDL_HINT_GAMECONTROLLER_SENSOR_FUSION "SDL_GAMECONTROLLER_SENSOR_FUSION" /** - * A variable controlling whether grabbing input grabs the keyboard + * This variable sets the default text of the TextInput window on GDK platforms. * - * This variable can be set to the following values: - * "0" - Grab will affect only the mouse - * "1" - Grab will affect mouse and keyboard + * This hint is available only if SDL_GDK_TEXTINPUT defined. * - * By default SDL will not grab the keyboard so system shortcuts still work. + * This hint should be set before calling SDL_StartTextInput() */ -#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD" +#define SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT "SDL_GDK_TEXTINPUT_DEFAULT_TEXT" /** - * A variable to control whether SDL_hid_enumerate() enumerates all HID devices or only controllers. + * This variable sets the description of the TextInput window on GDK platforms. * - * This 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 + * This hint is available only if SDL_GDK_TEXTINPUT defined. * - * 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 should be set before calling SDL_StartTextInput() + */ +#define SDL_HINT_GDK_TEXTINPUT_DESCRIPTION "SDL_GDK_TEXTINPUT_DESCRIPTION" + +/** + * 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. + * + * This hint is available only if SDL_GDK_TEXTINPUT defined. + * + * This hint should be set before calling SDL_StartTextInput() + */ +#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. + * + * 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() + */ +#define SDL_HINT_GDK_TEXTINPUT_SCOPE "SDL_GDK_TEXTINPUT_SCOPE" + +/** + * This variable sets the title 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() + */ +#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. + * + * 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. + * + * This hint can be set anytime. */ #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() + * A variable containing a list of devices to ignore in SDL_hid_enumerate() * - * For example, to ignore the Shanwan DS3 controller and any Valve controller, you might - * have the string "0x2563/0x0523,0x28de/0x0000" + * 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. */ #define SDL_HINT_HIDAPI_IGNORE_DEVICES "SDL_HIDAPI_IGNORE_DEVICES" @@ -595,6 +689,8 @@ extern "C" { * 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. */ #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" @@ -604,619 +700,741 @@ extern "C" { * The variable can be set to the following values: * "0" - Native UI components are not display. (default) * "1" - Native UI components are displayed. + * + * This hint should be set before SDL is initialized. */ #define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_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. * - * This 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. */ #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. - * "1" - Enable joystick & gamecontroller input events when the - * application 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. * - * The default value is "0". This hint may be set at any time. + * This hint can be set anytime. */ #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" /** - * A variable containing a list of arcade stick style controllers. + * 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. */ #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. This will override SDL_HINT_JOYSTICK_ARCADESTICK_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. */ #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 considerd 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. */ #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. */ #define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED" /** - * A variable containing a list of flightstick style controllers. + * A variable containing a comma separated list of devices to open as joysticks. + * + * This variable is currently only used by the Linux joystick driver. + */ +#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. */ #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. */ #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 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. */ #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. * - * 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. */ #define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED" /** - * A variable controlling whether the HIDAPI joystick drivers should be used. + * A variable controlling whether the HIDAPI joystick drivers should be used. * - * This variable can be set to the following values: - * "0" - HIDAPI drivers are not used - * "1" - HIDAPI drivers are used (the default) + * 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. + * 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. */ #define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI" /** - * A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used. + * A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver. * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is used + * 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) * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + * This hint should be set before enumerating controllers. + */ +#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. + * + * 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 + * + * This hint should be set before enumerating controllers. */ #define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE" /** - * A variable controlling whether "low_frequency_rumble" and "high_frequency_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" + * A variable controlling whether rumble is used to implement the GameCube controller's 3 rumble modes, Stop(0), Rumble(1), and StopHard(2) * - * This 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 + * 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. + * + * This hint can be set anytime. */ -#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_GAMECUBE_RUMBLE_BRAKE" +#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. - * - * 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 - */ + * 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. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before enumerating controllers. + */ #define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS" /** - * A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver - * - * This 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 (the default) - */ -#define SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS "SDL_JOYSTICK_HIDAPI_COMBINE_JOY_CONS" - -/** - * A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver - * - * This variable can be set to the following values: - * "0" - Left and right Joy-Con controllers will not be in vertical mode (the default) - * "1" - Left and right Joy-Con controllers will be in vertical mode - * - * This hint must be set before calling SDL_Init(SDL_INIT_GAMEPAD) - */ -#define SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS" - -/** - * A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth 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_LUNA "SDL_JOYSTICK_HIDAPI_LUNA" - -/** - * A variable controlling whether the HIDAPI driver for Nintendo Online classic 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_NINTENDO_CLASSIC "SDL_JOYSTICK_HIDAPI_NINTENDO_CLASSIC" - -/** - * A variable controlling whether the HIDAPI driver for NVIDIA SHIELD 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_SHIELD "SDL_JOYSTICK_HIDAPI_SHIELD" - -/** - * A variable controlling whether the HIDAPI driver for PS3 controllers should be used. + * A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Joy-Con controller is opened * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is used + * The variable can be set to the following values: + * "0" - home button LED is turned off + * "1" - home button LED is turned on * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI on macOS, and "0" on other platforms. + * 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. * - * It is not possible to use this driver on Windows, due to limitations in the default drivers - * installed. See https://github.com/ViGEm/DsHidMini for an alternative driver on Windows. - */ -#define SDL_HINT_JOYSTICK_HIDAPI_PS3 "SDL_JOYSTICK_HIDAPI_PS3" - -/** - * A variable controlling whether the HIDAPI driver for PS4 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_PS4 "SDL_JOYSTICK_HIDAPI_PS4" - -/** - * A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver. - * - * This variable can be set to the following values: - * "0" - extended reports are not enabled (the default) - * "1" - extended reports - * - * 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. - * - * 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. - */ -#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. - * - * 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_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. - * - * This variable can be set to the following values: - * "0" - player LEDs are not enabled - * "1" - player LEDs are enabled (the default) - */ -#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. - * - * This variable can be set to the following values: - * "0" - extended reports are not enabled (the default) - * "1" - extended reports - * - * Extended input reports allow rumble on Bluetooth PS5 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. - * - * 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. - */ -#define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE" - -/** - * A variable controlling whether the HIDAPI driver for Google Stadia 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_STADIA "SDL_JOYSTICK_HIDAPI_STADIA" - -/** - * A variable controlling whether the HIDAPI driver for Bluetooth 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 for Steam Controllers, which requires Bluetooth access - * and may prompt the user for permission on iOS and Android. - * - * The default is "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. - * - * 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_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" - -/** - * A variable controlling whether the HIDAPI driver for Nintendo Switch 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_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 - * - * This 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. - */ -#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED" - -/** - * A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Joy-Con controller is opened - * - * This 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. + * This hint can be set anytime. */ #define SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED "SDL_JOYSTICK_HIDAPI_JOYCON_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 HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used. * - * This variable can be set to the following values: - * "0" - player LEDs are not enabled - * "1" - player LEDs are enabled (the default) + * 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. + * + * This hint should be set before enumerating controllers. + */ +#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. + * + * 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. + * + * This hint should be set before enumerating controllers. + */ +#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. + * + * 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. + * + * 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. + */ +#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. + * + * The variable can be set to the following values: + * "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. + */ +#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. + * + * 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. + * + * This hint should be set before enumerating controllers. + */ +#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. + * + * 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. + * + * 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. + * + * This hint can be enabled anytime. + */ +#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. + * + * 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. + * + * This hint should be set before enumerating controllers. + */ +#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. + * + * The variable can be set to the following values: + * "0" - player LEDs are not enabled. + * "1" - player LEDs are enabled. (default) + */ +#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. + * + * 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. + * + * 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. + */ +#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. + * + * 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. + * + * This hint should be set before enumerating controllers. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_SHIELD "SDL_JOYSTICK_HIDAPI_SHIELD" + +/** + * 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. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA" + +/** + * 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. + * + * This hint should be set before enumerating controllers. + */ +#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. + * + * 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. + * + * This hint should be set before enumerating controllers. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" + +/** + * 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. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * This hint should be set before enumerating controllers. + */ +#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 + * + * 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. + * + * This hint can be set anytime. + */ +#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. + * + * The variable can be set to the following values: + * "0" - Player LEDs are not enabled. + * "1" - Player LEDs are enabled. (default) + * + * This hint can be set anytime. */ #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED" /** - * A variable controlling whether the HIDAPI driver for Nintendo Wii and Wii U controllers should be used. + * A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver. * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is used + * 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. * - * This driver doesn't work with the dolphinbar, so the default is SDL_FALSE for now. + * This hint should be set before opening a Joy-Con controller. + */ +#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. + * + * 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. + * + * This hint should be set before enumerating controllers. */ #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. * - * This variable can be set to the following values: - * "0" - player LEDs are not enabled - * "1" - player LEDs are enabled (the default) + * The variable can be set to the following values: + * "0" - Player LEDs are not enabled. + * "1" - Player LEDs are enabled. (default) + * + * This hint can be set anytime. */ #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. * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is 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 + * The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI + * + * This hint should be set before enumerating controllers. */ #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. * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is 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 + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX + * + * This hint should be set before enumerating controllers. */ #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. * - * This variable can be set to the following values: - * "0" - player LEDs are not enabled - * "1" - player LEDs are enabled (the default) + * The variable can be set to the following values: + * "0" - Player LEDs are not enabled. + * "1" - Player LEDs are enabled. (default) + * + * This hint can be set anytime. */ #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. * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is 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_360 + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 + * + * This hint should be set before enumerating controllers. */ #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. * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is 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 + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX. + * + * This hint should be set before enumerating controllers. */ #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. * - * This variable can be set to the following values: - * "0" - home button LED is turned off - * "1" - home button LED is turned on + * 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. + * 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. */ #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. - * - * This variable can be set to the following values: - * "0" - IOKit is not used - * "1" - IOKit is used (the default) - */ + * 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) + * + * This hint should be set before SDL is initialized. + */ #define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT" /** - * A variable controlling whether GCController should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - GCController is not used - * "1" - GCController is used (the default) - */ + * 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* + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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. + * + * This hint should be set before a controller is opened. + */ +#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. + * + * 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. + * + * This hint should be set before a controller is opened. + */ +#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. + * + * 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) + * + * This hint should be set before a controller is opened. + */ +#define SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES "SDL_JOYSTICK_LINUX_HAT_DEADZONES" + +/** + * 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) + * + * This hint should be set before SDL is initialized. + */ #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. - * - * This variable can be set to the following values: - * "0" - RAWINPUT drivers are not used - * "1" - RAWINPUT drivers are used (the default) - */ + * 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) + * + * This hint should be set before SDL is initialized. + */ #define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT" /** - * A variable controlling whether the RAWINPUT driver should pull correlated data from XInput. - * - * This 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, providing - * better trigger axes, guide button presses, and rumble support - * for Xbox controllers - * - * The default is "1". This hint applies to any joysticks opened after setting the hint. - */ + * 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) + * + * This hint should be set before a gamepad is opened. + */ #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 - * - * This variable can be set to the following values: - * "0" - ROG Chakram mice do not show up as joysticks (the default) - * "1" - ROG Chakram mice 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. + * + * This hint should be set before SDL is initialized. + */ #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 - * - * This variable can be set to the following values: - * "0" - A separate thread is not used (the default) - * "1" - A separate thread is used for handling raw input messages - * - */ + * 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: + * "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. + */ #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" /** - * A variable containing a list of throttle style controllers. + * 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. */ #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. * - * 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. */ #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. - * - * This variable can be set to the following values: - * "0" - WGI is not used - * "1" - WGI is used (the default) - */ + * 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) + * + * This hint should be set before SDL is initialized. + */ #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" /** - * A variable containing a list of wheel style controllers. + * 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. */ #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. */ #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. */ #define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" /** - * Determines whether SDL enforces that DRM master is required in order - * to initialize the KMSDRM video backend. + * 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. + * + * This hint should be set before SDL is initialized. + */ +#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. * * 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 @@ -1229,1483 +1447,67 @@ extern "C" { * 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. * - * This hint must be set before initializing the video subsystem. + * 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) * - * This 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) + * This hint should be set before SDL is initialized. */ #define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER" /** - * A comma separated list of devices to open as joysticks - * - * This variable is currently only used by the Linux joystick driver. - */ -#define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE" + * 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. + * + * 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" + * + * This hint can be set anytime. + */ +#define SDL_HINT_LOGGING "SDL_LOGGING" /** - * 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. - * - * This 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 (the default) - * "1" - Always handle the input axes numbered ABS_HAT0X to ABS_HAT3Y as digital hats - */ -#define SDL_HINT_LINUX_DIGITAL_HATS "SDL_LINUX_DIGITAL_HATS" - -/** - * A variable controlling whether digital hats on Linux will apply deadzones to their underlying input axes or use unfiltered values. - * - * This 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 (the default) - */ -#define SDL_HINT_LINUX_HAT_DEADZONES "SDL_LINUX_HAT_DEADZONES" - -/** - * A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux - * - * This variable can be set to the following values: - * "0" - Use /dev/input/event* - * "1" - Use /dev/input/js* - * - * By default the /dev/input/event* interfaces are used - */ -#define SDL_HINT_LINUX_JOYSTICK_CLASSIC "SDL_LINUX_JOYSTICK_CLASSIC" - -/** - * A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. - * - * This variable can be set to the following values: - * "0" - Return unfiltered joystick axis values (the default) - * "1" - Return axis values with deadzones taken into account - */ -#define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES" - -/** -* When set don't force the SDL app to become a foreground process -* -* This hint only applies to 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. + */ #define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP" /** - * A variable that determines whether ctrl+click should generate a right-click event on Mac + * A variable that determines whether Ctrl+Click should generate a right-click event on macOS. * - * If present, holding ctrl while left clicking will generate a right click - * event when on Mac. + * 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. + * + * This hint can be set anytime. */ #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 + * A variable controlling whether dispatching OpenGL context updates should block the dispatching thread until the main thread finishes processing on macOS. * - * This 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. + * 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. - * - * This hint only applies to macOS. - * - * This hint is available since SDL 2.24.0. + * 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. */ #define SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH "SDL_MAC_OPENGL_ASYNC_DISPATCH" -/** - * A variable setting the double click radius, in pixels. - */ -#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS" - -/** - * A variable setting the double click time, in milliseconds. - */ -#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME" - -/** - * Allow mouse click events when clicking to focus an SDL window - * - * This variable can be set to the following values: - * "0" - Ignore mouse clicks that activate a window - * "1" - Generate events for mouse clicks that activate a window - * - * By default SDL will ignore mouse clicks that activate a window - */ -#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 - */ -#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 - * - * This 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 - * - * 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. - * - * By default SDL will constrain the mouse to the center of the window - */ -#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER" - -/** - * A variable controlling whether relative mouse mode is implemented using mouse warping - * - * This variable can be set to the following values: - * "0" - Relative mouse mode uses raw input - * "1" - Relative mouse mode uses mouse warping - * - * By default SDL will use raw input for relative mouse mode - */ -#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 - */ -#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. - * - * This variable can be set to the following values: - * "0" - Relative mouse motion will be unscaled (the 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. - */ -#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. - * - * This 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. - */ -#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION" - -/** - * A variable controlling whether mouse events should generate synthetic touch events - * - * This 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) - */ -#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" - -/** - * A variable controlling whether the mouse is captured while mouse buttons are pressed - * - * This 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. - */ -#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE" - -/** - * Treat pen movement as separate from mouse movement - * - * By default, pens report both ::SDL_MouseMotionEvent and ::SDL_PenMotionEvent updates - * (analogously for button presses). This hint allows decoupling mouse and pen updates. - * - * This variable toggles between the following behaviour: - * "0" - (Default) Pen acts as a mouse with mouse ID ::SDL_PEN_MOUSEID. - * 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"). - */ -#define SDL_HINT_PEN_NOT_MOUSE "SDL_HINT_PEN_NOT_MOUSE" - -/** - * Pen mouse button emulation triggers only when the pen touches the tablet surface - * - * "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" - (Default) 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. - */ -#define SDL_HINT_PEN_DELAY_MOUSE_BUTTON "SDL_HINT_PEN_DELAY_MOUSE_BUTTON" - -/** - * Tell SDL not to catch the SIGINT or SIGTERM signals. - * - * This hint only applies to Unix-like platforms, and should set before - * any calls to SDL_Init() - * - * 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. - * "1" - SDL will not install a signal handler at all. - */ -#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" - -/** - * 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. - * - * This variable can be set to the following values: - * "0" - Use ES profile of OpenGL, if available. (Default when not set.) - * "1" - Load OpenGL ES library using the default library names. - * - */ -#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" - -/** - * A variable controlling which orientations are allowed on iOS/Android. - * - * In some circumstances it is necessary to be able to explicitly control - * which UI orientations are allowed. - * - * This variable is a space delimited list of the following values: - * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown" - */ -#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS" - -/** - * A variable controlling the use of a sentinel event when polling the event queue - * - * This variable can be set to the following values: - * "0" - Disable poll sentinels - * "1" - Enable poll sentinels - * - * 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. - * - * By default, poll sentinels are enabled. - */ -#define SDL_HINT_POLL_SENTINEL "SDL_POLL_SENTINEL" - -/** - * 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). - * - * 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" - */ -#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES" - -/** - * A variable describing the content orientation on QtWayland-based platforms. - * - * On QtWayland platforms, windows are rotated client-side to allow for custom - * transitions. In order to correctly position overlays (e.g. volume bar) and - * gestures (e.g. events view, close/minimize gestures), the system needs to - * know in which orientation the application is currently drawing its contents. - * - * This does not cause the window to be rotated or resized, the application - * needs to take care of drawing the content in the right orientation (the - * framebuffer is always in portrait mode). - * - * This variable can be one of the following values: - * "primary" (default), "portrait", "landscape", "inverted-portrait", "inverted-landscape" - * - * Since SDL 2.0.22 this variable accepts a comma-separated list of values above. - */ -#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION" - -/** - * Flags to set on QtWayland windows to integrate with the native window manager. - * - * On QtWayland platforms, this hint controls the flags to set on the windows. - * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures. - * - * This variable is a space-separated list of the following values (empty = no flags): - * "OverridesSystemGestures", "StaysOnTop", "BypassWindowManager" - */ -#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS" - -/** - * A variable controlling how the 2D render API renders lines - * - * This variable can be set to the following values: - * "0" - Use the default line drawing method (Bresenham's line algorithm as of SDL 2.0.20) - * "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, was the default before 2.0.20) - * "3" - Use the driver geometry API (correct, draws thicker diagonal lines) - * - * This variable should be set when the renderer is created. - */ -#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" - -/** - * A variable controlling whether to enable Direct3D 11+'s Debug Layer. - * - * This variable does not have any effect on the Direct3D 9 based renderer. - * - * This variable can be set to the following values: - * "0" - Disable Debug Layer use - * "1" - Enable Debug Layer use - * - * By default, SDL does not use Direct3D Debug Layer. - */ -#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" - -/** - * A variable controlling whether the Direct3D device is initialized for thread-safe operations. - * - * This variable can be set to the following values: - * "0" - Thread-safety is not enabled (faster) - * "1" - Thread-safety is enabled - * - * By default the Direct3D device is created with thread-safety disabled. - */ -#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE" - -/** - * 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, the normal default renderer is used. - * - * This variable is case insensitive and can be set to the following values: - * "direct3d" - * "direct3d11" - * "direct3d12" - * "opengl" - * "opengles2" - * "opengles" - * "metal" - * "software" - * - * The default varies by platform, but it's the first one in the list that - * is available on the current platform. - */ -#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER" - -/** - * A variable controlling whether the OpenGL render driver uses shaders if they are available. - * - * This variable can be set to the following values: - * "0" - Disable shaders - * "1" - Enable shaders - * - * By default shaders are used if OpenGL supports them. - */ -#define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS" - -/** - * A variable controlling the scaling quality - * - * This variable can be set to the following values: - * "0" or "nearest" - Nearest pixel sampling - * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D) - * "2" or "best" - Currently this is the same as "linear" - * - * By default nearest pixel sampling is used - */ -#define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY" - -/** - * A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing. - * - * This variable can be set to the following values: - * "0" - Disable vsync - * "1" - Enable vsync - * - * By default SDL does not sync screen surface updates with vertical refresh. - */ -#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC" - -/** - * A variable controlling whether the Metal render driver select low power device over default one - * - * This variable can be set to the following values: - * "0" - Use the prefered OS device - * "1" - Select a low power one - * - * By default the prefered OS device is used. - */ -#define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" - -/** - * 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. - * - * 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. - */ -#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. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 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. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" - -/** - * A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS - * - * This 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 - * - * By default SDL does not enable the automatic VSYNC - */ -#define SDL_HINT_PS2_DYNAMIC_VSYNC "SDL_PS2_DYNAMIC_VSYNC" - -/** - * A variable to control whether the return key on the soft keyboard - * should hide the soft keyboard on Android and iOS. - * - * The variable can be set to the following values: - * "0" - The return key will be handled as a key event. This is the behaviour of SDL <= 2.0.3. (default) - * "1" - The return key will hide the keyboard. - * - * The value of this hint is used at runtime, so it can be changed at any time. - */ -#define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME" - -/** - * Tell SDL which Dispmanx layer to use on a Raspberry PI - * - * Also known as Z-order. The variable can take a negative or positive value. - * The default is 10000. - */ -#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. - * - * 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. - * - * On targets where this is not supported, this hint does nothing. - */ -#define SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME" - -/** - * 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 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. - * - * This 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 - */ -#define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL" - -/** -* A string specifying additional information to use with SDL_SetThreadPriority. -* -* 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. -* -* \note 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(). -*/ -#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY" - -/** -* A string specifying SDL's threads stack size in bytes or "0" for the backend's default size -* -* Use this hint in case you need to set SDL's threads stack size to other than the default. -* This is specially useful if you build SDL against a non glibc libc library (such as musl) which -* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses). -* Support for this hint is currently available only in the pthread, Windows, and PSP backend. -* -* Instead of this hint, in 2.0.9 and later, you can use -* SDL_CreateThreadWithStackSize(). This hint only works with the classic -* SDL_CreateThread(). -*/ -#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE" - -/** - * 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. - * - * See this blog post for more information: - * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/ - * - * If this variable is set to "0", the system timer resolution is not set. - * - * The default value is "1". This hint may be set at any time. - */ -#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION" - -/** - * A variable controlling whether touch events should generate synthetic mouse events - * - * This variable can be set to the following values: - * "0" - Touch events will not generate mouse events - * "1" - Touch events will generate mouse events - * - * By default SDL will generate mouse events for touch events - */ -#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" - -/** - * A variable controlling which touchpad should generate synthetic mouse events - * - * This 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. - * - * By default SDL will generate mouse events for all touch devices - */ -#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE" - -/** - * A variable controlling whether the Android / tvOS remotes - * should be listed as joystick devices, instead of sending keyboard events. - * - * This 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 (the default). - */ -#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK" - -/** - * A variable controlling whether the screensaver is enabled. - * - * This variable can be set to the following values: - * "0" - Disable screensaver - * "1" - Enable screensaver - * - * By default SDL will disable the 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. - * We do so by waiting for vsync immediately after issuing a flip, usually just - * after eglSwapBuffers call in the backend's *_SwapWindow function. - * - * Since it's driver-specific, it's only supported where possible and - * implemented. Currently supported the following drivers: - * - * - KMSDRM (kmsdrm) - * - Raspberry Pi (raspberrypi) - */ -#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER" - -/** - * If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay. - * - * This 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. - * - * By default, SDL will fall back to eglGetDisplay if eglGetPlatformDisplay - * fails. - */ -#define SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK "SDL_VIDEO_EGL_GETDISPLAY_FALLBACK" - -/** - * A variable controlling whether the graphics context is externally managed. - * - * This variable can be set to the following values: - * "0" - SDL will manage graphics contexts that are attached to windows. - * "1" - Disable graphics context management on windows. - * - * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the - * context will be automatically saved and restored when pausing the application. Additionally, some - * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this - * behavior, which is desirable when the application manages the graphics context, such as - * an externally managed OpenGL context or attaching a Vulkan surface to the window. - */ -#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT" - -/** - * A variable that dictates policy for fullscreen Spaces on macOS. - * - * This hint only applies to 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). - * - * The default value is "1". This hint must be set before any windows are created. - */ -#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" - -/** - * Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false. - * \warning Before SDL 2.0.14, this defaulted to true! In 2.0.14, we're - * seeing if "true" causes more problems than it solves in modern times. - * - */ -#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" - -/** - * A variable controlling whether the libdecor Wayland backend is allowed to be used. - * - * This variable can be set to the following values: - * "0" - libdecor use is disabled. - * "1" - libdecor use is enabled (default). - * - * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable. - */ -#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR" - -/** - * A variable controlling whether the libdecor Wayland backend is preferred over native decrations. - * - * 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). - * - * This variable can be set to the following values: - * "0" - libdecor is enabled only if server-side decorations are unavailable. - * "1" - libdecor is always enabled if available. - * - * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable. - */ -#define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR" - -/** - * 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. - * - * This variable can be set to the following values: - * "0" - Video mode emulation is disabled. - * "1" - Video mode emulation is enabled. - * - * By default video mode emulation is enabled. - */ -#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. - * - * 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. - * - * This 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. - * "none" - Video modes will be displayed as 1:1 with no scaling. - * - * By default 'stretch' is used. - */ -#define SDL_HINT_VIDEO_WAYLAND_MODE_SCALING "SDL_VIDEO_WAYLAND_MODE_SCALING" - -/** - * Enable or disable mouse pointer warp emulation, needed by some older games. - * - * 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. - * - * This 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. - */ -#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" - -/** -* Set 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. -* -* 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 variable can be set to the following values: -* "0" - Window operations are non-blocking -* "1" - Window operations will block until completed -* -* By default SDL will run in non-blocking mode - */ -#define SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS "SDL_VIDEO_SYNC_WINDOW_OPERATIONS" - -/** -* 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. -* -* This variable can be set to the following values: -* "d3dcompiler_46.dll" - default, best for Vista or later. -* "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. -* -*/ -#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" - -/** - * Set whether the OpenGL context should be created with EGL by default - * - * This variable can be set to the following values: - * "0" - Use platform-specific GL context creation API (GLX, WGL, CGL, etc) - * "1" - Use EGL - * - * By default SDL will use the platform-specific GL context API when both are present. - */ -#define SDL_HINT_VIDEO_FORCE_EGL "SDL_VIDEO_FORCE_EGL" - -/** - * A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used. - * - * This variable can be set to the following values: - * "0" - Disable _NET_WM_BYPASS_COMPOSITOR - * "1" - Enable _NET_WM_BYPASS_COMPOSITOR - * - * By default SDL will use _NET_WM_BYPASS_COMPOSITOR - * - */ -#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. - * - * This variable can be set to the following values: - * "0" - Disable _NET_WM_PING - * "1" - Enable _NET_WM_PING - * - * 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 hint is checked in CreateWindow. - */ -#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING" - -/** - * A variable forcing the visual ID chosen for new X11 windows - * - */ -#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID" - -/** - * A variable forcing the scaling factor for X11 windows - * - * This variable can be set to a floating point value in the range 1.0-10.0f - */ -#define SDL_HINT_VIDEO_X11_SCALING_FACTOR "SDL_VIDEO_X11_SCALING_FACTOR" - -/** - * A variable controlling whether the X11 XRandR extension should be used. - * - * This variable can be set to the following values: - * "0" - Disable XRandR - * "1" - Enable XRandR - * - * By default SDL will use XRandR. - */ -#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR" - -/** - * Controls how the fact chunk affects the loading of a WAVE file. - * - * 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. - * - * This 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) - */ -#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" - -/** - * Controls 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. - * - * 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. - * - * This 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) - */ -#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" - -/** - * Controls 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. - * - * This 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) - */ -#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" - -/** - * Tell SDL not to name threads on Windows with the 0x406D1388 Exception. - * The 0x406D1388 Exception is a trick used to inform Visual Studio of a - * thread's name, but it tends to cause problems with other debuggers, - * and the .NET runtime. Note that SDL 2.0.6 and later will still use - * the (safer) SetThreadDescription API, introduced in the Windows 10 - * Creators Update, if available. - * - * The variable can be set to the following values: - * "0" - SDL will raise the 0x406D1388 Exception to name threads. - * This is the default behavior of SDL <= 2.0.4. - * "1" - SDL will not raise this exception, and threads will be unnamed. (default) - * This is necessary with .NET languages or debuggers that aren't Visual Studio. - */ -#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING" - -/** - * Controls 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! - * - * 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. - * - * This 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. - */ -#define SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS "SDL_WINDOWS_ENABLE_MENU_MNEMONICS" - -/** - * A variable controlling whether the windows message loop is processed by SDL - * - * This 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() - * - * By default SDL will process the windows message loop - */ -#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP" - -/** - * Force SDL to use 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. - * - * This variable can be set to the following values: - * "0" - Use SRW Locks when available. If not, fall back to Critical Sections. (default) - * "1" - Force the use of Critical Sections in all cases. - * - */ -#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS" - -/** - * Force SDL to use 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. - * - * This variable can be set to the following values: - * "0" - Use Atomics and WaitOnAddress API when available. If not, fall back to Kernel Objects. (default) - * "1" - Force the use of Kernel Objects in all cases. - * - */ -#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 - */ -#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON" -#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL" - -/** - * Tell SDL not to generate window-close events for Alt+F4 on Windows. - * - * The variable can be set to the following values: - * "0" - SDL will generate a window-close event when it sees Alt+F4. - * "1" - SDL will only do normal key handling for Alt+F4. - */ -#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4" - -/** - * Use 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. - * - * This hint must be set before initializing the video subsystem. - * - * 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 - * - * This 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) - * - */ -#define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX" - -/** - * A variable controlling whether the window frame and title bar are interactive when the cursor is hidden - * - * This 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 - * - * By default SDL will allow interaction with the window frame when the cursor is hidden - */ -#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN" - -/** -* A variable controlling whether the window is activated when the SDL_ShowWindow function is called -* -* This 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 -* -* By default SDL will activate the window when the SDL_ShowWindow function is called -*/ -#define SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN "SDL_WINDOW_ACTIVATE_WHEN_SHOWN" - -/** Allows 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. - * - * 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.) - * - * 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. - * - * 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. - * - * 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 - */ -#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON" - -/** Label text for a WinRT app's privacy policy link - * - * 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. - * - * 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. - * - * The contents of this hint should be encoded as a UTF8 string. - * - * The default value is "Privacy Policy". This hint should only be set during app - * initialization, preferably before any calls to SDL_Init(). - * - * For additional information on linking to a privacy policy, see the documentation for - * SDL_HINT_WINRT_PRIVACY_POLICY_URL. - */ -#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL" - -/** - * A 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". - * - * 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. - * - * The label text of an app's "Privacy Policy" link may be customized via another - * hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL. - * - * 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. - */ -#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL" - -/** - * Mark X11 windows as override-redirect. - * - * 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. - * - * 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! - */ -#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" - -/** - * A variable that lets you disable the detection and use of Xinput gamepad devices - * - * The variable can be set to the following values: - * "0" - Disable XInput detection (only uses direct input) - * "1" - Enable XInput detection (the default) - */ -#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" - - /** - * A variable that lets you disable the detection and use of DirectInput gamepad devices - * - * The variable can be set to the following values: - * "0" - Disable DirectInput detection (only uses XInput) - * "1" - Enable DirectInput detection (the default) - */ -#define SDL_HINT_DIRECTINPUT_ENABLED "SDL_DIRECTINPUT_ENABLED" - -/** - * A variable that causes SDL to use the old axis and button mapping for XInput devices. - * - * This hint is for backwards compatibility only and will be removed in SDL 2.1 - * - * The default value is "0". This hint must be set before SDL_Init() - */ -#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING" - -/** - * A variable that causes SDL to not ignore audio "monitors" - * - * This is currently only used for PulseAudio and ignored elsewhere. - * - * 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 default value is "0". This hint must be set before SDL_Init(). - * - * This hint is available since SDL 2.0.16. Before then, virtual devices are - * always ignored. - */ -#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS" - -/** - * A variable that forces X11 windows to create as a custom type. - * - * This is currently only used for X11 and ignored elsewhere. - * - * 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". - * - * If not set or set to "", this hint is ignored. This hint must be set - * before the SDL_CreateWindow() call that it is intended to affect. - * - * This hint is available since SDL 2.0.22. - */ -#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE" - -/** - * A variable that decides whether to send SDL_EVENT_QUIT when closing the final window. - * - * By default, SDL sends an SDL_EVENT_QUIT event when there is only one window - * and it receives an SDL_EVENT_WINDOW_CLOSE_REQUESTED event, under the assumption most - * apps would also take the loss of this window as a signal to terminate the - * program. - * - * However, it's not unreasonable in some cases to have the program continue - * to live on, perhaps to create new windows later. - * - * Changing this hint to "0" will cause SDL to not send an SDL_EVENT_QUIT event - * when the final 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. - * - * The default value is "1". This hint can be changed at any time. - * - * This hint is available since SDL 2.0.22. Before then, you always get - * an SDL_EVENT_QUIT event when closing the final window. - */ -#define SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE "SDL_QUIT_ON_LAST_WINDOW_CLOSE" - - -/** - * A variable that decides what 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. - * - * This functionality has existed since SDL 2.0.0 (indeed, before that) - * but before 2.0.22 this was an environment variable only. In 2.0.22, - * it was upgraded to a full SDL hint, so you can set the environment - * variable as usual or programmatically set the hint with SDL_SetHint, - * which won't propagate to child processes. - * - * The default value is unset, in which case SDL will try to figure out - * the best video backend on your behalf. This hint needs to be set - * before SDL_Init() is called to be useful. - * - * This hint is available since SDL 2.0.22. Before then, you could set - * the environment variable to get the same effect. - */ -#define SDL_HINT_VIDEO_DRIVER "SDL_VIDEO_DRIVER" - -/** - * A variable that decides what 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 target, such as "alsa" if, say, you are - * on PulseAudio but want to try talking to the lower level instead. - * - * This functionality has existed since SDL 2.0.0 (indeed, before that) - * but before 2.0.22 this was an environment variable only. In 2.0.22, - * it was upgraded to a full SDL hint, so you can set the environment - * variable as usual or programmatically set the hint with SDL_SetHint, - * which won't propagate to child processes. - * - * The default value is unset, in which case SDL will try to figure out - * the best audio backend on your behalf. This hint needs to be set - * before SDL_Init() is called to be useful. - * - * This hint is available since SDL 2.0.22. Before then, you could set - * the environment variable to get the same effect. - */ -#define SDL_HINT_AUDIO_DRIVER "SDL_AUDIO_DRIVER" - -/** - * A variable that decides what KMSDRM device to use. - * - * Internally, 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 is available since SDL 2.24.0. - */ -#define SDL_HINT_KMSDRM_DEVICE_INDEX "SDL_KMSDRM_DEVICE_INDEX" - - -/** - * A variable that treats trackpads 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. - * - * Setting this hint to true will make the trackpad input report as a - * multitouch device instead of a mouse. The default is false. - * - * Note that most platforms don't support this hint. As of 2.24.0, it - * only supports MacBooks' trackpads on macOS. Others may follow later. - * - * This hint is checked during SDL_Init and can not be changed after. - * - * This hint is available since SDL 2.24.0. - */ -#define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY" - - -/** - * Sets the title of the TextInput window on GDK platforms. - * - * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the - * standard SDL text input and virtual keyboard capabilities - * to get text from the user. - * - * This hint allows you to customize the virtual keyboard - * window that will be shown to the user. - * - * Set this hint to change the title of the window. - * - * This hint will not affect a window that is already being - * shown to the user. It will only affect new input windows. - * - * This hint is available only if SDL_GDK_TEXTINPUT defined. - */ -#define SDL_HINT_GDK_TEXTINPUT_TITLE "SDL_GDK_TEXTINPUT_TITLE" - -/** - * Sets the description of the TextInput window on GDK platforms. - * - * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the - * standard SDL text input and virtual keyboard capabilities - * to get text from the user. - * - * This hint allows you to customize the virtual keyboard - * window that will be shown to the user. - * - * Set this hint to change the description of the window. - * - * This hint will not affect a window that is already being - * shown to the user. It will only affect new input windows. - * - * This hint is available only if SDL_GDK_TEXTINPUT defined. - */ -#define SDL_HINT_GDK_TEXTINPUT_DESCRIPTION "SDL_GDK_TEXTINPUT_DESCRIPTION" - -/** - * Sets the default text of the TextInput window on GDK platforms. - * - * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the - * standard SDL text input and virtual keyboard capabilities - * to get text from the user. - * - * This hint allows you to customize the virtual keyboard - * window that will be shown to the user. - * - * Set this hint to change the default text value of the window. - * - * This hint will not affect a window that is already being - * shown to the user. It will only affect new input windows. - * - * This hint is available only if SDL_GDK_TEXTINPUT defined. - */ -#define SDL_HINT_GDK_TEXTINPUT_DEFAULT "SDL_GDK_TEXTINPUT_DEFAULT" - -/** - * Sets the input scope of the TextInput window on GDK platforms. - * - * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the - * standard SDL text input and virtual keyboard capabilities - * to get text from the user. - * - * This hint allows you to customize the virtual keyboard - * window that will be shown to the user. - * - * 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 will not affect a window that is already being - * shown to the user. It will only affect new input windows. - * - * This hint is available only if SDL_GDK_TEXTINPUT defined. - */ -#define SDL_HINT_GDK_TEXTINPUT_SCOPE "SDL_GDK_TEXTINPUT_SCOPE" - -/** - * Sets the maximum input length of the TextInput window on GDK platforms. - * - * On GDK, if SDL_GDK_TEXTINPUT is defined, you can use the - * standard SDL text input and virtual keyboard capabilities - * to get text from the user. - * - * This hint allows you to customize the virtual keyboard - * window that will be shown to the user. - * - * Set this hint to change the maximum allowed input - * length of the text box in the virtual keyboard window. - * - * The value must be a stringified integer, - * for example "10" to allow for up to 10 characters of text input. - * - * This hint will not affect a window that is already being - * shown to the user. It will only affect new input windows. - * - * This hint is available only if SDL_GDK_TEXTINPUT defined. - */ -#define SDL_HINT_GDK_TEXTINPUT_MAX_LENGTH "SDL_GDK_TEXTINPUT_MAX_LENGTH" - -/** - * Set the next device open's 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). - * - * 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. - * - * 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. - * - * This hint is checked when opening an audio device and can be changed - * between calls. - */ -#define SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES "SDL_AUDIO_DEVICE_SAMPLE_FRAMES" - /** * Request SDL_AppIterate() be called at a specific rate. * @@ -2717,25 +1519,1054 @@ extern "C" { * * This defaults to 60, and specifying NULL for the hint's value will restore * the default. + * + * This hint can be set anytime. */ #define SDL_HINT_MAIN_CALLBACK_RATE "SDL_MAIN_CALLBACK_RATE" /** - * Cause SDL to call dbus_shutdown() on quit. + * A variable controlling whether the mouse is captured while mouse buttons are pressed. * - * 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(). + * 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. * - * This 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 + * 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 is available since SDL 3.0.0. + * This hint can be set anytime. + */ +#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. + */ +#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. + */ +#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME" + +/** + * 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. + * + * This hint can be set anytime. + */ +#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. + * + * This hint can be set anytime. + */ +#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. + * + * 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) + * + * This hint can be set anytime. + */ +#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER" + +/** + * 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. + * + * This hint can be set anytime relative mode is not currently enabled. + */ +#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. + * + * This hint can be set anytime. + */ +#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. + * + * 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. + * + * This hint can be set anytime. + */ +#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. + * + * 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. + * + * This hint can be set anytime. + */ +#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION" + +/** + * A variable controlling whether mouse events should generate synthetic touch events + * + * 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 hint can be set anytime. + */ +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + +/** + * Tell SDL not to catch the SIGINT or SIGTERM signals on POSIX platforms. + * + * 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. + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" + +/** + * 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" - 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. + */ +#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" + +/** + * A variable controlling which orientations are allowed on iOS/Android. + * + * In some circumstances it is necessary to be able to explicitly control which UI orientations are allowed. + * + * This variable is a space delimited list of the following values: + * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown" + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS" + +/** + * A variable controlling whether pen mouse button emulation triggers only when the pen touches the tablet surface. + * + * 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. + */ +#define SDL_HINT_PEN_DELAY_MOUSE_BUTTON "SDL_HINT_PEN_DELAY_MOUSE_BUTTON" + +/** + * A variable controlling whether to treat pen movement as separate from mouse movement + * + * By default, pens report both ::SDL_MouseMotionEvent and ::SDL_PenMotionEvent updates (analogously for button presses). This hint allows decoupling mouse and pen updates. + * + * 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 hint can be set anytime. + */ +#define SDL_HINT_PEN_NOT_MOUSE "SDL_HINT_PEN_NOT_MOUSE" + +/** + * 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. + * + * The variable can be set to the following values: + * "0" - Disable poll sentinels. + * "1" - Enable poll sentinels. (default) + * + * This hint can be set anytime. + */ +#define SDL_HINT_POLL_SENTINEL "SDL_POLL_SENTINEL" + +/** + * 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). + * + * 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. + */ +#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES" + +/** + * 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) + * + * This hint can be set anytime. + */ +#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. + * + * The variable can be set to the following values: + * "0" - Thread-safety is not enabled. (default) + * "1" - Thread-safety is enabled. + * + * This hint should be set before creating a renderer. + */ +#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE" + +/** + * A variable controlling whether to enable Direct3D 11+'s Debug Layer. + * + * 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. + * + * This hint should be set before creating a renderer. + */ +#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" + +/** + * 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 + * + * By default, SDL does not use Vulkan Validation Layers. + */ +#define SDL_HINT_RENDER_VULKAN_DEBUG "SDL_RENDER_VULKAN_DEBUG" + +/** + * 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, the normal default renderer is used. + * + * 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. + */ +#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 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. + */ +#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" + +/** + * 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" - Use the prefered OS device. (default) + * "1" - Select a low power device. + * + * This hint should be set before creating a renderer. + */ +#define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" + +/** + * A variable controlling whether vsync is automatically disabled if doesn't reach enough FPS. + * + * 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 + * + * This hint should be set before creating a renderer. + */ +#define SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC "SDL_RENDER_PS2_DYNAMIC_VSYNC" + +/** + * 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. + * + * This hint should be set before creating a renderer. + */ +#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. + * + * 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. + * + * This hint can be set anytime. + */ +#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. + * + * 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. + */ +#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. + * + * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * + * 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. + */ +#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" + +/** + * A variable controlling which Dispmanx layer to use on a Raspberry PI. + * + * Also known as Z-order. The variable can take a negative or positive value. + * The default is 10000. + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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. + * + * This hint should be set before calling SDL_DisableScreenSaver() + */ +#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(). + * + * 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. + * + * This hint can be set anytime. */ #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. + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_STORAGE_USER_DRIVER "SDL_STORAGE_USER_DRIVER" + +/** + * 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 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() + */ +#define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL" + +/** + * A string specifying additional information to use with SDL_SetThreadPriority. + * + * 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. + * + * 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_SetThreadPriority() + */ +#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. + * + * See this blog post for more information: + * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/ + * + * The default value is "1". + * + * If this variable is set to "0", the system timer resolution is not set. + * + * This hint can be set anytime. + */ +#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION" + +/** + * 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) + * + * This hint can be set anytime. + */ +#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" + +/** + * 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. + * + * The variable can be set to the following values: + * "0" - Trackpad will send mouse events. (default) + * "1" - Trackpad will send touch events. + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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) + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK" + +/** + * A variable controlling whether the screensaver is enabled. + * + * The variable can be set to the following values: + * "0" - Disable screensaver. (default) + * "1" - Enable screensaver. + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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) + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_VIDEO_DRIVER "SDL_VIDEO_DRIVER" + +/** + * 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) + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK "SDL_VIDEO_EGL_GETDISPLAY_FALLBACK" + +/** + * 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 + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_VIDEO_FORCE_EGL "SDL_VIDEO_FORCE_EGL" + +/** + * 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) + * + * This hint should be set before creating a window. + */ +#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" + +/** + * 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. + * + * This hint can be set anytime. + */ +#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. + * + * 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" - Window operations are non-blocking. (default) + * "1" - Window operations will block until completed. + * + * This hint can be set anytime. + */ +#define SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS "SDL_VIDEO_SYNC_WINDOW_OPERATIONS" + +/** + * A variable controlling whether the libdecor Wayland backend is allowed to be used. + * + * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable. + * + * 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. + */ +#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR" + +/** + * Enable or disable mouse pointer warp emulation, needed by some older games. + * + * 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. + * + * 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. + * + * This hint can be set anytime. + */ +#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" + +/** + * 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. + * + * The variable can be set to the following values: + * "0" - Video mode emulation is disabled. + * "1" - Video mode emulation is enabled. (default) + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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. + * + * This hint should be set before creating a window. + */ +#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. + * + * 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. + * + * This hint should be set before SDL is initialized. + */ +#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 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. + * + * 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. + * + * This hint should be set before creating a window. + */ +#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. + * + * 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. + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" + +/** + * 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) + * + * This hint should be set before creating a window. + */ +#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. + * + * 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) + * + * This hint should be set before creating a window. + */ +#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING" + +/** + * A variable forcing the content scaling factor for X11 displays. + * + * 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. + */ +#define SDL_HINT_VIDEO_X11_SCALING_FACTOR "SDL_VIDEO_X11_SCALING_FACTOR" + +/** + * A variable forcing the visual ID chosen for new X11 windows + * + * This hint should be set before creating a window. + */ +#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) + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR" + +/** + * 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. + */ +#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE" + +/** + * A variable controlling how the fact chunk affects the loading of a WAVE file. + * + * 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) + * + * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + */ +#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" + +/** + * 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. + * + * 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. + * + * 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) + * + * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + */ +#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. + * + * 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) + * + * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + */ +#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" + +/** + * 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) + * + * This hint can be set anytime. + */ +#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. + * + * 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) + * + * This hint can be set anytime. + */ +#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. + * + * 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) + * + * This hint can be set anytime. + */ +#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 + * + * 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) + * + * This hint can be set anytime. + */ +#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. + * + * 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) + * + * This hint can be set anytime. + */ +#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). + * + * 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. + * + * 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. + * + * This hint can be set anytime. + */ +#define SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS "SDL_WINDOWS_ENABLE_MENU_MNEMONICS" + +/** + * 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) + * + * This hint can be set anytime. + */ +#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP" + +/** + * A variable controlling whether raw keyboard events are used 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. + */ +#define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD" + +/** + * 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. + * + * 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. + */ +#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS" + +/** + * 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. + * + * 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. + * + * This hint should be set before SDL is initialized. + */ +#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 + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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 + * + * 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) + * + * This hint should be set before SDL is initialized. + */ +#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. + * + * 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.) + * + * 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. + * + * 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. + * + * 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 + */ +#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON" + +/** + * A variable specifying the label text for a WinRT app's privacy policy link + * + * 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. + * + * 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. + * + * The contents of this hint should be encoded as a UTF8 string. + * + * The default value is "Privacy Policy". + * + * 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 SDL is initialized. + */ +#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL" + +/** + * 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". + * + * 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. + * + * The label text of an app's "Privacy Policy" link may be customized via another hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL. + * + * 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. + */ +#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL" + +/** + * A variable controlling whether X11 windows are marked as override-redirect. + * + * 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. + * + * 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 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. + */ +#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" + +/** + * A variable specifying the type of an X11 window. + * + * 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". + * + * This hint should be set before creating a window. + */ +#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE" + +/** + * A variable controlling whether XInput should be used for controller handling. + * + * The variable can be set to the following values: + * "0" - XInput is not enabled. + * "1" - XInput is enabled. (default) + * + * This hint should be set before SDL is initialized. + */ +#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" /** * An enumeration of hint priorities @@ -2763,6 +2594,7 @@ typedef enum * \since This function is available since SDL 3.0.0. * * \sa SDL_GetHint + * \sa SDL_ResetHint * \sa SDL_SetHint */ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, @@ -2783,6 +2615,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, * \since This function is available since SDL 3.0.0. * * \sa SDL_GetHint + * \sa SDL_ResetHint * \sa SDL_SetHintWithPriority */ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, @@ -2800,8 +2633,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetHint * \sa SDL_SetHint + * \sa SDL_ResetHints */ extern DECLSPEC SDL_bool SDLCALL SDL_ResetHint(const char *name); @@ -2814,8 +2647,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ResetHint(const char *name); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetHint - * \sa SDL_SetHint * \sa SDL_ResetHint */ extern DECLSPEC void SDLCALL SDL_ResetHints(void); @@ -2892,23 +2723,6 @@ extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata); -/** - * Clear all hints. - * - * This function is automatically called during SDL_Quit(), and deletes all - * callbacks without calling them and frees all memory associated with hints. - * If you're calling this from application code you probably want to call - * SDL_ResetHints() instead. - * - * This function will be removed from the API the next time we rev the ABI. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_ResetHints - */ -extern DECLSPEC void SDLCALL SDL_ClearHints(void); - - /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/include/SDL3/SDL_init.h b/include/SDL3/SDL_init.h index 472afc99..cb2de999 100644 --- a/include/SDL3/SDL_init.h +++ b/include/SDL3/SDL_init.h @@ -53,18 +53,15 @@ extern "C" { typedef enum { SDL_INIT_TIMER = 0x00000001, - SDL_INIT_AUDIO = 0x00000010, + 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 = 0x00008000, /**< `SDL_INIT_SENSOR` implies `SDL_INIT_EVENTS` */ + SDL_INIT_CAMERA = 0x00010000 /**< `SDL_INIT_CAMERA` implies `SDL_INIT_EVENTS` */ } SDL_InitFlags; -#define SDL_INIT_EVERYTHING ( \ - SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \ - SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_SENSOR \ - ) /** * Initialize the SDL library. @@ -73,7 +70,7 @@ typedef enum * two may be used interchangeably. Though for readability of your code * SDL_InitSubSystem() might be preferred. * - * The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread) + * The file I/O (for example: SDL_IOFromFile) and threading (SDL_CreateThread) * subsystems are initialized by default. Message boxes * (SDL_ShowSimpleMessageBox) also attempt to work without initializing the * video subsystem, in hopes of being useful in showing an error dialog when @@ -94,7 +91,7 @@ typedef enum * - `SDL_INIT_GAMEPAD`: gamepad subsystem; automatically initializes the * joystick subsystem * - `SDL_INIT_EVENTS`: events subsystem - * - `SDL_INIT_EVERYTHING`: all of the above subsystems + * - `SDL_INIT_SENSOR`: sensor subsystem * * Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem() * for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or diff --git a/include/SDL3/SDL_intrin.h b/include/SDL3/SDL_intrin.h index d75ce788..f907df9c 100644 --- a/include/SDL3/SDL_intrin.h +++ b/include/SDL3/SDL_intrin.h @@ -64,7 +64,7 @@ _m_prefetch(void *__P) # ifdef __ARM_NEON # define SDL_NEON_INTRINSICS 1 # include -# elif defined(__WINDOWS__) || defined(__WINRT__) || defined(__GDK__) +# elif defined(SDL_PLATFORM_WINDOWS) /* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */ # ifdef _M_ARM # define SDL_NEON_INTRINSICS 1 diff --git a/include/SDL3/SDL_rwops.h b/include/SDL3/SDL_iostream.h similarity index 62% rename from include/SDL3/SDL_rwops.h rename to include/SDL3/SDL_iostream.h index 557bdb81..52e218e6 100644 --- a/include/SDL3/SDL_rwops.h +++ b/include/SDL3/SDL_iostream.h @@ -20,14 +20,17 @@ */ /** - * \file SDL_rwops.h + * \file SDL_iostream.h * * This file provides a general interface for SDL to read and write * data streams. It can easily be extended to files, memory, etc. + * + * SDL_IOStream is not related to the standard C++ iostream class, other + * than both are abstract interfaces to read/write data. */ -#ifndef SDL_rwops_h_ -#define SDL_rwops_h_ +#ifndef SDL_iostream_h_ +#define SDL_iostream_h_ #include #include @@ -39,122 +42,85 @@ extern "C" { #endif -/* RWops types */ -#define SDL_RWOPS_UNKNOWN 0 /**< Unknown stream type */ -#define SDL_RWOPS_WINFILE 1 /**< Win32 file */ -#define SDL_RWOPS_STDFILE 2 /**< Stdio file */ -#define SDL_RWOPS_JNIFILE 3 /**< Android asset */ -#define SDL_RWOPS_MEMORY 4 /**< Memory stream */ -#define SDL_RWOPS_MEMORY_RO 5 /**< Read-Only memory stream */ +/* SDL_IOStream status, set by a read or write operation */ +typedef enum SDL_IOStatus +{ + SDL_IO_STATUS_READY, /**< Everything is ready */ + 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 */ + SDL_IO_STATUS_READONLY, /**< Tried to write a read-only buffer */ + SDL_IO_STATUS_WRITEONLY /**< Tried to read a write-only buffer */ +} SDL_IOStatus; -/* RWops status, set by a read or write operation */ -#define SDL_RWOPS_STATUS_READY 0 /**< Everything is ready */ -#define SDL_RWOPS_STATUS_ERROR 1 /**< Read or write I/O error */ -#define SDL_RWOPS_STATUS_EOF 2 /**< End of file */ -#define SDL_RWOPS_STATUS_NOT_READY 3 /**< Non blocking I/O, not ready */ -#define SDL_RWOPS_STATUS_READONLY 4 /**< Tried to write a read-only buffer */ -#define SDL_RWOPS_STATUS_WRITEONLY 5 /**< Tried to read a write-only buffer */ - -/** - * This is the read/write operation structure -- very basic. - */ -typedef struct SDL_RWops +typedef struct SDL_IOStreamInterface { /** - * Return the number of bytes in this rwops + * Return the number of bytes in this SDL_IOStream * * \return the total size of the data stream, or -1 on error. */ - Sint64 (SDLCALL *size)(struct SDL_RWops *context); + Sint64 (SDLCALL *size)(void *userdata); /** * Seek to \c offset relative to \c whence, one of stdio's whence values: - * SDL_RW_SEEK_SET, SDL_RW_SEEK_CUR, SDL_RW_SEEK_END + * 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)(struct SDL_RWops *context, Sint64 offset, int whence); + Sint64 (SDLCALL *seek)(void *userdata, Sint64 offset, int whence); /** * Read up to \c size bytes from the data stream to the area pointed * at by \c 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 + * a complete, successful read. + * * \return the number of bytes read */ - size_t (SDLCALL *read)(struct SDL_RWops *context, void *ptr, size_t size); + 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 * to data stream. * + * On an incomplete write, you should set `*status` to a value from the + * SDL_IOStatus enum. You do not have to explicitly set this on + * a complete, successful write. + * * \return the number of bytes written */ - size_t (SDLCALL *write)(struct SDL_RWops *context, const void *ptr, size_t size); + size_t (SDLCALL *write)(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status); /** - * Close and free an allocated SDL_RWops structure. + * Close and free any allocated resources. + * + * The SDL_IOStream is still destroyed even if this fails, so clean up anything + * even if flushing to disk returns an error. * * \return 0 if successful or -1 on write error when flushing data. */ - int (SDLCALL *close)(struct SDL_RWops *context); - - Uint32 type; - Uint32 status; - SDL_PropertiesID props; - union - { -#ifdef __ANDROID__ - struct - { - void *asset; - } androidio; - -#elif defined(__WIN32__) || defined(__GDK__) || defined(__WINRT__) - struct - { - SDL_bool append; - void *h; - struct - { - void *data; - size_t size; - size_t left; - } buffer; - } windowsio; -#endif - - struct - { - SDL_bool autoclose; - void *fp; - } stdio; - - struct - { - Uint8 *base; - Uint8 *here; - Uint8 *stop; - } mem; - - struct - { - void *data1; - void *data2; - } unknown; - } hidden; - -} SDL_RWops; + int (SDLCALL *close)(void *userdata); +} SDL_IOStreamInterface; /** - * \name RWFrom functions + * This is the read/write operation structure -- opaque, as of SDL3! + */ +typedef struct SDL_IOStream SDL_IOStream; + + +/** + * \name IOFrom functions * - * Functions to create SDL_RWops structures from various data streams. + * Functions to create SDL_IOStream structures from various data streams. */ /* @{ */ /** - * Use this function to create a new SDL_RWops structure for reading from + * Use this function to create a new SDL_IOStream structure for reading from * and/or writing to a named file. * * The `mode` string is treated roughly the same as in a call to the C @@ -192,151 +158,193 @@ typedef struct SDL_RWops * This function supports Unicode filenames, but they must be encoded in UTF-8 * format, regardless of the underlying operating system. * - * As a fallback, SDL_RWFromFile() will transparently open a matching filename + * As a fallback, SDL_IOFromFile() will transparently open a matching filename * in an Android app's `assets`. * - * Closing the SDL_RWops will close the file handle SDL is holding internally. + * Closing the SDL_IOStream will close SDL's internal file handle. + * + * The following properties may be set at creation time by SDL: + * + * - `SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER`: a pointer, that can be cast + * to a win32 `HANDLE`, that this SDL_IOStream is using to access the + * filesystem. If the program isn't running on Windows, or SDL used some + * other method to access the filesystem, this property will not be set. + * - `SDL_PROP_IOSTREAM_STDIO_FILE_POINTER`: a pointer, that can be cast to a + * stdio `FILE *`, 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. PLEASE NOTE that if SDL is using a different C runtime + * 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_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 mode an ASCII string representing the mode to be used for opening * the file. - * \returns a pointer to the SDL_RWops 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_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWtell - * \sa SDL_RWwrite + * \sa SDL_CloseIO + * \sa SDL_ReadIO + * \sa SDL_SeekIO + * \sa SDL_TellIO + * \sa SDL_WriteIO */ -extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file, const char *mode); +extern 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_ANDROID_AASSET_POINTER "SDL.iostream.android.aasset" /** * Use this function to prepare a read-write memory buffer for use with - * SDL_RWops. + * SDL_IOStream. * - * This function sets up an SDL_RWops struct based on a memory area of a + * This function sets up an SDL_IOStream struct based on a memory area of a * certain size, for both read and write access. * - * This memory buffer is not copied by the RWops; the pointer you provide must - * remain valid until you close the stream. Closing the stream will not free - * the original buffer. + * This memory buffer is not copied by the SDL_IOStream; the pointer you + * provide must remain valid until you close the stream. Closing the stream + * will not free the original buffer. * - * If you need to make sure the RWops never writes to the memory buffer, you - * should use SDL_RWFromConstMem() with a read-only buffer of memory instead. + * If you need to make sure the SDL_IOStream never writes to the memory + * 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_RWops stream + * \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_RWops structure, or NULL if it fails; call - * SDL_GetError() for more information. + * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; + * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWtell - * \sa SDL_RWwrite + * \sa SDL_IOFromConstMem + * \sa SDL_CloseIO + * \sa SDL_ReadIO + * \sa SDL_SeekIO + * \sa SDL_TellIO + * \sa SDL_WriteIO */ -extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, size_t size); +extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromMem(void *mem, size_t size); /** - * Use this function to prepare a read-only memory buffer for use with RWops. + * Use this function to prepare a read-only memory buffer for use with + * SDL_IOStream. * - * This function sets up an SDL_RWops struct based on a memory area of a + * This function sets up an SDL_IOStream struct based on a memory area of a * certain size. It assumes the memory area is not writable. * - * Attempting to write to this RWops stream will report an error without - * writing to the memory buffer. + * Attempting to write to this SDL_IOStream stream will report an error + * without writing to the memory buffer. * - * This memory buffer is not copied by the RWops; the pointer you provide must - * remain valid until you close the stream. Closing the stream will not free - * the original buffer. + * This memory buffer is not copied by the SDL_IOStream; the pointer you + * provide must remain valid until you close the stream. Closing the stream + * will not free the original buffer. * - * If you need to write to a memory buffer, you should use SDL_RWFromMem() + * 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_RWops stream + * \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_RWops structure, or NULL if it fails; call - * SDL_GetError() for more information. + * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; + * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWtell + * \sa SDL_IOFromMem + * \sa SDL_CloseIO + * \sa SDL_ReadIO + * \sa SDL_SeekIO + * \sa SDL_TellIO */ -extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem, size_t size); +extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromConstMem(const void *mem, size_t size); -/* @} *//* RWFrom functions */ +/** + * 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CloseIO + * \sa SDL_ReadIO + * \sa SDL_SeekIO + * \sa SDL_TellIO + * \sa SDL_WriteIO + */ +extern 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" + +/* @} *//* IOFrom functions */ /** - * Use this function to allocate an empty, unpopulated SDL_RWops structure. + * Create a custom SDL_IOStream. * * Applications do not need to use this function unless they are providing - * their own SDL_RWops implementation. If you just need an SDL_RWops to + * their own SDL_IOStream implementation. If you just need an SDL_IOStream to * read/write a common data source, you should use the built-in - * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc. + * implementations in SDL, like SDL_IOFromFile() or SDL_IOFromMem(), etc. * - * You must free the returned pointer with SDL_DestroyRW(). Depending on your - * operating system and compiler, there may be a difference between the - * malloc() and free() your program uses and the versions SDL calls - * internally. Trying to mix the two can cause crashing such as segmentation - * faults. Since all SDL_RWops must free themselves when their **close** - * method is called, all SDL_RWops must be allocated through this function, so - * they can all be freed correctly with SDL_DestroyRW(). + * You must free the returned pointer with SDL_CloseIO(). * + * \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; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_DestroyRW + * \sa SDL_CloseIO + * \sa SDL_IOFromConstMem + * \sa SDL_IOFromFile + * \sa SDL_IOFromMem */ -extern DECLSPEC SDL_RWops *SDLCALL SDL_CreateRW(void); +extern DECLSPEC SDL_IOStream *SDLCALL SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata); /** - * Use this function to free an SDL_RWops structure allocated by - * SDL_CreateRW(). + * Close and free an allocated SDL_IOStream structure. * - * Applications do not need to use this function unless they are providing - * their own SDL_RWops implementation. If you just need an SDL_RWops to - * read/write a common data source, you should use the built-in - * implementations in SDL, like SDL_RWFromFile() or SDL_RWFromMem(), etc, and - * call the **close** method on those SDL_RWops pointers when you are done - * with them. + * 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). * - * Only use SDL_DestroyRW() on pointers returned by SDL_CreateRW(). The - * pointer is invalid as soon as this function returns. Any extra memory - * allocated during creation of the SDL_RWops is not freed by SDL_DestroyRW(); - * the programmer must be responsible for managing that memory in their - * **close** method. + * 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 the SDL_RWops structure to be freed + * \param context SDL_IOStream structure to close + * \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_CreateRW + * \sa SDL_OpenIO */ -extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context); +extern DECLSPEC int SDLCALL SDL_CloseIO(SDL_IOStream *context); /** - * Get the properties associated with an SDL_RWops. + * Get the properties associated with an SDL_IOStream. * - * \param context a pointer to an SDL_RWops 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. * @@ -345,83 +353,89 @@ extern DECLSPEC void SDLCALL SDL_DestroyRW(SDL_RWops *context); * \sa SDL_GetProperty * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRWProperties(SDL_RWops *context); +extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *context); -#define SDL_RW_SEEK_SET 0 /**< Seek from the beginning of data */ -#define SDL_RW_SEEK_CUR 1 /**< Seek relative to current read point */ -#define SDL_RW_SEEK_END 2 /**< Seek relative to the end of data */ +#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 */ /** - * Use this function to get the size of the data stream in an SDL_RWops. + * Query the stream status of an SDL_IOStream. * - * \param context the SDL_RWops to get the size of the data stream from - * \returns the size of the data stream in the SDL_RWops on success or a + * This information can be useful to decide if a short read or write was due + * to an error, an EOF, or a non-blocking operation that isn't yet ready to + * complete. + * + * An SDL_IOStream's status is only expected to change after a SDL_ReadIO or + * SDL_WriteIO call; don't expect it to change if you just call this query + * function in a tight loop. + * + * \param context the SDL_IOStream to query. + * \returns an SDL_IOStatus enum with the current state. + * + * \threadsafety This function should not be called at the same time that + * another thread is operating on the same SDL_IOStream. + * + * \since This function is available since SDL 3.0.0. + */ +extern 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 + * \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_RWsize(SDL_RWops *context); +extern DECLSPEC Sint64 SDLCALL SDL_GetIOSize(SDL_IOStream *context); /** - * Seek within an SDL_RWops data stream. + * Seek within an SDL_IOStream data stream. * * This function seeks to byte `offset`, relative to `whence`. * * `whence` may be any of the following values: * - * - `SDL_RW_SEEK_SET`: seek from the beginning of data - * - `SDL_RW_SEEK_CUR`: seek relative to current read point - * - `SDL_RW_SEEK_END`: seek relative to the end of data + * - `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 * * If this stream can not seek, it will return -1. * - * SDL_RWseek() is actually a wrapper function that calls the SDL_RWops's - * `seek` method appropriately, to simplify application development. - * - * \param context a pointer to an SDL_RWops structure + * \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_RW_SEEK_SET`, `SDL_RW_SEEK_CUR`, - * `SDL_RW_SEEK_END` + * \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. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWtell - * \sa SDL_RWwrite + * \sa SDL_TellIO */ -extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence); +extern DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offset, int whence); /** - * Determine the current read/write offset in an SDL_RWops data stream. + * Determine the current read/write offset in an SDL_IOStream data stream. * - * SDL_RWtell is actually a wrapper function that calls the SDL_RWops's `seek` - * method, with an offset of 0 bytes from `SDL_RW_SEEK_CUR`, to simplify - * application development. + * SDL_TellIO is actually a wrapper function that calls the SDL_IOStream's + * `seek` method, with an offset of 0 bytes from `SDL_IO_SEEK_CUR`, to + * simplify application development. * - * \param context an SDL_RWops data stream object from which to get the + * \param context an SDL_IOStream data stream object from which to get the * current offset * \returns the current offset in the stream, or -1 if the information can not * be determined. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWwrite + * \sa SDL_SeekIO */ -extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context); +extern DECLSPEC Sint64 SDLCALL SDL_TellIO(SDL_IOStream *context); /** * Read from a data source. @@ -434,31 +448,20 @@ extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context); * that this is not an error or end-of-file, and the caller can try again * later. * - * SDL_RWread() is actually a function wrapper that calls the SDL_RWops's - * `read` method appropriately, to simplify application development. - * - * 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. - * - * \param context a pointer to an SDL_RWops structure + * \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. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWseek - * \sa SDL_RWwrite + * \sa SDL_SeekIO + * \sa SDL_WriteIO */ -extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t size); +extern DECLSPEC size_t SDLCALL SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size); /** - * Write to an SDL_RWops data stream. + * 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` @@ -471,14 +474,11 @@ extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t * 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. * - * SDL_RWwrite is actually a function wrapper that calls the SDL_RWops's - * `write` method appropriately, to simplify application development. - * * 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. * - * \param context a pointer to an SDL_RWops structure + * \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 @@ -486,22 +486,18 @@ extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, void *ptr, size_t * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWprint - * \sa SDL_RWread - * \sa SDL_RWseek + * \sa SDL_IOprintf + * \sa SDL_ReadIO + * \sa SDL_SeekIO */ -extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size); +extern DECLSPEC size_t SDLCALL SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size); /** - * Print to an SDL_RWops data stream. + * Print to an SDL_IOStream data stream. * * This function does formatted printing to the stream. * - * \param context a pointer to an SDL_RWops structure + * \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 @@ -510,22 +506,17 @@ extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, const void *ptr, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWwrite + * \sa SDL_IOvprintf + * \sa SDL_WriteIO */ -extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern 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_RWops data stream. + * Print to an SDL_IOStream data stream. * * This function does formatted printing to the stream. * - * \param context a pointer to an SDL_RWops structure + * \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() @@ -533,41 +524,10 @@ extern DECLSPEC size_t SDLCALL SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMA * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RWclose - * \sa SDL_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWwrite + * \sa SDL_IOprintf + * \sa SDL_WriteIO */ -extern DECLSPEC size_t SDLCALL SDL_RWvprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); - -/** - * Close and free an allocated SDL_RWops structure. - * - * SDL_RWclose() closes and cleans up the SDL_RWops stream. It releases any - * resources used by the stream and frees the SDL_RWops itself with - * SDL_DestroyRW(). 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_RWops is still invalid once this function returns. - * - * \param context SDL_RWops structure to close - * \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_RWFromConstMem - * \sa SDL_RWFromFile - * \sa SDL_RWFromMem - * \sa SDL_RWread - * \sa SDL_RWseek - * \sa SDL_RWwrite - */ -extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context); +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); /** * Load all the data from an SDL data stream. @@ -578,15 +538,17 @@ extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context); * * The data should be freed with SDL_free(). * - * \param src the SDL_RWops to read all available data from + * \param src the SDL_IOStream to read all available data from * \param datasize if not NULL, will store the number of bytes read - * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning, + * \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. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_LoadFile */ -extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc); +extern DECLSPEC void *SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio); /** * Load all the data from a file path. @@ -602,6 +564,8 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, * \returns the data, or NULL if there was an error. * * \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); @@ -613,19 +577,51 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); /* @{ */ /** - * Use this function to read a byte from an SDL_RWops. + * Use this function to read a byte from an SDL_IOStream. * - * \param src the SDL_RWops to read from + * \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. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_RWops *src, Uint8 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_IOStream *src, Uint8 *value); /** - * Use this function to read 16 bits of little-endian data from an SDL_RWops + * Use this function to read 16 bits of little-endian data from an + * SDL_IOStream and return in native format. + * + * 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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value); + +/** + * Use this function to read 16 bits of little-endian data from an + * SDL_IOStream and return in native format. + * + * 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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value); + +/** + * Use this function to read 16 bits of big-endian data from an SDL_IOStream * and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in @@ -638,10 +634,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_RWops *src, Uint8 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_RWops *src, Uint16 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value); /** - * Use this function to read 16 bits of little-endian data from an SDL_RWops + * Use this function to read 16 bits of big-endian data from an SDL_IOStream * and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in @@ -654,11 +650,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_RWops *src, Uint16 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_RWops *src, Sint16 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value); /** - * Use this function to read 16 bits of big-endian data from an SDL_RWops and - * return in native format. + * Use this function to read 32 bits of little-endian data from an + * SDL_IOStream and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. @@ -670,11 +666,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_RWops *src, Sint16 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_RWops *src, Uint16 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value); /** - * Use this function to read 16 bits of big-endian data from an SDL_RWops and - * return in native format. + * Use this function to read 32 bits of little-endian data from an + * SDL_IOStream and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. @@ -686,10 +682,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_RWops *src, Uint16 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_RWops *src, Sint16 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value); /** - * Use this function to read 32 bits of little-endian data from an SDL_RWops + * Use this function to read 32 bits of big-endian data from an SDL_IOStream * and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in @@ -702,10 +698,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_RWops *src, Sint16 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_RWops *src, Uint32 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value); /** - * Use this function to read 32 bits of little-endian data from an SDL_RWops + * Use this function to read 32 bits of big-endian data from an SDL_IOStream * and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in @@ -718,11 +714,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_RWops *src, Uint32 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_RWops *src, Sint32 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value); /** - * Use this function to read 32 bits of big-endian data from an SDL_RWops and - * return in native format. + * Use this function to read 64 bits of little-endian data from an + * SDL_IOStream and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. @@ -734,11 +730,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_RWops *src, Sint32 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_RWops *src, Uint32 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value); /** - * Use this function to read 32 bits of big-endian data from an SDL_RWops and - * return in native format. + * Use this function to read 64 bits of little-endian data from an + * SDL_IOStream and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. @@ -750,10 +746,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_RWops *src, Uint32 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_RWops *src, Sint32 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value); /** - * Use this function to read 64 bits of little-endian data from an SDL_RWops + * Use this function to read 64 bits of big-endian data from an SDL_IOStream * and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in @@ -766,10 +762,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_RWops *src, Sint32 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_RWops *src, Uint64 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value); /** - * Use this function to read 64 bits of little-endian data from an SDL_RWops + * Use this function to read 64 bits of big-endian data from an SDL_IOStream * and return in native format. * * SDL byteswaps the data only if necessary, so the data returned will be in @@ -782,39 +778,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_RWops *src, Uint64 *value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_RWops *src, Sint64 *value); - -/** - * Use this function to read 64 bits of big-endian data from an SDL_RWops and - * return in native format. - * - * 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. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_RWops *src, Uint64 *value); - -/** - * Use this function to read 64 bits of big-endian data from an SDL_RWops and - * return in native format. - * - * 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. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_RWops *src, Sint64 *value); +extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value); /* @} *//* Read endian functions */ /** @@ -825,19 +789,19 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_RWops *src, Sint64 *value); /* @{ */ /** - * Use this function to write a byte to an SDL_RWops. + * Use this function to write a byte to an SDL_IOStream. * - * \param dst the SDL_RWops to write to + * \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. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_RWops *dst, Uint8 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_IOStream *dst, Uint8 value); /** - * Use this function to write 16 bits in native format to an SDL_RWops as + * Use this function to write 16 bits in native format to an SDL_IOStream as * little-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -851,10 +815,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_RWops *dst, Uint8 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_RWops *dst, Uint16 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value); /** - * Use this function to write 16 bits in native format to an SDL_RWops as + * Use this function to write 16 bits in native format to an SDL_IOStream as * little-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -868,10 +832,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_RWops *dst, Uint16 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_RWops *dst, Sint16 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value); /** - * Use this function to write 16 bits in native format to an SDL_RWops as + * Use this function to write 16 bits in native format to an SDL_IOStream as * big-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -884,10 +848,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_RWops *dst, Sint16 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_RWops *dst, Uint16 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value); /** - * Use this function to write 16 bits in native format to an SDL_RWops as + * Use this function to write 16 bits in native format to an SDL_IOStream as * big-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -900,10 +864,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_RWops *dst, Uint16 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_RWops *dst, Sint16 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value); /** - * Use this function to write 32 bits in native format to an SDL_RWops as + * Use this function to write 32 bits in native format to an SDL_IOStream as * little-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -917,10 +881,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_RWops *dst, Sint16 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_RWops *dst, Uint32 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value); /** - * Use this function to write 32 bits in native format to an SDL_RWops as + * Use this function to write 32 bits in native format to an SDL_IOStream as * little-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -934,10 +898,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_RWops *dst, Uint32 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_RWops *dst, Sint32 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value); /** - * Use this function to write 32 bits in native format to an SDL_RWops as + * Use this function to write 32 bits in native format to an SDL_IOStream as * big-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -950,10 +914,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_RWops *dst, Sint32 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_RWops *dst, Uint32 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value); /** - * Use this function to write 32 bits in native format to an SDL_RWops as + * Use this function to write 32 bits in native format to an SDL_IOStream as * big-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -966,10 +930,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_RWops *dst, Uint32 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_RWops *dst, Sint32 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value); /** - * Use this function to write 64 bits in native format to an SDL_RWops as + * Use this function to write 64 bits in native format to an SDL_IOStream as * little-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -983,10 +947,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_RWops *dst, Sint32 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_RWops *dst, Uint64 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value); /** - * Use this function to write 64 bits in native format to an SDL_RWops as + * Use this function to write 64 bits in native format to an SDL_IOStream as * little-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -1000,10 +964,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_RWops *dst, Uint64 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_RWops *dst, Sint64 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value); /** - * Use this function to write 64 bits in native format to an SDL_RWops as + * Use this function to write 64 bits in native format to an SDL_IOStream as * big-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -1016,10 +980,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_RWops *dst, Sint64 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_RWops *dst, Uint64 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value); /** - * Use this function to write 64 bits in native format to an SDL_RWops as + * Use this function to write 64 bits in native format to an SDL_IOStream as * big-endian data. * * SDL byteswaps the data only if necessary, so the application always @@ -1032,7 +996,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_RWops *dst, Uint64 value); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_RWops *dst, Sint64 value); +extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value); /* @} *//* Write endian functions */ @@ -1042,4 +1006,4 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_RWops *dst, Sint64 value); #endif #include -#endif /* SDL_rwops_h_ */ +#endif /* SDL_iostream_h_ */ diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index 80f210d6..337815cb 100644 --- a/include/SDL3/SDL_joystick.h +++ b/include/SDL3/SDL_joystick.h @@ -137,6 +137,17 @@ extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lo */ extern 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoysticks + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasJoystick(void); + /** * Get a list of currently connected joysticks. * @@ -147,6 +158,7 @@ extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_ * * \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); @@ -163,7 +175,7 @@ extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetJoysticks(int *count); * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickName - * \sa SDL_OpenJoystick + * \sa SDL_GetJoysticks */ extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstanceName(SDL_JoystickID instance_id); @@ -179,7 +191,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstanceName(SDL_JoystickID i * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickPath - * \sa SDL_OpenJoystick + * \sa SDL_GetJoysticks */ extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstancePath(SDL_JoystickID instance_id); @@ -194,7 +206,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstancePath(SDL_JoystickID i * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickPlayerIndex - * \sa SDL_OpenJoystick + * \sa SDL_GetJoysticks */ extern DECLSPEC int SDLCALL SDL_GetJoystickInstancePlayerIndex(SDL_JoystickID instance_id); @@ -204,8 +216,8 @@ extern DECLSPEC int SDLCALL SDL_GetJoystickInstancePlayerIndex(SDL_JoystickID in * This can be called before any joysticks are opened. * * \param instance_id the joystick instance ID - * \returns the GUID of the selected joystick. If called on an invalid index, - * this function returns a zero GUID + * \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. * @@ -221,10 +233,13 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickInstanceGUID(SDL_Joystic * available this function returns 0. * * \param instance_id the joystick instance ID - * \returns the USB vendor ID of the selected joystick. If called on an - * invalid index, this function returns zero + * \returns the USB vendor ID of the selected joystick. If called with an + * invalid instance_id, this function returns 0. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoystickVendor + * \sa SDL_GetJoysticks */ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceVendor(SDL_JoystickID instance_id); @@ -235,10 +250,13 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceVendor(SDL_JoystickID inst * available this function returns 0. * * \param instance_id the joystick instance ID - * \returns the USB product ID of the selected joystick. If called on an - * invalid index, this function returns zero + * \returns the USB product ID of the selected joystick. If called with an + * invalid instance_id, this function returns 0. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoystickProduct + * \sa SDL_GetJoysticks */ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProduct(SDL_JoystickID instance_id); @@ -249,10 +267,13 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProduct(SDL_JoystickID ins * isn't available this function returns 0. * * \param instance_id the joystick instance ID - * \returns the product version of the selected joystick. If called on an - * invalid index, this function returns zero + * \returns the product version of the selected joystick. If called with an + * invalid instance_id, this function returns 0. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoystickProductVersion + * \sa SDL_GetJoysticks */ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProductVersion(SDL_JoystickID instance_id); @@ -262,10 +283,14 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProductVersion(SDL_Joystic * This can be called before any joysticks are opened. * * \param instance_id the joystick instance ID - * \returns the SDL_JoystickType of the selected joystick. If called on an - * invalid index, this function returns `SDL_JOYSTICK_TYPE_UNKNOWN` + * \returns the SDL_JoystickType of the selected joystick. If called with an + * invalid instance_id, this function returns + * `SDL_JOYSTICK_TYPE_UNKNOWN`. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoystickType + * \sa SDL_GetJoysticks */ extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickInstanceType(SDL_JoystickID instance_id); @@ -304,6 +329,9 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromInstanceID(SDL_Joystick * for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoystickPlayerIndex + * \sa SDL_SetJoystickPlayerIndex */ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromPlayerIndex(int player_index); @@ -318,6 +346,9 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromPlayerIndex(int player_ * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AttachVirtualJoystickEx + * \sa SDL_DetachVirtualJoystick */ extern DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystick(SDL_JoystickType type, int naxes, @@ -371,6 +402,9 @@ typedef struct SDL_VirtualJoystickDesc * 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); @@ -383,6 +417,9 @@ extern DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystickEx(const SDL_Vir * 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); @@ -460,6 +497,19 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, in /** * Get the properties associated with a joystick. * + * The following read-only properties are provided by SDL: + * + * - `SDL_PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN`: true if this joystick has an + * LED that has adjustable brightness + * - `SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN`: true if this joystick has an LED + * that has adjustable color + * - `SDL_PROP_JOYSTICK_CAP_PLAYER_LED_BOOLEAN`: true if this joystick has a + * player LED + * - `SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN`: true if this joystick has + * left/right rumble + * - `SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN`: true if this joystick has + * simple trigger rumble + * * \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. @@ -471,6 +521,12 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, in */ extern 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" +#define SDL_PROP_JOYSTICK_CAP_PLAYER_LED_BOOLEAN "SDL.joystick.cap.player_led" +#define SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN "SDL.joystick.cap.rumble" +#define SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN "SDL.joystick.cap.trigger_rumble" + /** * Get the implementation dependent name of a joystick. * @@ -481,7 +537,6 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joystick * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickInstanceName - * \sa SDL_OpenJoystick */ extern DECLSPEC const char *SDLCALL SDL_GetJoystickName(SDL_Joystick *joystick); @@ -508,6 +563,8 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickPath(SDL_Joystick *joystick); * \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); @@ -521,6 +578,8 @@ extern DECLSPEC int SDLCALL SDL_GetJoystickPlayerIndex(SDL_Joystick *joystick); * 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); @@ -550,6 +609,8 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickGUID(SDL_Joystick *joyst * \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 */ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendor(SDL_Joystick *joystick); @@ -562,6 +623,8 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendor(SDL_Joystick *joystick); * \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 */ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickProduct(SDL_Joystick *joystick); @@ -574,6 +637,8 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickProduct(SDL_Joystick *joystick); * \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 */ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductVersion(SDL_Joystick *joystick); @@ -610,6 +675,8 @@ extern DECLSPEC const char * SDLCALL SDL_GetJoystickSerial(SDL_Joystick *joystic * \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); @@ -675,9 +742,6 @@ extern DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CloseJoystick - * \sa SDL_OpenJoystick */ extern DECLSPEC SDL_bool SDLCALL SDL_JoystickConnected(SDL_Joystick *joystick); @@ -689,8 +753,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_JoystickConnected(SDL_Joystick *joystick); * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_OpenJoystick */ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickInstanceID(SDL_Joystick *joystick); @@ -709,10 +771,33 @@ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickInstanceID(SDL_Joystick *j * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickAxis - * \sa SDL_OpenJoystick + * \sa SDL_GetNumJoystickBalls + * \sa SDL_GetNumJoystickButtons + * \sa SDL_GetNumJoystickHats */ extern DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); +/** + * Get the number of trackballs on a joystick. + * + * Joystick trackballs have only relative motion events associated with them + * and their state cannot be polled. + * + * 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetJoystickBall + * \sa SDL_GetNumJoystickAxes + * \sa SDL_GetNumJoystickButtons + * \sa SDL_GetNumJoystickHats + */ +extern DECLSPEC int SDLCALL SDL_GetNumJoystickBalls(SDL_Joystick *joystick); + /** * Get the number of POV hats on a joystick. * @@ -723,7 +808,9 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickHat - * \sa SDL_OpenJoystick + * \sa SDL_GetNumJoystickAxes + * \sa SDL_GetNumJoystickBalls + * \sa SDL_GetNumJoystickButtons */ extern DECLSPEC int SDLCALL SDL_GetNumJoystickHats(SDL_Joystick *joystick); @@ -737,7 +824,9 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickHats(SDL_Joystick *joystick); * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickButton - * \sa SDL_OpenJoystick + * \sa SDL_GetNumJoystickAxes + * \sa SDL_GetNumJoystickBalls + * \sa SDL_GetNumJoystickHats */ extern DECLSPEC int SDLCALL SDL_GetNumJoystickButtons(SDL_Joystick *joystick); @@ -753,6 +842,7 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickButtons(SDL_Joystick *joystick); * \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); @@ -804,8 +894,7 @@ extern DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); * * \sa SDL_GetNumJoystickAxes */ -extern DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, - int axis); +extern DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, int axis); /** * Get the initial state of an axis control on a joystick. @@ -821,8 +910,28 @@ extern DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, * * \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 DECLSPEC SDL_bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state); + +/** + * Get the ball axis change since the last poll. + * + * Trackballs can only return relative motion since the last call to + * SDL_GetJoystickBall(), these motion deltas are placed into `dx` and `dy`. + * + * 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. + * + * \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 @@ -862,8 +971,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *j * * \sa SDL_GetNumJoystickHats */ -extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, - int hat); +extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, int hat); /** * Get the current state of a button on a joystick. @@ -877,8 +985,7 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, * * \sa SDL_GetNumJoystickButtons */ -extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, - int button); +extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, int button); /** * Start a rumble effect. @@ -886,6 +993,9 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, * Each call to this function cancels any previous rumble effect, and calling * it with 0 intensity stops any rumbling. * + * 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 @@ -895,8 +1005,6 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, * \returns 0, or -1 if rumble isn't supported on this joystick * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_JoystickHasRumble */ extern DECLSPEC int SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); @@ -911,6 +1019,9 @@ extern DECLSPEC int SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 lo * want the (more common) whole-controller rumble, use SDL_RumbleJoystick() * instead. * + * 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 @@ -922,47 +1033,9 @@ extern DECLSPEC int SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 lo * * \since This function is available since SDL 3.0.0. * - * \sa SDL_JoystickHasRumbleTriggers - */ -extern DECLSPEC int SDLCALL SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); - -/** - * Query whether a joystick has an LED. - * - * An example of a joystick LED is the light on the back of a PlayStation 4's - * DualShock 4 controller. - * - * \param joystick The joystick to query - * \returns SDL_TRUE if the joystick has a modifiable LED, SDL_FALSE - * otherwise. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasLED(SDL_Joystick *joystick); - -/** - * Query whether a joystick has rumble support. - * - * \param joystick The joystick to query - * \returns SDL_TRUE if the joystick has rumble, SDL_FALSE otherwise. - * - * \since This function is available since SDL 3.0.0. - * * \sa SDL_RumbleJoystick */ -extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumble(SDL_Joystick *joystick); - -/** - * Query whether a joystick has rumble support on triggers. - * - * \param joystick The joystick to query - * \returns SDL_TRUE if the joystick has trigger rumble, SDL_FALSE otherwise. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_RumbleJoystickTriggers - */ -extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick); +extern DECLSPEC int SDLCALL SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); /** * Update a joystick's LED color. @@ -970,6 +1043,9 @@ extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumbleTriggers(SDL_Joystick *joy * An example of a joystick LED is the light on the back of a PlayStation 4's * DualShock 4 controller. * + * 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 diff --git a/include/SDL3/SDL_keyboard.h b/include/SDL3/SDL_keyboard.h index 042ae43d..fe06957c 100644 --- a/include/SDL3/SDL_keyboard.h +++ b/include/SDL3/SDL_keyboard.h @@ -39,6 +39,8 @@ extern "C" { #endif +typedef Uint32 SDL_KeyboardID; + /** * The SDL keysym structure, used in key events. * @@ -54,6 +56,52 @@ typedef struct SDL_Keysym /* Function prototypes */ +/** + * Return whether a keyboard is currently connected. + * + * \returns SDL_TRUE if a keyboard is connected, SDL_FALSE otherwise. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetKeyboards + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasKeyboard(void); + +/** + * Get a list of currently connected keyboards. + * + * Note that this will include any device or virtual driver that includes + * keyboard functionality, including some mice, KVM switches, motherboard + * 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetKeyboardInstanceName + * \sa SDL_HasKeyboard + */ +extern 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 + * 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); + /** * Query the window which currently has keyboard focus. * @@ -251,6 +299,8 @@ extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name); * and SDL_TextEditingEvent (SDL_EVENT_TEXT_EDITING) events. Please use this * function in pair with SDL_StopTextInput(). * + * Text input events are received by default. + * * On some platforms using this function activates the screen keyboard. * * \since This function is available since SDL 3.0.0. @@ -274,6 +324,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_TextInputActive(void); /** * Stop receiving any text input events. * + * Text input events are received by default. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput @@ -290,15 +342,6 @@ extern DECLSPEC void SDLCALL SDL_StopTextInput(void); */ extern DECLSPEC void SDLCALL SDL_ClearComposition(void); -/** - * Returns if an IME Composite or Candidate window is currently shown. - * - * \returns SDL_TRUE if shown, else SDL_FALSE - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_bool SDLCALL SDL_TextInputShown(void); - /** * Set the rectangle used to type Unicode text inputs. * diff --git a/include/SDL3/SDL_loadso.h b/include/SDL3/SDL_loadso.h index 58e14d37..c406f8d4 100644 --- a/include/SDL3/SDL_loadso.h +++ b/include/SDL3/SDL_loadso.h @@ -87,7 +87,6 @@ extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile); * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadObject - * \sa SDL_UnloadObject */ extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_LoadFunction(void *handle, const char *name); @@ -98,7 +97,6 @@ extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_LoadFunction(void *handle, const * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LoadFunction * \sa SDL_LoadObject */ extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle); diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h index dd33ad94..99d2f2c3 100644 --- a/include/SDL3/SDL_log.h +++ b/include/SDL3/SDL_log.h @@ -59,7 +59,7 @@ extern "C" { * 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 - * CRITICAL level. + * ERROR level. */ typedef enum { @@ -118,6 +118,7 @@ typedef enum * * \since This function is available since SDL 3.0.0. * + * \sa SDL_LogResetPriorities * \sa SDL_LogSetPriority */ extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority); @@ -131,6 +132,7 @@ extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority); * \since This function is available since SDL 3.0.0. * * \sa SDL_LogGetPriority + * \sa SDL_LogResetPriorities * \sa SDL_LogSetAllPriority */ extern DECLSPEC void SDLCALL SDL_LogSetPriority(int category, @@ -358,7 +360,7 @@ extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, * * This function is called by SDL when there is new text to be logged. * - * \param userdata what was passed as `userdata` to SDL_LogSetOutputFunction() + * \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 @@ -375,9 +377,9 @@ typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_ * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LogSetOutputFunction + * \sa SDL_SetLogOutputFunction */ -extern DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata); +extern DECLSPEC void SDLCALL SDL_GetLogOutputFunction(SDL_LogOutputFunction *callback, void **userdata); /** * Replace the default log output function with one of your own. @@ -387,9 +389,9 @@ extern DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *cal * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LogGetOutputFunction + * \sa SDL_GetLogOutputFunction */ -extern DECLSPEC void SDLCALL SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata); +extern DECLSPEC void SDLCALL SDL_SetLogOutputFunction(SDL_LogOutputFunction callback, void *userdata); /* Ends C function definitions when using C++ */ diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h index 76f08f10..0659ad61 100644 --- a/include/SDL3/SDL_main.h +++ b/include/SDL3/SDL_main.h @@ -22,6 +22,7 @@ #ifndef SDL_main_h_ #define SDL_main_h_ +#include #include #include @@ -40,94 +41,93 @@ */ #ifndef SDL_MAIN_HANDLED -#ifdef __WIN32__ -/* On Windows SDL provides WinMain(), which parses the command line and passes - the arguments to your main function. + #ifdef SDL_PLATFORM_WIN32 + /* On Windows SDL provides WinMain(), which parses the command line and passes + the arguments to your main function. - If you provide your own WinMain(), you may define SDL_MAIN_HANDLED - */ -#define SDL_MAIN_AVAILABLE + If you provide your own WinMain(), you may define SDL_MAIN_HANDLED + */ + #define SDL_MAIN_AVAILABLE -#elif defined(__WINRT__) -/* On WinRT, SDL provides a main function that initializes CoreApplication, - creating an instance of IFrameworkView in the process. + #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 + 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(__GDK__) -/* On GDK, SDL provides a main function that initializes the game runtime. + #elif defined(SDL_PLATFORM_GDK) + /* On GDK, SDL provides a main function that initializes the game runtime. - If you prefer to write your own WinMain-function instead of having SDL - provide one that calls your main() function, - #define SDL_MAIN_HANDLED before #include'ing SDL_main.h - and call the SDL_RunApp function from your entry point. -*/ -#define SDL_MAIN_NEEDED + If you prefer to write your own WinMain-function instead of having SDL + provide one that calls your main() function, + #define SDL_MAIN_HANDLED before #include'ing SDL_main.h + and call the SDL_RunApp function from your entry point. + */ + #define SDL_MAIN_NEEDED -#elif defined(__IOS__) -/* On iOS SDL provides a main function that creates an application delegate - and starts the iOS application run loop. + #elif defined(SDL_PLATFORM_IOS) + /* On iOS SDL provides a main function that creates an application delegate + and starts the iOS application run loop. - To use it, just #include SDL_main.h in the source file that contains your - main() function. + To use it, just #include SDL_main.h in the source file that contains your + main() function. - See src/video/uikit/SDL_uikitappdelegate.m for more details. - */ -#define SDL_MAIN_NEEDED + See src/video/uikit/SDL_uikitappdelegate.m for more details. + */ + #define SDL_MAIN_NEEDED -#elif defined(__ANDROID__) -/* On Android SDL provides a Java class in SDLActivity.java that is the - main activity entry point. + #elif defined(SDL_PLATFORM_ANDROID) + /* On Android SDL provides a Java class in SDLActivity.java that is the + main activity entry point. - See docs/README-android.md for more details on extending that class. - */ -#define SDL_MAIN_NEEDED + See docs/README-android.md for more details on extending that class. + */ + #define SDL_MAIN_NEEDED -/* We need to export SDL_main so it can be launched from Java */ -#define SDLMAIN_DECLSPEC DECLSPEC + /* We need to export SDL_main so it can be launched from Java */ + #define SDLMAIN_DECLSPEC DECLSPEC -#elif defined(__PSP__) -/* On PSP SDL provides a main function that sets the module info, - activates the GPU and starts the thread required to be able to exit - the software. + #elif defined(SDL_PLATFORM_PSP) + /* On PSP SDL provides a main function that sets the module info, + activates the GPU and starts the thread required to be able to exit + the software. - If you provide this yourself, you may define SDL_MAIN_HANDLED - */ -#define SDL_MAIN_AVAILABLE + If you provide this yourself, you may define SDL_MAIN_HANDLED + */ + #define SDL_MAIN_AVAILABLE -#elif defined(__PS2__) -#define SDL_MAIN_AVAILABLE + #elif defined(SDL_PLATFORM_PS2) + #define SDL_MAIN_AVAILABLE -#define SDL_PS2_SKIP_IOP_RESET() \ - void reset_IOP(); \ - void reset_IOP() {} + #define SDL_PS2_SKIP_IOP_RESET() \ + void reset_IOP(); \ + void reset_IOP() {} -#elif defined(__3DS__) -/* - On N3DS, SDL provides a main function that sets up the screens - and storage. + #elif defined(SDL_PLATFORM_3DS) + /* + On N3DS, SDL provides a main function that sets up the screens + and storage. - If you provide this yourself, you may define SDL_MAIN_HANDLED -*/ -#define SDL_MAIN_AVAILABLE + If you provide this yourself, you may define SDL_MAIN_HANDLED + */ + #define SDL_MAIN_AVAILABLE -#elif defined(__NGAGE__) + #elif defined(SDL_PLATFORM_NGAGE) + /* + TODO: not sure if it should be SDL_MAIN_NEEDED, in SDL2 ngage had a + main implementation, but wasn't mentioned in SDL_main.h + */ + #define SDL_MAIN_AVAILABLE -/* - TODO: not sure if it should be SDL_MAIN_NEEDED, in SDL2 ngage had a - main implementation, but wasn't mentioned in SDL_main.h - */ -#define SDL_MAIN_AVAILABLE - -#endif + #endif #endif /* SDL_MAIN_HANDLED */ #ifndef SDLMAIN_DECLSPEC @@ -150,7 +150,7 @@ */ #if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) || defined(SDL_MAIN_USE_CALLBACKS) -#define main SDL_main +#define main SDL_main #endif #include @@ -158,10 +158,10 @@ extern "C" { #endif -typedef int (SDLCALL *SDL_AppInit_func)(int argc, char *argv[]); -typedef int (SDLCALL *SDL_AppIterate_func)(void); -typedef int (SDLCALL *SDL_AppEvent_func)(const SDL_Event *event); -typedef void (SDLCALL *SDL_AppQuit_func)(void); +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 @@ -203,6 +203,12 @@ typedef void (SDLCALL *SDL_AppQuit_func)(void); * 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 @@ -210,6 +216,7 @@ typedef void (SDLCALL *SDL_AppQuit_func)(void); * 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. @@ -222,7 +229,7 @@ typedef void (SDLCALL *SDL_AppQuit_func)(void); * \sa SDL_AppEvent * \sa SDL_AppQuit */ -extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(int argc, char *argv[]); +extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(void **appstate, int argc, char *argv[]); /** * App-implemented iteration entry point for SDL_MAIN_USE_CALLBACKS apps. @@ -248,6 +255,9 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(int argc, char *argv[]); * This function should not go into an infinite mainloop; it should do one * iteration of whatever the program does 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 @@ -255,6 +265,7 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(int argc, char *argv[]); * platform. If it returns > 0, the 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. * * \threadsafety This function is not thread safe. @@ -263,9 +274,8 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(int argc, char *argv[]); * * \sa SDL_AppInit * \sa SDL_AppEvent - * \sa SDL_AppQuit */ -extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void); +extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void *appstate); /** * App-implemented event entry point for SDL_MAIN_USE_CALLBACKS apps. @@ -294,6 +304,9 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void); * 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 @@ -301,6 +314,8 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void); * platform. If it returns > 0, the 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. * * \threadsafety This function is not thread safe. @@ -309,9 +324,8 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void); * * \sa SDL_AppInit * \sa SDL_AppIterate - * \sa SDL_AppQuit */ -extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppEvent(const SDL_Event *event); +extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppEvent(void *appstate, const SDL_Event *event); /** * App-implemented deinit entry point for SDL_MAIN_USE_CALLBACKS apps. @@ -332,15 +346,20 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppEvent(const SDL_Event *event); * 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. + * + * \param appstate an optional pointer, provided by the app in SDL_AppInit. + * * \threadsafety This function is not thread safe. * * \since This function is available since SDL 3.0.0. * * \sa SDL_AppInit - * \sa SDL_AppIterate - * \sa SDL_AppEvent */ -extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void); +extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void *appstate); #endif /* SDL_MAIN_USE_CALLBACKS */ @@ -422,7 +441,7 @@ extern DECLSPEC int SDLCALL SDL_RunApp(int argc, char* argv[], SDL_main_func mai 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); -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) /** * Register a win32 window class for SDL's use. @@ -467,27 +486,9 @@ extern DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void */ extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); -#endif /* defined(__WIN32__) || defined(__GDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ - -#ifdef __WINRT__ - -/* for compatibility with SDL2's function of this name */ -#define SDL_WinRTRunApp(MAIN_FUNC, RESERVED) SDL_RunApp(0, NULL, MAIN_FUNC, RESERVED) - -#endif /* __WINRT__ */ - -#ifdef __IOS__ - -/* for compatibility with SDL2's function of this name */ -#define SDL_UIKitRunApp(ARGC, ARGV, MAIN_FUNC) SDL_RunApp(ARGC, ARGV, MAIN_FUNC, NULL) - -#endif /* __IOS__ */ - -#ifdef __GDK__ - -/* for compatibility with SDL2's function of this name */ -#define SDL_GDKRunApp(MAIN_FUNC, RESERVED) SDL_RunApp(0, NULL, MAIN_FUNC, RESERVED) +#ifdef SDL_PLATFORM_GDK /** * Callback from the application to let the suspend continue. @@ -496,7 +497,7 @@ extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); */ extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); -#endif /* __GDK__ */ +#endif /* SDL_PLATFORM_GDK */ #ifdef __cplusplus } @@ -505,31 +506,29 @@ extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); #include #if !defined(SDL_MAIN_HANDLED) && !defined(SDL_MAIN_NOIMPL) -/* include header-only SDL_main implementations */ -#if defined(SDL_MAIN_USE_CALLBACKS) \ - || defined(__WIN32__) || defined(__GDK__) || defined(__IOS__) || defined(__TVOS__) \ - || defined(__3DS__) || defined(__NGAGE__) || defined(__PS2__) || defined(__PSP__) + /* 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) -/* platforms which main (-equivalent) can be implemented in plain C */ -#include + /* platforms which main (-equivalent) can be implemented in plain C */ + #include -#elif defined(__WINRT__) /* C++ platforms */ + #elif defined(SDL_PLATFORM_WINRT) /* C++ platforms */ + #ifdef __cplusplus + #include + #else + /* Note: to get rid of the following warning, you can #define SDL_MAIN_NOIMPL before including SDL_main.h + * in your C sourcefile that contains the standard main. Do *not* use SDL_MAIN_HANDLED for that, then SDL_main won't find your main()! + */ + #ifdef _MSC_VER + #pragma message("Note: Your platform needs the SDL_main implementation in a C++ source file. You can keep your main() in plain C (then continue including SDL_main.h there!) and create a fresh .cpp file that only contains #include ") + #elif defined(__GNUC__) /* gcc, clang, mingw and compatible are matched by this and have #warning */ + #warning "Note: Your platform needs the SDL_main implementation in a C++ source file. You can keep your main() in plain C and create a fresh .cpp file that only contains #include " + #endif /* __GNUC__ */ + #endif /* __cplusplus */ -#ifdef __cplusplus -#include -#else -/* Note: to get rid of the following warning, you can #define SDL_MAIN_NOIMPL before including SDL_main.h - * in your C sourcefile that contains the standard main. Do *not* use SDL_MAIN_HANDLED for that, then SDL_main won't find your main()! - */ -#ifdef _MSC_VER -#pragma message("Note: Your platform needs the SDL_main implementation in a C++ source file. You can keep your main() in plain C (then continue including SDL_main.h there!) and create a fresh .cpp file that only contains #include ") -#elif defined(__GNUC__) /* gcc, clang, mingw and compatible are matched by this and have #warning */ -#warning "Note: Your platform needs the SDL_main implementation in a C++ source file. You can keep your main() in plain C and create a fresh .cpp file that only contains #include " -#endif /* __GNUC__ */ -#endif /* __cplusplus */ - -#endif /* C++ platforms like __WINRT__ etc */ - -#endif /* SDL_MAIN_HANDLED */ + #endif /* C++ platforms like SDL_PLATFORM_WINRT etc */ +#endif #endif /* SDL_main_h_ */ diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h index 2ba34271..1a5f921e 100644 --- a/include/SDL3/SDL_main_impl.h +++ b/include/SDL3/SDL_main_impl.h @@ -35,181 +35,180 @@ and main() is implemented in plain C */ #if !defined(SDL_MAIN_HANDLED) && !defined(SDL_MAIN_NOIMPL) -/* the implementations below must be able to use the implement real main(), nothing renamed - (the user's main() will be renamed to SDL_main so it can be called from here) */ -#ifdef main -# undef main -#endif /* main */ + /* the implementations below must be able to use the implement real main(), nothing renamed + (the user's main() will be renamed to SDL_main so it can be called from here) */ + #ifdef main + #undef main + #endif -#ifdef SDL_MAIN_USE_CALLBACKS + #ifdef SDL_MAIN_USE_CALLBACKS -#if 0 - /* currently there are no platforms that _need_ a magic entry point here - for callbacks, but if one shows up, implement it here. */ + #if 0 + /* currently there are no platforms that _need_ a magic entry point here + for callbacks, but if one shows up, implement it here. */ -#else /* use a standard SDL_main, which the app SHOULD NOT ALSO SUPPLY. */ + #else /* use a standard SDL_main, which the app SHOULD NOT ALSO SUPPLY. */ -/* this define makes the normal SDL_main entry point stuff work...we just provide SDL_main() instead of the app. */ -#define SDL_MAIN_CALLBACK_STANDARD 1 + /* this define makes the normal SDL_main entry point stuff work...we just provide SDL_main() instead of the app. */ + #define SDL_MAIN_CALLBACK_STANDARD 1 -int SDL_main(int argc, char **argv) -{ - return SDL_EnterAppMainCallbacks(argc, argv, SDL_AppInit, SDL_AppIterate, SDL_AppEvent, SDL_AppQuit); -} + int SDL_main(int argc, char **argv) + { + return SDL_EnterAppMainCallbacks(argc, argv, SDL_AppInit, SDL_AppIterate, SDL_AppEvent, SDL_AppQuit); + } -#endif /* platform-specific tests */ + #endif /* platform-specific tests */ -#endif /* SDL_MAIN_USE_CALLBACKS */ + #endif /* SDL_MAIN_USE_CALLBACKS */ -/* 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) + /* 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(__WIN32__) || defined(__GDK__) + #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) -/* these defines/typedefs are needed for the WinMain() definition */ -#ifndef WINAPI -#define WINAPI __stdcall -#endif + /* these defines/typedefs are needed for the WinMain() definition */ + #ifndef WINAPI + #define WINAPI __stdcall + #endif -typedef struct HINSTANCE__ * HINSTANCE; -typedef char* LPSTR; -typedef wchar_t* PWSTR; + typedef struct HINSTANCE__ * HINSTANCE; + typedef char* LPSTR; + typedef wchar_t* PWSTR; -/* The VC++ compiler needs main/wmain defined, but not for GDK */ -#if defined(_MSC_VER) && !defined(__GDK__) + /* The VC++ compiler needs main/wmain defined, but not for GDK */ + #if defined(_MSC_VER) && !defined(SDL_PLATFORM_GDK) -/* This is where execution begins [console apps] */ -#if defined( UNICODE ) && UNICODE -int wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) -{ - (void)argc; - (void)wargv; - (void)wenvp; - return SDL_RunApp(0, NULL, SDL_main, NULL); -} -#else /* ANSI */ -int main(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - return SDL_RunApp(0, NULL, SDL_main, NULL); -} -#endif /* UNICODE */ + /* This is where execution begins [console apps] */ + #if defined( UNICODE ) && UNICODE + int wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) + { + (void)argc; + (void)wargv; + (void)wenvp; + return SDL_RunApp(0, NULL, SDL_main, NULL); + } + #else /* ANSI */ + int main(int argc, char *argv[]) + { + (void)argc; + (void)argv; + return SDL_RunApp(0, NULL, SDL_main, NULL); + } + #endif /* UNICODE */ -#endif /* _MSC_VER && ! __GDK__ */ + #endif /* _MSC_VER && ! SDL_PLATFORM_GDK */ -/* This is where execution begins [windowed apps and GDK] */ + /* This is where execution begins [windowed apps and GDK] */ -#ifdef __cplusplus -extern "C" { -#endif -#if defined( UNICODE ) && UNICODE -int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrev, PWSTR szCmdLine, int sw) -#else /* ANSI */ -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) -#endif -{ - (void)hInst; - (void)hPrev; - (void)szCmdLine; - (void)sw; - return SDL_RunApp(0, NULL, SDL_main, NULL); -} -#ifdef __cplusplus -} /* extern "C" */ -#endif + #ifdef __cplusplus + extern "C" { + #endif -/* end of __WIN32__ and __GDK__ impls */ -#elif defined(__WINRT__) + #if defined( UNICODE ) && UNICODE + int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrev, PWSTR szCmdLine, int sw) + #else /* ANSI */ + int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) + #endif + { + (void)hInst; + (void)hPrev; + (void)szCmdLine; + (void)sw; + return SDL_RunApp(0, NULL, SDL_main, NULL); + } -/* WinRT main based on SDL_winrt_main_NonXAML.cpp, placed in the public domain by David Ludwig 3/13/14 */ + #ifdef __cplusplus + } /* extern "C" */ + #endif -#include + /* end of SDL_PLATFORM_WIN32 and SDL_PLATFORM_GDK impls */ -/* 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. + #elif defined(SDL_PLATFORM_WINRT) - 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. + /* WinRT main based on SDL_winrt_main_NonXAML.cpp, placed in the public domain by David Ludwig 3/13/14 */ - 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. + #include - 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 + /* 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. -/* 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). + 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. - 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) -#endif + 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. -/* Make sure the function to initialize the Windows Runtime gets linked in. */ -#ifdef _MSC_VER -#pragma comment(lib, "runtimeobject.lib") -#endif + 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 -#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 + /* 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). -/* end of WinRT impl */ -#elif defined(__NGAGE__) + 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 -/* same typedef as in ngage SDKs e32def.h */ -typedef signed int TInt; -/* TODO: if it turns out that this only works when built as C++, - move __NGAGE__ into the C++ section in SDL_main.h */ -TInt E32Main() -{ - return SDL_RunApp(0, NULL, SDL_main, NULL); -} + #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 __NGAGE__ impl */ + /* end of WinRT impl */ -#else /* platforms that use a standard main() and just call SDL_RunApp(), like iOS and 3DS */ + #elif defined(SDL_PLATFORM_NGAGE) + /* same typedef as in ngage SDKs e32def.h */ + typedef signed int TInt; + /* TODO: if it turns out that this only works when built as C++, + move SDL_PLATFORM_NGAGE into the C++ section in SDL_main.h */ + TInt E32Main() + { + return SDL_RunApp(0, NULL, SDL_main, NULL); + } -int main(int argc, char *argv[]) -{ - return SDL_RunApp(argc, argv, SDL_main, NULL); -} + /* end of SDL_PLATFORM_NGAGE impl */ -/* end of impls for standard-conforming platforms */ + #else /* platforms that use a standard main() and just call SDL_RunApp(), like iOS and 3DS */ + int main(int argc, char *argv[]) + { + return SDL_RunApp(argc, argv, SDL_main, NULL); + } -#endif /* __WIN32__ etc */ + /* end of impls for standard-conforming platforms */ -#endif /* !defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD) */ + #endif /* SDL_PLATFORM_WIN32 etc */ -/* rename users main() function to SDL_main() so it can be called from the wrappers above */ -#define main SDL_main + #endif /* !defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD) */ + + /* rename users main() function to SDL_main() so it can be called from the wrappers above */ + #define main SDL_main #endif /* SDL_MAIN_HANDLED */ diff --git a/include/SDL3/SDL_messagebox.h b/include/SDL3/SDL_messagebox.h index 17696c64..b9c4d93f 100644 --- a/include/SDL3/SDL_messagebox.h +++ b/include/SDL3/SDL_messagebox.h @@ -58,8 +58,8 @@ typedef enum typedef struct { Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */ - int buttonid; /**< User defined button id (value returned via SDL_ShowMessageBox) */ - const char * text; /**< The UTF-8 button text */ + int buttonID; /**< User defined button id (value returned via SDL_ShowMessageBox) */ + const char *text; /**< The UTF-8 button text */ } SDL_MessageBoxButtonData; /** diff --git a/include/SDL3/SDL_metal.h b/include/SDL3/SDL_metal.h index 016ee947..e08ff361 100644 --- a/include/SDL3/SDL_metal.h +++ b/include/SDL3/SDL_metal.h @@ -89,8 +89,6 @@ extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view); * \returns a pointer * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_Metal_CreateView */ extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view); diff --git a/include/SDL3/SDL_mouse.h b/include/SDL3/SDL_mouse.h index d9df80df..a374277c 100644 --- a/include/SDL3/SDL_mouse.h +++ b/include/SDL3/SDL_mouse.h @@ -81,6 +81,52 @@ typedef enum /* Function prototypes */ +/** + * Return whether a mouse is currently connected. + * + * \returns SDL_TRUE if a mouse is connected, SDL_FALSE otherwise. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetMice + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasMouse(void); + +/** + * Get a list of currently connected mice. + * + * Note that this will include any device or virtual driver that includes + * mouse functionality, including some game controllers, KVM switches, 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 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetMouseInstanceName + * \sa SDL_HasMouse + */ +extern 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 + * \returns the name of the selected mouse, or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetMice + */ +extern DECLSPEC const char *SDLCALL SDL_GetMouseInstanceName(SDL_MouseID instance_id); + /** * Get the window which currently has mouse focus. * @@ -109,7 +155,6 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void); * * \sa SDL_GetGlobalMouseState * \sa SDL_GetRelativeMouseState - * \sa SDL_PumpEvents */ extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(float *x, float *y); @@ -139,6 +184,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(float *x, float *y); * \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); @@ -239,8 +285,8 @@ 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_SetWindowGrab(), depending - * on your goals. + * probably use SDL_SetRelativeMouseMode() or SDL_SetWindowMouseGrab(), + * depending on your goals. * * While captured, mouse events still report coordinates relative to the * current (foreground) window, but those coordinates may be outside the @@ -318,6 +364,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateColorCursor + * \sa SDL_CreateSystemCursor * \sa SDL_DestroyCursor * \sa SDL_SetCursor */ @@ -338,7 +386,9 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data, * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateCursor + * \sa SDL_CreateSystemCursor * \sa SDL_DestroyCursor + * \sa SDL_SetCursor */ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, @@ -371,7 +421,6 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateCursor * \sa SDL_GetCursor */ extern DECLSPEC int SDLCALL SDL_SetCursor(SDL_Cursor * cursor); @@ -399,8 +448,6 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void); * \returns the default cursor on success or NULL on failure. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateSystemCursor */ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void); diff --git a/include/SDL3/SDL_mutex.h b/include/SDL3/SDL_mutex.h index d4610cb4..8c6c5a6d 100644 --- a/include/SDL3/SDL_mutex.h +++ b/include/SDL3/SDL_mutex.h @@ -171,6 +171,9 @@ extern DECLSPEC SDL_Mutex *SDLCALL SDL_CreateMutex(void); * \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); @@ -193,8 +196,6 @@ extern DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateMutex - * \sa SDL_DestroyMutex * \sa SDL_LockMutex * \sa SDL_UnlockMutex */ @@ -213,6 +214,9 @@ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0 * \param mutex the mutex to unlock. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_LockMutex + * \sa SDL_TryLockMutex */ extern DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex); @@ -230,9 +234,6 @@ extern DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateMutex - * \sa SDL_LockMutex - * \sa SDL_TryLockMutex - * \sa SDL_UnlockMutex */ extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_Mutex *mutex); @@ -290,8 +291,8 @@ typedef struct SDL_RWLock SDL_RWLock; * * \sa SDL_DestroyRWLock * \sa SDL_LockRWLockForReading - * \sa SDL_TryLockRWLockForReading * \sa SDL_LockRWLockForWriting + * \sa SDL_TryLockRWLockForReading * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ @@ -328,6 +329,8 @@ extern DECLSPEC SDL_RWLock *SDLCALL SDL_CreateRWLock(void); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_LockRWLockForWriting + * \sa SDL_TryLockRWLockForReading * \sa SDL_UnlockRWLock */ extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock); @@ -357,6 +360,8 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_AC * * \since This function is available since SDL 3.0.0. * + * \sa SDL_LockRWLockForReading + * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock); @@ -383,9 +388,8 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_AC * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateRWLock - * \sa SDL_DestroyRWLock - * \sa SDL_TryLockRWLockForReading + * \sa SDL_LockRWLockForReading + * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(0, rwlock); @@ -417,9 +421,8 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_ * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateRWLock - * \sa SDL_DestroyRWLock - * \sa SDL_TryLockRWLockForWriting + * \sa SDL_LockRWLockForWriting + * \sa SDL_TryLockRWLockForReading * \sa SDL_UnlockRWLock */ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(0, rwlock); @@ -441,6 +444,11 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_ * \param rwlock the rwlock to unlock. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_LockRWLockForReading + * \sa SDL_LockRWLockForWriting + * \sa SDL_TryLockRWLockForReading + * \sa SDL_TryLockRWLockForWriting */ extern DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock); @@ -458,11 +466,6 @@ extern DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GE * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRWLock - * \sa SDL_LockRWLockForReading - * \sa SDL_LockRWLockForWriting - * \sa SDL_TryLockRWLockForReading - * \sa SDL_TryLockRWLockForWriting - * \sa SDL_UnlockRWLock */ extern DECLSPEC void SDLCALL SDL_DestroyRWLock(SDL_RWLock *rwlock); @@ -513,11 +516,6 @@ extern DECLSPEC SDL_Semaphore *SDLCALL SDL_CreateSemaphore(Uint32 initial_value) * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateSemaphore - * \sa SDL_PostSemaphore - * \sa SDL_TryWaitSemaphore - * \sa SDL_GetSemaphoreValue - * \sa SDL_WaitSemaphore - * \sa SDL_WaitSemaphoreTimeout */ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem); @@ -538,12 +536,8 @@ extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateSemaphore - * \sa SDL_DestroySemaphore * \sa SDL_PostSemaphore * \sa SDL_TryWaitSemaphore - * \sa SDL_GetSemaphoreValue - * \sa SDL_WaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ extern DECLSPEC int SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem); @@ -563,10 +557,7 @@ extern DECLSPEC int SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateSemaphore - * \sa SDL_DestroySemaphore * \sa SDL_PostSemaphore - * \sa SDL_GetSemaphoreValue * \sa SDL_WaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ @@ -588,11 +579,8 @@ extern DECLSPEC int SDLCALL SDL_TryWaitSemaphore(SDL_Semaphore *sem); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateSemaphore - * \sa SDL_DestroySemaphore * \sa SDL_PostSemaphore * \sa SDL_TryWaitSemaphore - * \sa SDL_GetSemaphoreValue * \sa SDL_WaitSemaphore */ extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 timeoutMS); @@ -606,10 +594,7 @@ extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateSemaphore - * \sa SDL_DestroySemaphore * \sa SDL_TryWaitSemaphore - * \sa SDL_GetSemaphoreValue * \sa SDL_WaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ @@ -622,8 +607,6 @@ extern DECLSPEC int SDLCALL SDL_PostSemaphore(SDL_Semaphore *sem); * \returns the current value of the semaphore. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateSemaphore */ extern DECLSPEC Uint32 SDLCALL SDL_GetSemaphoreValue(SDL_Semaphore *sem); @@ -662,10 +645,6 @@ extern DECLSPEC SDL_Condition *SDLCALL SDL_CreateCondition(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_BroadcastCondition - * \sa SDL_SignalCondition - * \sa SDL_WaitCondition - * \sa SDL_WaitConditionTimeout * \sa SDL_CreateCondition */ extern DECLSPEC void SDLCALL SDL_DestroyCondition(SDL_Condition *cond); @@ -682,8 +661,6 @@ extern DECLSPEC void SDLCALL SDL_DestroyCondition(SDL_Condition *cond); * \sa SDL_BroadcastCondition * \sa SDL_WaitCondition * \sa SDL_WaitConditionTimeout - * \sa SDL_CreateCondition - * \sa SDL_DestroyCondition */ extern DECLSPEC int SDLCALL SDL_SignalCondition(SDL_Condition *cond); @@ -699,8 +676,6 @@ extern DECLSPEC int SDLCALL SDL_SignalCondition(SDL_Condition *cond); * \sa SDL_SignalCondition * \sa SDL_WaitCondition * \sa SDL_WaitConditionTimeout - * \sa SDL_CreateCondition - * \sa SDL_DestroyCondition */ extern DECLSPEC int SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); @@ -729,8 +704,6 @@ extern DECLSPEC int SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); * \sa SDL_BroadcastCondition * \sa SDL_SignalCondition * \sa SDL_WaitConditionTimeout - * \sa SDL_CreateCondition - * \sa SDL_DestroyCondition */ extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mutex); @@ -760,8 +733,6 @@ extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mu * \sa SDL_BroadcastCondition * \sa SDL_SignalCondition * \sa SDL_WaitCondition - * \sa SDL_CreateCondition - * \sa SDL_DestroyCondition */ extern DECLSPEC int SDLCALL SDL_WaitConditionTimeout(SDL_Condition *cond, SDL_Mutex *mutex, Sint32 timeoutMS); diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h index bc5366ee..618100b9 100644 --- a/include/SDL3/SDL_oldnames.h +++ b/include/SDL3/SDL_oldnames.h @@ -40,6 +40,11 @@ #ifdef SDL_ENABLE_OLD_NAMES /* ##SDL_atomic.h */ +#define SDL_AtomicCAS SDL_AtomicCompareAndSwap +#define SDL_AtomicCASPtr SDL_AtomicCompareAndSwapPointer +#define SDL_AtomicLock SDL_LockSpinlock +#define SDL_AtomicTryLock SDL_TryLockSpinlock +#define SDL_AtomicUnlock SDL_UnlockSpinlock #define SDL_atomic_t SDL_AtomicInt /* ##SDL_audio.h */ @@ -64,6 +69,7 @@ #define SDL_AudioStreamPut SDL_PutAudioStreamData #define SDL_FreeAudioStream SDL_DestroyAudioStream #define SDL_FreeWAV SDL_free +#define SDL_LoadWAV_RW SDL_LoadWAV_IO #define SDL_NewAudioStream SDL_CreateAudioStream /* ##SDL_events.h */ @@ -110,6 +116,7 @@ #define SDL_JOYBUTTONUP SDL_EVENT_JOYSTICK_BUTTON_UP #define SDL_JOYDEVICEADDED SDL_EVENT_JOYSTICK_ADDED #define SDL_JOYDEVICEREMOVED SDL_EVENT_JOYSTICK_REMOVED +#define SDL_JOYBALLMOTION SDL_EVENT_JOYSTICK_BALL_MOTION #define SDL_JOYHATMOTION SDL_EVENT_JOYSTICK_HAT_MOTION #define SDL_KEYDOWN SDL_EVENT_KEY_DOWN #define SDL_KEYMAPCHANGED SDL_EVENT_KEYMAP_CHANGED @@ -198,7 +205,7 @@ #define SDL_GameController SDL_Gamepad #define SDL_GameControllerAddMapping SDL_AddGamepadMapping #define SDL_GameControllerAddMappingsFromFile SDL_AddGamepadMappingsFromFile -#define SDL_GameControllerAddMappingsFromRW SDL_AddGamepadMappingsFromRW +#define SDL_GameControllerAddMappingsFromRW SDL_AddGamepadMappingsFromIO #define SDL_GameControllerAxis SDL_GamepadAxis #define SDL_GameControllerBindType SDL_GamepadBindingType #define SDL_GameControllerButton SDL_GamepadButton @@ -230,9 +237,6 @@ #define SDL_GameControllerGetVendor SDL_GetGamepadVendor #define SDL_GameControllerHasAxis SDL_GamepadHasAxis #define SDL_GameControllerHasButton SDL_GamepadHasButton -#define SDL_GameControllerHasLED SDL_GamepadHasLED -#define SDL_GameControllerHasRumble SDL_GamepadHasRumble -#define SDL_GameControllerHasRumbleTriggers SDL_GamepadHasRumbleTriggers #define SDL_GameControllerHasSensor SDL_GamepadHasSensor #define SDL_GameControllerIsSensorEnabled SDL_GamepadSensorEnabled #define SDL_GameControllerMapping SDL_GetGamepadMapping @@ -251,6 +255,43 @@ #define SDL_INIT_GAMECONTROLLER SDL_INIT_GAMEPAD #define SDL_IsGameController SDL_IsGamepad +/* ##SDL_haptic.h */ +#define SDL_HapticClose SDL_CloseHaptic +#define SDL_HapticDestroyEffect SDL_DestroyHapticEffect +#define SDL_HapticGetEffectStatus SDL_GetHapticEffectStatus +#define SDL_HapticNewEffect SDL_CreateHapticEffect +#define SDL_HapticNumAxes SDL_GetNumHapticAxes +#define SDL_HapticNumEffects SDL_GetMaxHapticEffects +#define SDL_HapticNumEffectsPlaying SDL_GetMaxHapticEffectsPlaying +#define SDL_HapticOpen SDL_OpenHaptic +#define SDL_HapticOpenFromJoystick SDL_OpenHapticFromJoystick +#define SDL_HapticOpenFromMouse SDL_OpenHapticFromMouse +#define SDL_HapticPause SDL_PauseHaptic +#define SDL_HapticQuery SDL_GetHapticFeatures +#define SDL_HapticRumbleInit SDL_InitHapticRumble +#define SDL_HapticRumblePlay SDL_PlayHapticRumble +#define SDL_HapticRumbleStop SDL_StopHapticRumble +#define SDL_HapticRunEffect SDL_RunHapticEffect +#define SDL_HapticSetAutocenter SDL_SetHapticAutocenter +#define SDL_HapticSetGain SDL_SetHapticGain +#define SDL_HapticStopAll SDL_StopHapticEffects +#define SDL_HapticStopEffect SDL_StopHapticEffect +#define SDL_HapticUnpause SDL_ResumeHaptic +#define SDL_HapticUpdateEffect SDL_UpdateHapticEffect +#define SDL_JoystickIsHaptic SDL_IsJoystickHaptic +#define SDL_MouseIsHaptic SDL_IsMouseHaptic + +/* ##SDL_hints.h */ +#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 +#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE +#define SDL_HINT_LINUX_DIGITAL_HATS SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS +#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 @@ -263,6 +304,7 @@ #define SDL_JoystickGetAttached SDL_JoystickConnected #define SDL_JoystickGetAxis SDL_GetJoystickAxis #define SDL_JoystickGetAxisInitialState SDL_GetJoystickAxisInitialState +#define SDL_JoystickGetBall SDL_GetJoystickBall #define SDL_JoystickGetButton SDL_GetJoystickButton #define SDL_JoystickGetFirmwareVersion SDL_GetJoystickFirmwareVersion #define SDL_JoystickGetGUID SDL_GetJoystickGUID @@ -279,6 +321,7 @@ #define SDL_JoystickIsVirtual SDL_IsJoystickVirtual #define SDL_JoystickName SDL_GetJoystickName #define SDL_JoystickNumAxes SDL_GetNumJoystickAxes +#define SDL_JoystickNumBalls SDL_GetNumJoystickBalls #define SDL_JoystickNumButtons SDL_GetNumJoystickButtons #define SDL_JoystickNumHats SDL_GetNumJoystickHats #define SDL_JoystickOpen SDL_OpenJoystick @@ -296,7 +339,6 @@ /* ##SDL_keyboard.h */ #define SDL_IsScreenKeyboardShown SDL_ScreenKeyboardShown #define SDL_IsTextInputActive SDL_TextInputActive -#define SDL_IsTextInputShown SDL_TextInputShown /* ##SDL_keycode.h */ #define KMOD_ALT SDL_KMOD_ALT @@ -318,6 +360,10 @@ #define KMOD_SCROLL SDL_KMOD_SCROLL #define KMOD_SHIFT SDL_KMOD_SHIFT +/* ##SDL_log.h */ +#define SDL_LogGetOutputFunction SDL_GetLogOutputFunction +#define SDL_LogSetOutputFunction SDL_SetLogOutputFunction + /* ##SDL_mouse.h */ #define SDL_FreeCursor SDL_DestroyCursor @@ -349,14 +395,6 @@ #define SDL_PIXELFORMAT_RGB888 SDL_PIXELFORMAT_XRGB8888 #define SDL_PixelFormatEnumToMasks SDL_GetMasksForPixelFormatEnum -/* ##SDL_platform.h */ -#ifdef __IOS__ -#define __IPHONEOS__ __IOS__ -#endif -#ifdef __MACOS__ -#define __MACOSX__ __MACOS__ -#endif - /* ##SDL_rect.h */ #define SDL_EncloseFPoints SDL_GetRectEnclosingPointsFloat #define SDL_EnclosePoints SDL_GetRectEnclosingPoints @@ -415,11 +453,19 @@ #define SDL_ScaleModeNearest SDL_SCALEMODE_NEAREST /* ##SDL_rwops.h */ -#define RW_SEEK_CUR SDL_RW_SEEK_CUR -#define RW_SEEK_END SDL_RW_SEEK_END -#define RW_SEEK_SET SDL_RW_SEEK_SET -#define SDL_AllocRW SDL_CreateRW -#define SDL_FreeRW SDL_DestroyRW +#define RW_SEEK_CUR SDL_IO_SEEK_CUR +#define RW_SEEK_END SDL_IO_SEEK_END +#define RW_SEEK_SET SDL_IO_SEEK_SET +#define SDL_RWFromConstMem SDL_IOFromConstMem +#define SDL_RWFromFile SDL_IOFromFile +#define SDL_RWFromMem SDL_IOFromMem +#define SDL_RWclose SDL_CloseIO +#define SDL_RWops SDL_IOStream +#define SDL_RWread SDL_ReadIO +#define SDL_RWseek SDL_SeekIO +#define SDL_RWsize SDL_GetIOSize +#define SDL_RWtell SDL_TellIO +#define SDL_RWwrite SDL_WriteIO #define SDL_ReadBE16 SDL_ReadU16BE #define SDL_ReadBE32 SDL_ReadU32BE #define SDL_ReadBE64 SDL_ReadU64BE @@ -455,8 +501,10 @@ #define SDL_GetColorKey SDL_GetSurfaceColorKey #define SDL_HasColorKey SDL_SurfaceHasColorKey #define SDL_HasSurfaceRLE SDL_SurfaceHasRLE +#define SDL_LoadBMP_RW SDL_LoadBMP_IO #define SDL_LowerBlit SDL_BlitSurfaceUnchecked #define SDL_LowerBlitScaled SDL_BlitSurfaceUncheckedScaled +#define SDL_SaveBMP_RW SDL_SaveBMP_IO #define SDL_SetClipRect SDL_SetSurfaceClipRect #define SDL_SetColorKey SDL_SetSurfaceColorKey #define SDL_UpperBlit SDL_BlitSurface @@ -467,10 +515,14 @@ #define SDL_TLSCreate SDL_CreateTLS #define SDL_TLSGet SDL_GetTLS #define SDL_TLSSet SDL_SetTLS +#define SDL_threadID SDL_ThreadID /* ##SDL_timer.h */ #define SDL_GetTicks64 SDL_GetTicks +/* ##SDL_version.h */ +#define SDL_version SDL_Version + /* ##SDL_video.h */ #define SDL_GetClosestDisplayMode SDL_GetClosestFullscreenDisplayMode #define SDL_GetDisplayOrientation SDL_GetCurrentDisplayOrientation @@ -478,6 +530,7 @@ #define SDL_GetRectDisplayIndex SDL_GetDisplayForRect #define SDL_GetWindowDisplayIndex SDL_GetDisplayForWindow #define SDL_GetWindowDisplayMode SDL_GetWindowFullscreenMode +#define SDL_HasWindowSurface SDL_WindowHasSurface #define SDL_IsScreenSaverEnabled SDL_ScreenSaverEnabled #define SDL_SetWindowDisplayMode SDL_SetWindowFullscreenMode #define SDL_WINDOW_ALLOW_HIGHDPI SDL_WINDOW_HIGH_PIXEL_DENSITY @@ -486,6 +539,13 @@ #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_AtomicLock SDL_AtomicLock_renamed_SDL_LockSpinlock +#define SDL_AtomicTryLock SDL_AtomicTryLock_renamed_SDL_TryLockSpinlock +#define SDL_AtomicUnlock SDL_AtomicUnlock_renamed_SDL_UnlockSpinlock + /* ##SDL_audio.h */ #define AUDIO_F32 AUDIO_F32_renamed_SDL_AUDIO_F32LE #define AUDIO_F32LSB AUDIO_F32LSB_renamed_SDL_AUDIO_F32LE @@ -508,6 +568,7 @@ #define SDL_AudioStreamPut SDL_AudioStreamPut_renamed_SDL_PutAudioStreamData #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_NewAudioStream SDL_NewAudioStream_renamed_SDL_CreateAudioStream /* ##SDL_events.h */ @@ -554,6 +615,7 @@ #define SDL_JOYBUTTONUP SDL_JOYBUTTONUP_renamed_SDL_EVENT_JOYSTICK_BUTTON_UP #define SDL_JOYDEVICEADDED SDL_JOYDEVICEADDED_renamed_SDL_EVENT_JOYSTICK_ADDED #define SDL_JOYDEVICEREMOVED SDL_JOYDEVICEREMOVED_renamed_SDL_EVENT_JOYSTICK_REMOVED +#define SDL_JOYBALLMOTION SDL_JOYBALLMOTION_renamed_SDL_EVENT_JOYSTICK_BALL_MOTION #define SDL_JOYHATMOTION SDL_JOYHATMOTION_renamed_SDL_EVENT_JOYSTICK_HAT_MOTION #define SDL_KEYDOWN SDL_KEYDOWN_renamed_SDL_EVENT_KEY_DOWN #define SDL_KEYMAPCHANGED SDL_KEYMAPCHANGED_renamed_SDL_EVENT_KEYMAP_CHANGED @@ -642,7 +704,7 @@ #define SDL_GameController SDL_GameController_renamed_SDL_Gamepad #define SDL_GameControllerAddMapping SDL_GameControllerAddMapping_renamed_SDL_AddGamepadMapping #define SDL_GameControllerAddMappingsFromFile SDL_GameControllerAddMappingsFromFile_renamed_SDL_AddGamepadMappingsFromFile -#define SDL_GameControllerAddMappingsFromRW SDL_GameControllerAddMappingsFromRW_renamed_SDL_AddGamepadMappingsFromRW +#define SDL_GameControllerAddMappingsFromRW SDL_GameControllerAddMappingsFromRW_renamed_SDL_AddGamepadMappingsFromIO #define SDL_GameControllerAxis SDL_GameControllerAxis_renamed_SDL_GamepadAxis #define SDL_GameControllerBindType SDL_GameControllerBindType_renamed_SDL_GamepadBindingType #define SDL_GameControllerButton SDL_GameControllerButton_renamed_SDL_GamepadButton @@ -674,9 +736,6 @@ #define SDL_GameControllerGetVendor SDL_GameControllerGetVendor_renamed_SDL_GetGamepadVendor #define SDL_GameControllerHasAxis SDL_GameControllerHasAxis_renamed_SDL_GamepadHasAxis #define SDL_GameControllerHasButton SDL_GameControllerHasButton_renamed_SDL_GamepadHasButton -#define SDL_GameControllerHasLED SDL_GameControllerHasLED_renamed_SDL_GamepadHasLED -#define SDL_GameControllerHasRumble SDL_GameControllerHasRumble_renamed_SDL_GamepadHasRumble -#define SDL_GameControllerHasRumbleTriggers SDL_GameControllerHasRumbleTriggers_renamed_SDL_GamepadHasRumbleTriggers #define SDL_GameControllerHasSensor SDL_GameControllerHasSensor_renamed_SDL_GamepadHasSensor #define SDL_GameControllerIsSensorEnabled SDL_GameControllerIsSensorEnabled_renamed_SDL_GamepadSensorEnabled #define SDL_GameControllerMapping SDL_GameControllerMapping_renamed_SDL_GetGamepadMapping @@ -696,6 +755,43 @@ #define SDL_INIT_GAMECONTROLLER SDL_INIT_GAMECONTROLLER_renamed_SDL_INIT_GAMEPAD #define SDL_IsGameController SDL_IsGameController_renamed_SDL_IsGamepad +/* ##SDL_haptic.h */ +#define SDL_HapticClose SDL_HapticClose_renamed_SDL_CloseHaptic +#define SDL_HapticDestroyEffect SDL_HapticDestroyEffect_renamed_SDL_DestroyHapticEffect +#define SDL_HapticGetEffectStatus SDL_HapticGetEffectStatus_renamed_SDL_GetHapticEffectStatus +#define SDL_HapticNewEffect SDL_HapticNewEffect_renamed_SDL_CreateHapticEffect +#define SDL_HapticNumAxes SDL_HapticNumAxes_renamed_SDL_GetNumHapticAxes +#define SDL_HapticNumEffects SDL_HapticNumEffects_renamed_SDL_GetMaxHapticEffects +#define SDL_HapticNumEffectsPlaying SDL_HapticNumEffectsPlaying_renamed_SDL_GetMaxHapticEffectsPlaying +#define SDL_HapticOpen SDL_HapticOpen_renamed_SDL_OpenHaptic +#define SDL_HapticOpenFromJoystick SDL_HapticOpenFromJoystick_renamed_SDL_OpenHapticFromJoystick +#define SDL_HapticOpenFromMouse SDL_HapticOpenFromMouse_renamed_SDL_OpenHapticFromMouse +#define SDL_HapticPause SDL_HapticPause_renamed_SDL_PauseHaptic +#define SDL_HapticQuery SDL_HapticQuery_renamed_SDL_GetHapticFeatures +#define SDL_HapticRumbleInit SDL_HapticRumbleInit_renamed_SDL_InitHapticRumble +#define SDL_HapticRumblePlay SDL_HapticRumblePlay_renamed_SDL_PlayHapticRumble +#define SDL_HapticRumbleStop SDL_HapticRumbleStop_renamed_SDL_StopHapticRumble +#define SDL_HapticRunEffect SDL_HapticRunEffect_renamed_SDL_RunHapticEffect +#define SDL_HapticSetAutocenter SDL_HapticSetAutocenter_renamed_SDL_SetHapticAutocenter +#define SDL_HapticSetGain SDL_HapticSetGain_renamed_SDL_SetHapticGain +#define SDL_HapticStopAll SDL_HapticStopAll_renamed_SDL_StopHapticEffects +#define SDL_HapticStopEffect SDL_HapticStopEffect_renamed_SDL_StopHapticEffect +#define SDL_HapticUnpause SDL_HapticUnpause_renamed_SDL_ResumeHaptic +#define SDL_HapticUpdateEffect SDL_HapticUpdateEffect_renamed_SDL_UpdateHapticEffect +#define SDL_JoystickIsHaptic SDL_JoystickIsHaptic_renamed_SDL_IsJoystickHaptic +#define SDL_MouseIsHaptic SDL_MouseIsHaptic_renamed_SDL_IsMouseHaptic + +/* ##SDL_hints.h */ +#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 +#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE_renamed_SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE +#define SDL_HINT_LINUX_DIGITAL_HATS SDL_HINT_LINUX_DIGITAL_HATS_renamed_SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS +#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 @@ -708,6 +804,7 @@ #define SDL_JoystickGetAttached SDL_JoystickGetAttached_renamed_SDL_JoystickConnected #define SDL_JoystickGetAxis SDL_JoystickGetAxis_renamed_SDL_GetJoystickAxis #define SDL_JoystickGetAxisInitialState SDL_JoystickGetAxisInitialState_renamed_SDL_GetJoystickAxisInitialState +#define SDL_JoystickGetBall SDL_JoystickGetBall_renamed_SDL_GetJoystickBall #define SDL_JoystickGetButton SDL_JoystickGetButton_renamed_SDL_GetJoystickButton #define SDL_JoystickGetFirmwareVersion SDL_JoystickGetFirmwareVersion_renamed_SDL_GetJoystickFirmwareVersion #define SDL_JoystickGetGUID SDL_JoystickGetGUID_renamed_SDL_GetJoystickGUID @@ -724,6 +821,7 @@ #define SDL_JoystickIsVirtual SDL_JoystickIsVirtual_renamed_SDL_IsJoystickVirtual #define SDL_JoystickName SDL_JoystickName_renamed_SDL_GetJoystickName #define SDL_JoystickNumAxes SDL_JoystickNumAxes_renamed_SDL_GetNumJoystickAxes +#define SDL_JoystickNumBalls SDL_JoystickNumBalls_renamed_SDL_GetNumJoystickBalls #define SDL_JoystickNumButtons SDL_JoystickNumButtons_renamed_SDL_GetNumJoystickButtons #define SDL_JoystickNumHats SDL_JoystickNumHats_renamed_SDL_GetNumJoystickHats #define SDL_JoystickOpen SDL_JoystickOpen_renamed_SDL_OpenJoystick @@ -741,7 +839,6 @@ /* ##SDL_keyboard.h */ #define SDL_IsScreenKeyboardShown SDL_IsScreenKeyboardShown_renamed_SDL_ScreenKeyboardShown #define SDL_IsTextInputActive SDL_IsTextInputActive_renamed_SDL_TextInputActive -#define SDL_IsTextInputShown SDL_IsTextInputShown_renamed_SDL_TextInputShown /* ##SDL_keycode.h */ #define KMOD_ALT KMOD_ALT_renamed_SDL_KMOD_ALT @@ -763,6 +860,10 @@ #define KMOD_SCROLL KMOD_SCROLL_renamed_SDL_KMOD_SCROLL #define KMOD_SHIFT KMOD_SHIFT_renamed_SDL_KMOD_SHIFT +/* ##SDL_log.h */ +#define SDL_LogGetOutputFunction SDL_LogGetOutputFunction_renamed_SDL_GetLogOutputFunction +#define SDL_LogSetOutputFunction SDL_LogSetOutputFunction_renamed_SDL_SetLogOutputFunction + /* ##SDL_mouse.h */ #define SDL_FreeCursor SDL_FreeCursor_renamed_SDL_DestroyCursor @@ -794,14 +895,6 @@ #define SDL_PIXELFORMAT_RGB888 SDL_PIXELFORMAT_RGB888_renamed_SDL_PIXELFORMAT_XRGB8888 #define SDL_PixelFormatEnumToMasks SDL_PixelFormatEnumToMasks_renamed_SDL_GetMasksForPixelFormatEnum -/* ##SDL_platform.h */ -#ifdef __IOS__ -#define __IPHONEOS__ __IPHONEOS___renamed___IOS__ -#endif -#ifdef __MACOS__ -#define __MACOSX__ __MACOSX___renamed___MACOS__ -#endif - /* ##SDL_rect.h */ #define SDL_EncloseFPoints SDL_EncloseFPoints_renamed_SDL_GetRectEnclosingPointsFloat #define SDL_EnclosePoints SDL_EnclosePoints_renamed_SDL_GetRectEnclosingPoints @@ -860,11 +953,19 @@ #define SDL_ScaleModeNearest SDL_ScaleModeNearest_renamed_SDL_SCALEMODE_NEAREST /* ##SDL_rwops.h */ -#define RW_SEEK_CUR RW_SEEK_CUR_renamed_SDL_RW_SEEK_CUR -#define RW_SEEK_END RW_SEEK_END_renamed_SDL_RW_SEEK_END -#define RW_SEEK_SET RW_SEEK_SET_renamed_SDL_RW_SEEK_SET -#define SDL_AllocRW SDL_AllocRW_renamed_SDL_CreateRW -#define SDL_FreeRW SDL_FreeRW_renamed_SDL_DestroyRW +#define RW_SEEK_CUR RW_SEEK_CUR_renamed_SDL_IO_SEEK_CUR +#define RW_SEEK_END RW_SEEK_END_renamed_SDL_IO_SEEK_END +#define RW_SEEK_SET RW_SEEK_SET_renamed_SDL_IO_SEEK_SET +#define SDL_RWFromConstMem SDL_RWFromConstMem_renamed_SDL_IOFromConstMem +#define SDL_RWFromFile SDL_RWFromFile_renamed_SDL_IOFromFile +#define SDL_RWFromMem SDL_RWFromMem_renamed_SDL_IOFromMem +#define SDL_RWclose SDL_RWclose_renamed_SDL_CloseIO +#define SDL_RWops SDL_RWops_renamed_SDL_IOStream +#define SDL_RWread SDL_RWread_renamed_SDL_ReadIO +#define SDL_RWseek SDL_RWseek_renamed_SDL_SeekIO +#define SDL_RWsize SDL_RWsize_renamed_SDL_GetIOSize +#define SDL_RWtell SDL_RWtell_renamed_SDL_TellIO +#define SDL_RWwrite SDL_RWwrite_renamed_SDL_WriteIO #define SDL_ReadBE16 SDL_ReadBE16_renamed_SDL_ReadU16BE #define SDL_ReadBE32 SDL_ReadBE32_renamed_SDL_ReadU32BE #define SDL_ReadBE64 SDL_ReadBE64_renamed_SDL_ReadU64BE @@ -900,8 +1001,10 @@ #define SDL_GetColorKey SDL_GetColorKey_renamed_SDL_GetSurfaceColorKey #define SDL_HasColorKey SDL_HasColorKey_renamed_SDL_SurfaceHasColorKey #define SDL_HasSurfaceRLE SDL_HasSurfaceRLE_renamed_SDL_SurfaceHasRLE +#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_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 @@ -912,10 +1015,14 @@ #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 /* ##SDL_timer.h */ #define SDL_GetTicks64 SDL_GetTicks64_renamed_SDL_GetTicks +/* ##SDL_version.h */ +#define SDL_version SDL_version_renamed_SDL_Version + /* ##SDL_video.h */ #define SDL_GetClosestDisplayMode SDL_GetClosestDisplayMode_renamed_SDL_GetClosestFullscreenDisplayMode #define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_renamed_SDL_GetCurrentDisplayOrientation @@ -923,6 +1030,7 @@ #define SDL_GetRectDisplayIndex SDL_GetRectDisplayIndex_renamed_SDL_GetDisplayForRect #define SDL_GetWindowDisplayIndex SDL_GetWindowDisplayIndex_renamed_SDL_GetDisplayForWindow #define SDL_GetWindowDisplayMode SDL_GetWindowDisplayMode_renamed_SDL_GetWindowFullscreenMode +#define SDL_HasWindowSurface SDL_HasWindowSurface_renamed_SDL_WindowHasSurface #define SDL_IsScreenSaverEnabled SDL_IsScreenSaverEnabled_renamed_SDL_ScreenSaverEnabled #define SDL_SetWindowDisplayMode SDL_SetWindowDisplayMode_renamed_SDL_SetWindowFullscreenMode #define SDL_WINDOW_ALLOW_HIGHDPI SDL_WINDOW_ALLOW_HIGHDPI_renamed_SDL_WINDOW_HIGH_PIXEL_DENSITY diff --git a/include/SDL3/SDL_opengl.h b/include/SDL3/SDL_opengl.h index 9fb298f9..575f6461 100644 --- a/include/SDL3/SDL_opengl.h +++ b/include/SDL3/SDL_opengl.h @@ -37,7 +37,7 @@ #include -#ifndef __IOS__ /* No OpenGL on iOS. */ +#ifndef SDL_PLATFORM_IOS /* No OpenGL on iOS. */ /* * Mesa 3-D graphics library @@ -77,11 +77,7 @@ * Begin system-specific stuff. */ -#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__) -#define __WIN32__ -#endif - -#if defined(__WIN32__) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) # if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */ # define GLAPI __declspec(dllexport) # elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */ @@ -90,7 +86,7 @@ # define GLAPI extern # endif /* _STATIC_MESA support */ # if defined(__MINGW32__) && defined(GL_NO_STDCALL) || defined(UNDER_CE) /* The generated DLLs by MingW with STDCALL are not compatible with the ones done by Microsoft's compilers */ -# define GLAPIENTRY +# define GLAPIENTRY # else # define GLAPIENTRY __stdcall # endif @@ -2118,6 +2114,6 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLsh #endif /* __gl_h_ */ -#endif /* !__IOS__ */ +#endif /* !SDL_PLATFORM_IOS */ #endif /* SDL_opengl_h_ */ diff --git a/include/SDL3/SDL_opengles.h b/include/SDL3/SDL_opengles.h index 8f4b6676..d1734639 100644 --- a/include/SDL3/SDL_opengles.h +++ b/include/SDL3/SDL_opengles.h @@ -26,7 +26,7 @@ */ #include -#ifdef __IOS__ +#ifdef SDL_PLATFORM_IOS #include #include #else diff --git a/include/SDL3/SDL_opengles2.h b/include/SDL3/SDL_opengles2.h index a3b37885..85abf2b8 100644 --- a/include/SDL3/SDL_opengles2.h +++ b/include/SDL3/SDL_opengles2.h @@ -28,7 +28,7 @@ #if !defined(_MSC_VER) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) -#ifdef __IOS__ +#ifdef SDL_PLATFORM_IOS #include #include #else diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h index 36c67b7c..9eab3c0a 100644 --- a/include/SDL3/SDL_pen.h +++ b/include/SDL3/SDL_pen.h @@ -45,9 +45,9 @@ #ifndef SDL_pen_h_ #define SDL_pen_h_ -#include "SDL_error.h" -#include "SDL_guid.h" -#include "SDL_stdinc.h" +#include +#include +#include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -56,9 +56,9 @@ extern "C" { typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a session */ -#define SDL_PEN_INVALID ((Uint32)0) /**< Reserved invalid ::SDL_PenID is valid */ +#define SDL_PEN_INVALID ((SDL_PenID)0) /**< Reserved invalid ::SDL_PenID is valid */ -#define SDL_PEN_MOUSEID ((Uint32)-2) /**< Device ID for mouse events triggered by pen events */ +#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 */ @@ -78,9 +78,9 @@ 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 */ + 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 */ + 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 */ @@ -133,6 +133,7 @@ typedef enum */ 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 */ @@ -190,8 +191,6 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, * SDL_PenID. * * \since This function is available since SDL 3.0.0 - * - * \sa SDL_GUID */ extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); @@ -203,8 +202,6 @@ extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); * If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID. * * \since This function is available since SDL 3.0.0 - * - * \sa SDL_PenForID */ extern DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id); diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 383def8c..94533f24 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -129,9 +129,11 @@ typedef enum { SDL_ARRAYORDER_NONE, SDL_ARRAYORDER_RGB, - SDL_ARRAYORDER_UNUSED1, /* Left for compatibility with SDL2 */ - SDL_ARRAYORDER_UNUSED2, /* Left for compatibility with SDL2 */ - SDL_ARRAYORDER_BGR + SDL_ARRAYORDER_RGBA, + SDL_ARRAYORDER_ARGB, + SDL_ARRAYORDER_BGR, + SDL_ARRAYORDER_BGRA, + SDL_ARRAYORDER_ABGR } SDL_ArrayOrder; /** Packed component layout. */ @@ -163,7 +165,8 @@ typedef enum (SDL_ISPIXELFORMAT_FOURCC(X) ? \ ((((X) == SDL_PIXELFORMAT_YUY2) || \ ((X) == SDL_PIXELFORMAT_UYVY) || \ - ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF)) + ((X) == SDL_PIXELFORMAT_YVYU) || \ + ((X) == SDL_PIXELFORMAT_P010)) ? 2 : 1) : (((X) >> 0) & 0xFF)) #define SDL_ISPIXELFORMAT_INDEXED(format) \ (!SDL_ISPIXELFORMAT_FOURCC(format) && \ @@ -194,8 +197,14 @@ typedef enum (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA)))) #define SDL_ISPIXELFORMAT_10BIT(format) \ - ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32) && \ - (SDL_PIXELLAYOUT(format) == SDL_PACKEDLAYOUT_2101010)) + (!SDL_ISPIXELFORMAT_FOURCC(format) && \ + ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32) && \ + (SDL_PIXELLAYOUT(format) == SDL_PACKEDLAYOUT_2101010))) + +#define SDL_ISPIXELFORMAT_FLOAT(format) \ + (!SDL_ISPIXELFORMAT_FOURCC(format) && \ + ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF16) || \ + (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF32))) /* The flag is set to 1 because 0x1? is not in the printable ASCII range */ #define SDL_ISPIXELFORMAT_FOURCC(format) \ @@ -316,6 +325,60 @@ typedef enum 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), /* Aliases for RGBA byte arrays of color data, for the current platform */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -352,10 +415,250 @@ typedef enum 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; +/** + * Pixels are a representation of a color in a particular color space. + * + * The first characteristic of a color space is the color type. SDL understands two different color types, RGB and YCbCr, or in SDL also referred to as YUV. + * + * RGB colors consist of red, green, and blue channels of color that are added together to represent the colors we see on the screen. + * https://en.wikipedia.org/wiki/RGB_color_model + * + * YCbCr colors represent colors as a Y luma brightness component and red and blue chroma color offsets. This color representation takes advantage of the fact that the human eye is more sensitive to brightness than the color in an image. The Cb and Cr components are often compressed and have lower resolution than the luma component. + * https://en.wikipedia.org/wiki/YCbCr + * + * When the color information in YCbCr is compressed, the Y pixels are left at full resolution and each Cr and Cb pixel represents an average of the color information in a block of Y pixels. The chroma location determines where in that block of pixels the color information is coming from. + * + * The color range defines how much of the pixel to use when converting a pixel into a color on the display. When the full color range is used, the entire numeric range of the pixel bits is significant. When narrow color range is used, for historical reasons, the pixel uses only a portion of the numeric range to represent colors. + * + * The color primaries and white point are a definition of the colors in the color space relative to the standard XYZ color space. + * https://en.wikipedia.org/wiki/CIE_1931_color_space + * + * The transfer characteristic, or opto-electrical transfer function (OETF), is the way a color is converted from mathematically linear space into a non-linear output signals. + * https://en.wikipedia.org/wiki/Rec._709#Transfer_characteristics + * + * The matrix coefficients are used to convert between YCbCr and RGB colors. + */ + +/** + * The color type + */ +typedef enum +{ + SDL_COLOR_TYPE_UNKNOWN = 0, + SDL_COLOR_TYPE_RGB = 1, + SDL_COLOR_TYPE_YCBCR = 2 +} SDL_ColorType; + +/** + * The color range, as described by https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en + */ +typedef enum +{ + 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 */ + SDL_COLOR_RANGE_FULL = 2 /**< Full range, e.g. 0-255 for 8-bit RGB and luma, and 1-255 for 8-bit chroma */ +} SDL_ColorRange; + +/** + * The color primaries, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + */ +typedef enum +{ + 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_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 */ + SDL_COLOR_PRIMARIES_XYZ = 10, /**< SMPTE ST 428-1 */ + SDL_COLOR_PRIMARIES_SMPTE431 = 11, /**< SMPTE RP 431-2 */ + SDL_COLOR_PRIMARIES_SMPTE432 = 12, /**< SMPTE EG 432-1 / DCI P3 */ + SDL_COLOR_PRIMARIES_EBU3213 = 22, /**< EBU Tech. 3213-E */ + SDL_COLOR_PRIMARIES_CUSTOM = 31 +} SDL_ColorPrimaries; + +/** + * The transfer characteristics, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + */ +typedef enum +{ + SDL_TRANSFER_CHARACTERISTICS_UNKNOWN = 0, + SDL_TRANSFER_CHARACTERISTICS_BT709 = 1, /**< Rec. ITU-R BT.709-6 / ITU-R BT1361 */ + SDL_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2, + SDL_TRANSFER_CHARACTERISTICS_GAMMA22 = 4, /**< ITU-R BT.470-6 System M / ITU-R BT1700 625 PAL & SECAM */ + SDL_TRANSFER_CHARACTERISTICS_GAMMA28 = 5, /**< ITU-R BT.470-6 System B, G */ + SDL_TRANSFER_CHARACTERISTICS_BT601 = 6, /**< SMPTE ST 170M / ITU-R BT.601-7 525 or 625 */ + SDL_TRANSFER_CHARACTERISTICS_SMPTE240 = 7, /**< SMPTE ST 240M */ + SDL_TRANSFER_CHARACTERISTICS_LINEAR = 8, + SDL_TRANSFER_CHARACTERISTICS_LOG100 = 9, + SDL_TRANSFER_CHARACTERISTICS_LOG100_SQRT10 = 10, + SDL_TRANSFER_CHARACTERISTICS_IEC61966 = 11, /**< IEC 61966-2-4 */ + SDL_TRANSFER_CHARACTERISTICS_BT1361 = 12, /**< ITU-R BT1361 Extended Colour Gamut */ + SDL_TRANSFER_CHARACTERISTICS_SRGB = 13, /**< IEC 61966-2-1 (sRGB or sYCC) */ + SDL_TRANSFER_CHARACTERISTICS_BT2020_10BIT = 14, /**< ITU-R BT2020 for 10-bit system */ + SDL_TRANSFER_CHARACTERISTICS_BT2020_12BIT = 15, /**< ITU-R BT2020 for 12-bit system */ + SDL_TRANSFER_CHARACTERISTICS_PQ = 16, /**< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems */ + SDL_TRANSFER_CHARACTERISTICS_SMPTE428 = 17, /**< SMPTE ST 428-1 */ + SDL_TRANSFER_CHARACTERISTICS_HLG = 18, /**< ARIB STD-B67, known as "hybrid log-gamma" (HLG) */ + SDL_TRANSFER_CHARACTERISTICS_CUSTOM = 31 +} SDL_TransferCharacteristics; + +/** + * The matrix coefficients, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + */ +typedef enum +{ + 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_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 */ + SDL_MATRIX_COEFFICIENTS_YCGCO = 8, + SDL_MATRIX_COEFFICIENTS_BT2020_NCL = 9, /**< ITU-R BT.2020-2 non-constant luminance */ + SDL_MATRIX_COEFFICIENTS_BT2020_CL = 10, /**< ITU-R BT.2020-2 constant luminance */ + SDL_MATRIX_COEFFICIENTS_SMPTE2085 = 11, /**< SMPTE ST 2085 */ + SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL = 12, + SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL = 13, + SDL_MATRIX_COEFFICIENTS_ICTCP = 14, /**< ITU-R BT.2100-0 ICTCP */ + SDL_MATRIX_COEFFICIENTS_CUSTOM = 31 +} SDL_MatrixCoefficients; + +/** + * The chroma sample location + */ +typedef enum +{ + 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. */ + SDL_CHROMA_LOCATION_CENTER = 2, /**< In JPEG/JFIF, H.261, and MPEG-1, Cb and Cr are taken at the center of the 2x2 square. In other words, they are offset one-half pixel to the right and one-half pixel down compared to the top-left pixel. */ + SDL_CHROMA_LOCATION_TOPLEFT = 3 /**< In HEVC for BT.2020 and BT.2100 content (in particular on Blu-rays), Cb and Cr are sampled at the same location as the group's top-left Y pixel ("co-sited", "co-located"). */ +} SDL_ChromaLocation; + + +/* Colorspace definition */ +#define SDL_DEFINE_COLORSPACE(type, range, primaries, transfer, matrix, chroma) \ + (((Uint32)(type) << 28) | ((Uint32)(range) << 24) | ((Uint32)(chroma) << 20) | \ + ((Uint32)(primaries) << 10) | ((Uint32)(transfer) << 5) | ((Uint32)(matrix) << 0)) + +#define SDL_COLORSPACETYPE(X) (SDL_ColorType)(((X) >> 28) & 0x0F) +#define SDL_COLORSPACERANGE(X) (SDL_ColorRange)(((X) >> 24) & 0x0F) +#define SDL_COLORSPACECHROMA(X) (SDL_ChromaLocation)(((X) >> 20) & 0x0F) +#define SDL_COLORSPACEPRIMARIES(X) (SDL_ColorPrimaries)(((X) >> 10) & 0x1F) +#define SDL_COLORSPACETRANSFER(X) (SDL_TransferCharacteristics)(((X) >> 5) & 0x1F) +#define SDL_COLORSPACEMATRIX(X) (SDL_MatrixCoefficients)((X) & 0x1F) + +#define SDL_ISCOLORSPACE_MATRIX_BT601(X) (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT601 || SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT470BG) +#define SDL_ISCOLORSPACE_MATRIX_BT709(X) (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT709) +#define SDL_ISCOLORSPACE_MATRIX_BT2020_NCL(X) (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT2020_NCL) +#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 +{ + SDL_COLORSPACE_UNKNOWN, + + /* 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), + + /* 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), + + /* 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; + /** * The bits of this structure can be directly reinterpreted as an integer-packed * color which uses the SDL_PIXELFORMAT_RGBA32 format (SDL_PIXELFORMAT_ABGR8888 @@ -370,6 +673,19 @@ typedef struct SDL_Color } 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 + */ +typedef struct SDL_FColor +{ + float r; + float g; + float b; + float a; +} SDL_FColor; +#define SDL_FColour SDL_FColor + typedef struct SDL_Palette { int ncolors; @@ -383,10 +699,10 @@ typedef struct SDL_Palette */ typedef struct SDL_PixelFormat { - Uint32 format; + SDL_PixelFormatEnum format; SDL_Palette *palette; - Uint8 BitsPerPixel; - Uint8 BytesPerPixel; + Uint8 bits_per_pixel; + Uint8 bytes_per_pixel; Uint8 padding[2]; Uint32 Rmask; Uint32 Gmask; @@ -413,7 +729,7 @@ typedef struct SDL_PixelFormat * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(Uint32 format); +extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(SDL_PixelFormatEnum format); /** * Convert one of the enumerated pixel formats to a bpp value and RGBA masks. @@ -431,7 +747,7 @@ extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(Uint32 format); * * \sa SDL_GetPixelFormatEnumForMasks */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetMasksForPixelFormatEnum(Uint32 format, +extern DECLSPEC SDL_bool SDLCALL SDL_GetMasksForPixelFormatEnum(SDL_PixelFormatEnum format, int *bpp, Uint32 * Rmask, Uint32 * Gmask, @@ -449,13 +765,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetMasksForPixelFormatEnum(Uint32 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 one of the SDL_PixelFormatEnum values + * \returns the SDL_PixelFormatEnum value corresponding to the format masks, + * or SDL_PIXELFORMAT_UNKNOWN if there isn't a match. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetMasksForPixelFormatEnum */ -extern DECLSPEC Uint32 SDLCALL SDL_GetPixelFormatEnumForMasks(int bpp, +extern DECLSPEC SDL_PixelFormatEnum SDLCALL SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, @@ -475,8 +792,9 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetPixelFormatEnumForMasks(int bpp, * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroyPixelFormat + * \sa SDL_SetPixelFormatPalette */ -extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_CreatePixelFormat(Uint32 pixel_format); +extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_CreatePixelFormat(SDL_PixelFormatEnum pixel_format); /** * Free an SDL_PixelFormat structure allocated by SDL_CreatePixelFormat(). @@ -502,6 +820,8 @@ extern DECLSPEC void SDLCALL SDL_DestroyPixelFormat(SDL_PixelFormat *format); * \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); @@ -514,9 +834,6 @@ extern DECLSPEC SDL_Palette *SDLCALL SDL_CreatePalette(int ncolors); * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreatePalette - * \sa SDL_DestroyPalette */ extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette); @@ -532,9 +849,6 @@ extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format, * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreatePalette - * \sa SDL_CreateSurface */ extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors, diff --git a/include/SDL3/SDL_platform_defines.h b/include/SDL3/SDL_platform_defines.h index 55a55c30..de0908f4 100644 --- a/include/SDL3/SDL_platform_defines.h +++ b/include/SDL3/SDL_platform_defines.h @@ -29,48 +29,40 @@ #define SDL_platform_defines_h_ #ifdef _AIX -#undef __AIX__ -#define __AIX__ 1 +#define SDL_PLATFORM_AIX 1 #endif #ifdef __HAIKU__ -#undef __HAIKU__ -#define __HAIKU__ 1 +#define SDL_PLATFORM_HAIKU 1 #endif #if defined(bsdi) || defined(__bsdi) || defined(__bsdi__) -#undef __BSDI__ -#define __BSDI__ 1 -#endif -#ifdef _arch_dreamcast -#undef __DREAMCAST__ -#define __DREAMCAST__ 1 +#define SDL_PLATFORM_BSDI 1 #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -#undef __FREEBSD__ -#define __FREEBSD__ 1 +#define SDL_PLATFORM_FREEBSD 1 #endif #if defined(hpux) || defined(__hpux) || defined(__hpux__) -#undef __HPUX__ -#define __HPUX__ 1 +#define SDL_PLATFORM_HPUX 1 #endif #if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE) -#undef __IRIX__ -#define __IRIX__ 1 +#define SDL_PLATFORM_IRIX 1 #endif #if (defined(linux) || defined(__linux) || defined(__linux__)) -#undef __LINUX__ -#define __LINUX__ 1 +#define SDL_PLATFORM_LINUX 1 #endif #if defined(ANDROID) || defined(__ANDROID__) -#undef __ANDROID__ -#undef __LINUX__ /* do we need to do this? */ -#define __ANDROID__ 1 +#undef SDL_PLATFORM_LINUX /* do we need to do this? */ +#define SDL_PLATFORM_ANDROID 1 #endif #ifdef __NGAGE__ -#undef __NGAGE__ -#define __NGAGE__ 1 +#define SDL_PLATFORM_NGAGE 1 +#endif + +#if defined(__unix__) || defined(__unix) || defined(unix) +#define SDL_PLATFORM_UNIX 1 #endif #ifdef __APPLE__ +#define SDL_PLATFORM_APPLE 1 /* lets us know what version of macOS we're compiling on */ #include #include @@ -94,56 +86,58 @@ #ifndef TARGET_OS_SIMULATOR #define TARGET_OS_SIMULATOR 0 #endif -#ifndef TARGET_OS_XR -#define TARGET_OS_XR 0 +#ifndef TARGET_OS_VISION +#define TARGET_OS_VISION 0 #endif #if TARGET_OS_TV -#undef __TVOS__ -#define __TVOS__ 1 +#define SDL_PLATFORM_TVOS 1 +#endif +#if TARGET_OS_VISION +#define SDL_PLATFORM_VISIONOS 1 #endif #if TARGET_OS_IPHONE -#undef __IOS__ -#define __IOS__ 1 +#define SDL_PLATFORM_IOS 1 #else -#undef __MACOS__ -#define __MACOS__ 1 +#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. #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1070 */ #endif /* TARGET_OS_IPHONE */ -#endif /* defined(__APPLE__) */ +#endif /* defined(SDL_PLATFORM_APPLE) */ +#ifdef __EMSCRIPTEN__ +#define SDL_PLATFORM_EMSCRIPTEN 1 +#endif #ifdef __NetBSD__ -#undef __NETBSD__ -#define __NETBSD__ 1 +#define SDL_PLATFORM_NETBSD 1 #endif #ifdef __OpenBSD__ -#undef __OPENBSD__ -#define __OPENBSD__ 1 +#define SDL_PLATFORM_OPENBSD 1 #endif #if defined(__OS2__) || defined(__EMX__) -#undef __OS2__ -#define __OS2__ 1 +#define SDL_PLATFORM_OS2 1 #endif #if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE) -#undef __OSF__ -#define __OSF__ 1 +#define SDL_PLATFORM_OSF 1 #endif #ifdef __QNXNTO__ -#undef __QNXNTO__ -#define __QNXNTO__ 1 +#define SDL_PLATFORM_QNXNTO 1 #endif #if defined(riscos) || defined(__riscos) || defined(__riscos__) -#undef __RISCOS__ -#define __RISCOS__ 1 +#define SDL_PLATFORM_RISCOS 1 #endif #if defined(__sun) && defined(__SVR4) -#undef __SOLARIS__ -#define __SOLARIS__ 1 +#define SDL_PLATFORM_SOLARIS 1 #endif -#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +#if defined(__CYGWIN__) +#define SDL_PLATFORM_CYGWIN 1 +#endif + +#if defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) +#define SDL_PLATFORM_WINDOWS 1 /* Win32 api and Windows-based OSs */ + /* 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() @@ -173,47 +167,36 @@ #endif #if WINAPI_FAMILY_WINRT -#undef __WINRT__ -#define __WINRT__ 1 +#define SDL_PLATFORM_WINRT 1 #elif defined(_GAMING_DESKTOP) /* GDK project configuration always defines _GAMING_XXX */ -#undef __WINGDK__ -#define __WINGDK__ 1 +#define SDL_PLATFORM_WINGDK 1 #elif defined(_GAMING_XBOX_XBOXONE) -#undef __XBOXONE__ -#define __XBOXONE__ 1 +#define SDL_PLATFORM_XBOXONE 1 #elif defined(_GAMING_XBOX_SCARLETT) -#undef __XBOXSERIES__ -#define __XBOXSERIES__ 1 +#define SDL_PLATFORM_XBOXSERIES 1 #else -#undef __WINDOWS__ -#define __WINDOWS__ 1 +#define SDL_PLATFORM_WIN32 1 #endif -#endif /* defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) */ +#endif /* defined(WIN32) || defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) */ -#ifdef __WINDOWS__ -#undef __WIN32__ -#define __WIN32__ 1 -#endif /* This is to support generic "any GDK" separate from a platform-specific GDK */ -#if defined(__WINGDK__) || defined(__XBOXONE__) || defined(__XBOXSERIES__) -#undef __GDK__ -#define __GDK__ 1 +#if defined(SDL_PLATFORM_WINGDK) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) +#define SDL_PLATFORM_GDK 1 #endif -#ifdef __PSP__ -#undef __PSP__ -#define __PSP__ 1 +#if defined(__PSP__) || defined(__psp__) +#define SDL_PLATFORM_PSP 1 #endif -#ifdef PS2 -#define __PS2__ 1 +#if defined(__PS2__) || defined(PS2) +#define SDL_PLATFORM_PS2 1 #endif -#ifdef __vita__ -#define __VITA__ 1 +#if defined(__vita__) || defined(__psp2__) +#define SDL_PLATFORM_VITA 1 #endif #ifdef __3DS__ #undef __3DS__ -#define __3DS__ 1 +#define SDL_PLATFORM_3DS 1 #endif #endif /* SDL_platform_defines_h_ */ diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index c5d3daca..80c2f523 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -28,6 +28,8 @@ #ifndef SDL_properties_h_ #define SDL_properties_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -81,6 +83,25 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGlobalProperties(void); */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); +/** + * Copy a set of properties + * + * Copy all the properties from one set 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. + * + * \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. + * + * \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); + /** * Lock a set of properties * @@ -122,6 +143,9 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); * Set a property on a set 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 @@ -154,13 +178,21 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c * \since This function is available since SDL 3.0.0. * * \sa SDL_GetProperty + * \sa SDL_HasProperty + * \sa SDL_SetBooleanProperty + * \sa SDL_SetFloatProperty + * \sa SDL_SetNumberProperty * \sa SDL_SetPropertyWithCleanup + * \sa SDL_SetStringProperty */ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value); /** * Set a string property on a set 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 @@ -226,6 +258,21 @@ extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const c */ extern DECLSPEC int SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool value); +/** + * Return whether a property exists in a set 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. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetPropertyType + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasProperty(SDL_PropertiesID props, const char *name); + /** * Get the type of a property on a set of properties * @@ -237,6 +284,8 @@ extern DECLSPEC int SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_HasProperty */ extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID props, const char *name); @@ -262,7 +311,12 @@ extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID pr * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetBooleanProperty + * \sa SDL_GetFloatProperty + * \sa SDL_GetNumberProperty * \sa SDL_GetPropertyType + * \sa SDL_GetStringProperty + * \sa SDL_HasProperty * \sa SDL_SetProperty */ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value); @@ -281,6 +335,7 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char * \since This function is available since SDL 3.0.0. * * \sa SDL_GetPropertyType + * \sa SDL_HasProperty * \sa SDL_SetStringProperty */ extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value); @@ -302,6 +357,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props * \since This function is available since SDL 3.0.0. * * \sa SDL_GetPropertyType + * \sa SDL_HasProperty * \sa SDL_SetNumberProperty */ extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value); @@ -323,6 +379,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, con * \since This function is available since SDL 3.0.0. * * \sa SDL_GetPropertyType + * \sa SDL_HasProperty * \sa SDL_SetFloatProperty */ extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value); @@ -344,6 +401,7 @@ extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const * \since This function is available since SDL 3.0.0. * * \sa SDL_GetPropertyType + * \sa SDL_HasProperty * \sa SDL_SetBooleanProperty */ extern DECLSPEC SDL_bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool default_value); @@ -359,8 +417,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty */ extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); diff --git a/include/SDL3/SDL_rect.h b/include/SDL3/SDL_rect.h index 4d03884d..4b496e34 100644 --- a/include/SDL3/SDL_rect.h +++ b/include/SDL3/SDL_rect.h @@ -30,8 +30,6 @@ #include #include -#include -#include #include /* Set up for C function definitions, even when using C++ */ diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 2a5958df..edd80a1c 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -79,8 +79,8 @@ typedef struct SDL_RendererInfo { const char *name; /**< The name of the renderer */ Uint32 flags; /**< Supported ::SDL_RendererFlags */ - Uint32 num_texture_formats; /**< The number of available texture formats */ - Uint32 texture_formats[16]; /**< The available texture formats */ + 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; @@ -91,7 +91,7 @@ typedef struct SDL_RendererInfo typedef struct SDL_Vertex { SDL_FPoint position; /**< Vertex position, in SDL_Renderer coordinates */ - SDL_Color color; /**< Vertex color */ + SDL_FColor color; /**< Vertex color */ SDL_FPoint tex_coord; /**< Normalized texture coordinates, if needed */ } SDL_Vertex; @@ -105,16 +105,6 @@ typedef enum SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */ } SDL_TextureAccess; -/** - * Flip constants for SDL_RenderTextureRotated - */ -typedef enum -{ - SDL_FLIP_NONE = 0x00000000, /**< Do not flip */ - SDL_FLIP_HORIZONTAL = 0x00000001, /**< flip horizontally */ - SDL_FLIP_VERTICAL = 0x00000002 /**< flip vertically */ -} SDL_RendererFlip; - /** * How the logical size is mapped to the output */ @@ -202,7 +192,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetRenderDriver(int index); * \sa SDL_CreateRenderer * \sa SDL_CreateWindow */ -extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags, SDL_Window **window, SDL_Renderer **renderer); +extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer); /** * Create a 2D rendering context for a window. @@ -213,6 +203,10 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, U * 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. @@ -240,21 +234,44 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * * These are the supported properties: * - * - `SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER`: the window where rendering - * is displayed - * - `SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER`: the surface where - * rendering is displayed, if you want a software renderer without a window - * - `SDL_PROPERTY_RENDERER_CREATE_NAME_STRING`: the name of the rendering - * driver to use, if a specific one is desired - * - `SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want + * - `SDL_PROP_RENDERER_CREATE_NAME_STRING`: the name of the rendering driver + * to use, if a specific one is desired + * - `SDL_PROP_RENDERER_CREATE_WINDOW_POINTER`: the window where rendering is + * displayed, required if this isn't a software renderer using a surface + * - `SDL_PROP_RENDERER_CREATE_SURFACE_POINTER`: the surface where rendering + * is displayed, if you want a software renderer without a window + * - `SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace + * value describing the colorspace for output to the display, defaults to + * SDL_COLORSPACE_SRGB. The direct3d11, direct3d12, and metal renderers + * support SDL_COLORSPACE_SRGB_LINEAR, which is a linear color space and + * 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 * + * With the vulkan renderer: + * + * - `SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER`: the VkInstance to use + * with the renderer, optional. + * - `SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER`: the VkSurfaceKHR to use + * with the renderer, optional. + * - `SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER`: the + * VkPhysicalDevice to use with the renderer, optional. + * - `SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER`: the VkDevice to use + * with the renderer, optional. + * - `SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER`: the + * queue family index used for rendering. + * - `SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER`: the + * queue family index used for presentation. + * * \param props the properties to use * \returns a valid rendering context or NULL if there was an error; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateProperties * \sa SDL_CreateRenderer * \sa SDL_CreateSoftwareRenderer * \sa SDL_DestroyRenderer @@ -262,10 +279,17 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co */ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); -#define SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER "window" -#define SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER "surface" -#define SDL_PROPERTY_RENDERER_CREATE_NAME_STRING "name" -#define SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync" +#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" /** * Create a 2D software rendering context for a surface. @@ -282,8 +306,6 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_Prop * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateRenderer - * \sa SDL_CreateWindowRenderer * \sa SDL_DestroyRenderer */ extern DECLSPEC SDL_Renderer *SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface *surface); @@ -296,8 +318,6 @@ extern DECLSPEC SDL_Renderer *SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface *su * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateRenderer */ extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetRenderer(SDL_Window *window); @@ -324,6 +344,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetRenderWindow(SDL_Renderer *renderer); * \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); @@ -332,14 +353,61 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * The following read-only properties are provided by SDL: * - * - `SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 + * - `SDL_PROP_RENDERER_NAME_STRING`: the name of the rendering driver + * - `SDL_PROP_RENDERER_WINDOW_POINTER`: the window where rendering is + * 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_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace value + * describing the colorspace for output to the display, defaults to + * SDL_COLORSPACE_SRGB. + * - `SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN`: true if the output colorspace is + * SDL_COLORSPACE_SRGB_LINEAR and the renderer is showing on a display with + * HDR enabled. This property can change dynamically when + * SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent. + * - `SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT`: the value of SDR white in the + * SDL_COLORSPACE_SRGB_LINEAR colorspace. When HDR is enabled, this value is + * automatically multiplied into the color scale. This property can change + * dynamically when SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent. + * - `SDL_PROP_RENDERER_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. + * + * With the direct3d renderer: + * + * - `SDL_PROP_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 associated + * with the renderer + * + * With the direct3d11 renderer: + * + * - `SDL_PROP_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated + * with the renderer + * + * With the direct3d12 renderer: + * + * - `SDL_PROP_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device associated + * with the renderer + * - `SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the ID3D12CommandQueue * associated with the renderer - * - `SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated + * + * With the vulkan renderer: + * + * - `SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER`: the VkInstance associated * with the renderer - * - `SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device associated + * - `SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER`: the VkSurfaceKHR associated * with the renderer - * - `SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the - * ID3D12CommandQueue associated with the renderer + * - `SDL_PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER`: the VkPhysicalDevice + * associated with the renderer + * - `SDL_PROP_RENDERER_VULKAN_DEVICE_POINTER`: the VkDevice associated with + * the renderer + * - `SDL_PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER`: the queue + * family index used for rendering + * - `SDL_PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER`: the queue + * family index used for presentation + * - `SDL_PROP_RENDERER_VULKAN_SWAPCHAIN_IMAGE_COUNT_NUMBER`: the number of + * swapchain images, or potential frames in flight, used by the Vulkan + * renderer * * \param renderer the rendering context * \returns a valid property ID on success or 0 on failure; call @@ -352,10 +420,24 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); -#define SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device" -#define SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device" -#define SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" -#define SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue" +#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_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_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" +#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" +#define SDL_PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER "SDL.renderer.vulkan.physical_device" +#define SDL_PROP_RENDERER_VULKAN_DEVICE_POINTER "SDL.renderer.vulkan.device" +#define SDL_PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.vulkan.graphics_queue_family_index" +#define SDL_PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.vulkan.present_queue_family_index" +#define SDL_PROP_RENDERER_VULKAN_SWAPCHAIN_IMAGE_COUNT_NUMBER "SDL.renderer.vulkan.swapchain_image_count" /** * Get the output size in pixels of a rendering context. @@ -371,7 +453,7 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetRenderer + * \sa SDL_GetCurrentRenderOutputSize */ extern DECLSPEC int SDLCALL SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h); @@ -392,7 +474,6 @@ extern DECLSPEC int SDLCALL SDL_GetRenderOutputSize(SDL_Renderer *renderer, int * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderOutputSize - * \sa SDL_GetRenderer */ extern DECLSPEC int SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *renderer, int *w, int *h); @@ -419,7 +500,7 @@ extern DECLSPEC int SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *rendere * \sa SDL_QueryTexture * \sa SDL_UpdateTexture */ -extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h); +extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, SDL_PixelFormatEnum format, int access, int w, int h); /** * Create a texture from an existing surface. @@ -453,68 +534,94 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * These are the supported properties: * - * - `SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER`: one of the enumerated values - * in SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer - * - `SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER`: one of the enumerated values - * in SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC - * - `SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER`: the width of the texture in + * - `SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER`: an SDL_ColorSpace value + * describing the texture colorspace, defaults to SDL_COLORSPACE_SRGB_LINEAR + * for floating point textures, SDL_COLORSPACE_HDR10 for 10-bit textures, + * 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_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 * pixels, required - * - `SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in + * - `SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in * pixels, required + * - `SDL_PROP_TEXTURE_CREATE_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 + * to 100 for HDR10 textures and 1.0 for floating point textures. + * - `SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT`: for HDR10 and floating + * point textures, this defines the maximum dynamic range used by the + * content, in terms of the SDR white point. This would be equivalent to + * maxCLL / SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT for HDR10 content. + * If this is defined, any values outside the range supported by the display + * will be scaled into the available HDR headroom, otherwise they are + * clipped. * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D + * - `SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D * associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER`: the - * ID3D11Texture2D associated with the U plane of a YUV texture, if you want - * to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER`: the - * ID3D11Texture2D associated with the V plane of a YUV texture, if you want - * to wrap an existing texture. - * - * With the direct3d12 renderer: - * - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER`: the ID3D12Resource - * associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource + * - `SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D * associated with the U plane of a YUV texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource + * - `SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D * associated with the V plane of a YUV texture, if you want to wrap an * existing texture. * - * With the opengl renderer: + * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER`: the ID3D12Resource * associated with the texture, if you want to wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint - * texture associated with the UV plane of an NV12 texture, if you want to - * wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource * associated with the U plane of a YUV texture, if you want to wrap an * existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource + * associated with the V plane of a YUV texture, if you want to wrap an + * existing texture. + * + * With the metal renderer: + * + * - `SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER`: the CVPixelBufferRef + * associated with the texture, if you want to create a texture from an + * existing pixel buffer. + * + * With the opengl renderer: + * + * - `SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER`: the GLuint texture + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture + * associated with the UV plane of an NV12 texture, if you want to wrap an + * existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture + * associated with the U plane of a YUV texture, if you want to wrap an + * existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture * associated with the V plane of a YUV texture, if you want to wrap an * existing texture. * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint - * texture associated with the texture, if you want to wrap an existing - * texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint - * texture associated with the texture, if you want to wrap an existing - * texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint - * texture associated with the UV plane of an NV12 texture, if you want to - * wrap an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint - * texture associated with the U plane of a YUV texture, if you want to wrap - * an existing texture. - * - `SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint - * texture associated with the V plane of a YUV texture, if you want to wrap - * an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture + * associated with the texture, if you want to wrap an existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture + * associated with the UV plane of an NV12 texture, if you want to wrap an + * existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture + * associated with the U plane of a YUV texture, if you want to wrap an + * existing texture. + * - `SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture + * associated with the V plane of a YUV texture, if you want to wrap an + * existing texture. + * + * With the vulkan renderer: + * + * - `SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER`: the VkImage with layout + * 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 @@ -524,88 +631,122 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateProperties * \sa SDL_CreateTexture + * \sa SDL_CreateTextureFromSurface * \sa SDL_DestroyTexture * \sa SDL_QueryTexture * \sa SDL_UpdateTexture */ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); -#define SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER "format" -#define SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER "access" -#define SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER "width" -#define SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER "height" -#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "d3d11.texture" -#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u" -#define SDL_PROPERTY_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v" -#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "d3d12.texture" -#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "d3d12.texture_u" -#define SDL_PROPERTY_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "d3d12.texture_v" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "opengl.texture" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "opengl.texture_uv" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "opengl.texture_u" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "opengl.texture_v" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "opengles2.texture_uv" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u" -#define SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v" - +#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" /** * Get the properties associated with a texture. * * 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 + * - `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 + * to 100 for HDR10 textures and 1.0 for other textures. + * - `SDL_PROP_TEXTURE_HDR_HEADROOM_FLOAT`: for HDR10 and floating point + * textures, this defines the maximum dynamic range used by the content, in + * terms of the SDR white point. If this is defined, any values outside the + * range supported by the display will be scaled into the available HDR + * headroom, otherwise they are clipped. This defaults to 1.0 for SDR + * textures, 4.0 for HDR10 textures, and no default for floating point + * textures. + * * With the direct3d11 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D - * associated with the texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D + * - `SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER`: the ID3D11Texture2D associated + * with the texture + * - `SDL_PROP_TEXTURE_D3D11_TEXTURE_U_POINTER`: the ID3D11Texture2D * associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D + * - `SDL_PROP_TEXTURE_D3D11_TEXTURE_V_POINTER`: the ID3D11Texture2D * associated with the V plane of a YUV texture * * With the direct3d12 renderer: * - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER`: the ID3D12Resource - * associated with the texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource - * associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource - * associated with the V plane of a YUV texture + * - `SDL_PROP_TEXTURE_D3D12_TEXTURE_POINTER`: the ID3D12Resource associated + * with the texture + * - `SDL_PROP_TEXTURE_D3D12_TEXTURE_U_POINTER`: the ID3D12Resource associated + * with the U plane of a YUV texture + * - `SDL_PROP_TEXTURE_D3D12_TEXTURE_V_POINTER`: the ID3D12Resource associated + * with the V plane of a YUV texture + * + * With the vulkan renderer: + * + * - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_POINTER`: the VkImage associated with + * the texture + * - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_U_POINTER`: the VkImage associated with + * the U plane of a YUV texture + * - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_V_POINTER`: the VkImage associated with + * the V plane of a YUV texture + * - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_UV_POINTER`: the VkImage associated with + * the UV plane of a NV12/NV21 texture * * With the opengl renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER`: the GLuint texture - * associated with the texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER`: the GLuint texture associated + * with the texture + * - `SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER`: the GLuint texture * associated with the UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture - * associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture - * associated with the V plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET`: the GLenum for the texture - * target (`GL_TEXTURE_2D`, `GL_TEXTURE_RECTANGLE_ARB`, etc) - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT`: the texture coordinate width - * of the texture (0.0 - 1.0) - * - `SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT`: the texture coordinate height - * of the texture (0.0 - 1.0) + * - `SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER`: the GLuint texture associated + * with the U plane of a YUV texture + * - `SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER`: the GLuint texture associated + * with the V plane of a YUV texture + * - `SDL_PROP_TEXTURE_OPENGL_TEXTURE_TARGET_NUMBER`: the GLenum for the + * texture target (`GL_TEXTURE_2D`, `GL_TEXTURE_RECTANGLE_ARB`, etc) + * - `SDL_PROP_TEXTURE_OPENGL_TEX_W_FLOAT`: the texture coordinate width of + * the texture (0.0 - 1.0) + * - `SDL_PROP_TEXTURE_OPENGL_TEX_H_FLOAT`: the texture coordinate height of + * the texture (0.0 - 1.0) * * With the opengles2 renderer: * - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER`: the GLuint texture * associated with the texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER`: the GLuint texture * associated with the UV plane of an NV12 texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER`: the GLuint texture * associated with the U plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture + * - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER`: the GLuint texture * associated with the V plane of a YUV texture - * - `SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET`: the GLenum for the + * - `SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER`: the GLenum for the * texture target (`GL_TEXTURE_2D`, `GL_TEXTURE_EXTERNAL_OES`, etc) * + * With the vulkan renderer: + * + * - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER`: the VkImage associated with the + * texture + * * \param texture the texture to query * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -617,24 +758,28 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" -#define SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" -#define SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET "SDL.texture.opengl.target" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" -#define SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" -#define SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET "SDL.texture.opengles2.target" +#define SDL_PROP_TEXTURE_COLORSPACE_NUMBER "SDL.texture.colorspace" +#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" +#define SDL_PROP_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u" +#define SDL_PROP_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v" +#define SDL_PROP_TEXTURE_D3D12_TEXTURE_POINTER "SDL.texture.d3d12.texture" +#define SDL_PROP_TEXTURE_D3D12_TEXTURE_U_POINTER "SDL.texture.d3d12.texture_u" +#define SDL_PROP_TEXTURE_D3D12_TEXTURE_V_POINTER "SDL.texture.d3d12.texture_v" +#define SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER "SDL.texture.opengl.texture" +#define SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.opengl.texture_uv" +#define SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.opengl.texture_u" +#define SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.opengl.texture_v" +#define SDL_PROP_TEXTURE_OPENGL_TEXTURE_TARGET_NUMBER "SDL.texture.opengl.target" +#define SDL_PROP_TEXTURE_OPENGL_TEX_W_FLOAT "SDL.texture.opengl.tex_w" +#define SDL_PROP_TEXTURE_OPENGL_TEX_H_FLOAT "SDL.texture.opengl.tex_h" +#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.opengles2.texture" +#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.opengles2.texture_uv" +#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.opengles2.texture_u" +#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.opengles2.texture_v" +#define SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER "SDL.texture.opengles2.target" +#define SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER "SDL.texture.vulkan.texture" /** * Get the renderer that created an SDL_Texture. @@ -646,10 +791,6 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *t * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateTexture - * \sa SDL_CreateTextureFromSurface - * \sa SDL_CreateTextureWithProperties */ extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetRendererFromTexture(SDL_Texture *texture); @@ -672,8 +813,6 @@ extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetRendererFromTexture(SDL_Texture *te * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateTexture */ extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture *texture, Uint32 *format, int *access, int *w, int *h); @@ -700,10 +839,39 @@ extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture *texture, Uint32 *forma * * \sa SDL_GetTextureColorMod * \sa SDL_SetTextureAlphaMod + * \sa SDL_SetTextureColorModFloat */ extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b); +/** + * Set an additional color value multiplied into render copy operations. + * + * When this texture is rendered, during the copy operation each source color + * channel is modulated by the appropriate color value according to the + * following formula: + * + * `srcC = srcC * color` + * + * Color modulation is not always supported by the renderer; it will return -1 + * 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetTextureColorModFloat + * \sa SDL_SetTextureAlphaModFloat + * \sa SDL_SetTextureColorMod + */ +extern DECLSPEC int SDLCALL SDL_SetTextureColorModFloat(SDL_Texture *texture, float r, float g, float b); + + /** * Get the additional color value multiplied into render copy operations. * @@ -717,10 +885,29 @@ extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r * \since This function is available since SDL 3.0.0. * * \sa SDL_GetTextureAlphaMod + * \sa SDL_GetTextureColorModFloat * \sa SDL_SetTextureColorMod */ extern DECLSPEC int 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetTextureAlphaModFloat + * \sa SDL_GetTextureColorMod + * \sa SDL_SetTextureColorModFloat + */ +extern DECLSPEC int SDLCALL SDL_GetTextureColorModFloat(SDL_Texture *texture, float *r, float *g, float *b); + /** * Set an additional alpha value multiplied into render copy operations. * @@ -740,10 +927,35 @@ extern DECLSPEC int SDLCALL SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetTextureAlphaMod + * \sa SDL_SetTextureAlphaModFloat * \sa SDL_SetTextureColorMod */ extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha); +/** + * Set an additional alpha value multiplied into render copy operations. + * + * When this texture is rendered, during the copy operation the source alpha + * value is modulated by this alpha value according to the following formula: + * + * `srcA = srcA * alpha` + * + * Alpha modulation is not always supported by the renderer; it will return -1 + * 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetTextureAlphaModFloat + * \sa SDL_SetTextureAlphaMod + * \sa SDL_SetTextureColorModFloat + */ +extern DECLSPEC int SDLCALL SDL_SetTextureAlphaModFloat(SDL_Texture *texture, float alpha); + /** * Get the additional alpha value multiplied into render copy operations. * @@ -754,11 +966,28 @@ extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 a * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetTextureAlphaModFloat * \sa SDL_GetTextureColorMod * \sa SDL_SetTextureAlphaMod */ extern DECLSPEC int 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetTextureAlphaMod + * \sa SDL_GetTextureColorModFloat + * \sa SDL_SetTextureAlphaModFloat + */ +extern DECLSPEC int SDLCALL SDL_GetTextureAlphaModFloat(SDL_Texture *texture, float *alpha); + /** * Set the blend mode for a texture, used by SDL_RenderTexture(). * @@ -773,7 +1002,6 @@ extern DECLSPEC int SDLCALL SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetTextureBlendMode - * \sa SDL_RenderTexture */ extern DECLSPEC int SDLCALL SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode); @@ -794,6 +1022,8 @@ extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_Bl /** * Set the scale mode used for texture scale operations. * + * The default texture scale mode is SDL_SCALEMODE_LINEAR. + * * If the scale mode is not supported, the closest supported mode is chosen. * * \param texture The texture to update. @@ -846,9 +1076,10 @@ extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_Sc * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateTexture * \sa SDL_LockTexture * \sa SDL_UnlockTexture + * \sa SDL_UpdateNVTexture + * \sa SDL_UpdateYUVTexture */ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); @@ -877,6 +1108,7 @@ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture *texture, const SDL_Re * * \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, @@ -905,6 +1137,9 @@ extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture *texture, * SDL_GetError() for more information. * * \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, const SDL_Rect *rect, @@ -936,6 +1171,7 @@ extern DECLSPEC int SDLCALL SDL_UpdateNVTexture(SDL_Texture *texture, * * \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, @@ -1150,6 +1386,7 @@ extern DECLSPEC int SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Renderer *re * \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); @@ -1163,10 +1400,29 @@ extern DECLSPEC int SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, const * * \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); +/** + * Return whether an explicit rectangle was set as the viewport. + * + * This is useful if you're saving and restoring the viewport and want to know + * 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) + * + * \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); + /** * Set the clip rectangle for rendering on the specified target. * @@ -1252,7 +1508,7 @@ extern DECLSPEC int SDLCALL SDL_SetRenderScale(SDL_Renderer *renderer, float sca extern DECLSPEC int SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY); /** - * Set the color used for drawing operations (Rect, Line and Clear). + * Set the color used for drawing operations. * * Set the color for drawing or filling rectangles, lines, and points, and for * SDL_RenderClear(). @@ -1270,18 +1526,33 @@ extern DECLSPEC int SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *sc * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderDrawColor - * \sa SDL_RenderClear - * \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_SetRenderDrawColorFloat */ extern DECLSPEC int 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). + * + * 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 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. + * + * \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); + /** * Get the color used for drawing operations (Rect, Line and Clear). * @@ -1299,10 +1570,69 @@ extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 * * \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); +/** + * Get the color used for drawing operations (Rect, Line and Clear). + * + * \param renderer the rendering context + * \param r a pointer filled in with the red value used to draw on the + * rendering target + * \param g a pointer filled in with the green value used to draw on the + * rendering target + * \param b a pointer filled in with the blue value used to draw on the + * 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. + * + * \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); + +/** + * Set the color scale used for render operations. + * + * The color scale is an additional scale multiplied into the pixel color + * value while rendering. This can be used to adjust the brightness of colors + * during HDR rendering, or changing HDR video brightness when playing on an + * SDR display. + * + * 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetRenderColorScale + */ +extern DECLSPEC int 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetRenderColorScale + */ +extern DECLSPEC int SDLCALL SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale); + /** * Set the blend mode used for drawing operations (Fill and Line). * @@ -1316,14 +1646,6 @@ extern DECLSPEC int SDLCALL SDL_GetRenderDrawColor(SDL_Renderer *renderer, Uint8 * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderDrawBlendMode - * \sa SDL_RenderLine - * \sa SDL_RenderLines - * \sa SDL_RenderPoint - * \sa SDL_RenderPoints - * \sa SDL_RenderRect - * \sa SDL_RenderRects - * \sa SDL_RenderFillRect - * \sa SDL_RenderFillRects */ extern DECLSPEC int SDLCALL SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); @@ -1366,6 +1688,8 @@ extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer *renderer); * \returns 0 on success, or -1 on error * * \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); @@ -1379,6 +1703,8 @@ extern DECLSPEC int SDLCALL SDL_RenderPoint(SDL_Renderer *renderer, float x, flo * SDL_GetError() for more information. * * \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); @@ -1393,6 +1719,8 @@ extern DECLSPEC int SDLCALL SDL_RenderPoints(SDL_Renderer *renderer, const SDL_F * \returns 0 on success, or -1 on error * * \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); @@ -1407,6 +1735,8 @@ extern DECLSPEC int SDLCALL SDL_RenderLine(SDL_Renderer *renderer, float x1, flo * SDL_GetError() for more information. * * \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); @@ -1419,6 +1749,8 @@ extern DECLSPEC int SDLCALL SDL_RenderLines(SDL_Renderer *renderer, const SDL_FP * \returns 0 on success, or -1 on error * * \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); @@ -1433,6 +1765,8 @@ extern DECLSPEC int SDLCALL SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRe * SDL_GetError() for more information. * * \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); @@ -1446,6 +1780,8 @@ extern DECLSPEC int SDLCALL SDL_RenderRects(SDL_Renderer *renderer, const SDL_FR * \returns 0 on success, or -1 on error * * \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); @@ -1460,6 +1796,8 @@ extern DECLSPEC int SDLCALL SDL_RenderFillRect(SDL_Renderer *renderer, const SDL * SDL_GetError() for more information. * * \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); @@ -1476,6 +1814,8 @@ extern DECLSPEC int SDLCALL SDL_RenderFillRects(SDL_Renderer *renderer, const SD * \returns 0 on success, or -1 on error * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RenderTextureRotated */ extern DECLSPEC int SDLCALL SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect); @@ -1494,17 +1834,19 @@ extern DECLSPEC int SDLCALL SDL_RenderTexture(SDL_Renderer *renderer, SDL_Textur * \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_RendererFlip value stating which flipping actions should - * be performed on the texture + * \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. * * \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, const SDL_FRect *srcrect, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, - const SDL_RendererFlip flip); + const SDL_FlipMode flip); /** * Render a list of triangles, optionally using a texture and indices into the @@ -1524,7 +1866,6 @@ extern DECLSPEC int SDLCALL SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderGeometryRaw - * \sa SDL_Vertex */ extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, SDL_Texture *texture, @@ -1555,7 +1896,6 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderGeometry - * \sa SDL_Vertex */ extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, @@ -1566,35 +1906,57 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, const void *indices, int num_indices, int size_indices); /** - * Read pixels from the current rendering target to an array of pixels. + * 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 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. + * + * \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, + SDL_Texture *texture, + const float *xy, int xy_stride, + const SDL_FColor *color, int color_stride, + const float *uv, int uv_stride, + int num_vertices, + const void *indices, int num_indices, int size_indices); + +/** + * Read pixels from the current rendering target. + * + * The returned surface should be freed with SDL_DestroySurface() * * **WARNING**: This is a very slow operation, and should not be used * frequently. If you're using this on the main rendering target, it should be * called after rendering and before SDL_RenderPresent(). * - * `pitch` specifies the number of bytes between rows in the destination - * `pixels` data. This allows you to write to a subrectangle or have padded - * rows in the destination. Generally, `pitch` should equal the number of - * pixels per row in the `pixels` data times the number of bytes per pixel, - * but it might contain additional padding (for example, 24bit RGB Windows - * Bitmap data pads all rows to multiples of 4 bytes). - * * \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 - * \param format an SDL_PixelFormatEnum value of the desired format of the - * pixel data, or 0 to use the format of the rendering target - * \param pixels a pointer to the pixel data to copy into - * \param pitch the pitch of the `pixels` parameter - * \returns 0 on success or a negative error code on failure; call + * \returns a new SDL_Surface on success or NULL on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_RenderReadPixels(SDL_Renderer *renderer, - const SDL_Rect *rect, - Uint32 format, - void *pixels, int pitch); +extern DECLSPEC SDL_Surface * SDLCALL SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect); /** * Update the screen with any rendering performed since the previous call. @@ -1658,6 +2020,10 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture *texture); * If `renderer` is NULL, this function will return immediately after setting * the SDL error message to "Invalid renderer". See SDL_GetError(). * + * 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 * * \since This function is available since SDL 3.0.0. @@ -1734,6 +2100,34 @@ extern DECLSPEC void *SDLCALL SDL_GetRenderMetalLayer(SDL_Renderer *renderer); */ extern DECLSPEC void *SDLCALL SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer); + +/** + * Add a set of synchronization semaphores for the current frame. + * + * The Vulkan renderer will wait for `wait_semaphore` before submitting + * rendering commands and signal `signal_semaphore` after rendering commands + * are complete for this frame. + * + * This should be called each frame that you want semaphore synchronization. + * The Vulkan renderer may have multiple frames in flight on the GPU, so you + * should have multiple semaphores that are used for synchronization. Querying + * 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 wait_semaphore a VkSempahore to wait on before rendering the current + * 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. + * + * \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); + /** * Toggle VSync of the given renderer. * @@ -1743,6 +2137,8 @@ extern DECLSPEC void *SDLCALL SDL_GetRenderMetalCommandEncoder(SDL_Renderer *ren * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetRenderVSync */ extern DECLSPEC int SDLCALL SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync); @@ -1756,6 +2152,8 @@ extern DECLSPEC int SDLCALL SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetRenderVSync */ extern DECLSPEC int SDLCALL SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync); diff --git a/include/SDL3/SDL_scancode.h b/include/SDL3/SDL_scancode.h index 6d3728dd..336d6f0b 100644 --- a/include/SDL3/SDL_scancode.h +++ b/include/SDL3/SDL_scancode.h @@ -33,6 +33,9 @@ /** * The SDL keyboard scancode representation. * + * 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. diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 4f864873..0a5cf33b 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -35,13 +35,14 @@ #endif #include #include +#include #include #ifndef SDL_DISABLE_ALLOCA # ifndef alloca # ifdef HAVE_ALLOCA_H # include -# elif defined(__NETBSD__) +# elif defined(SDL_PLATFORM_NETBSD) # if defined(__STRICT_ANSI__) # define SDL_DISABLE_ALLOCA # else @@ -58,7 +59,7 @@ # include # elif defined(__DMC__) # include -# elif defined(__AIX__) +# elif defined(SDL_PLATFORM_AIX) # pragma alloca # elif defined(__MRC__) void *alloca(unsigned); @@ -185,6 +186,16 @@ typedef int64_t Sint64; #define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */ typedef uint64_t Uint64; +/** + * 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(). + */ +#define SDL_MAX_TIME SDL_MAX_SINT64 +#define SDL_MIN_TIME SDL_MIN_SINT64 +typedef Sint64 SDL_Time; + /* @} *//* Basic data types */ /** @@ -206,9 +217,9 @@ typedef uint64_t Uint64; #ifndef SDL_PRIs64 #ifdef PRIs64 #define SDL_PRIs64 PRIs64 -#elif defined(__WIN32__) || defined(__GDK__) +#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #define SDL_PRIs64 "I64d" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIs64 "ld" #else #define SDL_PRIs64 "lld" @@ -217,9 +228,9 @@ typedef uint64_t Uint64; #ifndef SDL_PRIu64 #ifdef PRIu64 #define SDL_PRIu64 PRIu64 -#elif defined(__WIN32__) || defined(__GDK__) +#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #define SDL_PRIu64 "I64u" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIu64 "lu" #else #define SDL_PRIu64 "llu" @@ -228,9 +239,9 @@ typedef uint64_t Uint64; #ifndef SDL_PRIx64 #ifdef PRIx64 #define SDL_PRIx64 PRIx64 -#elif defined(__WIN32__) || defined(__GDK__) +#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #define SDL_PRIx64 "I64x" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIx64 "lx" #else #define SDL_PRIx64 "llx" @@ -239,9 +250,9 @@ typedef uint64_t Uint64; #ifndef SDL_PRIX64 #ifdef PRIX64 #define SDL_PRIX64 PRIX64 -#elif defined(__WIN32__) || defined(__GDK__) +#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #define SDL_PRIX64 "I64X" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIX64 "lX" #else #define SDL_PRIX64 "llX" @@ -369,7 +380,7 @@ SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); /** \cond */ #ifndef DOXYGEN_SHOULD_IGNORE_THIS -#if !defined(__ANDROID__) && !defined(__VITA__) && !defined(__3DS__) +#if !defined(SDL_PLATFORM_ANDROID) && !defined(SDL_PLATFORM_VITA) && !defined(SDL_PLATFORM_3DS) /* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */ typedef enum { @@ -497,6 +508,9 @@ extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int 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 */ @@ -522,22 +536,45 @@ extern DECLSPEC int SDLCALL SDL_tolower(int x); 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); +extern 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))) + +extern 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 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); +/* 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))) -#define SDL_copyp(dst, src) \ - { SDL_COMPILE_TIME_ASSERT(SDL_copyp, sizeof (*(dst)) == sizeof (*(src))); } \ - SDL_memcpy((dst), (src), sizeof (*(src))) - - - -extern DECLSPEC void *SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); - -extern DECLSPEC void *SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len); extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr); @@ -703,36 +740,41 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, #if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS) /* The analyzer knows about strlcpy even when the system doesn't provide it */ -#ifndef HAVE_STRLCPY +#if !defined(HAVE_STRLCPY) && !defined(strlcpy) 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 */ -#ifndef HAVE_STRLCAT +#if !defined(HAVE_STRLCAT) && !defined(strlcat) size_t strlcat(char* dst, const char* src, size_t size); #endif -#ifndef HAVE_WCSLCPY +#if !defined(HAVE_WCSLCPY) && !defined(wcslcpy) size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size); #endif -#ifndef HAVE_WCSLCAT +#if !defined(HAVE_WCSLCAT) && !defined(wcslcat) size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #endif /* Starting LLVM 16, the analyser errors out if these functions do not have their prototype defined (clang-diagnostic-implicit-function-declaration) */ #include -#include #include #define SDL_malloc malloc #define SDL_calloc calloc #define SDL_realloc realloc #define SDL_free free -#define SDL_memset memset +#ifndef SDL_memcpy #define SDL_memcpy memcpy +#endif +#ifndef SDL_memmove #define SDL_memmove memmove +#endif +#ifndef SDL_memset +#define SDL_memset memset +#endif #define SDL_memcmp memcmp #define SDL_strlcpy strlcpy #define SDL_strlcat strlcat @@ -759,11 +801,6 @@ size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #define SDL_vsnprintf vsnprintf #endif -SDL_FORCE_INLINE void *SDL_memcpy4(SDL_OUT_BYTECAP(dwords*4) void *dst, SDL_IN_BYTECAP(dwords*4) const void *src, size_t dwords) -{ - return SDL_memcpy(dst, src, dwords * 4); -} - /** * If a * b would overflow, return -1. Otherwise store a * b via ret * and return 0. diff --git a/include/SDL3/SDL_storage.h b/include/SDL3/SDL_storage.h new file mode 100644 index 00000000..61a75c38 --- /dev/null +++ b/include/SDL3/SDL_storage.h @@ -0,0 +1,350 @@ +/* + 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_storage.h + * + * Include file for storage container SDL API functions + */ + +#ifndef SDL_storage_h_ +#define SDL_storage_h_ + +#include +#include +#include + +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* !!! FIXME: Don't let this ship without async R/W support!!! */ + +typedef struct SDL_StorageInterface +{ + /* Called when the storage is closed */ + int (SDLCALL *close)(void *userdata); + + /* Optional, returns whether the storage is currently ready for access */ + SDL_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); + + /* Get path information, optional for write-only storage */ + int (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); + + /* Write a file to storage, optional for read-only storage */ + int (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); + + /* Remove a file or empty directory, optional for read-only storage */ + int (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); + + /* Get the space remaining, optional for read-only storage */ + Uint64 (SDLCALL *space_remaining)(void *userdata); + +} SDL_StorageInterface; + +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 + * \returns a title storage container on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CloseStorage + * \sa SDL_GetStorageFileSize + * \sa SDL_OpenUserStorage + * \sa SDL_ReadStorageFile + */ +extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override, SDL_PropertiesID props); + +/** + * Opens up a container for a user's unique read/write filesystem. + * + * While title storage can generally be kept open throughout runtime, user + * storage should only be opened when the client is ready to read/write files. + * 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 + * \returns a user storage container on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CloseStorage + * \sa SDL_GetStorageFileSize + * \sa SDL_GetStorageSpaceRemaining + * \sa SDL_OpenTitleStorage + * \sa SDL_ReadStorageFile + * \sa SDL_StorageReady + * \sa SDL_WriteStorageFile + */ +extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props); + +/** + * Opens up a container for local filesystem storage. + * + * This is provided for development and tools. Portable applications should + * use SDL_OpenTitleStorage() for access to game data and + * SDL_OpenUserStorage() for access to user data. + * + * \param path the base path prepended to all storage paths, or NULL for no + * base path + * \returns a filesystem storage container on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CloseStorage + * \sa SDL_GetStorageFileSize + * \sa SDL_GetStorageSpaceRemaining + * \sa SDL_OpenTitleStorage + * \sa SDL_OpenUserStorage + * \sa SDL_ReadStorageFile + * \sa SDL_WriteStorageFile + */ +extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenFileStorage(const char *path); + +/** + * Opens up a container using a client-provided storage interface. + * + * Applications do not need to use this function unless they are providing + * their own SDL_Storage implementation. If you just need an SDL_Storage, you + * 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 + * \returns a storage container on success or NULL on failure; call + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CloseStorage + * \sa SDL_GetStorageFileSize + * \sa SDL_GetStorageSpaceRemaining + * \sa SDL_ReadStorageFile + * \sa SDL_StorageReady + * \sa SDL_WriteStorageFile + */ +extern 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenFileStorage + * \sa SDL_OpenStorage + * \sa SDL_OpenTitleStorage + * \sa SDL_OpenUserStorage + */ +extern DECLSPEC int 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. + * + * \param storage a storage container to query + * \returns SDL_TRUE if the container is ready, SDL_FALSE otherwise + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC SDL_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 + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ReadStorageFile + * \sa SDL_StorageReady + */ +extern DECLSPEC int 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. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetStorageFileSize + * \sa SDL_StorageReady + * \sa SDL_WriteStorageFile + */ +extern DECLSPEC int 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 + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetStorageSpaceRemaining + * \sa SDL_ReadStorageFile + * \sa SDL_StorageReady + */ +extern DECLSPEC int 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. + * + * \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); + +/** + * Enumerate a directory in a storage container. + * + * \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. + * + * \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); + +/** + * 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. + * + * \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); + +/** + * 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. + * + * \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); + +/** + * Get information about a filesystem path in a storage container. + * + * \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. + * + * \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); + +/** + * Queries the remaining space in a storage container. + * + * \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); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_storage_h_ */ diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 7ccbda91..19f77e9f 100644 --- a/include/SDL3/SDL_surface.h +++ b/include/SDL3/SDL_surface.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -75,6 +75,15 @@ typedef enum SDL_SCALEMODE_BEST /**< anisotropic filtering */ } SDL_ScaleMode; +/** + * The flip mode + */ +typedef enum +{ + SDL_FLIP_NONE, /**< Do not flip */ + SDL_FLIP_HORIZONTAL, /**< flip horizontally */ + SDL_FLIP_VERTICAL /**< flip vertically */ +} SDL_FlipMode; /** * A collection of pixels used in software blitting. @@ -94,7 +103,6 @@ typedef enum * * \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. - * \sa SDL_CreateSurfaceFrom */ typedef struct SDL_Surface { @@ -128,16 +136,6 @@ typedef struct SDL_Surface typedef int (SDLCALL *SDL_blit) (struct SDL_Surface *src, const SDL_Rect *srcrect, struct SDL_Surface *dst, const SDL_Rect *dstrect); -/** - * The formula used for converting between YUV and RGB - */ -typedef enum -{ - SDL_YUV_CONVERSION_JPEG, /**< Full range JPEG */ - SDL_YUV_CONVERSION_BT601, /**< BT.601 (the default) */ - SDL_YUV_CONVERSION_BT709, /**< BT.709 */ - SDL_YUV_CONVERSION_AUTOMATIC /**< BT.601 for SD content, BT.709 for HD content */ -} SDL_YUV_CONVERSION_MODE; /** * Allocate a new RGB surface with a specific pixel format. @@ -153,8 +151,7 @@ typedef enum * \sa SDL_CreateSurfaceFrom * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface - (int width, int height, Uint32 format); +extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface(int width, int height, SDL_PixelFormatEnum format); /** * Allocate a new RGB surface with a specific pixel format and existing pixel @@ -172,7 +169,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface * \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 pitch of the surface in bytes + * \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; * call SDL_GetError() for more information. @@ -182,8 +179,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface * \sa SDL_CreateSurface * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom - (void *pixels, int width, int height, int pitch, Uint32 format); +extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitch, SDL_PixelFormatEnum format); /** * Free an RGB surface. @@ -196,14 +192,34 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom * * \sa SDL_CreateSurface * \sa SDL_CreateSurfaceFrom - * \sa SDL_LoadBMP - * \sa SDL_LoadBMP_RW */ extern 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 + * to 203 for HDR10 surfaces and 1.0 for floating point surfaces. + * - `SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT`: for HDR10 and floating point + * surfaces, this defines the maximum dynamic range used by the content, in + * terms of the SDR white point. This defaults to 0.0, which disables tone + * mapping. + * - `SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING`: the tone mapping operator + * used when compressing from a surface with high dynamic range to another + * with lower dynamic range. Currently this supports "chrome", which uses + * the same tone mapping that Chrome uses for HDR content, the form "*=N", + * 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 * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. @@ -215,6 +231,43 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); */ extern 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" + +/** + * Set the colorspace used by a surface. + * + * 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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace colorspace); + +/** + * Get the colorspace used by a surface. + * + * The 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 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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_GetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace *colorspace); + /** * Set the palette used by a surface. * @@ -227,8 +280,7 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *s * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, - SDL_Palette *palette); +extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette); /** * Set up a surface for directly accessing the pixels. @@ -271,7 +323,7 @@ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); * will result in a memory leak. * * \param src the data stream for the surface - * \param freesrc if SDL_TRUE, calls SDL_RWclose() on `src` before returning, + * \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. @@ -280,9 +332,9 @@ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); * * \sa SDL_DestroySurface * \sa SDL_LoadBMP - * \sa SDL_SaveBMP_RW + * \sa SDL_SaveBMP_IO */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc); +extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, SDL_bool closeio); /** * Load a BMP image from a file. @@ -297,7 +349,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool fre * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroySurface - * \sa SDL_LoadBMP_RW + * \sa SDL_LoadBMP_IO * \sa SDL_SaveBMP */ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP(const char *file); @@ -313,17 +365,17 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP(const char *file); * * \param surface the SDL_Surface structure containing the image to be saved * \param dst a data stream to save to - * \param freedst if SDL_TRUE, calls SDL_RWclose() on `dst` before returning, + * \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. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LoadBMP_RW + * \sa SDL_LoadBMP_IO * \sa SDL_SaveBMP */ -extern DECLSPEC int SDLCALL SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst); +extern DECLSPEC int SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, SDL_bool closeio); /** * Save a surface to a file. @@ -342,7 +394,7 @@ extern DECLSPEC int SDLCALL SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadBMP - * \sa SDL_SaveBMP_RW + * \sa SDL_SaveBMP_IO */ extern DECLSPEC int SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file); @@ -363,8 +415,7 @@ 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 DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, int flag); /** * Returns whether the surface is RLE enabled @@ -401,11 +452,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_BlitSurface * \sa SDL_GetSurfaceColorKey + * \sa SDL_SurfaceHasColorKey */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, - int flag, Uint32 key); +extern DECLSPEC int SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, int flag, Uint32 key); /** * Returns whether the surface has a color key @@ -437,11 +487,10 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_BlitSurface * \sa SDL_SetSurfaceColorKey + * \sa SDL_SurfaceHasColorKey */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, - Uint32 *key); +extern DECLSPEC int SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Uint32 *key); /** * Set an additional color value multiplied into blit operations. @@ -464,8 +513,7 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, * \sa SDL_GetSurfaceColorMod * \sa SDL_SetSurfaceAlphaMod */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, - Uint8 r, Uint8 g, Uint8 b); +extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b); /** @@ -483,9 +531,7 @@ extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, * \sa SDL_GetSurfaceAlphaMod * \sa SDL_SetSurfaceColorMod */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, - Uint8 *r, Uint8 *g, - Uint8 *b); +extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b); /** * Set an additional alpha value used in blit operations. @@ -505,8 +551,7 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, * \sa SDL_GetSurfaceAlphaMod * \sa SDL_SetSurfaceColorMod */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, - Uint8 alpha); +extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha); /** * Get the additional alpha value used in blit operations. @@ -521,8 +566,7 @@ extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, * \sa SDL_GetSurfaceColorMod * \sa SDL_SetSurfaceAlphaMod */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, - Uint8 *alpha); +extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha); /** * Set the blend mode used for blit operations. @@ -540,8 +584,7 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, * * \sa SDL_GetSurfaceBlendMode */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, - SDL_BlendMode blendMode); +extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode); /** * Get the blend mode used for blit operations. @@ -555,8 +598,7 @@ extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, * * \sa SDL_SetSurfaceBlendMode */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, - SDL_BlendMode *blendMode); +extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode); /** * Set the clipping rectangle for a surface. @@ -575,11 +617,9 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_BlitSurface * \sa SDL_GetSurfaceClipRect */ -extern DECLSPEC SDL_bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, - const SDL_Rect *rect); +extern DECLSPEC SDL_bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect); /** * Get the clipping rectangle for a surface. @@ -596,11 +636,21 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, * * \since This function is available since SDL 3.0.0. * - * \sa SDL_BlitSurface * \sa SDL_SetSurfaceClipRect */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, - SDL_Rect *rect); +extern DECLSPEC int 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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip); /* * Creates a new surface identical to the existing surface. @@ -612,6 +662,8 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, * 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); @@ -631,15 +683,15 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_DuplicateSurface(SDL_Surface *surface); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreatePixelFormat * \sa SDL_ConvertSurfaceFormat - * \sa SDL_CreateSurface + * \sa SDL_ConvertSurfaceFormatAndColorspace + * \sa SDL_CreatePixelFormat + * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface(SDL_Surface *surface, - const SDL_PixelFormat *format); +extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format); /** - * Copy an existing surface to a new surface of the specified format enum. + * 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, @@ -647,19 +699,40 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface(SDL_Surface *surface, * information for the destination surface, in case that would be important. * * \param surface the existing SDL_Surface structure to convert - * \param pixel_format the SDL_PixelFormatEnum that the new surface is - * optimized for + * \param pixel_format the new pixel format * \returns the new SDL_Surface structure that is created or NULL if it fails; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreatePixelFormat * \sa SDL_ConvertSurface - * \sa SDL_CreateSurface + * \sa SDL_ConvertSurfaceFormatAndColorspace + * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat(SDL_Surface *surface, - Uint32 pixel_format); +extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat(SDL_Surface *surface, SDL_PixelFormatEnum pixel_format); + +/** + * Copy an existing surface to a new surface of the specified format and + * colorspace. + * + * This function converts an existing surface to a new format and colorspace + * 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; + * call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ConvertSurface + * \sa SDL_ConvertSurfaceFormat + * \sa SDL_DestroySurface + */ +extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, SDL_PixelFormatEnum pixel_format, SDL_Colorspace colorspace, SDL_PropertiesID props); /** * Copy a block of pixels of one format to another format. @@ -676,12 +749,39 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat(SDL_Surface *surfa * 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, - Uint32 src_format, - const void *src, int src_pitch, - Uint32 dst_format, - void *dst, int dst_pitch); +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); + +/** + * 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 src_colorspace an SDL_ColorSpace value describing the colorspace of + * 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 + * \param dst_colorspace an SDL_ColorSpace value describing the colorspace of + * 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. + * + * \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); /** * Premultiply the alpha on a block of pixels. @@ -703,11 +803,7 @@ extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_PremultiplyAlpha(int width, int height, - Uint32 src_format, - const void *src, int src_pitch, - Uint32 dst_format, - void *dst, int dst_pitch); +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); /** * Perform a fast fill of a rectangle with a specific color. @@ -732,8 +828,7 @@ extern DECLSPEC int SDLCALL SDL_PremultiplyAlpha(int width, int height, * * \sa SDL_FillSurfaceRects */ -extern DECLSPEC int SDLCALL SDL_FillSurfaceRect - (SDL_Surface *dst, const SDL_Rect *rect, Uint32 color); +extern DECLSPEC int 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. @@ -758,8 +853,7 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRect * * \sa SDL_FillSurfaceRect */ -extern DECLSPEC int SDLCALL SDL_FillSurfaceRects - (SDL_Surface *dst, const SDL_Rect *rects, int count, Uint32 color); +extern DECLSPEC int 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. @@ -829,9 +923,7 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRects * * \sa SDL_BlitSurfaceScaled */ -extern DECLSPEC int SDLCALL SDL_BlitSurface - (SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); +extern DECLSPEC int SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect); /** * Perform low-level surface blitting only. @@ -852,9 +944,7 @@ extern DECLSPEC int SDLCALL SDL_BlitSurface * * \sa SDL_BlitSurface */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked - (SDL_Surface *src, const SDL_Rect *srcrect, - SDL_Surface *dst, const SDL_Rect *dstrect); +extern DECLSPEC int 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. @@ -876,14 +966,11 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked * * \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 DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); /** - * Perform a scaled surface copy to a destination surface. + * Perform a scaled blit to a destination surface, which may be of a different + * format. * * \param src the SDL_Surface structure to be copied from * \param srcrect the SDL_Rect structure representing the rectangle to be @@ -900,11 +987,7 @@ extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, * * \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 DECLSPEC int SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, SDL_ScaleMode scaleMode); /** * Perform low-level surface scaled blitting only. @@ -926,41 +1009,34 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, * * \sa SDL_BlitSurfaceScaled */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, - const SDL_Rect *srcrect, - SDL_Surface *dst, - const SDL_Rect *dstrect, - SDL_ScaleMode scaleMode); +extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); /** - * Set the YUV conversion mode + * Retrieves a single pixel from a surface. * - * \param mode YUV conversion mode + * This function prioritizes correctness over speed: it is suitable for unit + * tests, but is not intended for use in a game engine. + * + * 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 r a pointer filled in with the red channel, 0-255, or NULL to ignore + * this channel + * \param g a pointer filled in with the green channel, 0-255, or NULL to + * ignore this channel + * \param b a pointer filled in with the blue channel, 0-255, or NULL to + * 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. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode); - -/** - * Get the YUV conversion mode - * - * \returns YUV conversion mode - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionMode(void); - -/** - * Get the YUV conversion mode, returning the correct mode for the resolution - * when the current conversion mode is SDL_YUV_CONVERSION_AUTOMATIC - * - * \param width width - * \param height height - * \returns YUV conversion mode - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionModeForResolution(int width, int height); +extern DECLSPEC int SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h index 2b20dbe7..25964ba3 100644 --- a/include/SDL3/SDL_system.h +++ b/include/SDL3/SDL_system.h @@ -43,7 +43,7 @@ extern "C" { /* * Platform specific functions for Windows */ -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) typedef struct tagMSG MSG; typedef SDL_bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); @@ -62,9 +62,9 @@ typedef SDL_bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); */ extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata); -#endif /* defined(__WIN32__) || defined(__GDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) /** * Get the D3D9 adapter index that matches the specified display. @@ -80,9 +80,9 @@ extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook ca */ extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID); -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) /** * Get the DXGI Adapter and Output indices for the specified display. @@ -101,7 +101,7 @@ extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID */ extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex); -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ /* * Platform specific functions for UNIX @@ -127,7 +127,7 @@ extern DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void /* * Platform specific functions for Linux */ -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX /** * Sets the UNIX nice value for a thread. @@ -158,12 +158,12 @@ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int prio */ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); -#endif /* __LINUX__ */ +#endif /* SDL_PLATFORM_LINUX */ /* * Platform specific functions for iOS */ -#ifdef __IOS__ +#ifdef SDL_PLATFORM_IOS #define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam) @@ -219,13 +219,13 @@ extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, */ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); -#endif /* __IOS__ */ +#endif /* SDL_PLATFORM_IOS */ /* * Platform specific functions for Android */ -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID /** * Get the Android Java Native Interface Environment of the current thread. @@ -399,17 +399,38 @@ extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state); */ extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void); + +typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, const char *permission, SDL_bool granted); + /** - * Request permissions at runtime. + * Request permissions at runtime, asynchronously. * - * This blocks the calling thread until the permission is granted or denied. + * You do not need to call this for built-in functionality of SDL; recording + * from a microphone or reading images from a camera, using standard SDL APIs, + * will manage permission requests for you. + * + * This function never blocks. Instead, the app-supplied callback will be + * called when a decision has been made. This callback may happen on a + * different thread, and possibly much later, as it might wait on a user to + * respond to a system dialog. If permission has already been granted for a + * specific entitlement, the callback will still fire, probably on the current + * thread and before this function returns. + * + * If the request submission fails, this function returns -1 and the callback + * will NOT be called, but this should only happen in catastrophic conditions, + * like memory running out. Normally there will be a yes or no to the request + * through the callback. * * \param permission The permission to request. - * \returns SDL_TRUE if the permission was granted, SDL_FALSE otherwise. + * \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 + * submitting. The result of the request is only ever reported + * through the callback, not this return value. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission); +extern DECLSPEC int SDLCALL SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata); /** * Shows an Android toast notification. @@ -451,12 +472,12 @@ extern DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int durati */ extern DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); -#endif /* __ANDROID__ */ +#endif /* SDL_PLATFORM_ANDROID */ /* * Platform specific functions for WinRT */ -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT /** * WinRT / Windows Phone path types @@ -556,7 +577,7 @@ extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathT */ extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily(); -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ /** * Query if the current device is a tablet. @@ -610,7 +631,7 @@ extern DECLSPEC void SDLCALL SDL_OnApplicationWillEnterForeground(void); */ extern DECLSPEC void SDLCALL SDL_OnApplicationDidBecomeActive(void); -#ifdef __IOS__ +#ifdef SDL_PLATFORM_IOS /* * \since This function is available since SDL 3.0.0. */ @@ -620,7 +641,7 @@ extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void /* * Functions used only by GDK */ -#ifdef __GDK__ +#ifdef SDL_PLATFORM_GDK typedef struct XTaskQueueObject *XTaskQueueHandle; typedef struct XUser *XUserHandle; diff --git a/include/SDL3/SDL_test_common.h b/include/SDL3/SDL_test_common.h index 0d428e1c..5697c564 100644 --- a/include/SDL3/SDL_test_common.h +++ b/include/SDL3/SDL_test_common.h @@ -34,10 +34,10 @@ #include -#ifdef __PSP__ +#ifdef SDL_PLATFORM_PSP #define DEFAULT_WINDOW_WIDTH 480 #define DEFAULT_WINDOW_HEIGHT 272 -#elif defined(__VITA__) +#elif defined(SDL_PLATFORM_VITA) #define DEFAULT_WINDOW_WIDTH 960 #define DEFAULT_WINDOW_HEIGHT 544 #else @@ -65,7 +65,7 @@ typedef struct SDL_DisplayID displayID; const char *window_title; const char *window_icon; - Uint32 window_flags; + SDL_WindowFlags window_flags; SDL_bool flash_on_focus_loss; int window_x; int window_y; diff --git a/include/SDL3/SDL_test_compare.h b/include/SDL3/SDL_test_compare.h index 4bd0db31..82de5d24 100644 --- a/include/SDL3/SDL_test_compare.h +++ b/include/SDL3/SDL_test_compare.h @@ -44,27 +44,6 @@ extern "C" { #endif -/** - * 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. - * - * 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 - * \param x Horizontal coordinate, 0 <= x < width - * \param y Vertical coordinate, 0 <= y < height - * \param r Pointer to location to store red channel, 0-255 - * \param g Pointer to location to store green channel, 0-255 - * \param b Pointer to location to store blue channel, 0-255 - * \param a Pointer to location to store alpha channel, 0-255 - * \returns 0 if the surface is valid and the coordinates are in-bounds - */ -int SDLTest_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); - /** * Compares a surface and with reference image data for equality * diff --git a/include/SDL3/SDL_test_crc32.h b/include/SDL3/SDL_test_crc32.h index a4103f5c..07f89aba 100644 --- a/include/SDL3/SDL_test_crc32.h +++ b/include/SDL3/SDL_test_crc32.h @@ -63,7 +63,7 @@ extern "C" { /** * Data structure for CRC32 (checksum) computation */ - typedef struct { + typedef struct SDLTest_Crc32Context { CrcUint32 crc32_table[256]; /* CRC table */ } SDLTest_Crc32Context; diff --git a/include/SDL3/SDL_test_md5.h b/include/SDL3/SDL_test_md5.h index 4aa06340..06a6272b 100644 --- a/include/SDL3/SDL_test_md5.h +++ b/include/SDL3/SDL_test_md5.h @@ -68,7 +68,7 @@ extern "C" { typedef Uint32 MD5UINT4; /* Data structure for MD5 (Message-Digest) computation */ - typedef struct { + 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 */ diff --git a/include/SDL3/SDL_test_random.h b/include/SDL3/SDL_test_random.h index 5c3e84a8..73088e13 100644 --- a/include/SDL3/SDL_test_random.h +++ b/include/SDL3/SDL_test_random.h @@ -56,7 +56,7 @@ extern "C" { /* * Context structure for the random number generator state. */ - typedef struct { + typedef struct SDLTest_RandomContext { unsigned int a; unsigned int x; unsigned int c; diff --git a/include/SDL3/SDL_thread.h b/include/SDL3/SDL_thread.h index 22b91cba..ad16fc25 100644 --- a/include/SDL3/SDL_thread.h +++ b/include/SDL3/SDL_thread.h @@ -35,7 +35,7 @@ #include #include -#if (defined(__WIN32__) || defined(__GDK__)) && !defined(__WINRT__) +#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && !defined(SDL_PLATFORM_WINRT) #include /* _beginthreadex() and _endthreadex() */ #endif @@ -50,10 +50,10 @@ struct SDL_Thread; typedef struct SDL_Thread SDL_Thread; /* The SDL thread ID */ -typedef unsigned long SDL_threadID; +typedef Uint64 SDL_ThreadID; /* Thread local storage ID, 0 is the invalid ID */ -typedef unsigned int SDL_TLSID; +typedef Uint32 SDL_TLSID; /** * The SDL thread priority. @@ -81,7 +81,7 @@ typedef enum { typedef int (SDLCALL * SDL_ThreadFunction) (void *data); -#if (defined(__WIN32__) || defined(__GDK__)) && !defined(__WINRT__) +#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && !defined(SDL_PLATFORM_WINRT) /** * \file SDL_thread.h * @@ -190,8 +190,7 @@ SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, * \sa SDL_CreateThreadWithStackSize * \sa SDL_WaitThread */ -extern DECLSPEC SDL_Thread *SDLCALL -SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); +extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); /** * Create a new thread with a specific stack size. @@ -220,10 +219,6 @@ SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); * multiple of the system's page size (in many cases, this is 4 kilobytes, but * check your system documentation). * - * In SDL 2.1, stack size will be folded into the original SDL_CreateThread - * function, but for backwards compatibility, this is currently a separate - * function. - * * \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. @@ -234,10 +229,10 @@ SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); * * \since This function is available since SDL 3.0.0. * + * \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 DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data); #endif @@ -252,8 +247,6 @@ SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const siz * NULL if it doesn't have a name. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreateThread */ extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread); @@ -273,7 +266,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread); * * \sa SDL_GetThreadID */ -extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void); +extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetCurrentThreadID(void); /** * Get the thread identifier for the specified thread. @@ -288,9 +281,9 @@ extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_ThreadID + * \sa SDL_GetCurrentThreadID */ -extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); +extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); /** * Set the priority for the current thread. @@ -402,7 +395,6 @@ extern DECLSPEC SDL_TLSID SDLCALL SDL_CreateTLS(void); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateTLS * \sa SDL_SetTLS */ extern DECLSPEC void * SDLCALL SDL_GetTLS(SDL_TLSID id); @@ -427,7 +419,6 @@ extern DECLSPEC void * SDLCALL SDL_GetTLS(SDL_TLSID id); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateTLS * \sa SDL_GetTLS */ extern DECLSPEC int SDLCALL SDL_SetTLS(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void*)); diff --git a/include/SDL3/SDL_time.h b/include/SDL3/SDL_time.h new file mode 100644 index 00000000..d69d4be7 --- /dev/null +++ b/include/SDL3/SDL_time.h @@ -0,0 +1,208 @@ +/* +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_time_h_ +#define SDL_time_h_ + +/** + * \file SDL_time.h + * + * Header for the SDL realtime clock and date/time routines. + */ + +#include +#include + +#include +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A structure holding a calendar date and time broken down into its components. + */ +typedef struct SDL_DateTime +{ + int year; /**< Year */ + int month; /**< Month [01-12] */ + int day; /**< Day of the month [01-31] */ + int hour; /**< Hour [0-23] */ + int minute; /**< Minute [0-59] */ + int second; /**< Seconds [0-60] */ + int nanosecond; /**< Nanoseconds [0-999999999] */ + int day_of_week; /**< Day of the week [0-6] (0 being Sunday) */ + int utc_offset; /**< Seconds east of UTC */ +} SDL_DateTime; + +/** + * The preferred date format of the current system locale. + * + * \sa SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER + */ +typedef enum SDL_DATE_FORMAT +{ + 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; + +/** + * The preferred time format of the current system locale. + * + * \sa SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER + */ +typedef enum SDL_TIME_FORMAT +{ + SDL_TIME_FORMAT_24HR = 0, /**< 24 hour time */ + SDL_TIME_FORMAT_12HR = 1, /**< 12 hour time */ +} SDL_TIME_FORMAT; + +/** + * Global date/time properties + * + * - `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. + */ +#define SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER "SDL.time.date_format" +#define SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER "SDL.time.time_format" + +/** + * 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 + * information. + * + * \since This function is available since SDL 3.0.0 + */ +extern DECLSPEC int 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 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 + * information. + * + * \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); + +/** + * Converts a calendar time to an SDL_Time in nanoseconds since the epoch. + * + * 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 + * information. + * + * \since This function is available since SDL 3.0.0 + */ +extern DECLSPEC int SDLCALL SDL_DateTimeToTime(const SDL_DateTime *dt, SDL_Time *ticks); + +/** + * Converts an SDL time into a Windows FILETIME (100-nanosecond intervals + * since January 1, 1601). + * + * This function fills in the two 32-bit values of the FILETIME structure. + * + * \param ticks the time to convert + * \param dwLowDateTime a pointer filled in with the low portion of the + * Windows FILETIME value + * \param dwHighDateTime a pointer filled in with the high portion of the + * 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); + +/** + * Converts a Windows FILETIME (100-nanosecond intervals since January 1, + * 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 + * + * \since This function is available since SDL 3.0.0. + */ +extern 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 + * SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0 + */ +extern 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. + * + * \since This function is available since SDL 3.0.0 + */ +extern 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. + * + * \since This function is available since SDL 3.0.0 + */ +extern DECLSPEC int SDLCALL SDL_GetDayOfWeek(int year, int month, int day); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_time_h_ */ diff --git a/include/SDL3/SDL_timer.h b/include/SDL3/SDL_timer.h index b8762040..d317bd81 100644 --- a/include/SDL3/SDL_timer.h +++ b/include/SDL3/SDL_timer.h @@ -45,10 +45,12 @@ extern "C" { #define SDL_NS_PER_SECOND 1000000000LL #define SDL_NS_PER_MS 1000000 #define SDL_NS_PER_US 1000 -#define SDL_MS_TO_NS(MS) (((Uint64)(MS)) * SDL_NS_PER_MS) -#define SDL_NS_TO_MS(NS) ((NS) / SDL_NS_PER_MS) -#define SDL_US_TO_NS(US) (((Uint64)(US)) * SDL_NS_PER_US) -#define SDL_NS_TO_US(NS) ((NS) / SDL_NS_PER_US) +#define SDL_SECONDS_TO_NS(S) (((Uint64)(S)) * SDL_NS_PER_SECOND) +#define SDL_NS_TO_SECONDS(NS) ((NS) / SDL_NS_PER_SECOND) +#define SDL_MS_TO_NS(MS) (((Uint64)(MS)) * SDL_NS_PER_MS) +#define SDL_NS_TO_MS(NS) ((NS) / SDL_NS_PER_MS) +#define SDL_US_TO_NS(US) (((Uint64)(US)) * SDL_NS_PER_US) +#define SDL_NS_TO_US(NS) ((NS) / SDL_NS_PER_US) /** * Get the number of milliseconds since SDL library initialization. @@ -137,7 +139,7 @@ typedef Uint32 (SDLCALL *SDL_TimerCallback)(Uint32 interval, void *param); /** * Definition of the timer ID type. */ -typedef int SDL_TimerID; +typedef Uint32 SDL_TimerID; /** * Call a callback function at a future time. diff --git a/include/SDL3/SDL_touch.h b/include/SDL3/SDL_touch.h index 4140668f..a8306005 100644 --- a/include/SDL3/SDL_touch.h +++ b/include/SDL3/SDL_touch.h @@ -38,8 +38,8 @@ extern "C" { #endif -typedef Sint64 SDL_TouchID; -typedef Sint64 SDL_FingerID; +typedef Uint64 SDL_TouchID; +typedef Uint64 SDL_FingerID; typedef enum { @@ -58,10 +58,10 @@ typedef struct SDL_Finger } SDL_Finger; /* Used as the device ID for mouse events simulated with touch input */ -#define SDL_TOUCH_MOUSEID ((Uint32)-1) +#define SDL_TOUCH_MOUSEID ((SDL_MouseID)-1) /* Used as the SDL_TouchID for touch events simulated with mouse input */ -#define SDL_MOUSE_TOUCHID ((Sint64)-1) +#define SDL_MOUSE_TOUCHID ((SDL_TouchID)-1) /** @@ -131,6 +131,8 @@ extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID); * given ID and index could be found. * * \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); diff --git a/include/SDL3/SDL_version.h b/include/SDL3/SDL_version.h index 61ab8548..1a71fab9 100644 --- a/include/SDL3/SDL_version.h +++ b/include/SDL3/SDL_version.h @@ -48,32 +48,32 @@ extern "C" { * \sa SDL_VERSION * \sa SDL_GetVersion */ -typedef struct SDL_version +typedef struct SDL_Version { Uint8 major; /**< major version */ Uint8 minor; /**< minor version */ Uint8 patch; /**< update version */ -} SDL_version; +} SDL_Version; /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ #define SDL_MAJOR_VERSION 3 -#define SDL_MINOR_VERSION 0 +#define SDL_MINOR_VERSION 1 #define SDL_PATCHLEVEL 0 /** * Macro to determine SDL version program was compiled against. * - * This macro fills in a SDL_version structure with the version of the + * 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. * - * \param x A pointer to a SDL_version struct to initialize. + * \param x A pointer to an SDL_Version struct to initialize. * - * \sa SDL_version + * \sa SDL_Version * \sa SDL_GetVersion */ #define SDL_VERSION(x) \ @@ -114,7 +114,7 @@ typedef struct SDL_version * * This function may be called safely at any time, even before SDL_Init(). * - * \param ver the SDL_version structure that contains the version information + * \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. * @@ -122,7 +122,7 @@ typedef struct SDL_version * * \sa SDL_GetRevision */ -extern DECLSPEC int SDLCALL SDL_GetVersion(SDL_version * ver); +extern DECLSPEC int SDLCALL SDL_GetVersion(SDL_Version * ver); /** * Get the code revision of SDL that is linked against your program. diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 94942a30..fff4e8fa 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -47,7 +47,7 @@ typedef Uint32 SDL_WindowID; /** * Global video properties * - * - `SDL_PROPERTY_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER`: the pointer to + * - `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 @@ -58,7 +58,7 @@ typedef Uint32 SDL_WindowID; * if one was set prior to initialization, or NULL. See * docs/README-wayland.md for more information. */ -#define SDL_PROPERTY_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER "video.wayland.wl_display" +#define SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER "SDL.video.wayland.wl_display" /** * System theme @@ -82,7 +82,7 @@ typedef enum typedef struct { SDL_DisplayID displayID; /**< the display this mode is associated with */ - Uint32 format; /**< pixel format */ + 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) */ @@ -104,35 +104,6 @@ typedef enum /** * The type used to identify a window - * - * \sa SDL_CreateWindow - * \sa SDL_CreateWindowWithProperties - * \sa SDL_DestroyWindow - * \sa SDL_FlashWindow - * \sa SDL_GetWindowFlags - * \sa SDL_GetWindowGrab - * \sa SDL_GetWindowKeyboardGrab - * \sa SDL_GetWindowMouseGrab - * \sa SDL_GetWindowPosition - * \sa SDL_GetWindowSize - * \sa SDL_GetWindowTitle - * \sa SDL_HideWindow - * \sa SDL_MaximizeWindow - * \sa SDL_MinimizeWindow - * \sa SDL_RaiseWindow - * \sa SDL_RestoreWindow - * \sa SDL_SetWindowFullscreen - * \sa SDL_SetWindowGrab - * \sa SDL_SetWindowKeyboardGrab - * \sa SDL_SetWindowMouseGrab - * \sa SDL_SetWindowIcon - * \sa SDL_SetWindowPosition - * \sa SDL_SetWindowSize - * \sa SDL_SetWindowBordered - * \sa SDL_SetWindowResizable - * \sa SDL_SetWindowTitle - * \sa SDL_ShowWindow - * \sa SDL_ShowWindowSystemMenu */ typedef struct SDL_Window SDL_Window; @@ -141,6 +112,8 @@ typedef struct SDL_Window SDL_Window; * * \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 */ @@ -353,6 +326,21 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); /** * Get the properties associated with a display. * + * 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. + * * \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. @@ -364,6 +352,10 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); */ extern 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" + /** * Get the name of a display in UTF-8 encoding. * @@ -654,8 +646,9 @@ extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); * * \param window the window to affect * \param mode a pointer to the display mode to use, which can be NULL for - * desktop mode, or one of the fullscreen modes returned by - * SDL_GetFullscreenDisplayModes(). + * 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. * @@ -671,7 +664,8 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreenMode(SDL_Window *window, cons * Query the display mode to use when a window is visible at fullscreen. * * \param window the window to query - * \returns a pointer to the fullscreen mode to use or NULL for desktop mode + * \returns a pointer to the exclusive fullscreen mode to use or NULL for + * borderless fullscreen desktop mode * * \since This function is available since SDL 3.0.0. * @@ -763,7 +757,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, Uint32 flags); +extern 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. @@ -818,93 +812,104 @@ 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, Uint32 flags); +extern 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. * * These are the supported properties: * - * - `SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window - * should be always on top - * - `SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has - * no window decoration - * - `SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should + * - `SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN`: true if the window should + * be always on top + * - `SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has no + * window decoration + * - `SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN`: true if the + * window will be used with an externally managed graphics context. + * - `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should * accept keyboard input (defaults true) - * - `SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN`: true if the window - * should start in fullscreen mode at desktop resolution - * - `SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER`: the height of the window - * - `SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN`: true if the window should - * start hidden - * - `SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN`: true if the - * window uses a high pixel density buffer if possible - * - `SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN`: true if the window should + * - `SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN`: true if the window should + * start in fullscreen mode at desktop resolution + * - `SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER`: the height of the window + * - `SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN`: true if the window should start + * hidden + * - `SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN`: true if the window + * uses a high pixel density buffer if possible + * - `SDL_PROP_WINDOW_CREATE_MAXIMIZED_BOOLEAN`: true if the window should * start maximized - * - `SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN`: true if the window is a popup - * menu - * - `SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN`: true if the window will be - * used with Metal rendering - * - `SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN`: true if the window should + * - `SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN`: true if the window is a popup menu + * - `SDL_PROP_WINDOW_CREATE_METAL_BOOLEAN`: true if the window will be used + * with Metal rendering + * - `SDL_PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN`: true if the window should * start minimized - * - `SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN`: true if the window - * starts with grabbed mouse focus - * - `SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN`: true if the window will be - * used with OpenGL rendering - * - `SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER`: an SDL_Window that will be - * the parent of this window, required for windows with the "toolip" and - * "menu" properties - * - `SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN`: true if the window should - * be resizable - * - `SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING`: the title of the window, in - * UTF-8 encoding - * - `SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN`: true if the window show + * - `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 + * - `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 + * encoding + * - `SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN`: true if the window show * transparent in the areas with alpha of 0 - * - `SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN`: true if the window is a - * tooltip - * - `SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN`: true if the window is a - * utility window, not showing in the task bar and window list - * - `SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN`: true if the window will be - * used with Vulkan rendering - * - `SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER`: the width of the window - * - `SDL_PROPERTY_WINDOW_CREATE_X_NUMBER`: the x position of the window, or + * - `SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN`: true if the window is a tooltip + * - `SDL_PROP_WINDOW_CREATE_UTILITY_BOOLEAN`: true if the window is a utility + * window, not showing in the task bar and window list + * - `SDL_PROP_WINDOW_CREATE_VULKAN_BOOLEAN`: true if the window will be used + * with Vulkan rendering + * - `SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER`: the width of the window + * - `SDL_PROP_WINDOW_CREATE_X_NUMBER`: the x position of the window, or * `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is * relative to the parent for windows with the "parent" property set. - * - `SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER`: the y position of the window, or + * - `SDL_PROP_WINDOW_CREATE_Y_NUMBER`: the y position of the window, or * `SDL_WINDOWPOS_CENTERED`, defaults to `SDL_WINDOWPOS_UNDEFINED`. This is * relative to the parent for windows with the "parent" property set. * * These are additional supported properties on macOS: * - * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER`: the + * - `SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER`: the * `(__unsafe_unretained)` NSWindow associated with the window, if you want * to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER`: the - * `(__unsafe_unretained)` NSView associated with the window, defaults to - * `[window contentView]` + * - `SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER`: the `(__unsafe_unretained)` + * NSView associated with the window, defaults to `[window contentView]` * * These are additional supported properties on Wayland: * - * - `SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` - true - * if the application wants to use the Wayland surface for a custom role and + * - `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_PROPERTY_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN - true if - * the application wants an associated `wl_egl_window` object to be created, + * - `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_PROPERTY_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER` - the wl_surface + * - `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. * * These are additional supported properties on Windows: * - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER`: the HWND associated with - * the window, if you want to wrap an existing window. - * - `SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER`: optional, + * - `SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER`: the HWND associated with the + * window, if you want to wrap an existing window. + * - `SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER`: optional, * another window to share pixel format with, useful for OpenGL windows * * These are additional supported properties with X11: * - * - `SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER`: the X11 Window associated + * - `SDL_PROP_WINDOW_CREATE_X11_WINDOW_NUMBER`: the X11 Window associated * with the window, if you want to wrap an existing window. * * The window is implicitly shown if the "hidden" property is not set. @@ -918,42 +923,45 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateProperties * \sa SDL_CreateWindow * \sa SDL_DestroyWindow */ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); -#define SDL_PROPERTY_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always-on-top" -#define SDL_PROPERTY_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" -#define SDL_PROPERTY_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" -#define SDL_PROPERTY_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" -#define SDL_PROPERTY_WINDOW_CREATE_HEIGHT_NUMBER "height" -#define SDL_PROPERTY_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" -#define SDL_PROPERTY_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high-pixel-density" -#define SDL_PROPERTY_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" -#define SDL_PROPERTY_WINDOW_CREATE_MENU_BOOLEAN "menu" -#define SDL_PROPERTY_WINDOW_CREATE_METAL_BOOLEAN "metal" -#define SDL_PROPERTY_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" -#define SDL_PROPERTY_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse-grabbed" -#define SDL_PROPERTY_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" -#define SDL_PROPERTY_WINDOW_CREATE_PARENT_POINTER "parent" -#define SDL_PROPERTY_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" -#define SDL_PROPERTY_WINDOW_CREATE_TITLE_STRING "title" -#define SDL_PROPERTY_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" -#define SDL_PROPERTY_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" -#define SDL_PROPERTY_WINDOW_CREATE_UTILITY_BOOLEAN "utility" -#define SDL_PROPERTY_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" -#define SDL_PROPERTY_WINDOW_CREATE_WIDTH_NUMBER "width" -#define SDL_PROPERTY_WINDOW_CREATE_X_NUMBER "x" -#define SDL_PROPERTY_WINDOW_CREATE_Y_NUMBER "y" -#define SDL_PROPERTY_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" -#define SDL_PROPERTY_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" -#define SDL_PROPERTY_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "wayland.surface_role_custom" -#define SDL_PROPERTY_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN "wayland.create_egl_window" -#define SDL_PROPERTY_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER "wayland.wl_surface" -#define SDL_PROPERTY_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" -#define SDL_PROPERTY_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" -#define SDL_PROPERTY_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" +#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" /** * Get the numeric ID of a window. @@ -1005,58 +1013,59 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * The following read-only properties are provided by SDL: * + * - `SDL_PROP_WINDOW_SHAPE_POINTER`: the surface associated with a shaped + * window + * * On Android: * - * - `SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER`: the ANativeWindow - * associated with the window - * - `SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER`: the EGLSurface associated + * - `SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER`: the ANativeWindow associated * with the window + * - `SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER`: the EGLSurface associated with + * the window * * On iOS: * - * - `SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER`: the `(__unsafe_unretained)` + * - `SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER`: the `(__unsafe_unretained)` * UIWindow associated with the window - * - `SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER`: the NSInteger tag + * - `SDL_PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER`: the NSInteger tag * assocated with metal views on the window * * On KMS/DRM: * - * - `SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER`: the device index - * associated with the window (e.g. the X in /dev/dri/cardX) - * - `SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER`: the DRM FD associated with - * the window - * - `SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER`: the GBM device - * associated with the window + * - `SDL_PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER`: the device index associated + * with the window (e.g. the X in /dev/dri/cardX) + * - `SDL_PROP_WINDOW_KMSDRM_DRM_FD_NUMBER`: the DRM FD associated with the + * window + * - `SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER`: the GBM device associated + * with the window * * On macOS: * - * - `SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER`: the `(__unsafe_unretained)` + * - `SDL_PROP_WINDOW_COCOA_WINDOW_POINTER`: the `(__unsafe_unretained)` * NSWindow associated with the window - * - `SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag + * - `SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER`: the NSInteger tag * assocated with metal views on the window * * On Vivante: * - * - `SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER`: the EGLNativeDisplayType + * - `SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER`: the EGLNativeDisplayType * associated with the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER`: the EGLNativeWindowType + * - `SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER`: the EGLNativeWindowType * associated with the window - * - `SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER`: the EGLSurface associated - * with the window + * - `SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER`: the EGLSurface associated with + * the window * * On UWP: * - * - `SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER`: the IInspectable CoreWindow + * - `SDL_PROP_WINDOW_WINRT_WINDOW_POINTER`: the IInspectable CoreWindow * associated with the window * * On Windows: * - * - `SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER`: the HWND associated with the - * window - * - `SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER`: the HDC associated with the - * window - * - `SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER`: the HINSTANCE associated - * with the window + * - `SDL_PROP_WINDOW_WIN32_HWND_POINTER`: the HWND associated with the window + * - `SDL_PROP_WINDOW_WIN32_HDC_POINTER`: the HDC associated with the window + * - `SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER`: the HINSTANCE associated with + * the window * * On Wayland: * @@ -1064,29 +1073,31 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * show/hide calls. They will be null if the window is hidden and must be * queried each time it is shown. * - * - `SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER`: the wl_display associated + * - `SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER`: the wl_display associated with + * the window + * - `SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER`: the wl_surface associated with + * the window + * - `SDL_PROP_WINDOW_WAYLAND_EGL_WINDOW_POINTER`: the wl_egl_window + * associated with the window + * - `SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER`: the xdg_surface associated * with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER`: the wl_surface associated - * with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER`: the wl_egl_window + * - `SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER`: the xdg_toplevel role * associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER`: the xdg_surface + * - 'SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_STRING': the export + * handle associated with the window + * - `SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER`: the xdg_popup role * associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER`: the xdg_toplevel role - * associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER`: the xdg_popup role - * associated with the window - * - `SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER`: the xdg_positioner + * - `SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER`: the xdg_positioner * associated with the window, in popup mode * * On X11: * - * - `SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER`: the X11 Display associated - * with the window - * - `SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER`: the screen number associated - * with the window - * - `SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER`: the X11 Window associated with + * - `SDL_PROP_WINDOW_X11_DISPLAY_POINTER`: the X11 Display associated with * the window + * - `SDL_PROP_WINDOW_X11_SCREEN_NUMBER`: the screen number associated with + * the window + * - `SDL_PROP_WINDOW_X11_WINDOW_NUMBER`: the X11 Window associated with the + * window * * \param window the window to query * \returns a valid property ID on success or 0 on failure; call @@ -1099,32 +1110,34 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); */ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); -#define SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" -#define SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" -#define SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" -#define SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" -#define SDL_PROPERTY_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" -#define SDL_PROPERTY_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" -#define SDL_PROPERTY_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" -#define SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" -#define SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" -#define SDL_PROPERTY_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" -#define SDL_PROPERTY_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" -#define SDL_PROPERTY_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" -#define SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" -#define SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" -#define SDL_PROPERTY_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" -#define SDL_PROPERTY_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" -#define SDL_PROPERTY_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" -#define SDL_PROPERTY_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" -#define SDL_PROPERTY_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" -#define SDL_PROPERTY_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" -#define SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" -#define SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" -#define SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.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" /** * Get the window flags. @@ -1139,10 +1152,10 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *win * \sa SDL_MaximizeWindow * \sa SDL_MinimizeWindow * \sa SDL_SetWindowFullscreen - * \sa SDL_SetWindowGrab + * \sa SDL_SetWindowMouseGrab * \sa SDL_ShowWindow */ -extern DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window *window); +extern DECLSPEC SDL_WindowFlags SDLCALL SDL_GetWindowFlags(SDL_Window *window); /** * Set the title of a window. @@ -1608,8 +1621,9 @@ extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); /** * Request that the window's fullscreen state be changed. * - * By default a window in fullscreen state uses fullscreen desktop mode, but a - * specific display mode can be set using SDL_SetWindowFullscreenMode(). + * By default a window in fullscreen state uses borderless fullscreen desktop + * mode, but a specific exclusive display mode can be set using + * SDL_SetWindowFullscreenMode(). * * On some windowing systems this request is asynchronous and the new * fullscreen state may not have have been applied immediately upon the return @@ -1673,7 +1687,7 @@ extern DECLSPEC int SDLCALL SDL_SyncWindow(SDL_Window *window); * * \sa SDL_GetWindowSurface */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasWindowSurface(SDL_Window *window); +extern DECLSPEC SDL_bool SDLCALL SDL_WindowHasSurface(SDL_Window *window); /** * Get the SDL surface associated with the window. @@ -1696,7 +1710,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasWindowSurface(SDL_Window *window); * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroyWindowSurface - * \sa SDL_HasWindowSurface + * \sa SDL_WindowHasSurface * \sa SDL_UpdateWindowSurface * \sa SDL_UpdateWindowSurfaceRects */ @@ -1758,32 +1772,10 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window *window, con * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowSurface - * \sa SDL_HasWindowSurface + * \sa SDL_WindowHasSurface */ extern DECLSPEC int SDLCALL SDL_DestroyWindowSurface(SDL_Window *window); -/** - * Set a window's input grab mode. - * - * When input is grabbed, the mouse is confined to the window. This function - * will also grab the keyboard if `SDL_HINT_GRAB_KEYBOARD` is set. To grab the - * keyboard without also grabbing the mouse, use SDL_SetWindowKeyboardGrab(). - * - * 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 input grab mode should be set - * \param grabbed SDL_TRUE to grab input or SDL_FALSE to release input - * \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_GetGrabbedWindow - * \sa SDL_GetWindowGrab - */ -extern DECLSPEC int SDLCALL SDL_SetWindowGrab(SDL_Window *window, SDL_bool grabbed); - /** * Set a window's keyboard grab mode. * @@ -1812,7 +1804,6 @@ extern DECLSPEC int SDLCALL SDL_SetWindowGrab(SDL_Window *window, SDL_bool grabb * * \sa SDL_GetWindowKeyboardGrab * \sa SDL_SetWindowMouseGrab - * \sa SDL_SetWindowGrab */ extern DECLSPEC int SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window *window, SDL_bool grabbed); @@ -1830,22 +1821,9 @@ extern DECLSPEC int SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window *window, SDL_bo * * \sa SDL_GetWindowMouseGrab * \sa SDL_SetWindowKeyboardGrab - * \sa SDL_SetWindowGrab */ extern DECLSPEC int SDLCALL SDL_SetWindowMouseGrab(SDL_Window *window, SDL_bool grabbed); -/** - * Get a window's input grab mode. - * - * \param window the window to query - * \returns SDL_TRUE if input is grabbed, SDL_FALSE otherwise. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_SetWindowGrab - */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window *window); - /** * Get a window's keyboard grab mode. * @@ -1855,7 +1833,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window *window); * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowKeyboardGrab - * \sa SDL_GetWindowGrab */ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window *window); @@ -1868,7 +1845,6 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window *window); * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowKeyboardGrab - * \sa SDL_GetWindowGrab */ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window *window); @@ -1879,8 +1855,8 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window *window); * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetWindowGrab - * \sa SDL_SetWindowGrab + * \sa SDL_SetWindowMouseGrab + * \sa SDL_SetWindowKeyboardGrab */ extern DECLSPEC SDL_Window *SDLCALL SDL_GetGrabbedWindow(void); @@ -2097,6 +2073,30 @@ typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win, */ extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window *window, SDL_HitTest callback, void *callback_data); +/** + * Set the shape of a transparent window. + * + * This sets the alpha channel of a transparent window and any fully + * transparent areas are also transparent to mouse clicks. If you are using + * something besides the SDL render API, then you are responsible for setting + * the alpha channel of the window yourself. + * + * The shape is copied inside this function, so you can free it afterwards. If + * your shape surface changes, you should call SDL_SetWindowShape() again to + * update the window. + * + * The window must have been created with the SDL_WINDOW_TRANSPARENT flag. + * + * \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. + * + * \since This function is available since SDL 3.0.0. + */ +extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape); + /** * Request a window to demand attention from the user. * @@ -2112,6 +2112,9 @@ extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperati /** * Destroy a window. * + * If the window has an associated SDL_Renderer, it will be implicitly + * destroyed as well. + * * If `window` is NULL, this function will return immediately after setting * the SDL error message to "Invalid window". See SDL_GetError(). * diff --git a/include/SDL3/SDL_video_capture.h b/include/SDL3/SDL_video_capture.h deleted file mode 100644 index 80a21605..00000000 --- a/include/SDL3/SDL_video_capture.h +++ /dev/null @@ -1,377 +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_video_capture.h - * - * Video Capture for the SDL library. - */ - -#ifndef SDL_video_capture_h_ -#define SDL_video_capture_h_ - -#include "SDL3/SDL_video.h" - -#include -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * This is a unique ID for a video capture device for the time it is connected to the system, - * and is never reused for the lifetime of the application. If the device is - * disconnected and reconnected, it will get a new ID. - * - * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. - * - * \sa SDL_GetVideoCaptureDevices - */ -typedef Uint32 SDL_VideoCaptureDeviceID; - - -/** - * The structure used to identify an SDL video capture device - */ -struct SDL_VideoCaptureDevice; -typedef struct SDL_VideoCaptureDevice SDL_VideoCaptureDevice; - -#define SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE 1 - -/** - * SDL_VideoCaptureSpec structure - * - * Only those field can be 'desired' when configuring the device: - * - format - * - width - * - height - * - * \sa SDL_GetVideoCaptureFormat - * \sa SDL_GetVideoCaptureFrameSize - * - */ -typedef struct SDL_VideoCaptureSpec -{ - Uint32 format; /**< Frame SDL_PixelFormatEnum format */ - int width; /**< Frame width */ - int height; /**< Frame height */ -} SDL_VideoCaptureSpec; - -/** - * SDL Video Capture Status - * - * Change states but calling the function in this order: - * - * SDL_OpenVideoCapture() - * SDL_SetVideoCaptureSpec() -> Init - * SDL_StartVideoCapture() -> Playing - * SDL_StopVideoCapture() -> Stopped - * SDL_CloseVideoCapture() - * - */ -typedef enum -{ - SDL_VIDEO_CAPTURE_FAIL = -1, /**< Failed */ - SDL_VIDEO_CAPTURE_INIT = 0, /**< Init, spec hasn't been set */ - SDL_VIDEO_CAPTURE_STOPPED, /**< Stopped */ - SDL_VIDEO_CAPTURE_PLAYING /**< Playing */ -} SDL_VideoCaptureStatus; - -/** - * SDL Video Capture Status - */ -typedef struct SDL_VideoCaptureFrame -{ - Uint64 timestampNS; /**< Frame timestamp in nanoseconds when read from the driver */ - int num_planes; /**< Number of planes */ - Uint8 *data[3]; /**< Pointer to data of i-th plane */ - int pitch[3]; /**< Pitch of i-th plane */ - void *internal; /**< Private field */ -} SDL_VideoCaptureFrame; - - -/** - * Get a list of currently connected video capture devices. - * - * \param count a pointer filled in with the number of video capture devices - * \returns a 0 terminated array of video capture instance IDs which should be - * freed with SDL_free(), or NULL on error; call SDL_GetError() for - * more details. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_OpenVideoCapture - */ -extern DECLSPEC SDL_VideoCaptureDeviceID *SDLCALL SDL_GetVideoCaptureDevices(int *count); - -/** - * Open a Video Capture device - * - * \param instance_id the video capture device instance ID - * \returns device, or NULL on failure; call SDL_GetError() for more - * information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetVideoCaptureDeviceName - * \sa SDL_GetVideoCaptureDevices - * \sa SDL_OpenVideoCaptureWithSpec - */ -extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id); - -/** - * Set specification - * - * \param device opened video capture device - * \param desired desired video capture spec - * \param obtained obtained video capture spec - * \param allowed_changes allow changes or not - * \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_OpenVideoCapture - * \sa SDL_OpenVideoCaptureWithSpec - * \sa SDL_GetVideoCaptureSpec - */ -extern DECLSPEC int SDLCALL SDL_SetVideoCaptureSpec(SDL_VideoCaptureDevice *device, - const SDL_VideoCaptureSpec *desired, - SDL_VideoCaptureSpec *obtained, - int allowed_changes); - -/** - * Open a Video Capture device and set specification - * - * \param instance_id the video capture device instance ID - * \param desired desired video capture spec - * \param obtained obtained video capture spec - * \param allowed_changes allow changes or not - * \returns device, or NULL on failure; call SDL_GetError() for more - * information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_OpenVideoCapture - * \sa SDL_SetVideoCaptureSpec - * \sa SDL_GetVideoCaptureSpec - */ -extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCaptureWithSpec(SDL_VideoCaptureDeviceID instance_id, - const SDL_VideoCaptureSpec *desired, - SDL_VideoCaptureSpec *obtained, - int allowed_changes); - -/** - * Get device name - * - * \param instance_id the video capture device instance ID - * \returns device name, shouldn't be freed - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetVideoCaptureDevices - */ -extern DECLSPEC const char * SDLCALL SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id); - -/** - * Get the obtained video capture spec - * - * \param device opened video capture device - * \param spec The SDL_VideoCaptureSpec to be initialized by this function. - * \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_SetVideoCaptureSpec - * \sa SDL_OpenVideoCaptureWithSpec - */ -extern DECLSPEC int SDLCALL SDL_GetVideoCaptureSpec(SDL_VideoCaptureDevice *device, SDL_VideoCaptureSpec *spec); - - -/** - * Get frame format of video capture device. - * - * The value can be used to fill SDL_VideoCaptureSpec structure. - * - * \param device opened video capture device - * \param index format between 0 and num -1 - * \param format pointer output format (SDL_PixelFormatEnum) - * \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_GetNumVideoCaptureFormats - */ -extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFormat(SDL_VideoCaptureDevice *device, - int index, - Uint32 *format); - -/** - * Number of available formats for the device - * - * \param device opened video capture device - * \returns number of formats 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_GetVideoCaptureFormat - * \sa SDL_SetVideoCaptureSpec - */ -extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDevice *device); - -/** - * Get frame sizes of the device and the specified input format. - * - * The value can be used to fill SDL_VideoCaptureSpec structure. - * - * \param device opened video capture device - * \param format a format that can be used by the device (SDL_PixelFormatEnum) - * \param index framesize between 0 and num -1 - * \param width output width - * \param height output height - * \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_GetNumVideoCaptureFrameSizes - */ -extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFrameSize(SDL_VideoCaptureDevice *device, Uint32 format, int index, int *width, int *height); - -/** - * Number of different framesizes available for the device and pixel format. - * - * \param device opened video capture device - * \param format frame pixel format (SDL_PixelFormatEnum) - * \returns number of framesizes 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_GetVideoCaptureFrameSize - * \sa SDL_SetVideoCaptureSpec - */ -extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFrameSizes(SDL_VideoCaptureDevice *device, Uint32 format); - - -/** - * Get video capture status - * - * \param device opened video capture device - * \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_VideoCaptureStatus - */ -extern DECLSPEC SDL_VideoCaptureStatus SDLCALL SDL_GetVideoCaptureStatus(SDL_VideoCaptureDevice *device); - -/** - * Start video capture - * - * \param device opened video capture device - * \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_StopVideoCapture - */ -extern DECLSPEC int SDLCALL SDL_StartVideoCapture(SDL_VideoCaptureDevice *device); - -/** - * Acquire a frame. - * - * The frame is a memory pointer to the image data, whose size and format are - * given by the the obtained spec. - * - * Non blocking API. If there is a frame available, frame->num_planes is non - * 0. If frame->num_planes is 0 and returned code is 0, there is no frame at - * that time. - * - * After used, the frame should be released with SDL_ReleaseVideoCaptureFrame - * - * \param device opened video capture device - * \param frame pointer to get the frame - * \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_ReleaseVideoCaptureFrame - */ -extern DECLSPEC int SDLCALL SDL_AcquireVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame); - -/** - * Release a frame. - * - * Let the back-end re-use the internal buffer for video capture. - * - * All acquired frames should be released before closing the device. - * - * \param device opened video capture device - * \param frame frame pointer. - * \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_AcquireVideoCaptureFrame - */ -extern DECLSPEC int SDLCALL SDL_ReleaseVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame); - -/** - * Stop Video Capture - * - * \param device opened video capture device - * \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_StartVideoCapture - */ -extern DECLSPEC int SDLCALL SDL_StopVideoCapture(SDL_VideoCaptureDevice *device); - -/** - * Use this function to shut down video_capture processing and close the - * video_capture device. - * - * \param device opened video capture device - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_OpenVideoCaptureWithSpec - * \sa SDL_OpenVideoCapture - */ -extern DECLSPEC void SDLCALL SDL_CloseVideoCapture(SDL_VideoCaptureDevice *device); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include - -#endif /* SDL_video_capture_h_ */ diff --git a/include/SDL3/SDL_vulkan.h b/include/SDL3/SDL_vulkan.h index 98590786..64544c8b 100644 --- a/include/SDL3/SDL_vulkan.h +++ b/include/SDL3/SDL_vulkan.h @@ -141,7 +141,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * This should be called after either calling SDL_Vulkan_LoadLibrary() or * creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag. * - * On return, the variable pointed to by `pCount` will be set to the number of + * On return, the variable pointed to by `count` will be set to the number of * elements returned, suitable for using with * VkInstanceCreateInfo::enabledExtensionCount, and the returned array can be * used with VkInstanceCreateInfo::ppEnabledExtensionNames, for calling @@ -149,15 +149,14 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * * You should not free the returned array; it is owned by SDL. * - * \param pCount A pointer to Uint32 that will be filled with the number of - * extensions returned. + * \param count a pointer filled in with the number of extensions returned. * \returns An array of extension name strings on success, NULL on error. * * \since This function is available since SDL 3.0.0. * * \sa SDL_Vulkan_CreateSurface */ -extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint32 *pCount); +extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint32 *count); /** * Create a Vulkan rendering surface for a window. diff --git a/include/build_config/SDL_build_config.h b/include/build_config/SDL_build_config.h index 6fa6d899..beaceb58 100644 --- a/include/build_config/SDL_build_config.h +++ b/include/build_config/SDL_build_config.h @@ -31,23 +31,23 @@ */ /* Add any platform that doesn't build using the configure system. */ -#if defined(__WIN32__) +#if defined(SDL_PLATFORM_WIN32) #include "SDL_build_config_windows.h" -#elif defined(__WINRT__) +#elif defined(SDL_PLATFORM_WINRT) #include "SDL_build_config_winrt.h" -#elif defined(__WINGDK__) +#elif defined(SDL_PLATFORM_WINGDK) #include "SDL_build_config_wingdk.h" -#elif defined(__XBOXONE__) || defined(__XBOXSERIES__) +#elif defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) #include "SDL_build_config_xbox.h" -#elif defined(__MACOS__) +#elif defined(SDL_PLATFORM_MACOS) #include "SDL_build_config_macos.h" -#elif defined(__IOS__) +#elif defined(SDL_PLATFORM_IOS) #include "SDL_build_config_ios.h" -#elif defined(__ANDROID__) +#elif defined(SDL_PLATFORM_ANDROID) #include "SDL_build_config_android.h" -#elif defined(__EMSCRIPTEN__) +#elif defined(SDL_PLATFORM_EMSCRIPTEN) #include "SDL_build_config_emscripten.h" -#elif defined(__NGAGE__) +#elif defined(SDL_PLATFORM_NGAGE) #include "SDL_build_config_ngage.h" #else /* This is a minimal configuration just to get SDL running on new platforms. */ diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 9deb5555..f8eb06ae 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -76,14 +76,12 @@ #cmakedefine HAVE_CALLOC 1 #cmakedefine HAVE_REALLOC 1 #cmakedefine HAVE_FREE 1 -#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */ +#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_QSORT 1 -#cmakedefine HAVE_BSEARCH 1 #cmakedefine HAVE_ABS 1 #cmakedefine HAVE_BCOPY 1 #cmakedefine HAVE_MEMSET 1 @@ -188,10 +186,16 @@ #cmakedefine HAVE_FOPEN64 1 #cmakedefine HAVE_FSEEKO 1 #cmakedefine HAVE_FSEEKO64 1 +#cmakedefine HAVE_MEMFD_CREATE 1 +#cmakedefine HAVE_POSIX_FALLOCATE 1 #cmakedefine HAVE_SIGACTION 1 #cmakedefine HAVE_SA_SIGACTION 1 +#cmakedefine HAVE_ST_MTIM 1 #cmakedefine HAVE_SETJMP 1 #cmakedefine HAVE_NANOSLEEP 1 +#cmakedefine HAVE_GMTIME_R 1 +#cmakedefine HAVE_LOCALTIME_R 1 +#cmakedefine HAVE_NL_LANGINFO 1 #cmakedefine HAVE_SYSCONF 1 #cmakedefine HAVE_SYSCTLBYNAME 1 #cmakedefine HAVE_CLOCK_GETTIME 1 @@ -246,33 +250,22 @@ #cmakedefine USE_POSIX_SPAWN @USE_POSIX_SPAWN@ -#cmakedefine HAVE_COREMEDIA - /* SDL internal assertion support */ #if @SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED@ #cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@ #endif -#cmakedefine SDL_VIDEO_CAPTURE - -/* Allow disabling of core subsystems */ -#cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@ +/* Allow disabling of major subsystems */ #cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@ -#cmakedefine SDL_CPUINFO_DISABLED @SDL_CPUINFO_DISABLED@ -#cmakedefine SDL_EVENTS_DISABLED @SDL_EVENTS_DISABLED@ -#cmakedefine SDL_FILE_DISABLED @SDL_FILE_DISABLED@ #cmakedefine SDL_JOYSTICK_DISABLED @SDL_JOYSTICK_DISABLED@ #cmakedefine SDL_HAPTIC_DISABLED @SDL_HAPTIC_DISABLED@ #cmakedefine SDL_HIDAPI_DISABLED @SDL_HIDAPI_DISABLED@ #cmakedefine SDL_SENSOR_DISABLED @SDL_SENSOR_DISABLED@ -#cmakedefine SDL_LOADSO_DISABLED @SDL_LOADSO_DISABLED@ #cmakedefine SDL_RENDER_DISABLED @SDL_RENDER_DISABLED@ #cmakedefine SDL_THREADS_DISABLED @SDL_THREADS_DISABLED@ #cmakedefine SDL_VIDEO_DISABLED @SDL_VIDEO_DISABLED@ #cmakedefine SDL_POWER_DISABLED @SDL_POWER_DISABLED@ -#cmakedefine SDL_FILESYSTEM_DISABLED @SDL_FILESYSTEM_DISABLED@ -#cmakedefine SDL_LOCALE_DISABLED @SDL_LOCALE_DISABLED@ -#cmakedefine SDL_MISC_DISABLED @SDL_MISC_DISABLED@ +#cmakedefine SDL_CAMERA_DISABLED @SDL_CAMERA_DISABLED@ /* Enable various audio drivers */ #cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@ @@ -331,7 +324,6 @@ #cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@ #cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@ #cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@ -#cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@ #cmakedefine SDL_HAPTIC_ANDROID @SDL_HAPTIC_ANDROID@ #cmakedefine SDL_LIBUSB_DYNAMIC @SDL_LIBUSB_DYNAMIC@ #cmakedefine SDL_UDEV_DYNAMIC @SDL_UDEV_DYNAMIC@ @@ -362,6 +354,14 @@ #cmakedefine SDL_THREAD_PS2 @SDL_THREAD_PS2@ #cmakedefine SDL_THREAD_N3DS @SDL_THREAD_N3DS@ +/* Enable various RTC systems */ +#cmakedefine SDL_TIME_UNIX @SDL_TIME_UNIX@ +#cmakedefine SDL_TIME_WINDOWS @SDL_TIME_WINDOWS@ +#cmakedefine SDL_TIME_VITA @SDL_TIME_VITA@ +#cmakedefine SDL_TIME_PSP @SDL_TIME_PSP@ +#cmakedefine SDL_TIME_PS2 @SDL_TIME_PS2@ +#cmakedefine SDL_TIME_N3DS @SDL_TIME_N3DS@ + /* Enable various timer systems */ #cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@ #cmakedefine SDL_TIMER_DUMMY @SDL_TIMER_DUMMY@ @@ -424,6 +424,7 @@ #cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@ #cmakedefine SDL_VIDEO_RENDER_D3D12 @SDL_VIDEO_RENDER_D3D12@ #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@ #cmakedefine SDL_VIDEO_RENDER_OGL_ES2 @SDL_VIDEO_RENDER_OGL_ES2@ #cmakedefine SDL_VIDEO_RENDER_PS2 @SDL_VIDEO_RENDER_PS2@ @@ -476,6 +477,24 @@ #cmakedefine SDL_FILESYSTEM_PS2 @SDL_FILESYSTEM_PS2@ #cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@ +/* Enable system storage support */ +#cmakedefine SDL_STORAGE_GENERIC @SDL_STORAGE_GENERIC@ +#cmakedefine SDL_STORAGE_STEAM @SDL_STORAGE_STEAM@ + +/* Enable system FSops support */ +#cmakedefine SDL_FSOPS_POSIX @SDL_FSOPS_POSIX@ +#cmakedefine SDL_FSOPS_WINDOWS @SDL_FSOPS_WINDOWS@ +#cmakedefine SDL_FSOPS_DUMMY @SDL_FSOPS_DUMMY@ + +/* Enable camera subsystem */ +#cmakedefine SDL_CAMERA_DRIVER_DUMMY @SDL_CAMERA_DRIVER_DUMMY@ +/* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK @SDL_CAMERA_DRIVER_DISK@ */ +#cmakedefine SDL_CAMERA_DRIVER_V4L2 @SDL_CAMERA_DRIVER_V4L2@ +#cmakedefine SDL_CAMERA_DRIVER_COREMEDIA @SDL_CAMERA_DRIVER_COREMEDIA@ +#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@ + /* Enable misc subsystem */ #cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@ @@ -501,7 +520,10 @@ #cmakedefine SDL_VIDEO_VITA_PVR @SDL_VIDEO_VITA_PVR@ #cmakedefine SDL_VIDEO_VITA_PVR_OGL @SDL_VIDEO_VITA_PVR_OGL@ -#cmakedefine SDL_HAVE_LIBDECOR_VER_0_2_0 @SDL_HAVE_LIBDECOR_VER_0_2_0@ +/* Libdecor version info */ +#define SDL_LIBDECOR_VERSION_MAJOR @SDL_LIBDECOR_VERSION_MAJOR@ +#define SDL_LIBDECOR_VERSION_MINOR @SDL_LIBDECOR_VERSION_MINOR@ +#define SDL_LIBDECOR_VERSION_PATCH @SDL_LIBDECOR_VERSION_PATCH@ #if !defined(HAVE_STDINT_H) && !defined(_STDINT_H_) /* Most everything except Visual Studio 2008 and earlier has stdint.h now */ diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h index ad75cc1f..49044b0b 100644 --- a/include/build_config/SDL_build_config_android.h +++ b/include/build_config/SDL_build_config_android.h @@ -52,6 +52,7 @@ #define HAVE_WCHAR_H 1 /* C library functions */ +#define HAVE_LIBC 1 #define HAVE_DLOPEN 1 #define HAVE_MALLOC 1 #define HAVE_CALLOC 1 @@ -62,8 +63,6 @@ #define HAVE_PUTENV 1 #define HAVE_SETENV 1 #define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_BCOPY 1 #define HAVE_MEMSET 1 @@ -138,6 +137,8 @@ #define HAVE_SIGACTION 1 #define HAVE_SETJMP 1 #define HAVE_NANOSLEEP 1 +#define HAVE_GMTIME_R 1 +#define HAVE_LOCALTIME_R 1 #define HAVE_SYSCONF 1 #define HAVE_CLOCK_GETTIME 1 @@ -163,6 +164,9 @@ #define SDL_THREAD_PTHREAD 1 #define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 +/* Enable RTC system */ +#define SDL_TIME_UNIX 1 + /* Enable various timer systems */ #define SDL_TIMER_UNIX 1 @@ -188,5 +192,16 @@ /* Enable the filesystem driver */ #define SDL_FILESYSTEM_ANDROID 1 +#define SDL_FSOPS_POSIX 1 + +/* Enable the camera driver */ +#define SDL_CAMERA_DRIVER_ANDROID 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 + +/* Enable nl_langinfo and high-res file times on version 26 and higher. */ +#if __ANDROID_API__ >= 26 +#define HAVE_NL_LANGINFO 1 +#define HAVE_ST_MTIM 1 +#endif #endif /* SDL_build_config_android_h_ */ diff --git a/include/build_config/SDL_build_config_emscripten.h b/include/build_config/SDL_build_config_emscripten.h index fcaa277c..bf6e919c 100644 --- a/include/build_config/SDL_build_config_emscripten.h +++ b/include/build_config/SDL_build_config_emscripten.h @@ -55,6 +55,7 @@ #define HAVE_WCHAR_H 1 /* C library functions */ +#define HAVE_LIBC 1 #define HAVE_DLOPEN 1 #define HAVE_MALLOC 1 #define HAVE_CALLOC 1 @@ -64,8 +65,6 @@ #define HAVE_SETENV 1 #define HAVE_PUTENV 1 #define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_BCOPY 1 #define HAVE_MEMSET 1 @@ -156,7 +155,6 @@ /* SDL internal assertion support */ /* #undef SDL_DEFAULT_ASSERT_LEVEL */ -#define SDL_CPUINFO_DISABLED 1 #define SDL_HAPTIC_DISABLED 1 #define SDL_HIDAPI_DISABLED 1 #ifndef __EMSCRIPTEN_PTHREADS__ @@ -208,5 +206,9 @@ /* Enable system filesystem support */ #define SDL_FILESYSTEM_EMSCRIPTEN 1 +#define SDL_FSOPS_POSIX 1 + +/* Enable the camera driver */ +#define SDL_CAMERA_DRIVER_EMSCRIPTEN 1 #endif /* SDL_build_config_emscripten_h */ diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index a6691465..44c185cc 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -44,6 +44,7 @@ #define HAVE_WCHAR_H 1 /* C library functions */ +#define HAVE_LIBC 1 #define HAVE_DLOPEN 1 #define HAVE_MALLOC 1 #define HAVE_CALLOC 1 @@ -54,8 +55,6 @@ #define HAVE_PUTENV 1 #define HAVE_SETENV 1 #define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_BCOPY 1 #define HAVE_MEMSET 1 @@ -130,6 +129,9 @@ #define HAVE_SIGACTION 1 #define HAVE_SETJMP 1 #define HAVE_NANOSLEEP 1 +#define HAVE_GMTIME_R 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_NL_LANGINFO 1 #define HAVE_SYSCONF 1 #define HAVE_SYSCTLBYNAME 1 #define HAVE_O_CLOEXEC 1 @@ -148,7 +150,7 @@ #define SDL_JOYSTICK_MFI 1 #define SDL_JOYSTICK_VIRTUAL 1 -#ifdef __TVOS__ +#ifdef SDL_PLATFORM_TVOS #define SDL_SENSOR_DUMMY 1 #else /* Enable the CoreMotion sensor driver */ @@ -162,6 +164,9 @@ #define SDL_THREAD_PTHREAD 1 #define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 +/* Enable various RTC system */ +#define SDL_TIME_UNIX 1 + /* Enable various timer systems */ #define SDL_TIMER_UNIX 1 @@ -170,7 +175,7 @@ #define SDL_VIDEO_DRIVER_DUMMY 1 /* Enable OpenGL ES */ -#if !TARGET_OS_MACCATALYST +#if !TARGET_OS_MACCATALYST && !TARGET_OS_VISION #define SDL_VIDEO_OPENGL_ES2 1 #define SDL_VIDEO_OPENGL_ES 1 #define SDL_VIDEO_RENDER_OGL_ES2 1 @@ -197,8 +202,6 @@ #define SDL_VIDEO_METAL 1 #endif -#define HAVE_COREMEDIA 1 - /* Enable system power support */ #define SDL_POWER_UIKIT 1 @@ -210,5 +213,13 @@ /* enable filesystem support */ #define SDL_FILESYSTEM_COCOA 1 +#define SDL_FSOPS_POSIX 1 + +/* enable camera support */ +#ifndef SDL_PLATFORM_TVOS +#define SDL_CAMERA_DRIVER_COREMEDIA 1 +#endif + +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_ios_h_ */ diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h index 66bdb5ea..8235af7f 100644 --- a/include/build_config/SDL_build_config_macos.h +++ b/include/build_config/SDL_build_config_macos.h @@ -49,6 +49,7 @@ #define HAVE_WCHAR_H 1 /* C library functions */ +#define HAVE_LIBC 1 #define HAVE_DLOPEN 1 #define HAVE_MALLOC 1 #define HAVE_CALLOC 1 @@ -58,8 +59,6 @@ #define HAVE_SETENV 1 #define HAVE_PUTENV 1 #define HAVE_UNSETENV 1 -#define HAVE_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_BCOPY 1 #define HAVE_MEMSET 1 @@ -134,6 +133,9 @@ #define HAVE_SIGACTION 1 #define HAVE_SETJMP 1 #define HAVE_NANOSLEEP 1 +#define HAVE_GMTIME_R 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_NL_LANGINFO 1 #define HAVE_SYSCONF 1 #define HAVE_SYSCTLBYNAME 1 @@ -175,6 +177,9 @@ #define SDL_THREAD_PTHREAD 1 #define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1 +/* Enable various RTC system */ +#define SDL_TIME_UNIX 1 + /* Enable various timer systems */ #define SDL_TIMER_UNIX 1 @@ -260,13 +265,16 @@ #endif #endif -#define HAVE_COREMEDIA 1 - /* Enable system power support */ #define SDL_POWER_MACOSX 1 /* enable filesystem support */ #define SDL_FILESYSTEM_COCOA 1 +#define SDL_FSOPS_POSIX 1 + +/* enable camera support */ +#define SDL_CAMERA_DRIVER_COREMEDIA 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 /* Enable assembly routines */ #ifdef __ppc__ diff --git a/include/build_config/SDL_build_config_minimal.h b/include/build_config/SDL_build_config_minimal.h index 276881a7..f949f94f 100644 --- a/include/build_config/SDL_build_config_minimal.h +++ b/include/build_config/SDL_build_config_minimal.h @@ -77,8 +77,8 @@ typedef unsigned int uintptr_t; /* Enable the stub sensor driver (src/sensor/dummy/\*.c) */ #define SDL_SENSOR_DISABLED 1 -/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */ -#define SDL_LOADSO_DISABLED 1 +/* Enable the dummy shared object loader (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DUMMY 1 /* Enable the stub thread support (src/thread/generic/\*.c) */ #define SDL_THREADS_DISABLED 1 @@ -88,5 +88,9 @@ typedef unsigned int uintptr_t; /* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */ #define SDL_FILESYSTEM_DUMMY 1 +#define SDL_FSOPS_DUMMY 1 + +/* Enable the camera driver (src/camera/dummy/\*.c) */ +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_minimal_h_ */ diff --git a/include/build_config/SDL_build_config_ngage.h b/include/build_config/SDL_build_config_ngage.h index 1942ef46..59694370 100644 --- a/include/build_config/SDL_build_config_ngage.h +++ b/include/build_config/SDL_build_config_ngage.h @@ -80,10 +80,14 @@ typedef unsigned long uintptr_t; /* Enable the stub sensor driver (src/sensor/dummy/\*.c) */ #define SDL_SENSOR_DISABLED 1 -/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */ -#define SDL_LOADSO_DISABLED 1 +/* Enable the dummy shared object loader (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DUMMY 1 /* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */ #define SDL_FILESYSTEM_DUMMY 1 +#define SDL_FSOPS_DUMMY 1 + +/* Enable the camera driver (src/camera/dummy/\*.c) */ +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_ngage_h_ */ diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h index d83857d6..9f55afff 100644 --- a/include/build_config/SDL_build_config_windows.h +++ b/include/build_config/SDL_build_config_windows.h @@ -111,8 +111,12 @@ typedef unsigned int uintptr_t; # define SDL_DISABLE_AVX 1 #endif -/* This is disabled by default to avoid C runtime dependencies and manifest requirements */ -#ifdef HAVE_LIBC +/* This can be disabled to avoid C runtime dependencies and manifest requirements */ +#ifndef HAVE_LIBC +#define HAVE_LIBC 1 +#endif + +#if HAVE_LIBC /* Useful headers */ #define HAVE_CTYPE_H 1 #define HAVE_FLOAT_H 1 @@ -131,8 +135,6 @@ typedef unsigned int uintptr_t; #define HAVE_CALLOC 1 #define HAVE_REALLOC 1 #define HAVE_FREE 1 -#define HAVE_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_MEMSET 1 #define HAVE_MEMCPY 1 @@ -162,6 +164,9 @@ typedef unsigned int uintptr_t; #define HAVE__WCSICMP 1 #define HAVE__WCSNICMP 1 #define HAVE__WCSDUP 1 +#define HAVE_SSCANF 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 #define HAVE_ACOS 1 #define HAVE_ASIN 1 #define HAVE_ATAN 1 @@ -231,8 +236,9 @@ typedef unsigned int uintptr_t; /* Enable various input drivers */ #define SDL_JOYSTICK_DINPUT 1 +/*#define SDL_JOYSTICK_GAMEINPUT 1*/ #define SDL_JOYSTICK_HIDAPI 1 -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT #define SDL_JOYSTICK_RAWINPUT 1 #endif #define SDL_JOYSTICK_VIRTUAL 1 @@ -241,7 +247,6 @@ typedef unsigned int uintptr_t; #endif #define SDL_JOYSTICK_XINPUT 1 #define SDL_HAPTIC_DINPUT 1 -#define SDL_HAPTIC_XINPUT 1 /* Enable the sensor driver */ #ifdef HAVE_SENSORSAPI_H @@ -258,6 +263,9 @@ typedef unsigned int uintptr_t; #define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1 #define SDL_THREAD_WINDOWS 1 +/* Enable RTC system */ +#define SDL_TIME_WINDOWS 1 + /* Enable various timer systems */ #define SDL_TIMER_WINDOWS 1 @@ -298,10 +306,19 @@ typedef unsigned int uintptr_t; /* Enable Vulkan support */ #define SDL_VIDEO_VULKAN 1 +#ifndef SDL_VIDEO_RENDER_VULKAN +#define SDL_VIDEO_RENDER_VULKAN 1 +#endif + /* Enable system power support */ #define SDL_POWER_WINDOWS 1 /* Enable filesystem support */ #define SDL_FILESYSTEM_WINDOWS 1 +#define SDL_FSOPS_WINDOWS 1 + +/* Enable the camera driver */ +#define SDL_CAMERA_DRIVER_MEDIAFOUNDATION 1 +#define SDL_CAMERA_DRIVER_DUMMY 1 #endif /* SDL_build_config_windows_h_ */ diff --git a/include/build_config/SDL_build_config_wingdk.h b/include/build_config/SDL_build_config_wingdk.h index 0999b87f..3fdaf4c7 100644 --- a/include/build_config/SDL_build_config_wingdk.h +++ b/include/build_config/SDL_build_config_wingdk.h @@ -56,8 +56,6 @@ # define SDL_DISABLE_AVX 1 #endif -/* This is disabled by default to avoid C runtime dependencies and manifest requirements */ -#ifdef HAVE_LIBC /* Useful headers */ #define HAVE_CTYPE_H 1 #define HAVE_FLOAT_H 1 @@ -73,12 +71,11 @@ #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_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_MEMSET 1 #define HAVE_MEMCPY 1 @@ -156,11 +153,6 @@ #define HAVE_TRUNCF 1 #define HAVE__FSEEKI64 1 #endif /* _MSC_VER */ -#else -#define HAVE_STDARG_H 1 -#define HAVE_STDDEF_H 1 -#define HAVE_STDINT_H 1 -#endif /* Enable various audio drivers */ #if defined(HAVE_MMDEVICEAPI_H) && defined(HAVE_AUDIOCLIENT_H) @@ -181,7 +173,16 @@ #endif #define SDL_JOYSTICK_XINPUT 1 #define SDL_HAPTIC_DINPUT 1 -#define SDL_HAPTIC_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 */ /* Enable the sensor driver */ #ifdef HAVE_SENSORSAPI_H @@ -198,6 +199,9 @@ #define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1 #define SDL_THREAD_WINDOWS 1 +/* Enable various time systems */ +#define SDL_TIME_WINDOWS 1 + /* Enable various timer systems */ #define SDL_TIMER_WINDOWS 1 @@ -243,6 +247,10 @@ /* 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 /* Use the (inferior) GDK text input method for GDK platforms */ /*#define SDL_GDK_TEXTINPUT 1*/ diff --git a/include/build_config/SDL_build_config_winrt.h b/include/build_config/SDL_build_config_winrt.h index 3b252cec..c9baf5ae 100644 --- a/include/build_config/SDL_build_config_winrt.h +++ b/include/build_config/SDL_build_config_winrt.h @@ -71,12 +71,11 @@ #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_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_MEMSET 1 #define HAVE_MEMCPY 1 @@ -168,7 +167,6 @@ #define SDL_HAPTIC_DISABLED 1 #else #define SDL_JOYSTICK_XINPUT 1 -#define SDL_HAPTIC_XINPUT 1 #endif /* WIN10 */ #endif @@ -191,6 +189,9 @@ #define SDL_THREAD_STDCPP 1 #endif +/* Enable RTC system */ +#define SDL_TIME_WINDOWS 1 + /* Enable various timer systems */ #define SDL_TIMER_WINDOWS 1 @@ -215,4 +216,11 @@ /* 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/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h index 1a31c0d7..13f1ceec 100644 --- a/include/build_config/SDL_build_config_xbox.h +++ b/include/build_config/SDL_build_config_xbox.h @@ -56,8 +56,6 @@ # define SDL_DISABLE_AVX 1 #endif -/* This is disabled by default to avoid C runtime dependencies and manifest requirements */ -#ifdef HAVE_LIBC /* Useful headers */ #define HAVE_CTYPE_H 1 #define HAVE_FLOAT_H 1 @@ -73,12 +71,11 @@ #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_QSORT 1 -#define HAVE_BSEARCH 1 #define HAVE_ABS 1 #define HAVE_MEMSET 1 #define HAVE_MEMCPY 1 @@ -156,11 +153,6 @@ #define HAVE_TRUNCF 1 #define HAVE__FSEEKI64 1 #endif /* _MSC_VER */ -#else -#define HAVE_STDARG_H 1 -#define HAVE_STDDEF_H 1 -#define HAVE_STDINT_H 1 -#endif /* Enable various audio drivers */ #if defined(HAVE_MMDEVICEAPI_H) && defined(HAVE_AUDIOCLIENT_H) @@ -179,9 +171,18 @@ #ifdef HAVE_WINDOWS_GAMING_INPUT_H #define SDL_JOYSTICK_WGI 1 #endif -#define SDL_JOYSTICK_XINPUT 1 +/* 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*/ -#define SDL_HAPTIC_XINPUT 1 /* Enable the sensor driver */ #ifdef HAVE_SENSORSAPI_H @@ -198,6 +199,9 @@ #define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1 #define SDL_THREAD_WINDOWS 1 +/* Enable various time systems */ +#define SDL_TIME_WINDOWS 1 + /* Enable various timer systems */ #define SDL_TIMER_WINDOWS 1 @@ -227,10 +231,15 @@ /* Enable filesystem support */ /* #define SDL_FILESYSTEM_WINDOWS 1*/ #define SDL_FILESYSTEM_XBOX 1 +#define SDL_FSOPS_WINDOWS 1 + /* Disable IME as not supported yet (TODO: Xbox IME?) */ #define SDL_DISABLE_WINDOWS_IME 1 /* Use the (inferior) GDK text input method for GDK platforms */ #define SDL_GDK_TEXTINPUT 1 +/* Enable the camera driver (src/camera/dummy/\*.c) */ +#define SDL_CAMERA_DRIVER_DUMMY 1 + #endif /* SDL_build_config_wingdk_h_ */ diff --git a/mingw/pkg-support/INSTALL.txt b/mingw/pkg-support/INSTALL.txt new file mode 100644 index 00000000..607dafd0 --- /dev/null +++ b/mingw/pkg-support/INSTALL.txt @@ -0,0 +1,18 @@ + +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/mingw/pkg-support/Makefile b/mingw/pkg-support/Makefile new file mode 100644 index 00000000..19732d7d --- /dev/null +++ b/mingw/pkg-support/Makefile @@ -0,0 +1,26 @@ +# +# 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/src/SDL.c b/src/SDL.c index ae2ab3bb..f3faf9d5 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -21,33 +21,39 @@ #include "SDL_internal.h" #include "SDL3/SDL_revision.h" -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #include "core/windows/SDL_windows.h" -#elif !defined(__WINRT__) +#elif !defined(SDL_PLATFORM_WINRT) #include /* _exit(), etc. */ #endif /* this checks for HAVE_DBUS_DBUS_H internally. */ #include "core/linux/SDL_dbus.h" -#ifdef __EMSCRIPTEN__ +#ifdef SDL_PLATFORM_EMSCRIPTEN #include #endif /* 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 "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 "sensor/SDL_sensor_c.h" +#include "camera/SDL_camera_c.h" + +#define SDL_INIT_EVERYTHING ~0U /* Initialization/Cleanup routines */ +#include "time/SDL_time_c.h" #include "timer/SDL_timer_c.h" #ifdef SDL_VIDEO_DRIVER_WINDOWS extern int SDL_HelperWindowCreate(void); @@ -64,11 +70,11 @@ SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MICRO_VERSION, #endif SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_min, SDL_MAJOR_VERSION >= 0); -/* Limited only by the need to fit in SDL_version */ +/* 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_MINOR_VERSION_min, SDL_MINOR_VERSION >= 0); -/* Limited only by the need to fit in SDL_version */ +/* 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); @@ -81,7 +87,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(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) /* "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 */ @@ -89,11 +95,11 @@ SDL_NORETURN void SDL_ExitProcess(int exitcode) /* MingW doesn't have TerminateProcess marked as noreturn, so add an ExitProcess here that will never be reached but make MingW happy. */ ExitProcess(exitcode); -#elif defined(__EMSCRIPTEN__) +#elif defined(SDL_PLATFORM_EMSCRIPTEN) emscripten_cancel_main_loop(); /* this should "kill" the app. */ emscripten_force_exit(exitcode); /* this should "kill" the app. */ exit(exitcode); -#elif defined(__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() */ _Exit(exitcode); @@ -126,7 +132,11 @@ static void SDL_DecrementSubsystemRefCount(Uint32 subsystem) { const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] > 0)) { - --SDL_SubsystemRefCount[subsystem_index]; + if (SDL_bInMainQuit) { + SDL_SubsystemRefCount[subsystem_index] = 0; + } else { + --SDL_SubsystemRefCount[subsystem_index]; + } } } @@ -200,11 +210,11 @@ int SDL_InitSubSystem(Uint32 flags) } #endif + SDL_InitTime(); SDL_InitTicks(); /* Initialize the event subsystem */ if (flags & SDL_INIT_EVENTS) { -#ifndef SDL_EVENTS_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) { SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); if (SDL_InitEvents() < 0) { @@ -215,10 +225,6 @@ int SDL_InitSubSystem(Uint32 flags) SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); } flags_initialized |= SDL_INIT_EVENTS; -#else - SDL_SetError("SDL not built with events support"); - goto quit_and_error; -#endif } /* Initialize the timer subsystem */ @@ -368,6 +374,30 @@ int SDL_InitSubSystem(Uint32 flags) #endif } + /* Initialize the camera subsystem */ + if (flags & SDL_INIT_CAMERA) { +#ifndef SDL_CAMERA_DISABLED + if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) { + /* camera implies events */ + if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { + goto quit_and_error; + } + + SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); + if (SDL_CameraInit(NULL) < 0) { + SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); + goto quit_and_error; + } + } else { + SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); + } + flags_initialized |= SDL_INIT_CAMERA; +#else + SDL_SetError("SDL not built with camera support"); + goto quit_and_error; +#endif + } + (void)flags_initialized; /* make static analysis happy, since this only gets used in error cases. */ return 0; @@ -385,6 +415,18 @@ int SDL_Init(Uint32 flags) void SDL_QuitSubSystem(Uint32 flags) { /* 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 */ + SDL_QuitSubSystem(SDL_INIT_EVENTS); + } + SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); + } +#endif + #ifndef SDL_SENSOR_DISABLED if (flags & SDL_INIT_SENSOR) { if (SDL_ShouldQuitSubsystem(SDL_INIT_SENSOR)) { @@ -452,14 +494,12 @@ void SDL_QuitSubSystem(Uint32 flags) SDL_DecrementSubsystemRefCount(SDL_INIT_TIMER); } -#ifndef SDL_EVENTS_DISABLED if (flags & SDL_INIT_EVENTS) { if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) { SDL_QuitEvents(); } SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS); } -#endif } Uint32 SDL_WasInit(Uint32 flags) @@ -503,6 +543,7 @@ void SDL_Quit(void) SDL_QuitSubSystem(SDL_INIT_EVERYTHING); SDL_QuitTicks(); + SDL_QuitTime(); #ifdef SDL_USE_LIBDBUS SDL_DBus_Quit(); @@ -511,6 +552,8 @@ void SDL_Quit(void) SDL_ClearHints(); SDL_AssertionsQuit(); + SDL_QuitCPUInfo(); + SDL_QuitProperties(); SDL_QuitLog(); @@ -539,7 +582,7 @@ Uint32 SDL_GetNextObjectID(void) } /* Get the library version number */ -int SDL_GetVersion(SDL_version *ver) +int SDL_GetVersion(SDL_Version *ver) { static SDL_bool check_hint = SDL_TRUE; static SDL_bool legacy_version = SDL_FALSE; @@ -572,69 +615,65 @@ const char *SDL_GetRevision(void) /* Get the name of the platform */ const char *SDL_GetPlatform(void) { -#ifdef __AIX__ +#if defined(SDL_PLATFORM_AIX) return "AIX"; -#elif defined(__ANDROID__) +#elif defined(SDL_PLATFORM_ANDROID) return "Android"; -#elif defined(__BSDI__) +#elif defined(SDL_PLATFORM_BSDI) return "BSDI"; -#elif defined(__DREAMCAST__) - return "Dreamcast"; -#elif defined(__EMSCRIPTEN__) +#elif defined(SDL_PLATFORM_EMSCRIPTEN) return "Emscripten"; -#elif defined(__FREEBSD__) +#elif defined(SDL_PLATFORM_FREEBSD) return "FreeBSD"; -#elif defined(__HAIKU__) +#elif defined(SDL_PLATFORM_HAIKU) return "Haiku"; -#elif defined(__HPUX__) +#elif defined(SDL_PLATFORM_HPUX) return "HP-UX"; -#elif defined(__IRIX__) +#elif defined(SDL_PLATFORM_IRIX) return "Irix"; -#elif defined(__LINUX__) +#elif defined(SDL_PLATFORM_LINUX) return "Linux"; #elif defined(__MINT__) return "Atari MiNT"; -#elif defined(__MACOS__) +#elif defined(SDL_PLATFORM_MACOS) return "macOS"; -#elif defined(__NACL__) - return "NaCl"; -#elif defined(__NETBSD__) +#elif defined(SDL_PLATFORM_NETBSD) return "NetBSD"; -#elif defined(__OPENBSD__) +#elif defined(SDL_PLATFORM_OPENBSD) return "OpenBSD"; -#elif defined(__OS2__) +#elif defined(SDL_PLATFORM_OS2) return "OS/2"; -#elif defined(__OSF__) +#elif defined(SDL_PLATFORM_OSF) return "OSF/1"; -#elif defined(__QNXNTO__) +#elif defined(SDL_PLATFORM_QNXNTO) return "QNX Neutrino"; -#elif defined(__RISCOS__) +#elif defined(SDL_PLATFORM_RISCOS) return "RISC OS"; -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) return "Solaris"; -#elif defined(__WIN32__) +#elif defined(SDL_PLATFORM_WIN32) return "Windows"; -#elif defined(__WINRT__) +#elif defined(SDL_PLATFORM_WINRT) return "WinRT"; -#elif defined(__WINGDK__) +#elif defined(SDL_PLATFORM_WINGDK) return "WinGDK"; -#elif defined(__XBOXONE__) +#elif defined(SDL_PLATFORM_XBOXONE) return "Xbox One"; -#elif defined(__XBOXSERIES__) +#elif defined(SDL_PLATFORM_XBOXSERIES) return "Xbox Series X|S"; -#elif defined(__IOS__) +#elif defined(SDL_PLATFORM_IOS) return "iOS"; -#elif defined(__TVOS__) +#elif defined(SDL_PLATFORM_TVOS) return "tvOS"; -#elif defined(__PS2__) +#elif defined(SDL_PLATFORM_PS2) return "PlayStation 2"; -#elif defined(__PSP__) +#elif defined(SDL_PLATFORM_PSP) return "PlayStation Portable"; -#elif defined(__VITA__) +#elif defined(SDL_PLATFORM_VITA) return "PlayStation Vita"; -#elif defined(__NGAGE__) +#elif defined(SDL_PLATFORM_NGAGE) return "Nokia N-Gage"; -#elif defined(__3DS__) +#elif defined(SDL_PLATFORM_3DS) return "Nintendo 3DS"; #elif defined(__managarm__) return "Managarm"; @@ -645,10 +684,10 @@ const char *SDL_GetPlatform(void) SDL_bool SDL_IsTablet(void) { -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID extern SDL_bool SDL_IsAndroidTablet(void); return SDL_IsAndroidTablet(); -#elif defined(__IOS__) +#elif defined(SDL_PLATFORM_IOS) extern SDL_bool SDL_IsIPad(void); return SDL_IsIPad(); #else @@ -656,7 +695,7 @@ SDL_bool SDL_IsTablet(void) #endif } -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB) /* FIXME: Still need to include DllMain() on Watcom C ? */ @@ -674,4 +713,4 @@ BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_rea } #endif /* Building DLL */ -#endif /* defined(__WIN32__) || defined(__GDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ diff --git a/src/SDL_assert.c b/src/SDL_assert.c index fd167430..3f0d5090 100644 --- a/src/SDL_assert.c +++ b/src/SDL_assert.c @@ -20,20 +20,20 @@ */ #include "SDL_internal.h" -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #include "core/windows/SDL_windows.h" #endif #include "SDL_assert_c.h" #include "video/SDL_sysvideo.h" -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #ifndef WS_OVERLAPPEDWINDOW #define WS_OVERLAPPEDWINDOW 0 #endif #endif -#ifdef __EMSCRIPTEN__ +#ifdef SDL_PLATFORM_EMSCRIPTEN #include /* older Emscriptens don't have this, but we need to for wasm64 compatibility. */ #ifndef MAIN_THREAD_EM_ASM_PTR @@ -86,7 +86,7 @@ static void SDL_AddAssertionToReport(SDL_AssertData *data) } } -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #define ENDLINE "\r\n" #else #define ENDLINE "\n" @@ -246,7 +246,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v state = (SDL_AssertState)selected; } } else { -#ifdef __EMSCRIPTEN__ +#ifdef SDL_PLATFORM_EMSCRIPTEN /* This is nasty, but we can't block on a custom UI. */ for (;;) { SDL_bool okay = SDL_TRUE; @@ -333,15 +333,15 @@ SDL_AssertState SDL_ReportAssertion(SDL_AssertData *data, const char *func, cons #ifndef SDL_THREADS_DISABLED static SDL_SpinLock spinlock = 0; - SDL_AtomicLock(&spinlock); + SDL_LockSpinlock(&spinlock); if (!assertion_mutex) { /* never called SDL_Init()? */ assertion_mutex = SDL_CreateMutex(); if (!assertion_mutex) { - SDL_AtomicUnlock(&spinlock); + SDL_UnlockSpinlock(&spinlock); return SDL_ASSERTION_IGNORE; /* oh well, I guess. */ } } - SDL_AtomicUnlock(&spinlock); + SDL_UnlockSpinlock(&spinlock); SDL_LockMutex(assertion_mutex); #endif /* !SDL_THREADS_DISABLED */ diff --git a/src/SDL_hints_c.h b/src/SDL_hints_c.h index 68cceac7..486280ec 100644 --- a/src/SDL_hints_c.h +++ b/src/SDL_hints_c.h @@ -27,5 +27,6 @@ extern SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value); extern int SDL_GetStringInteger(const char *value, int default_value); +extern void SDL_ClearHints(void); #endif /* SDL_hints_c_h_ */ diff --git a/src/SDL_internal.h b/src/SDL_internal.h index bfca0782..1494b9a4 100644 --- a/src/SDL_internal.h +++ b/src/SDL_internal.h @@ -74,7 +74,7 @@ #define DECLSPEC #endif -#ifdef __APPLE__ +#ifdef SDL_PLATFORM_APPLE #ifndef _DARWIN_C_SOURCE #define _DARWIN_C_SOURCE 1 /* for memset_pattern4() */ #endif @@ -137,13 +137,13 @@ #endif /* Optimized functions from 'SDL_blit_0.c' - - blit with source BitsPerPixel < 8, palette */ + - blit with source bits_per_pixel < 8, palette */ #ifndef SDL_HAVE_BLIT_0 #define SDL_HAVE_BLIT_0 !SDL_LEAN_AND_MEAN #endif /* Optimized functions from 'SDL_blit_1.c' - - blit with source BytesPerPixel == 1, palette */ + - blit with source bytes_per_pixel == 1, palette */ #ifndef SDL_HAVE_BLIT_1 #define SDL_HAVE_BLIT_1 !SDL_LEAN_AND_MEAN #endif @@ -194,6 +194,80 @@ #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 */ +#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_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 + #include #include diff --git a/src/SDL_list.c b/src/SDL_list.c index 4d03e78e..8c95876f 100644 --- a/src/SDL_list.c +++ b/src/SDL_list.c @@ -25,7 +25,7 @@ /* Push */ int SDL_ListAdd(SDL_ListNode **head, void *ent) { - SDL_ListNode *node = SDL_malloc(sizeof(*node)); + SDL_ListNode *node = (SDL_ListNode *)SDL_malloc(sizeof(*node)); if (!node) { return -1; diff --git a/src/SDL_log.c b/src/SDL_log.c index 198be022..2baf16a0 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) #include "core/windows/SDL_windows.h" #endif @@ -32,7 +32,7 @@ #include #endif -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID #include #endif @@ -41,10 +41,7 @@ /* The size of the stack buffer to use for rendering log messages. */ #define SDL_MAX_LOG_MESSAGE_STACK 256 -#define DEFAULT_PRIORITY SDL_LOG_PRIORITY_ERROR -#define DEFAULT_ASSERT_PRIORITY SDL_LOG_PRIORITY_WARN -#define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO -#define DEFAULT_TEST_PRIORITY SDL_LOG_PRIORITY_VERBOSE +#define DEFAULT_CATEGORY -1 typedef struct SDL_LogLevel { @@ -57,10 +54,8 @@ typedef struct SDL_LogLevel static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message); static SDL_LogLevel *SDL_loglevels; -static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY; -static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY; -static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; -static SDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY; +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; @@ -70,7 +65,8 @@ static SDL_Mutex *log_function_mutex = NULL; #pragma GCC diagnostic ignored "-Wunused-variable" #endif -static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = { +/* If this list changes, update the documentation for SDL_HINT_LOGGING */ +static const char *SDL_priority_prefixes[] = { NULL, "VERBOSE", "DEBUG", @@ -79,12 +75,9 @@ static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = { "ERROR", "CRITICAL" }; +SDL_COMPILE_TIME_ASSERT(priority_prefixes, SDL_arraysize(SDL_priority_prefixes) == SDL_NUM_LOG_PRIORITIES); -#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA -#pragma GCC diagnostic pop -#endif - -#ifdef __ANDROID__ +/* If this list changes, update the documentation for SDL_HINT_LOGGING */ static const char *SDL_category_prefixes[] = { "APP", "ERROR", @@ -96,9 +89,13 @@ static const char *SDL_category_prefixes[] = { "INPUT", "TEST" }; +SDL_COMPILE_TIME_ASSERT(category_prefixes, SDL_arraysize(SDL_category_prefixes) == SDL_LOG_CATEGORY_RESERVED1); -SDL_COMPILE_TIME_ASSERT(category_prefixes_enum, SDL_TABLESIZE(SDL_category_prefixes) == SDL_LOG_CATEGORY_RESERVED1); +#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA +#pragma GCC diagnostic pop +#endif +#ifdef SDL_PLATFORM_ANDROID static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = { ANDROID_LOG_UNKNOWN, ANDROID_LOG_VERBOSE, @@ -108,7 +105,7 @@ static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = { ANDROID_LOG_ERROR, ANDROID_LOG_FATAL }; -#endif /* __ANDROID__ */ +#endif /* SDL_PLATFORM_ANDROID */ void SDL_InitLog(void) { @@ -134,9 +131,9 @@ void SDL_LogSetAllPriority(SDL_LogPriority priority) for (entry = SDL_loglevels; entry; entry = entry->next) { entry->priority = priority; } - SDL_default_priority = priority; - SDL_assert_priority = priority; - SDL_application_priority = priority; + + SDL_forced_priority = SDL_TRUE; + SDL_forced_priority_level = priority; } void SDL_LogSetPriority(int category, SDL_LogPriority priority) @@ -160,6 +157,122 @@ void SDL_LogSetPriority(int category, SDL_LogPriority priority) } } +static SDL_bool SDL_ParseLogCategory(const char *string, size_t length, int *category) +{ + int i; + + if (SDL_isdigit(*string)) { + *category = SDL_atoi(string); + return SDL_TRUE; + } + + if (*string == '*') { + *category = DEFAULT_CATEGORY; + return SDL_TRUE; + } + + for (i = 0; i < SDL_arraysize(SDL_category_prefixes); ++i) { + if (SDL_strncasecmp(string, SDL_category_prefixes[i], length) == 0) { + *category = i; + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static SDL_bool SDL_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; + } + if (i >= SDL_LOG_PRIORITY_VERBOSE && i < SDL_NUM_LOG_PRIORITIES) { + *priority = (SDL_LogPriority)i; + return SDL_TRUE; + } + return SDL_FALSE; + } + + if (SDL_strncasecmp(string, "quiet", length) == 0) { + *priority = SDL_NUM_LOG_PRIORITIES; + return SDL_TRUE; + } + + for (i = SDL_LOG_PRIORITY_VERBOSE; i < SDL_NUM_LOG_PRIORITIES; ++i) { + if (SDL_strncasecmp(string, SDL_priority_prefixes[i], length) == 0) { + *priority = (SDL_LogPriority)i; + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static SDL_bool SDL_ParseLogCategoryPriority(const char *hint, int category, SDL_LogPriority *priority) +{ + const char *name, *next; + int current_category; + + if (category == DEFAULT_CATEGORY && SDL_strchr(hint, '=') == NULL) { + return SDL_ParseLogPriority(hint, SDL_strlen(hint), priority); + } + + for (name = hint; name; name = next) { + const char *sep = SDL_strchr(name, '='); + if (!sep) { + break; + } + next = SDL_strchr(sep, ','); + if (next) { + ++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); + } else { + len = SDL_strlen(value); + } + return SDL_ParseLogPriority(value, len, priority); + } + } + } + return SDL_FALSE; +} + +static SDL_LogPriority SDL_GetDefaultLogPriority(int category) +{ + const char *hint = SDL_GetHint(SDL_HINT_LOGGING); + if (hint) { + SDL_LogPriority priority; + + if (SDL_ParseLogCategoryPriority(hint, category, &priority)) { + return priority; + } + if (SDL_ParseLogCategoryPriority(hint, DEFAULT_CATEGORY, &priority)) { + return priority; + } + } + + 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; + } +} + SDL_LogPriority SDL_LogGetPriority(int category) { SDL_LogLevel *entry; @@ -170,15 +283,11 @@ SDL_LogPriority SDL_LogGetPriority(int category) } } - if (category == SDL_LOG_CATEGORY_TEST) { - return SDL_test_priority; - } else if (category == SDL_LOG_CATEGORY_APPLICATION) { - return SDL_application_priority; - } else if (category == SDL_LOG_CATEGORY_ASSERT) { - return SDL_assert_priority; - } else { - return SDL_default_priority; + if (SDL_forced_priority) { + return SDL_forced_priority_level; } + + return SDL_GetDefaultLogPriority(category); } void SDL_LogResetPriorities(void) @@ -190,11 +299,7 @@ void SDL_LogResetPriorities(void) SDL_loglevels = entry->next; SDL_free(entry); } - - SDL_default_priority = DEFAULT_PRIORITY; - SDL_assert_priority = DEFAULT_ASSERT_PRIORITY; - SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; - SDL_test_priority = DEFAULT_TEST_PRIORITY; + SDL_forced_priority = SDL_FALSE; } void SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) @@ -269,7 +374,7 @@ void SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_ST va_end(ap); } -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID static const char *GetCategoryPrefix(int category) { if (category < SDL_LOG_CATEGORY_RESERVED1) { @@ -280,7 +385,7 @@ static const char *GetCategoryPrefix(int category) } return "CUSTOM"; } -#endif /* __ANDROID__ */ +#endif /* SDL_PLATFORM_ANDROID */ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { @@ -351,7 +456,7 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S } } -#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) +#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; @@ -362,7 +467,7 @@ static HANDLE stderrHandle = NULL; static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message) { -#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) +#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. */ { @@ -371,7 +476,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority LPTSTR tstr; SDL_bool isstack; -#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) +#if !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) BOOL attachResult; DWORD attachError; DWORD charsWritten; @@ -410,7 +515,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority } } } -#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) */ +#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; output = SDL_small_alloc(char, length, &isstack); @@ -420,7 +525,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority /* Output to debugger */ OutputDebugString(tstr); -#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) +#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 (!WriteConsole(stderrHandle, tstr, (DWORD)SDL_tcslen(tstr), &charsWritten, NULL)) { @@ -435,19 +540,19 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority OutputDebugString(TEXT("Error calling WriteFile\r\n")); } } -#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) && !defined(__GDK__) */ +#endif /* !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) */ SDL_free(tstr); SDL_small_free(output, isstack); } -#elif defined(__ANDROID__) +#elif defined(SDL_PLATFORM_ANDROID) { char tag[32]; SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); __android_log_write(SDL_android_priority[priority], tag, message); } -#elif defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)) +#elif defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)) /* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now. */ extern void SDL_NSLog(const char *prefix, const char *text); @@ -455,7 +560,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority SDL_NSLog(SDL_priority_prefixes[priority], message); return; } -#elif defined(__PSP__) || defined(__PS2__) +#elif defined(SDL_PLATFORM_PSP) || defined(SDL_PLATFORM_PS2) { FILE *pFile; pFile = fopen("SDL_Log.txt", "a"); @@ -464,7 +569,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority (void)fclose(pFile); } } -#elif defined(__VITA__) +#elif defined(SDL_PLATFORM_VITA) { FILE *pFile; pFile = fopen("ux0:/data/SDL_Log.txt", "a"); @@ -473,7 +578,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority (void)fclose(pFile); } } -#elif defined(__3DS__) +#elif defined(SDL_PLATFORM_3DS) { FILE *pFile; pFile = fopen("sdmc:/3ds/SDL_Log.txt", "a"); @@ -484,12 +589,12 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority } #endif #if defined(HAVE_STDIO_H) && \ - !(defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))) + !(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); #endif } -void SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata) +void SDL_GetLogOutputFunction(SDL_LogOutputFunction *callback, void **userdata) { if (callback) { *callback = SDL_log_function; @@ -499,7 +604,7 @@ void SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata) } } -void SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata) +void SDL_SetLogOutputFunction(SDL_LogOutputFunction callback, void *userdata) { SDL_log_function = callback; SDL_log_userdata = userdata; diff --git a/src/SDL_properties.c b/src/SDL_properties.c index 83e5dd68..fd209c45 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -150,7 +150,7 @@ SDL_PropertiesID SDL_CreateProperties(void) return 0; } - properties = SDL_calloc(1, sizeof(*properties)); + properties = (SDL_Properties *)SDL_calloc(1, sizeof(*properties)); if (!properties) { goto error; } @@ -188,6 +188,78 @@ error: return 0; } +int SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) +{ + SDL_Properties *src_properties = NULL; + SDL_Properties *dst_properties = NULL; + int result = 0; + + if (!src) { + return SDL_InvalidParamError("src"); + } + if (!dst) { + return SDL_InvalidParamError("dst"); + } + + SDL_LockMutex(SDL_properties_lock); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)src, (const void **)&src_properties); + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)dst, (const void **)&dst_properties); + SDL_UnlockMutex(SDL_properties_lock); + + if (!src_properties) { + return SDL_InvalidParamError("src"); + } + if (!dst_properties) { + return SDL_InvalidParamError("dst"); + } + + SDL_LockMutex(src_properties->lock); + SDL_LockMutex(dst_properties->lock); + { + void *iter; + const void *key, *value; + + iter = NULL; + while (SDL_IterateHashTable(src_properties->props, &key, &value, &iter)) { + const char *src_name = (const char *)key; + const SDL_Property *src_property = (const SDL_Property *)value; + char *dst_name; + SDL_Property *dst_property; + + if (src_property->cleanup) { + /* Can't copy properties with cleanup functions, we don't know how to duplicate the data */ + continue; + } + + SDL_RemoveFromHashTable(dst_properties->props, src_name); + + dst_name = SDL_strdup(src_name); + if (!dst_name) { + result = -1; + continue; + } + dst_property = (SDL_Property *)SDL_malloc(sizeof(*dst_property)); + if (!dst_property) { + SDL_free(dst_name); + result = -1; + continue; + } + SDL_copyp(dst_property, src_property); + if (src_property->type == SDL_PROPERTY_TYPE_STRING) { + 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_UnlockMutex(dst_properties->lock); + SDL_UnlockMutex(src_properties->lock); + + return result; +} + int SDL_LockProperties(SDL_PropertiesID props) { SDL_Properties *properties = NULL; @@ -276,6 +348,7 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { + SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); return -1; } property->type = SDL_PROPERTY_TYPE_POINTER; @@ -302,6 +375,27 @@ int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) return SDL_PrivateSetProperty(props, name, property); } +static void SDLCALL CleanupFreeableProperty(void *userdata, void *value) +{ + SDL_free(value); +} + +int SDL_SetFreeableProperty(SDL_PropertiesID props, const char *name, void *value) +{ + return SDL_SetPropertyWithCleanup(props, name, value, CleanupFreeableProperty, NULL); +} + +static void SDLCALL CleanupSurface(void *userdata, void *value) +{ + SDL_Surface *surface = (SDL_Surface *)value; + + SDL_DestroySurface(surface); +} + +int SDL_SetSurfaceProperty(SDL_PropertiesID props, const char *name, SDL_Surface *surface) +{ + return SDL_SetPropertyWithCleanup(props, name, surface, CleanupSurface, NULL); +} int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value) { @@ -357,17 +451,20 @@ int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool va return SDL_PrivateSetProperty(props, name, property); } +SDL_bool SDL_HasProperty(SDL_PropertiesID props, const char *name) +{ + return (SDL_GetPropertyType(props, name) != SDL_PROPERTY_TYPE_INVALID); +} + SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) { SDL_Properties *properties = NULL; SDL_PropertyType type = SDL_PROPERTY_TYPE_INVALID; if (!props) { - SDL_InvalidParamError("props"); return SDL_PROPERTY_TYPE_INVALID; } if (!name || !*name) { - SDL_InvalidParamError("name"); return SDL_PROPERTY_TYPE_INVALID; } @@ -376,7 +473,6 @@ SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_InvalidParamError("props"); return SDL_PROPERTY_TYPE_INVALID; } @@ -385,8 +481,6 @@ SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { type = property->type; - } else { - SDL_SetError("Couldn't find property named %s", name); } } SDL_UnlockMutex(properties->lock); @@ -400,11 +494,9 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_va void *value = default_value; if (!props) { - SDL_InvalidParamError("props"); return value; } if (!name || !*name) { - SDL_InvalidParamError("name"); return value; } @@ -413,7 +505,6 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_va SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_InvalidParamError("props"); return value; } @@ -427,11 +518,7 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_va if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { if (property->type == SDL_PROPERTY_TYPE_POINTER) { value = property->value.pointer_value; - } else { - SDL_SetError("Property %s isn't a pointer value", name); } - } else { - SDL_SetError("Couldn't find property named %s", name); } } SDL_UnlockMutex(properties->lock); @@ -445,11 +532,9 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons const char *value = default_value; if (!props) { - SDL_InvalidParamError("props"); return value; } if (!name || !*name) { - SDL_InvalidParamError("name"); return value; } @@ -458,7 +543,6 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_InvalidParamError("props"); return value; } @@ -480,7 +564,7 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons if (property->string_storage) { value = property->string_storage; } else { - SDL_asprintf(&property->string_storage, "%" SDL_PRIs64 "", property->value.number_value); + SDL_asprintf(&property->string_storage, "%" SDL_PRIs64, property->value.number_value); if (property->string_storage) { value = property->string_storage; } @@ -500,11 +584,8 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons value = property->value.boolean_value ? "true" : "false"; break; default: - SDL_SetError("Property %s isn't a string value", name); break; } - } else { - SDL_SetError("Couldn't find property named %s", name); } } SDL_UnlockMutex(properties->lock); @@ -518,11 +599,9 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de Sint64 value = default_value; if (!props) { - SDL_InvalidParamError("props"); return value; } if (!name || !*name) { - SDL_InvalidParamError("name"); return value; } @@ -531,7 +610,6 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_InvalidParamError("props"); return value; } @@ -553,11 +631,8 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de value = property->value.boolean_value; break; default: - SDL_SetError("Property %s isn't a number value", name); break; } - } else { - SDL_SetError("Couldn't find property named %s", name); } } SDL_UnlockMutex(properties->lock); @@ -571,11 +646,9 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau float value = default_value; if (!props) { - SDL_InvalidParamError("props"); return value; } if (!name || !*name) { - SDL_InvalidParamError("name"); return value; } @@ -584,7 +657,6 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_InvalidParamError("props"); return value; } @@ -606,11 +678,8 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau value = (float)property->value.boolean_value; break; default: - SDL_SetError("Property %s isn't a float value", name); break; } - } else { - SDL_SetError("Couldn't find property named %s", name); } } SDL_UnlockMutex(properties->lock); @@ -624,11 +693,9 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo SDL_bool value = default_value; if (!props) { - SDL_InvalidParamError("props"); return value; } if (!name || !*name) { - SDL_InvalidParamError("name"); return value; } @@ -637,7 +704,6 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_InvalidParamError("props"); return value; } @@ -659,11 +725,8 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo value = property->value.boolean_value; break; default: - SDL_SetError("Property %s isn't a boolean value", name); break; } - } else { - SDL_SetError("Couldn't find property named %s", name); } } SDL_UnlockMutex(properties->lock); diff --git a/src/SDL_properties_c.h b/src/SDL_properties_c.h index 9b590cde..d996fa12 100644 --- a/src/SDL_properties_c.h +++ b/src/SDL_properties_c.h @@ -20,4 +20,6 @@ */ 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 void SDL_QuitProperties(void); diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index 2919e800..e350c15b 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -25,11 +25,11 @@ #define HAVE_MSC_ATOMICS 1 #endif -#ifdef __MACOS__ /* !!! FIXME: should we favor gcc atomics? */ +#ifdef SDL_PLATFORM_MACOS /* !!! FIXME: should we favor gcc atomics? */ #include #endif -#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__) +#if !defined(HAVE_GCC_ATOMICS) && defined(SDL_PLATFORM_SOLARIS) #include #endif @@ -38,7 +38,7 @@ #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. It might be in a later NDK or we might need an extra library? --ryan. */ -#ifndef __ANDROID__ +#ifndef SDL_PLATFORM_ANDROID #define HAVE_ATOMIC_LOAD_N 1 #endif #endif @@ -100,7 +100,7 @@ extern __inline int _SDL_xadd_watcom(volatile int *a, int v); Contributed by Bob Pendleton, bob@pendleton.com */ -#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(__MACOS__) && !defined(__SOLARIS__) && !defined(HAVE_WATCOM_ATOMICS) +#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(SDL_PLATFORM_MACOS) && !defined(SDL_PLATFORM_SOLARIS) && !defined(HAVE_WATCOM_ATOMICS) #define EMULATE_CAS 1 #endif @@ -111,18 +111,18 @@ static SDL_INLINE void enterLock(void *a) { uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f); - SDL_AtomicLock(&locks[index]); + SDL_LockSpinlock(&locks[index]); } static SDL_INLINE void leaveLock(void *a) { uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f); - SDL_AtomicUnlock(&locks[index]); + SDL_UnlockSpinlock(&locks[index]); } #endif -SDL_bool SDL_AtomicCAS(SDL_AtomicInt *a, int oldval, int newval) +SDL_bool SDL_AtomicCompareAndSwap(SDL_AtomicInt *a, int oldval, int newval) { #ifdef HAVE_MSC_ATOMICS SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(long) == sizeof(a->value)); @@ -131,9 +131,9 @@ SDL_bool SDL_AtomicCAS(SDL_AtomicInt *a, int oldval, int newval) return _SDL_cmpxchg_watcom(&a->value, newval, oldval); #elif defined(HAVE_GCC_ATOMICS) return __sync_bool_compare_and_swap(&a->value, oldval, newval); -#elif defined(__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(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) 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; @@ -151,7 +151,7 @@ SDL_bool SDL_AtomicCAS(SDL_AtomicInt *a, int oldval, int newval) #endif } -SDL_bool SDL_AtomicCASPtr(void **a, void *oldval, void *newval) +SDL_bool SDL_AtomicCompareAndSwapPointer(void **a, void *oldval, void *newval) { #ifdef HAVE_MSC_ATOMICS return _InterlockedCompareExchangePointer(a, newval, oldval) == oldval; @@ -159,11 +159,11 @@ SDL_bool SDL_AtomicCASPtr(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(__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(__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(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) return (atomic_cas_ptr(a, oldval, newval) == oldval); #elif defined(EMULATE_CAS) SDL_bool retval = SDL_FALSE; @@ -190,13 +190,13 @@ int SDL_AtomicSet(SDL_AtomicInt *a, int v) return _SDL_xchg_watcom(&a->value, v); #elif defined(HAVE_GCC_ATOMICS) return __sync_lock_test_and_set(&a->value, v); -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) return (int)atomic_swap_uint((volatile uint_t *)&a->value, v); #else int value; do { value = a->value; - } while (!SDL_AtomicCAS(a, value, v)); + } while (!SDL_AtomicCompareAndSwap(a, value, v)); return value; #endif } @@ -209,13 +209,13 @@ void *SDL_AtomicSetPtr(void **a, void *v) return (void *)_SDL_xchg_watcom((int *)a, (long)v); #elif defined(HAVE_GCC_ATOMICS) return __sync_lock_test_and_set(a, v); -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) return atomic_swap_ptr(a, v); #else void *value; do { value = *a; - } while (!SDL_AtomicCASPtr(a, value, v)); + } while (!SDL_AtomicCompareAndSwapPointer(a, value, v)); return value; #endif } @@ -229,7 +229,7 @@ int SDL_AtomicAdd(SDL_AtomicInt *a, int v) return _SDL_xadd_watcom(&a->value, v); #elif defined(HAVE_GCC_ATOMICS) return __sync_fetch_and_add(&a->value, v); -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) int pv = a->value; membar_consumer(); atomic_add_int((volatile uint_t *)&a->value, v); @@ -238,7 +238,7 @@ int SDL_AtomicAdd(SDL_AtomicInt *a, int v) int value; do { value = a->value; - } while (!SDL_AtomicCAS(a, value, (value + v))); + } while (!SDL_AtomicCompareAndSwap(a, value, (value + v))); return value; #endif } @@ -254,15 +254,15 @@ 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(__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(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) return atomic_or_uint((volatile uint_t *)&a->value, 0); #else int value; do { value = a->value; - } while (!SDL_AtomicCAS(a, value, value)); + } while (!SDL_AtomicCompareAndSwap(a, value, value)); return value; #endif } @@ -275,13 +275,13 @@ void *SDL_AtomicGetPtr(void **a) return _InterlockedCompareExchangePointer(a, NULL, NULL); #elif defined(HAVE_GCC_ATOMICS) return __sync_val_compare_and_swap(a, (void *)0, (void *)0); -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) return atomic_cas_ptr(a, (void *)0, (void *)0); #else void *value; do { value = *a; - } while (!SDL_AtomicCASPtr(a, value, value)); + } while (!SDL_AtomicCompareAndSwapPointer(a, value, value)); return value; #endif } diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index 82dcace1..0896b41c 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -20,15 +20,15 @@ */ #include "SDL_internal.h" -#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) #include "../core/windows/SDL_windows.h" #endif -#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__) +#if !defined(HAVE_GCC_ATOMICS) && defined(SDL_PLATFORM_SOLARIS) #include #endif -#if !defined(HAVE_GCC_ATOMICS) && defined(__RISCOS__) +#if !defined(HAVE_GCC_ATOMICS) && defined(SDL_PLATFORM_RISCOS) #include #endif @@ -40,7 +40,7 @@ #include #endif -#if !defined(HAVE_GCC_ATOMICS) && defined(__MACOS__) +#if !defined(HAVE_GCC_ATOMICS) && defined(SDL_PLATFORM_MACOS) #include #endif @@ -57,27 +57,9 @@ extern __inline int _SDL_xchg_watcom(volatile int *a, int v); /* *INDENT-ON* */ /* clang-format on */ /* This function is where all the magic happens... */ -SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) +SDL_bool SDL_TryLockSpinlock(SDL_SpinLock *lock) { -#ifdef SDL_ATOMIC_DISABLED - /* Terrible terrible damage */ - static SDL_Mutex *_spinlock_mutex; - - if (!_spinlock_mutex) { - /* 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; - } else { - SDL_UnlockMutex(_spinlock_mutex); - return SDL_FALSE; - } - -#elif defined(HAVE_GCC_ATOMICS) || defined(HAVE_GCC_SYNC_LOCK_TEST_AND_SET) +#if defined(HAVE_GCC_ATOMICS) || defined(HAVE_GCC_SYNC_LOCK_TEST_AND_SET) return __sync_lock_test_and_set(lock, 1) == 0; #elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) @@ -97,7 +79,7 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) defined(__ARM_ARCH_5TEJ__)) int result; -#ifdef __RISCOS__ +#ifdef SDL_PLATFORM_RISCOS if (__cpucap_have_rex()) { __asm__ __volatile__( "ldrex %0, [%2]\nteq %0, #0\nstrexeq %0, %1, [%2]" @@ -133,15 +115,15 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) : "cc", "memory"); return result == 0; -#elif defined(__MACOS__) || defined(__IOS__) || defined(__TVOS__) +#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. */ return OSAtomicCompareAndSwap32Barrier(0, 1, lock); -#elif defined(__SOLARIS__) && defined(_LP64) +#elif defined(SDL_PLATFORM_SOLARIS) && defined(_LP64) /* Used for Solaris with non-gcc compilers. */ return ((int)atomic_cas_64((volatile uint64_t *)lock, 0, 1) == 0); -#elif defined(__SOLARIS__) && !defined(_LP64) +#elif defined(SDL_PLATFORM_SOLARIS) && !defined(_LP64) /* Used for Solaris with non-gcc compilers. */ return ((int)atomic_cas_32((volatile uint32_t *)lock, 0, 1) == 0); #elif defined(PS2) @@ -160,16 +142,30 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) } return res; #else -#error Please implement for your platform. - return SDL_FALSE; + /* Terrible terrible damage */ + static SDL_Mutex *_spinlock_mutex; + + if (!_spinlock_mutex) { + /* 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; + } else { + SDL_UnlockMutex(_spinlock_mutex); + return SDL_FALSE; + } #endif } -void SDL_AtomicLock(SDL_SpinLock *lock) +void SDL_LockSpinlock(SDL_SpinLock *lock) { int iterations = 0; /* FIXME: Should we have an eventual timeout? */ - while (!SDL_AtomicTryLock(lock)) { + while (!SDL_TryLockSpinlock(lock)) { if (iterations < 32) { iterations++; SDL_CPUPauseInstruction(); @@ -180,7 +176,7 @@ void SDL_AtomicLock(SDL_SpinLock *lock) } } -void SDL_AtomicUnlock(SDL_SpinLock *lock) +void SDL_UnlockSpinlock(SDL_SpinLock *lock) { #if defined(HAVE_GCC_ATOMICS) || defined(HAVE_GCC_SYNC_LOCK_TEST_AND_SET) __sync_lock_release(lock); @@ -196,7 +192,7 @@ void SDL_AtomicUnlock(SDL_SpinLock *lock) SDL_CompilerBarrier(); *lock = 0; -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) /* Used for Solaris when not using gcc. */ *lock = 0; membar_producer(); diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index b8f3d17b..a2468e8c 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -306,17 +306,17 @@ static void ReleaseAudioDevice(SDL_AudioDevice *device) SDL_NO_THREAD_SAFETY_ANA } // If found, this locks _the physical device_ this logical device is associated with, before returning. -static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, SDL_AudioDevice **device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_ACQUIRE +static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, SDL_AudioDevice **_device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_ACQUIRE { - SDL_assert(device != NULL); - - *device = NULL; + SDL_assert(_device != NULL); if (!SDL_GetCurrentAudioDriver()) { SDL_SetError("Audio subsystem is not initialized"); + *_device = NULL; return NULL; } + SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = NULL; // bit #1 of devid is set for physical devices and unset for logical. @@ -325,19 +325,36 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev); if (logdev) { - *device = logdev->physical_device; - RefPhysicalAudioDevice(*device); // reference it, in case the logical device migrates to a new default. + device = logdev->physical_device; + SDL_assert(device != NULL); + RefPhysicalAudioDevice(device); // reference it, in case the logical device migrates to a new default. } SDL_UnlockRWLock(current_audio.device_hash_lock); + + 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) { + SDL_LockMutex(device->lock); + SDL_AudioDevice *recheck_device = (SDL_AudioDevice *) SDL_AtomicGetPtr((void **) &logdev->physical_device); + if (device == recheck_device) { + break; + } + + // default changed from under us! Try again! + RefPhysicalAudioDevice(recheck_device); + SDL_UnlockMutex(device->lock); + UnrefPhysicalAudioDevice(device); + device = recheck_device; + } + } } if (!logdev) { SDL_SetError("Invalid audio device instance ID"); - } else { - SDL_assert(*device != NULL); - SDL_LockMutex((*device)->lock); } + *_device = device; return logdev; } @@ -635,7 +652,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)); SDL_UnlockRWLock(current_audio.device_hash_lock); - const SDL_bool first_disconnect = SDL_AtomicCAS(&device->zombie, 0, 1); + const SDL_bool first_disconnect = SDL_AtomicCompareAndSwap(&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 @@ -809,7 +826,7 @@ int SDL_InitAudio(const char *driver_name) } // 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_AtomicCAS(&last_device_instance_id, 0, 2); + SDL_AtomicCompareAndSwap(&last_device_instance_id, 0, 2); SDL_ChooseAudioConverters(); SDL_SetupAudioResampler(); @@ -1775,15 +1792,11 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int if (retval != 0) { int j; - for (j = 0; j <= i; j++) { -#ifdef _MSC_VER /* Visual Studio analyzer can't tell that we've already verified streams[j] isn't NULL */ -#pragma warning(push) -#pragma warning(disable : 28182) -#endif + for (j = 0; j < i; j++) { SDL_UnlockMutex(streams[j]->lock); -#ifdef _MSC_VER -#pragma warning(pop) -#endif + } + if (stream) { + SDL_UnlockMutex(stream->lock); } break; } @@ -1890,7 +1903,7 @@ void SDL_UnbindAudioStreams(SDL_AudioStream **streams, int num_streams) // Finalize and unlock everything. for (int i = 0; i < num_streams; i++) { SDL_AudioStream *stream = streams[i]; - if (stream && stream->bound_device) { + if (stream) { SDL_LogicalAudioDevice *logdev = stream->bound_device; stream->bound_device = NULL; SDL_UnlockMutex(stream->lock); @@ -1945,12 +1958,18 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au stream = SDL_CreateAudioStream(spec, &device->spec); } - if (!stream || (SDL_BindAudioStream(logdevid, stream) == -1)) { + if (!stream) { failed = SDL_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. + + stream->bound_device = logdev; stream->simplified = SDL_TRUE; // so we know to close the audio device when this is destroyed. + UpdateAudioStreamFormatsPhysical(device); + if (callback) { int rc; if (iscapture) { diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 54b8189d..77dc4df2 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -666,7 +666,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) SDL_UnlockMutex(stream->lock); size_t chunk_size = SDL_GetAudioQueueChunkSize(stream->queue); - track = SDL_CreateChunkedAudioTrack(&src_spec, buf, len, chunk_size); + track = SDL_CreateChunkedAudioTrack(&src_spec, (const Uint8 *)buf, len, chunk_size); if (!track) { return -1; @@ -682,7 +682,7 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) if (track) { SDL_AddTrackToAudioQueue(stream->queue, track); } else { - retval = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, buf, len); + retval = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, (const Uint8 *)buf, len); } if (retval == 0) { @@ -874,7 +874,7 @@ static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int ou // 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 = buf; + input_buffer = (Uint8 *)buf; } else { input_buffer = EnsureAudioStreamWorkBufferSize(stream, output_frames * max_frame_size); diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index ad8a2ad0..46e4c4db 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -32,7 +32,7 @@ #include "SDL_audiodev_c.h" #ifndef SDL_PATH_DEV_DSP -#if defined(__NETBSD__) || defined(__OPENBSD__) +#if defined(SDL_PLATFORM_NETBSD) || defined(SDL_PLATFORM_OPENBSD) #define SDL_PATH_DEV_DSP "/dev/audio" #else #define SDL_PATH_DEV_DSP "/dev/dsp" @@ -48,9 +48,9 @@ static void test_device(const SDL_bool iscapture, const char *fname, int flags, SDL_bool (*test)(int fd)) { struct stat sb; - if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) { - const int audio_fd = open(fname, flags | O_CLOEXEC, 0); - if (audio_fd >= 0) { + 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); close(audio_fd); if (okay) { @@ -65,6 +65,8 @@ static void test_device(const SDL_bool iscapture, const char *fname, int flags, */ SDL_AddAudioDevice(iscapture, fname, NULL, (void *)(uintptr_t)dummyhandle); } + } else { + close(audio_fd); } } } diff --git a/src/audio/SDL_audioqueue.c b/src/audio/SDL_audioqueue.c index d5a9e3ac..92387367 100644 --- a/src/audio/SDL_audioqueue.c +++ b/src/audio/SDL_audioqueue.c @@ -134,14 +134,14 @@ static SDL_AudioChunk *CreateAudioTrackChunk(SDL_ChunkedAudioTrack *track) static size_t AvailChunkedAudioTrack(void *ctx) { - SDL_ChunkedAudioTrack *track = ctx; + SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; return track->queued_bytes; } static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) { - SDL_ChunkedAudioTrack *track = ctx; + SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; SDL_AudioChunk *chunk = track->tail; @@ -200,7 +200,7 @@ static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) static size_t ReadFromChunkedAudioTrack(void *ctx, Uint8 *data, size_t len, SDL_bool advance) { - SDL_ChunkedAudioTrack *track = ctx; + SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; SDL_AudioChunk *chunk = track->head; size_t total = 0; @@ -245,7 +245,7 @@ static size_t ReadFromChunkedAudioTrack(void *ctx, Uint8 *data, size_t len, SDL_ static void DestroyChunkedAudioTrack(void *ctx) { - SDL_ChunkedAudioTrack *track = ctx; + SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; DestroyAudioChunks(track->head); DestroyAudioChunks(track->free_chunks); SDL_free(track); @@ -420,7 +420,7 @@ void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue) size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, SDL_bool *out_flushed) { - SDL_AudioTrack *iter = *inout_iter; + SDL_AudioTrack *iter = (SDL_AudioTrack *)(*inout_iter); SDL_assert(iter != NULL); SDL_copyp(out_spec, &iter->spec); diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index 770922bb..43cabd9b 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -25,26 +25,9 @@ // TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 can be fixed #undef SDL_NEON_INTRINSICS -#ifndef SDL_CPUINFO_DISABLED -#if defined(__x86_64__) && defined(SDL_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // x86_64 guarantees SSE2. -#elif defined(__MACOS__) && defined(SDL_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // macOS/Intel guarantees SSE2. -#elif defined(__ARM_ARCH) && (__ARM_ARCH >= 8) && defined(SDL_NEON_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // ARMv8+ promise NEON. -#elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7) && defined(SDL_NEON_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 // All Apple ARMv7 chips promise NEON support. -#endif -#endif - -// Set to zero if platform is guaranteed to use a SIMD codepath here. -#if !defined(NEED_SCALAR_CONVERTER_FALLBACKS) || defined(SDL_CPUINFO_DISABLED) -#define NEED_SCALAR_CONVERTER_FALLBACKS 1 -#endif - #define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f -#if NEED_SCALAR_CONVERTER_FALLBACKS +// start fallback scalar converters // This code requires that floats are in the IEEE-754 binary32 format SDL_COMPILE_TIME_ASSERT(float_bits, sizeof(float) == sizeof(Uint32)); @@ -201,7 +184,7 @@ static void SDL_Convert_F32_to_S32_Scalar(Sint32 *dst, const float *src, int num #undef SIGNMASK -#endif // NEED_SCALAR_CONVERTER_FALLBACKS +// end fallback scalar converters #ifdef SDL_SSE2_INTRINSICS static void SDL_TARGETING("sse2") SDL_Convert_S8_to_F32_SSE2(float *dst, const Sint8 *src, int num_samples) @@ -999,9 +982,7 @@ void SDL_ChooseAudioConverters(void) } #endif -#if NEED_SCALAR_CONVERTER_FALLBACKS SET_CONVERTER_FUNCS(Scalar); -#endif #undef SET_CONVERTER_FUNCS diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index 633783af..280bd9a9 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -1502,7 +1502,7 @@ static void WaveFreeChunkData(WaveChunk *chunk) chunk->size = 0; } -static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk) +static int WaveNextChunk(SDL_IOStream *src, WaveChunk *chunk) { Uint32 chunkheader[2]; Sint64 nextposition = chunk->position + chunk->length; @@ -1520,10 +1520,10 @@ static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk) nextposition++; } - if (SDL_RWseek(src, nextposition, SDL_RW_SEEK_SET) != nextposition) { + if (SDL_SeekIO(src, nextposition, SDL_IO_SEEK_SET) != nextposition) { /* Not sure how we ended up here. Just abort. */ return -2; - } else if (SDL_RWread(src, chunkheader, sizeof(Uint32) * 2) != (sizeof(Uint32) * 2)) { + } else if (SDL_ReadIO(src, chunkheader, sizeof(Uint32) * 2) != (sizeof(Uint32) * 2)) { return -1; } @@ -1534,7 +1534,7 @@ static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk) return 0; } -static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t length) +static int WaveReadPartialChunkData(SDL_IOStream *src, WaveChunk *chunk, size_t length) { WaveFreeChunkData(chunk); @@ -1548,12 +1548,12 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len return -1; } - if (SDL_RWseek(src, chunk->position, SDL_RW_SEEK_SET) != chunk->position) { + if (SDL_SeekIO(src, chunk->position, SDL_IO_SEEK_SET) != chunk->position) { /* Not sure how we ended up here. Just abort. */ return -2; } - chunk->size = SDL_RWread(src, chunk->data, length); + chunk->size = SDL_ReadIO(src, chunk->data, length); if (chunk->size != length) { /* Expected to be handled by the caller. */ } @@ -1562,7 +1562,7 @@ static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t len return 0; } -static int WaveReadChunkData(SDL_RWops *src, WaveChunk *chunk) +static int WaveReadChunkData(SDL_IOStream *src, WaveChunk *chunk) { return WaveReadPartialChunkData(src, chunk, chunk->length); } @@ -1602,14 +1602,14 @@ static int WaveReadFormat(WaveFile *file) { WaveChunk *chunk = &file->chunk; WaveFormat *format = &file->format; - SDL_RWops *fmtsrc; + SDL_IOStream *fmtsrc; size_t fmtlen = chunk->size; if (fmtlen > SDL_MAX_SINT32) { - /* Limit given by SDL_RWFromConstMem. */ + /* Limit given by SDL_IOFromConstMem. */ return SDL_SetError("Data of WAVE fmt chunk too big"); } - fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size); + fmtsrc = SDL_IOFromConstMem(chunk->data, (int)chunk->size); if (!fmtsrc) { return -1; } @@ -1629,7 +1629,7 @@ static int WaveReadFormat(WaveFile *file) return -1; } } else if (format->encoding == PCM_CODE) { - SDL_RWclose(fmtsrc); + SDL_CloseIO(fmtsrc); return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk"); } @@ -1649,19 +1649,19 @@ static int WaveReadFormat(WaveFile *file) /* Extensible header must be at least 22 bytes. */ if (fmtlen < 40 || format->extsize < 22) { - SDL_RWclose(fmtsrc); + SDL_CloseIO(fmtsrc); return SDL_SetError("Extensible WAVE header too small"); } if (!SDL_ReadU16LE(fmtsrc, &format->validsamplebits) || !SDL_ReadU32LE(fmtsrc, &format->channelmask) || - SDL_RWread(fmtsrc, format->subformat, 16) != 16) { + SDL_ReadIO(fmtsrc, format->subformat, 16) != 16) { } format->samplesperblock = format->validsamplebits; format->encoding = WaveGetFormatGUIDEncoding(format); } - SDL_RWclose(fmtsrc); + SDL_CloseIO(fmtsrc); return 0; } @@ -1769,7 +1769,7 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength) return 0; } -static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { int result; Uint32 chunkcount = 0; @@ -1795,7 +1795,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 * } } - RIFFstart = SDL_RWtell(src); + RIFFstart = SDL_TellIO(src); if (RIFFstart < 0) { return SDL_SetError("Could not seek in file"); } @@ -1897,7 +1897,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 * file->fact.status = -1; } else { /* Let's use src directly, it's just too convenient. */ - Sint64 position = SDL_RWseek(src, chunk->position, SDL_RW_SEEK_SET); + 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; } else { @@ -1940,7 +1940,7 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 * if (chunk->fourcc != DATA && chunk->length > 0) { Uint8 tmp; Uint64 position = (Uint64)chunk->position + chunk->length - 1; - if (position > SDL_MAX_SINT64 || SDL_RWseek(src, (Sint64)position, SDL_RW_SEEK_SET) != (Sint64)position) { + if (position > SDL_MAX_SINT64 || SDL_SeekIO(src, (Sint64)position, SDL_IO_SEEK_SET) != (Sint64)position) { return SDL_SetError("Could not seek to WAVE chunk data"); } else if (!SDL_ReadU8(src, &tmp)) { return SDL_SetError("RIFF size truncates chunk"); @@ -2075,14 +2075,14 @@ static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 * return 0; } -int SDL_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +int SDL_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { int result = -1; WaveFile file; /* Make sure we are passed a valid data source */ if (!src) { - goto done; /* Error may come from RWops. */ + goto done; /* Error may come from SDL_IOStream. */ } else if (!spec) { SDL_InvalidParamError("spec"); goto done; @@ -2110,20 +2110,20 @@ int SDL_LoadWAV_RW(SDL_RWops *src, SDL_bool freesrc, SDL_AudioSpec *spec, Uint8 } /* Cleanup */ - if (!freesrc) { - SDL_RWseek(src, file.chunk.position, SDL_RW_SEEK_SET); + if (!closeio) { + SDL_SeekIO(src, file.chunk.position, SDL_IO_SEEK_SET); } WaveFreeChunkData(&file.chunk); SDL_free(file.decoderdata); done: - if (freesrc && src) { - SDL_RWclose(src); + if (closeio && src) { + SDL_CloseIO(src); } return result; } int SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { - return SDL_LoadWAV_RW(SDL_RWFromFile(path, "rb"), 1, spec, audio_buf, audio_len); + return SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len); } diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c index 4445ba8c..265eaaca 100644 --- a/src/audio/aaudio/SDL_aaudio.c +++ b/src/audio/aaudio/SDL_aaudio.c @@ -381,6 +381,12 @@ static int BuildAAudioStream(SDL_AudioDevice *device) return 0; } +// !!! FIXME: make this non-blocking! +static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted) +{ + SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1); +} + static int AAUDIO_OpenDevice(SDL_AudioDevice *device) { #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES @@ -390,7 +396,18 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device) LOGI(__func__); if (device->iscapture) { - if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) { + // !!! 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; + } + + while (SDL_AtomicGet(&permission_response) == 0) { + SDL_Delay(10); + } + + if (SDL_AtomicGet(&permission_response) < 0) { LOGI("This app doesn't have RECORD_AUDIO permission"); return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); } diff --git a/src/audio/coreaudio/SDL_coreaudio.h b/src/audio/coreaudio/SDL_coreaudio.h index ffa221fe..cd64e303 100644 --- a/src/audio/coreaudio/SDL_coreaudio.h +++ b/src/audio/coreaudio/SDL_coreaudio.h @@ -25,7 +25,7 @@ #include "../SDL_sysaudio.h" -#ifndef __IOS__ +#ifndef SDL_PLATFORM_IOS #define MACOSX_COREAUDIO #endif diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m index 79fc65aa..c38fa520 100644 --- a/src/audio/coreaudio/SDL_coreaudio.m +++ b/src/audio/coreaudio/SDL_coreaudio.m @@ -417,7 +417,7 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b category = AVAudioSessionCategoryRecord; } - #if !TARGET_OS_TV + #ifndef SDL_PLATFORM_TVOS if (category == AVAudioSessionCategoryPlayAndRecord) { options |= AVAudioSessionCategoryOptionDefaultToSpeaker; } @@ -753,7 +753,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) // Make sure we can feed the device a minimum amount of time double MINIMUM_AUDIO_BUFFER_TIME_MS = 15.0; - #ifdef __IOS__ + #ifdef SDL_PLATFORM_IOS if (SDL_floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { // Older iOS hardware, use 40 ms as a minimum time MINIMUM_AUDIO_BUFFER_TIME_MS = 40.0; @@ -846,17 +846,17 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) AVAudioSession *session = [AVAudioSession sharedInstance]; [session setPreferredSampleRate:device->spec.freq error:nil]; device->spec.freq = (int)session.sampleRate; - #if TARGET_OS_TV + #ifdef SDL_PLATFORM_TVOS if (device->iscapture) { [session setPreferredInputNumberOfChannels:device->spec.channels error:nil]; - device->spec.channels = session.preferredInputNumberOfChannels; + device->spec.channels = (int)session.preferredInputNumberOfChannels; } else { [session setPreferredOutputNumberOfChannels:device->spec.channels error:nil]; - device->spec.channels = session.preferredOutputNumberOfChannels; + device->spec.channels = (int)session.preferredOutputNumberOfChannels; } #else // Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS - #endif // TARGET_OS_TV + #endif /* SDL_PLATFORM_TVOS */ } #endif diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index cd659c06..2d810112 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -51,6 +51,10 @@ static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 = NULL; static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL; static fnGetDeviceID pGetDeviceID = NULL; +#include +DEFINE_GUID(SDL_DSDEVID_DefaultPlayback, 0xdef00000, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); +DEFINE_GUID(SDL_DSDEVID_DefaultCapture, 0xdef00001, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + 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 } }; @@ -214,12 +218,12 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi data.iscapture = SDL_TRUE; data.default_device = default_capture; - data.default_device_guid = (pGetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) ? &guid : NULL; + 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.default_device_guid = (pGetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) ? &guid : NULL; + data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultPlayback, &guid) == DS_OK) ? &guid : NULL; pDirectSoundEnumerateW(FindAllDevs, &data); } @@ -528,6 +532,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) } const DWORD numchunks = 8; + DWORD bufsize; SDL_bool tried_format = SDL_FALSE; SDL_AudioFormat test_format; const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); @@ -544,7 +549,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) // Update the fragment size as size in bytes SDL_UpdatedAudioDeviceFormat(device); - const DWORD bufsize = numchunks * device->buffer_size; + bufsize = numchunks * device->buffer_size; if ((bufsize < DSBSIZE_MIN) || (bufsize > DSBSIZE_MAX)) { SDL_SetError("Sound buffer size must be between %d and %d", (int)((DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks), @@ -583,7 +588,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) wfmt.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; default: - SDL_assert(0 && "Unsupported channel count!"); + SDL_assert(!"Unsupported channel count!"); break; } } else if (SDL_AUDIO_ISFLOAT(device->spec.format)) { diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index e0fd415f..c68f8a24 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -43,7 +43,7 @@ static int DISKAUDIO_WaitDevice(SDL_AudioDevice *device) static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { - const int written = (int)SDL_RWwrite(device->hidden->io, buffer, (size_t)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; } @@ -64,11 +64,11 @@ static int DISKAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, in const int origbuflen = buflen; if (h->io) { - const int br = (int)SDL_RWread(h->io, buffer, (size_t)buflen); + const int br = (int)SDL_ReadIO(h->io, buffer, (size_t)buflen); buflen -= br; buffer = ((Uint8 *)buffer) + br; if (buflen > 0) { // EOF (or error, but whatever). - SDL_RWclose(h->io); + SDL_CloseIO(h->io); h->io = NULL; } } @@ -88,7 +88,7 @@ static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { if (device->hidden->io) { - SDL_RWclose(device->hidden->io); + SDL_CloseIO(device->hidden->io); } SDL_free(device->hidden->mixbuf); SDL_free(device->hidden); @@ -123,7 +123,7 @@ static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) } // Open the "audio device" - device->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb"); + device->hidden->io = SDL_IOFromFile(fname, iscapture ? "rb" : "wb"); if (!device->hidden->io) { return -1; } diff --git a/src/audio/disk/SDL_diskaudio.h b/src/audio/disk/SDL_diskaudio.h index 81d22b65..3a7bbc7e 100644 --- a/src/audio/disk/SDL_diskaudio.h +++ b/src/audio/disk/SDL_diskaudio.h @@ -28,7 +28,7 @@ struct SDL_PrivateAudioData { // The file descriptor for the audio device - SDL_RWops *io; + SDL_IOStream *io; Uint32 io_delay; Uint8 *mixbuf; }; diff --git a/src/audio/jack/SDL_jackaudio.c b/src/audio/jack/SDL_jackaudio.c index 3fb16fde..726b22d9 100644 --- a/src/audio/jack/SDL_jackaudio.c +++ b/src/audio/jack/SDL_jackaudio.c @@ -416,6 +416,7 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) 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; } JACK_jack_client_close(client); diff --git a/src/audio/openslES/SDL_openslES.c b/src/audio/openslES/SDL_openslES.c index 84f92a41..bda1b91c 100644 --- a/src/audio/openslES/SDL_openslES.c +++ b/src/audio/openslES/SDL_openslES.c @@ -228,6 +228,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) +{ + SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1); +} + static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; @@ -241,9 +247,22 @@ static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) SLresult result; int i; - if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) { - LOGE("This app doesn't have RECORD_AUDIO permission"); - return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); + // !!! 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; + } + + while (SDL_AtomicGet(&permission_response) == 0) { + SDL_Delay(10); + } + + if (SDL_AtomicGet(&permission_response) < 0) { + LOGE("This app doesn't have RECORD_AUDIO permission"); + return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); + } } // Just go with signed 16-bit audio as it's the most compatible diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index 492b0e49..9941f17d 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -826,11 +826,13 @@ 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)); if (pipewire_default_sink_id && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) { - SDL_assert(!io->is_capture); - *default_output = device; + if (!io->is_capture) { + *default_output = device; + } } else if (pipewire_default_source_id && SDL_strcmp(io->path, pipewire_default_source_id) == 0) { - SDL_assert(io->is_capture); - *default_capture = device; + if (io->is_capture) { + *default_capture = device; + } } } diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 5eae508b..ee1f25b7 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -71,7 +71,7 @@ static void ManagementThreadMainloop(void) { SDL_LockMutex(ManagementThreadLock); ManagementThreadPendingTask *task; - while (((task = SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks)) != NULL) || !SDL_AtomicGet(&ManagementThreadShutdown)) { + while (((task = (ManagementThreadPendingTask *)SDL_AtomicGetPtr((void **)&ManagementThreadPendingTasks)) != NULL) || !SDL_AtomicGet(&ManagementThreadShutdown)) { if (!task) { SDL_WaitCondition(ManagementThreadCondition, ManagementThreadLock); // block until there's something to do. } else { @@ -93,7 +93,7 @@ static void ManagementThreadMainloop(void) int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *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_ThreadID() == SDL_GetThreadID(ManagementThread))) { + if ((wait_on_result) && (SDL_GetCurrentThreadID() == SDL_GetThreadID(ManagementThread))) { *wait_on_result = task(userdata); return 0; // completed! } @@ -102,7 +102,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in return SDL_SetError("Can't add task, we're shutting down"); } - ManagementThreadPendingTask *pending = SDL_calloc(1, sizeof(ManagementThreadPendingTask)); + ManagementThreadPendingTask *pending = (ManagementThreadPendingTask *)SDL_calloc(1, sizeof(ManagementThreadPendingTask)); if (!pending) { return -1; } @@ -124,7 +124,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in // add to end of task list. ManagementThreadPendingTask *prev = NULL; - for (ManagementThreadPendingTask *i = SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks); i; i = i->next) { + for (ManagementThreadPendingTask *i = (ManagementThreadPendingTask *)SDL_AtomicGetPtr((void **)&ManagementThreadPendingTasks); i; i = i->next) { prev = i; } @@ -265,7 +265,9 @@ static void WASAPI_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi { int rc; // this blocks because it needs to finish before the audio subsystem inits - mgmtthrtask_DetectDevicesData data = { default_output, default_capture }; + mgmtthrtask_DetectDevicesData data; + data.default_output = default_output; + data.default_capture = default_capture; WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc); } @@ -432,7 +434,11 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) BYTE *buffer = NULL; if (device->hidden->render) { - if (WasapiFailed(device, IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer))) { + const HRESULT ret = IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer); + if (ret == AUDCLNT_E_BUFFER_TOO_LARGE) { + SDL_assert(buffer == NULL); + *buffer_size = 0; // just go back to WaitDevice and try again after the hardware has consumed some more data. + } else if (WasapiFailed(device, ret)) { SDL_assert(buffer == NULL); if (device->hidden->device_lost) { // just use an available buffer, we won't be playing it anyhow. *buffer_size = 0; // we'll recover during WaitDevice and try again. @@ -564,7 +570,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) IAudioClient *client = device->hidden->client; SDL_assert(client != NULL); -#if defined(__WINRT__) || defined(__GDK__) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP. +#if defined(SDL_PLATFORM_WINRT) || 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); @@ -642,11 +648,16 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't determine buffer size", ret); } - /* Match the callback size to the period size to cut down on the number of - interrupts waited for in each call to WaitDevice */ + // 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; - const int new_sample_frames = (int) SDL_ceilf(period_frames); + int 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) { + new_sample_frames = (int) bufsize; + } // Update the fragment size as size in bytes if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) < 0) { diff --git a/src/audio/wasapi/SDL_wasapi_win32.c b/src/audio/wasapi/SDL_wasapi_win32.c index fd84394f..c72c54b4 100644 --- a/src/audio/wasapi/SDL_wasapi_win32.c +++ b/src/audio/wasapi/SDL_wasapi_win32.c @@ -26,7 +26,7 @@ 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(__WINRT__) +#if defined(SDL_AUDIO_DRIVER_WASAPI) && !defined(SDL_PLATFORM_WINRT) #include "../../core/windows/SDL_windows.h" #include "../../core/windows/SDL_immdevice.h" @@ -202,4 +202,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device) SDL_IMMDevice_FreeDeviceHandle(device); } -#endif // SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__) +#endif // SDL_AUDIO_DRIVER_WASAPI && !defined(SDL_PLATFORM_WINRT) diff --git a/src/audio/wasapi/SDL_wasapi_winrt.cpp b/src/audio/wasapi/SDL_wasapi_winrt.cpp index 0af821d7..700f5cf5 100644 --- a/src/audio/wasapi/SDL_wasapi_winrt.cpp +++ b/src/audio/wasapi/SDL_wasapi_winrt.cpp @@ -25,7 +25,7 @@ // 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(__WINRT__) +#if defined(SDL_AUDIO_DRIVER_WASAPI) && defined(SDL_PLATFORM_WINRT) #include #include @@ -357,4 +357,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device) SDL_free(device->handle); } -#endif // SDL_AUDIO_DRIVER_WASAPI && defined(__WINRT__) +#endif // SDL_AUDIO_DRIVER_WASAPI && defined(SDL_PLATFORM_WINRT) diff --git a/src/camera/SDL_camera.c b/src/camera/SDL_camera.c new file mode 100644 index 00000000..49cc9c13 --- /dev/null +++ b/src/camera/SDL_camera.c @@ -0,0 +1,1505 @@ +/* + 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_syscamera.h" +#include "SDL_camera_c.h" +#include "../video/SDL_pixels_c.h" +#include "../thread/SDL_systhread.h" + + +// A lot of this is a simplified version of SDL_audio.c; if fixing stuff here, +// maybe check that file, too. + +// Available camera drivers +static const CameraBootStrap *const bootstrap[] = { +#ifdef SDL_CAMERA_DRIVER_V4L2 + &V4L2_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_COREMEDIA + &COREMEDIA_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_ANDROID + &ANDROIDCAMERA_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_EMSCRIPTEN + &EMSCRIPTENCAMERA_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_MEDIAFOUNDATION + &MEDIAFOUNDATION_bootstrap, +#endif +#ifdef SDL_CAMERA_DRIVER_DUMMY + &DUMMYCAMERA_bootstrap, +#endif + NULL +}; + +static SDL_CameraDriver camera_driver; + + +int SDL_GetNumCameraDrivers(void) +{ + return SDL_arraysize(bootstrap) - 1; +} + +const char *SDL_GetCameraDriver(int index) +{ + if (index >= 0 && index < SDL_GetNumCameraDrivers()) { + return bootstrap[index]->name; + } + return NULL; +} + +const char *SDL_GetCurrentCameraDriver(void) +{ + return camera_driver.name; +} + +char *SDL_GetCameraThreadName(SDL_CameraDevice *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) +{ + 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; + } + data->specs = (SDL_CameraSpec *) ptr; + data->allocated_specs = newalloc; + } + + SDL_CameraSpec *spec = &data->specs[data->num_specs]; + spec->format = fmt; + spec->width = w; + spec->height = h; + spec->interval_numerator = interval_numerator; + spec->interval_denominator = interval_denominator; + + data->num_specs++; + + return 0; +} + + +// Zombie device implementation... + +// 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) +{ + 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)); + SDL_Delay((Uint32) (duration * 1000.0)); + } + return 0; +} + +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; + + switch (fmt) { + // Some YUV formats have a larger Y plane than their U or V planes. + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + return wxh + (wxh / 2); + + default: break; + } + + // this is correct for most things. + return wxh * SDL_BYTESPERPIXEL(fmt); +} + +static int ZombieAcquireFrame(SDL_CameraDevice *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); + 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...? + } + + Uint8 *dst = device->zombie_pixels; + switch (spec->format) { + // in YUV formats, the U and V values must be 128 to get a black frame. If set to zero, it'll be bright green. + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + SDL_memset(dst, 0, spec->width * spec->height); // set Y to zero. + SDL_memset(dst + (spec->width * spec->height), 128, (spec->width * spec->height) / 2); // set U and V to 128. + break; + + case SDL_PIXELFORMAT_YUY2: + case SDL_PIXELFORMAT_YVYU: + // Interleaved Y1[U1|V1]Y2[U2|V2]. + for (size_t i = 0; i < buflen; i += 4) { + dst[i] = 0; + dst[i+1] = 128; + dst[i+2] = 0; + dst[i+3] = 128; + } + break; + + + case SDL_PIXELFORMAT_UYVY: + // Interleaved [U1|V1]Y1[U2|V2]Y2. + for (size_t i = 0; i < buflen; i += 4) { + dst[i] = 128; + dst[i+1] = 0; + dst[i+2] = 128; + dst[i+3] = 0; + } + break; + + default: + // just zero everything else, it'll _probably_ be okay. + SDL_memset(dst, 0, buflen); + break; + } + } + + + *timestampNS = SDL_GetTicksNS(); + frame->pixels = device->zombie_pixels; + + // SDL (currently) wants the pitch of YUV formats to be the pitch of the (1-byte-per-pixel) Y plane. + frame->pitch = spec->width; + if (!SDL_ISPIXELFORMAT_FOURCC(spec->format)) { // checking if it's not FOURCC to only do this for non-YUV data is good enough for now. + frame->pitch *= SDL_BYTESPERPIXEL(spec->format); + } + + #if DEBUG_CAMERA + SDL_Log("CAMERA: dev[%p] Acquired Zombie frame, timestamp %llu", device, (unsigned long long) *timestampNS); + #endif + + return 1; // frame is available. +} + +static void ZombieReleaseFrame(SDL_CameraDevice *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. + camera_driver.impl.ReleaseFrame(device, 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) +{ + if (!device) { + return; + } + + SDL_AtomicSet(&device->shutdown, 1); + +// !!! FIXME: the close_cond stuff from audio might help the race condition here. + + if (device->thread != NULL) { + SDL_WaitThread(device->thread, NULL); + device->thread = NULL; + } + + // release frames that are queued up somewhere... + if (!device->needs_conversion && !device->needs_scaling) { + for (SurfaceList *i = device->filled_output_surfaces.next; i != NULL; i = i->next) { + device->ReleaseFrame(device, i->surface); + } + for (SurfaceList *i = device->app_held_output_surfaces.next; i != NULL; i = i->next) { + device->ReleaseFrame(device, i->surface); + } + } + + camera_driver.impl.CloseDevice(device); + + SDL_DestroyProperties(device->props); + + SDL_DestroySurface(device->acquire_surface); + device->acquire_surface = NULL; + SDL_DestroySurface(device->conversion_surface); + device->conversion_surface = NULL; + + for (int i = 0; i < SDL_arraysize(device->output_surfaces); i++) { + SDL_DestroySurface(device->output_surfaces[i].surface); + } + SDL_zeroa(device->output_surfaces); + + SDL_aligned_free(device->zombie_pixels); + + device->permission = 0; + device->zombie_pixels = NULL; + device->filled_output_surfaces.next = NULL; + device->empty_output_surfaces.next = NULL; + device->app_held_output_surfaces.next = NULL; + + device->base_timestamp = 0; + device->adjust_timestamp = 0; +} + +// 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) +{ + if (device) { + // Destroy any logical devices that still exist... + ClosePhysicalCameraDevice(device); + camera_driver.impl.FreeDeviceHandle(device); + SDL_DestroyMutex(device->lock); + SDL_free(device->all_specs); + SDL_free(device->name); + SDL_free(device); + } +} + + +// Don't hold the device lock when calling this, as we may destroy the device! +void UnrefPhysicalCameraDevice(SDL_CameraDevice *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_UnlockRWLock(camera_driver.device_hash_lock); + DestroyPhysicalCameraDevice(device); // ...and nuke it. + } +} + +void RefPhysicalCameraDevice(SDL_CameraDevice *device) +{ + SDL_AtomicIncRef(&device->refcount); +} + +static void ObtainPhysicalCameraDeviceObj(SDL_CameraDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXMEL SDL_ACQUIRE +{ + if (device) { + RefPhysicalCameraDevice(device); + SDL_LockMutex(device->lock); + } +} + +static SDL_CameraDevice *ObtainPhysicalCameraDevice(SDL_CameraDeviceID devid) // !!! FIXME: SDL_ACQUIRE +{ + if (!SDL_GetCurrentCameraDriver()) { + SDL_SetError("Camera subsystem is not initialized"); + return NULL; + } + + SDL_CameraDevice *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); + } + return device; +} + +static void ReleaseCameraDevice(SDL_CameraDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_RELEASE +{ + if (device) { + SDL_UnlockMutex(device->lock); + UnrefPhysicalCameraDevice(device); + } +} + +// we want these sorted by format first, so you can find a block of all +// resolutions that are supported for a format. The formats are sorted in +// "best" order, but that's subjective: right now, we prefer planar +// formats, since they're likely what the cameras prefer to produce +// anyhow, and they basically send the same information in less space +// than an RGB-style format. After that, sort by bits-per-pixel. + +// we want specs sorted largest to smallest dimensions, larger width taking precedence over larger height. +static int SDLCALL CameraSpecCmp(const void *vpa, const void *vpb) +{ + const SDL_CameraSpec *a = (const SDL_CameraSpec *) vpa; + const SDL_CameraSpec *b = (const SDL_CameraSpec *) vpb; + + // driver shouldn't send specs like this, check here since we're eventually going to sniff the whole array anyhow. + SDL_assert(a->format != SDL_PIXELFORMAT_UNKNOWN); + SDL_assert(a->width > 0); + SDL_assert(a->height > 0); + SDL_assert(b->format != SDL_PIXELFORMAT_UNKNOWN); + SDL_assert(b->width > 0); + SDL_assert(b->height > 0); + + const Uint32 afmt = a->format; + const Uint32 bfmt = b->format; + if (SDL_ISPIXELFORMAT_FOURCC(afmt) && !SDL_ISPIXELFORMAT_FOURCC(bfmt)) { + return -1; + } else if (!SDL_ISPIXELFORMAT_FOURCC(afmt) && SDL_ISPIXELFORMAT_FOURCC(bfmt)) { + return 1; + } else if (SDL_BITSPERPIXEL(afmt) > SDL_BITSPERPIXEL(bfmt)) { + return -1; + } else if (SDL_BITSPERPIXEL(bfmt) > SDL_BITSPERPIXEL(afmt)) { + return 1; + } else if (a->width > b->width) { + return -1; + } else if (b->width > a->width) { + return 1; + } else if (a->height > b->height) { + return -1; + } else if (b->height > a->height) { + return 1; + } + + // still here? We care about framerate less than format or size, but faster is better than slow. + if (a->interval_numerator && !b->interval_numerator) { + return -1; + } else if (!a->interval_numerator && b->interval_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); + if (fpsa > fpsb) { + return -1; + } else if (fpsb > fpsa) { + 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_assert(name != NULL); + SDL_assert(num_specs >= 0); + SDL_assert((specs != NULL) == (num_specs > 0)); + SDL_assert(handle != NULL); + + SDL_LockRWLockForReading(camera_driver.device_hash_lock); + const int shutting_down = SDL_AtomicGet(&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)); + if (!device) { + return NULL; + } + + device->name = SDL_strdup(name); + if (!device->name) { + SDL_free(device); + return NULL; + } + + device->position = position; + + device->lock = SDL_CreateMutex(); + if (!device->lock) { + SDL_free(device->name); + SDL_free(device); + return NULL; + } + + device->all_specs = (SDL_CameraSpec *)SDL_calloc(num_specs + 1, sizeof (*specs)); + if (!device->all_specs) { + SDL_DestroyMutex(device->lock); + SDL_free(device->name); + SDL_free(device); + return NULL; + } + + if (num_specs > 0) { + SDL_memcpy(device->all_specs, specs, sizeof (*specs) * num_specs); + SDL_qsort(device->all_specs, num_specs, sizeof (*specs), CameraSpecCmp); + + // weed out duplicates, just in case. + for (int i = 0; i < num_specs; i++) { + SDL_CameraSpec *a = &device->all_specs[i]; + SDL_CameraSpec *b = &device->all_specs[i + 1]; + if (SDL_memcmp(a, b, sizeof (*a)) == 0) { + SDL_memmove(a, b, sizeof (*specs) * (num_specs - i)); + i--; + num_specs--; + } + } + } + + #if DEBUG_CAMERA + const char *posstr = "unknown position"; + if (position == SDL_CAMERA_POSITION_FRONT_FACING) { + posstr = "front-facing"; + } else if (position == SDL_CAMERA_POSITION_BACK_FACING) { + posstr = "back-facing"; + } + 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); + } + #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_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); + } else { + SDL_DestroyMutex(device->lock); + SDL_free(device->all_specs); + SDL_free(device->name); + SDL_free(device); + device = NULL; + } + + // 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)); + 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; + p->next = NULL; + SDL_assert(camera_driver.pending_events_tail != NULL); + SDL_assert(camera_driver.pending_events_tail->next == NULL); + camera_driver.pending_events_tail->next = p; + camera_driver.pending_events_tail = p; + } + } + SDL_UnlockRWLock(camera_driver.device_hash_lock); + + return device; +} + +// 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) +{ + if (!device) { + return; + } + + #if DEBUG_CAMERA + SDL_Log("CAMERA: DISCONNECTED! dev[%p]", device); + #endif + + // Save off removal info in a list so we can send events for each, next + // 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; + pending.next = NULL; + SDL_PendingCameraDeviceEvent *pending_tail = &pending; + + ObtainPhysicalCameraDeviceObj(device); + + const SDL_bool first_disconnect = SDL_AtomicCompareAndSwap(&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 + // accumulate waste data that never drains, apps that depend on audio callbacks to + // progress will freeze, etc. + device->WaitDevice = ZombieWaitDevice; + device->AcquireFrame = ZombieAcquireFrame; + device->ReleaseFrame = ZombieReleaseFrame; + + // Zombie functions will just report the timestamp as SDL_GetTicksNS(), so we don't need to adjust anymore to get it to match. + device->adjust_timestamp = 0; + device->base_timestamp = 0; + + SDL_PendingCameraDeviceEvent *p = (SDL_PendingCameraDeviceEvent *) SDL_malloc(sizeof (SDL_PendingCameraDeviceEvent)); + 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; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } + } + + ReleaseCameraDevice(device); + + if (first_disconnect) { + 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); + } + } +} + +void SDL_CameraDevicePermissionOutcome(SDL_CameraDevice *device, SDL_bool approved) +{ + if (!device) { + return; + } + + SDL_PendingCameraDeviceEvent pending; + pending.next = NULL; + SDL_PendingCameraDeviceEvent *pending_tail = &pending; + + const int permission = approved ? 1 : -1; + + ObtainPhysicalCameraDeviceObj(device); + if (device->permission != permission) { + device->permission = permission; + SDL_PendingCameraDeviceEvent *p = (SDL_PendingCameraDeviceEvent *) SDL_malloc(sizeof (SDL_PendingCameraDeviceEvent)); + 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; + p->next = NULL; + pending_tail->next = p; + pending_tail = p; + } + } + + ReleaseCameraDevice(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); +} + + +SDL_CameraDevice *SDL_FindPhysicalCameraDeviceByCallback(SDL_bool (*callback)(SDL_CameraDevice *device, void *userdata), void *userdata) +{ + if (!SDL_GetCurrentCameraDriver()) { + SDL_SetError("Camera subsystem is not initialized"); + return NULL; + } + + const void *key; + const void *value; + void *iter = NULL; + + SDL_LockRWLockForReading(camera_driver.device_hash_lock); + while (SDL_IterateHashTable(camera_driver.device_hash, &key, &value, &iter)) { + SDL_CameraDevice *device = (SDL_CameraDevice *) value; + if (callback(device, userdata)) { // found it? + SDL_UnlockRWLock(camera_driver.device_hash_lock); + return device; + } + } + + SDL_UnlockRWLock(camera_driver.device_hash_lock); + + SDL_SetError("Device not found"); + return NULL; +} + +void SDL_CloseCamera(SDL_Camera *camera) +{ + SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. + ClosePhysicalCameraDevice(device); +} + +int SDL_GetCameraFormat(SDL_Camera *camera, SDL_CameraSpec *spec) +{ + 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_copyp(spec, &device->spec); + } else { + SDL_zerop(spec); + } + ReleaseCameraDevice(device); + return 0; +} + +char *SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id) +{ + char *retval = NULL; + SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); + if (device) { + retval = SDL_strdup(device->name); + ReleaseCameraDevice(device); + } + return retval; +} + +SDL_CameraPosition SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id) +{ + SDL_CameraPosition retval = SDL_CAMERA_POSITION_UNKNOWN; + SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); + if (device) { + retval = device->position; + ReleaseCameraDevice(device); + } + return retval; +} + + +SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) +{ + int dummy_count; + if (!count) { + count = &dummy_count; + } + + if (!SDL_GetCurrentCameraDriver()) { + *count = 0; + SDL_SetError("Camera subsystem is not initialized"); + return NULL; + } + + SDL_CameraDeviceID *retval = 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) { + num_devices = 0; + } else { + int devs_seen = 0; + const void *key; + const void *value; + void *iter = NULL; + while (SDL_IterateHashTable(camera_driver.device_hash, &key, &value, &iter)) { + retval[devs_seen++] = (SDL_CameraDeviceID) (uintptr_t) key; + } + + SDL_assert(devs_seen == num_devices); + retval[devs_seen] = 0; // null-terminated. + } + SDL_UnlockRWLock(camera_driver.device_hash_lock); + + *count = num_devices; + + return retval; +} + +SDL_CameraSpec *SDL_GetCameraDeviceSupportedFormats(SDL_CameraDeviceID instance_id, int *count) +{ + if (count) { + *count = 0; + } + + SDL_CameraDevice *device = ObtainPhysicalCameraDevice(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); + if (count) { + *count = device->num_specs; + } + } + + ReleaseCameraDevice(device); + + return retval; +} + + +// 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) +{ + //camera_driver.impl.ThreadInit(device); +#ifdef SDL_VIDEO_DRIVER_ANDROID + // TODO + /* + { + // Set thread priority to THREAD_PRIORITY_VIDEO + extern void Android_JNI_CameraSetThreadPriority(int, int); + Android_JNI_CameraSetThreadPriority(device->iscapture, device); + }*/ +#else + // The camera capture is always a high priority thread + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); +#endif +} + +SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device) +{ + SDL_LockMutex(device->lock); + + if (SDL_AtomicGet(&device->shutdown)) { + SDL_UnlockMutex(device->lock); + return SDL_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. + } + + SDL_bool failed = SDL_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); + + if (rc == 1) { // 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 + + if (device->drop_frames > 0) { + #if DEBUG_CAMERA + SDL_Log("CAMERA: Dropping an initial frame"); + #endif + device->drop_frames--; + device->ReleaseFrame(device, device->acquire_surface); + device->acquire_surface->pixels = NULL; + device->acquire_surface->pitch = 0; + } else if (device->empty_output_surfaces.next == NULL) { + // uhoh, no output frames available! Either the app is slow, or it forgot to release frames when done with them. Drop this new frame. + #if DEBUG_CAMERA + SDL_Log("CAMERA: No empty output surfaces! Dropping frame!"); + #endif + device->ReleaseFrame(device, device->acquire_surface); + device->acquire_surface->pixels = NULL; + device->acquire_surface->pitch = 0; + } else { + if (!device->adjust_timestamp) { + device->adjust_timestamp = SDL_GetTicksNS(); + device->base_timestamp = timestampNS; + } + timestampNS = (timestampNS - device->base_timestamp) + device->adjust_timestamp; + + slist = device->empty_output_surfaces.next; + output_surface = slist->surface; + device->empty_output_surfaces.next = slist->next; + acquired = device->acquire_surface; + slist->timestampNS = timestampNS; + } + } else if (rc == 0) { // 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; + } + + // 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. + // this lets us chew up the CPU for conversion and scaling without blocking other threads. + SDL_UnlockMutex(device->lock); + + if (failed) { + SDL_assert(slist == NULL); + SDL_assert(acquired == NULL); + SDL_CameraDeviceDisconnected(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->pixels = acquired->pixels; + output_surface->pitch = acquired->pitch; + } else { // convert/scale into a different surface. + #if DEBUG_CAMERA + SDL_Log("CAMERA: Frame is getting converted!"); + #endif + SDL_Surface *srcsurf = acquired; + if (device->needs_scaling == -1) { // downscaling? Do it first. -1: downscale, 0: no scaling, 1: upscale + SDL_Surface *dstsurf = device->needs_conversion ? device->conversion_surface : output_surface; + SDL_SoftStretch(srcsurf, NULL, dstsurf, NULL, SDL_SCALEMODE_NEAREST); // !!! FIXME: linear scale? letterboxing? + srcsurf = dstsurf; + } + 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 = dstsurf; + } + if (device->needs_scaling == 1) { // upscaling? Do it last. -1: downscale, 0: no scaling, 1: upscale + SDL_SoftStretch(srcsurf, NULL, output_surface, NULL, SDL_SCALEMODE_NEAREST); // !!! FIXME: linear scale? letterboxing? + } + + // we made a copy, so we can give the driver back its resources. + device->ReleaseFrame(device, acquired); + } + + // we either released these already after we copied the data, or the pointer was migrated to output_surface. + acquired->pixels = NULL; + acquired->pitch = 0; + + // make the filled output surface available to the app. + SDL_LockMutex(device->lock); + slist->next = device->filled_output_surfaces.next; + device->filled_output_surfaces.next = slist; + SDL_UnlockMutex(device->lock); + } + + return SDL_TRUE; // always go on if not shutting down, even if device failed. +} + +void SDL_CameraThreadShutdown(SDL_CameraDevice *device) +{ + //device->FlushCapture(device); + //camera_driver.impl.ThreadDeinit(device); + //SDL_CameraThreadFinalize(device); +} + +// Actual thread entry point, if driver didn't handle this itself. +static int SDLCALL CameraThread(void *devicep) +{ + SDL_CameraDevice *device = (SDL_CameraDevice *) devicep; + + #if DEBUG_CAMERA + SDL_Log("CAMERA: dev[%p] Start thread 'CameraThread'", devicep); + #endif + + SDL_assert(device != NULL); + 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!) + } + } while (SDL_CameraThreadIterate(device)); + + SDL_CameraThreadShutdown(device); + + #if DEBUG_CAMERA + SDL_Log("CAMERA: dev[%p] End thread 'CameraThread'", devicep); + #endif + + return 0; +} + +static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec *spec, SDL_CameraSpec *closest) +{ + // Find the closest available native format/size... + // + // We want the exact size if possible, even if we have + // to convert formats, because we can _probably_ do that + // conversion losslessly at less expense verses scaling. + // + // Failing that, we want the size that's closest to the + // requested aspect ratio, then the closest size within + // that. + + SDL_zerop(closest); + SDL_assert(((Uint32) SDL_PIXELFORMAT_UNKNOWN) == 0); // since we SDL_zerop'd to this value. + + if (device->num_specs == 0) { // device listed no specs! You get whatever you want! + if (spec) { + SDL_copyp(closest, spec); + } + return; + } else if (!spec) { // nothing specifically requested, get the best format we can... + // we sorted this into the "best" format order when adding the camera. + SDL_copyp(closest, &device->all_specs[0]); + } else { // specific thing requested, try to get as close to that as possible... + const int num_specs = device->num_specs; + 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) { + 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; + } + } + + 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; + 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 (thisspec->format == wantfmt) { + bestfmt = thisspec->format; + break; // exact match, stop looking. + } + } + } + + SDL_assert(bestfmt != SDL_PIXELFORMAT_UNKNOWN); + closest->format = bestfmt; + + // 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; + 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; + 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); + 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; + } + } + } + } + + SDL_assert(closest->width > 0); + SDL_assert(closest->height > 0); + SDL_assert(closest->format != SDL_PIXELFORMAT_UNKNOWN); +} + +SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID 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); + if (!device) { + return NULL; + } + + if (device->hidden != NULL) { + ReleaseCameraDevice(device); + SDL_SetError("Camera already opened"); // we may remove this limitation at some point. + return NULL; + } + + SDL_AtomicSet(&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; + device->AcquireFrame = camera_driver.impl.AcquireFrame; + device->ReleaseFrame = camera_driver.impl.ReleaseFrame; + + SDL_CameraSpec closest; + 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); + #endif + + if (camera_driver.impl.OpenDevice(device, &closest) < 0) { + ClosePhysicalCameraDevice(device); // in case anything is half-initialized. + ReleaseCameraDevice(device); + return NULL; + } + + if (!spec) { + SDL_copyp(&device->spec, &closest); + } else { + SDL_copyp(&device->spec, spec); + } + + SDL_copyp(&device->actual_spec, &closest); + + if ((closest.width == device->spec.width) && (closest.height == device->spec.height)) { + device->needs_scaling = 0; + } else { + const Uint64 srcarea = ((Uint64) closest.width) * ((Uint64) closest.height); + const Uint64 dstarea = ((Uint64) device->spec.width) * ((Uint64) device->spec.height); + if (dstarea <= srcarea) { + device->needs_scaling = -1; // downscaling (or changing to new aspect ratio with same area) + } else { + device->needs_scaling = 1; // upscaling + } + } + + device->needs_conversion = (closest.format != device->spec.format); + + device->acquire_surface = SDL_CreateSurfaceFrom(NULL, closest.width, closest.height, 0, closest.format); + if (!device->acquire_surface) { + ClosePhysicalCameraDevice(device); + ReleaseCameraDevice(device); + return NULL; + } + + // 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 SDL_CameraSpec *s = downsampling_first ? &device->spec : &closest; + const SDL_PixelFormatEnum fmt = downsampling_first ? closest.format : device->spec.format; + device->conversion_surface = SDL_CreateSurface(s->width, s->height, fmt); + } + + // output surfaces are in the app-requested format. If no conversion is necessary, we'll just use the pointers + // the backend fills into acquired_surface, and you can get all the way from DMA access in the camera hardware + // to the app without a single copy. Otherwise, these will be full surfaces that hold converted/scaled copies. + + for (int i = 0; i < (SDL_arraysize(device->output_surfaces) - 1); i++) { + device->output_surfaces[i].next = &device->output_surfaces[i + 1]; + } + device->empty_output_surfaces.next = device->output_surfaces; + + for (int i = 0; i < SDL_arraysize(device->output_surfaces); i++) { + SDL_Surface *surf; + 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); + } + + if (!surf) { + ClosePhysicalCameraDevice(device); + ReleaseCameraDevice(device); + return NULL; + } + + device->output_surfaces[i].surface = surf; + } + + device->drop_frames = 1; + + // Start the camera thread if necessary + if (!camera_driver.impl.ProvidesOwnCallbackThread) { + char threadname[64]; + SDL_GetCameraThreadName(device, threadname, sizeof (threadname)); + device->thread = SDL_CreateThreadInternal(CameraThread, threadname, 0, device); + if (!device->thread) { + ClosePhysicalCameraDevice(device); + ReleaseCameraDevice(device); + SDL_SetError("Couldn't create camera thread"); + return NULL; + } + } + + ReleaseCameraDevice(device); // unlock, we're good to go! + + return (SDL_Camera *) device; // currently there's no separation between physical and logical device. +} + +SDL_Surface *SDL_AcquireCameraFrame(SDL_Camera *camera, Uint64 *timestampNS) +{ + if (timestampNS) { + *timestampNS = 0; + } + + if (!camera) { + SDL_InvalidParamError("camera"); + return NULL; + } + + SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. + + ObtainPhysicalCameraDeviceObj(device); + + if (device->permission <= 0) { + ReleaseCameraDevice(device); + SDL_SetError("Camera permission has not been granted"); + return NULL; + } + + SDL_Surface *retval = NULL; + + // frames are in this list from newest to oldest, so find the end of the list... + SurfaceList *slistprev = &device->filled_output_surfaces; + SurfaceList *slist = slistprev; + while (slist->next) { + slistprev = slist; + slist = slist->next; + } + + const SDL_bool list_is_empty = (slist == slistprev); + if (!list_is_empty) { // report the oldest frame. + if (timestampNS) { + *timestampNS = slist->timestampNS; + } + retval = 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); + + return retval; +} + +int SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame) +{ + if (!camera) { + return SDL_InvalidParamError("camera"); + } else if (frame == NULL) { + return SDL_InvalidParamError("frame"); + } + + SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraDeviceObj(device); + + SurfaceList *slistprev = &device->app_held_output_surfaces; + SurfaceList *slist; + for (slist = slistprev->next; slist != NULL; slist = slist->next) { + if (slist->surface == frame) { + break; + } + slistprev = slist; + } + + if (!slist) { + ReleaseCameraDevice(device); + return SDL_SetError("Surface was not acquired from this camera, or was already released"); + } + + // this pointer was owned by the backend (DMA memory or whatever), clear it out. + if (!device->needs_conversion && !device->needs_scaling) { + device->ReleaseFrame(device, frame); + frame->pixels = NULL; + frame->pitch = 0; + } + + slist->timestampNS = 0; + + // remove from app_held list... + slistprev->next = slist->next; + + // insert at front of empty list (and we'll use it first when we need to fill a new frame). + slist->next = device->empty_output_surfaces.next; + device->empty_output_surfaces.next = slist; + + ReleaseCameraDevice(device); + + return 0; +} + +SDL_CameraDeviceID SDL_GetCameraInstanceID(SDL_Camera *camera) +{ + SDL_CameraDeviceID retval = 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); + } + + return retval; +} + +SDL_PropertiesID SDL_GetCameraProperties(SDL_Camera *camera) +{ + SDL_PropertiesID retval = 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); + if (device->props == 0) { + device->props = SDL_CreateProperties(); + } + retval = device->props; + ReleaseCameraDevice(device); + } + + return retval; +} + +int SDL_GetCameraPermissionState(SDL_Camera *camera) +{ + int retval; + if (!camera) { + retval = SDL_InvalidParamError("camera"); + } else { + SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraDeviceObj(device); + retval = device->permission; + ReleaseCameraDevice(device); + } + + return retval; +} + + +static void CompleteCameraEntryPoints(void) +{ + // this doesn't currently fill in stub implementations, it just asserts the backend filled them all in. + #define FILL_STUB(x) SDL_assert(camera_driver.impl.x != NULL) + FILL_STUB(DetectDevices); + FILL_STUB(OpenDevice); + FILL_STUB(CloseDevice); + FILL_STUB(AcquireFrame); + FILL_STUB(ReleaseFrame); + FILL_STUB(FreeDeviceHandle); + FILL_STUB(Deinitialize); + #undef FILL_STUB +} + +void SDL_QuitCamera(void) +{ + if (!camera_driver.name) { // not initialized?! + return; + } + + SDL_LockRWLockForWriting(camera_driver.device_hash_lock); + SDL_AtomicSet(&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; + camera_driver.pending_events.next = NULL; + SDL_AtomicSet(&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) { + pending_next = i->next; + SDL_free(i); + } + + const void *key; + const void *value; + void *iter = NULL; + while (SDL_IterateHashTable(device_hash, &key, &value, &iter)) { + DestroyPhysicalCameraDevice((SDL_CameraDevice *) value); + } + + // Free the driver data + camera_driver.impl.Deinitialize(); + + SDL_DestroyRWLock(camera_driver.device_hash_lock); + SDL_DestroyHashTable(device_hash); + + SDL_zero(camera_driver); +} + + +static Uint32 HashCameraDeviceID(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) +{ + return (a == b); // simple integers, just compare them as pointer values. +} + +static void NukeCameraDeviceHashItem(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) +{ + if (SDL_GetCurrentCameraDriver()) { + SDL_QuitCamera(); // shutdown driver if already running. + } + + 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; + } + + SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashCameraDeviceID, MatchCameraDeviceID, NukeCameraDeviceHashItem, SDL_FALSE); + if (!device_hash) { + SDL_DestroyRWLock(device_hash_lock); + return -1; + } + + // Select the proper camera driver + if (!driver_name) { + driver_name = SDL_GetHint(SDL_HINT_CAMERA_DRIVER); + } + + SDL_bool initialized = SDL_FALSE; + SDL_bool tried_to_init = SDL_FALSE; + + if (driver_name && (*driver_name != 0)) { + char *driver_name_copy = SDL_strdup(driver_name); + const char *driver_attempt = driver_name_copy; + + if (!driver_name_copy) { + SDL_DestroyRWLock(device_hash_lock); + SDL_DestroyHashTable(device_hash); + return -1; + } + + while (driver_attempt && (*driver_attempt != 0) && !initialized) { + char *driver_attempt_end = SDL_strchr(driver_attempt, ','); + if (driver_attempt_end) { + *driver_attempt_end = '\0'; + } + + for (int i = 0; bootstrap[i]; i++) { + if (SDL_strcasecmp(bootstrap[i]->name, driver_attempt) == 0) { + tried_to_init = SDL_TRUE; + SDL_zero(camera_driver); + camera_driver.pending_events_tail = &camera_driver.pending_events; + camera_driver.device_hash_lock = device_hash_lock; + camera_driver.device_hash = device_hash; + if (bootstrap[i]->init(&camera_driver.impl)) { + camera_driver.name = bootstrap[i]->name; + camera_driver.desc = bootstrap[i]->desc; + initialized = SDL_TRUE; + } + break; + } + } + + driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL; + } + + SDL_free(driver_name_copy); + } else { + for (int i = 0; !initialized && bootstrap[i]; i++) { + if (bootstrap[i]->demand_only) { + continue; + } + + tried_to_init = SDL_TRUE; + SDL_zero(camera_driver); + camera_driver.pending_events_tail = &camera_driver.pending_events; + camera_driver.device_hash_lock = device_hash_lock; + camera_driver.device_hash = device_hash; + if (bootstrap[i]->init(&camera_driver.impl)) { + camera_driver.name = bootstrap[i]->name; + camera_driver.desc = bootstrap[i]->desc; + initialized = SDL_TRUE; + } + } + } + + if (!initialized) { + // specific drivers will set the error message if they fail, but otherwise we do it here. + if (!tried_to_init) { + if (driver_name) { + SDL_SetError("Camera driver '%s' not available", driver_name); + } else { + SDL_SetError("No available camera driver"); + } + } + + SDL_zero(camera_driver); + SDL_DestroyRWLock(device_hash_lock); + SDL_DestroyHashTable(device_hash); + return -1; // No driver was available, so fail. + } + + CompleteCameraEntryPoints(); + + // Make sure we have a list of devices available at startup... + camera_driver.impl.DetectDevices(); + + return 0; +} + +// This is an internal function, so SDL_PumpEvents() can check for pending camera device events. +// ("UpdateSubsystem" is the same naming that the other things that hook into PumpEvents use.) +void SDL_UpdateCamera(void) +{ + SDL_LockRWLockForReading(camera_driver.device_hash_lock); + SDL_PendingCameraDeviceEvent *pending_events = camera_driver.pending_events.next; + SDL_UnlockRWLock(camera_driver.device_hash_lock); + + if (!pending_events) { + return; // nothing to do, check next time. + } + + // okay, let's take this whole list of events so we can dump the lock, and new ones can queue up for a later update. + SDL_LockRWLockForWriting(camera_driver.device_hash_lock); + pending_events = camera_driver.pending_events.next; // in case this changed... + camera_driver.pending_events.next = NULL; + 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) { + 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; + SDL_PushEvent(&event); + } + SDL_free(i); + } +} + diff --git a/src/video/SDL_video_capture_c.h b/src/camera/SDL_camera_c.h similarity index 76% rename from src/video/SDL_video_capture_c.h rename to src/camera/SDL_camera_c.h index d7f1aa17..6fae3101 100644 --- a/src/video/SDL_video_capture_c.h +++ b/src/camera/SDL_camera_c.h @@ -19,15 +19,17 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "../SDL_internal.h" -#include "../../include/SDL3/SDL_video_capture.h" -#ifndef SDL_video_capture_c_h_ -#define SDL_video_capture_c_h_ +#ifndef SDL_camera_c_h_ +#define SDL_camera_c_h_ -/* Initialize the video_capture subsystem */ -int SDL_VideoCaptureInit(void); +// Initialize the camera subsystem +int SDL_CameraInit(const char *driver_name); -/* Shutdown the video_capture subsystem */ -void SDL_QuitVideoCapture(void); +// Shutdown the camera subsystem +void SDL_QuitCamera(void); -#endif /* SDL_video_capture_c_h_ */ +// "Pump" the event queue. +extern void SDL_UpdateCamera(void); + +#endif // SDL_camera_c_h_ diff --git a/src/camera/SDL_syscamera.h b/src/camera/SDL_syscamera.h new file mode 100644 index 00000000..335ce4b1 --- /dev/null +++ b/src/camera/SDL_syscamera.h @@ -0,0 +1,213 @@ +/* + 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_syscamera_h_ +#define SDL_syscamera_h_ + +#include "../SDL_hashtable.h" + +#define DEBUG_CAMERA 0 + +typedef struct SDL_CameraDevice SDL_CameraDevice; + +/* 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); + +/* 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); + +// 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); + +// Backends should call this when the user has approved/denied access to a camera. +extern void SDL_CameraDevicePermissionOutcome(SDL_CameraDevice *device, SDL_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); + +// Backends can call these to change a device's refcount. +extern void RefPhysicalCameraDevice(SDL_CameraDevice *device); +extern void UnrefPhysicalCameraDevice(SDL_CameraDevice *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); + +// common utility functionality to gather up camera specs. Not required! +typedef struct CameraFormatAddData +{ + SDL_CameraSpec *specs; + int num_specs; + int allocated_specs; +} CameraFormatAddData; + +int SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormatEnum fmt, int w, int h, int interval_numerator, int interval_denominator); + +typedef struct SurfaceList +{ + SDL_Surface *surface; + Uint64 timestampNS; + struct SurfaceList *next; +} SurfaceList; + +// Define the SDL camera driver structure +struct SDL_CameraDevice +{ + // A mutex for locking + SDL_Mutex *lock; + + // Human-readable device name. + char *name; + + // Position of camera (front-facing, back-facing, etc). + SDL_CameraPosition position; + + // When refcount hits zero, we destroy the device object. + 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); + + // All supported formats/dimensions for this device. + SDL_CameraSpec *all_specs; + + // Elements in all_specs. + int num_specs; + + // The device's actual specification that the camera is outputting, before conversion. + SDL_CameraSpec actual_spec; + + // The device's current camera specification, after conversions. + SDL_CameraSpec spec; + + // Unique value assigned at creation time. + SDL_CameraDeviceID instance_id; + + // Driver-specific hardware data on how to open device (`hidden` is driver-specific data _when opened_). + void *handle; + + // Dropping the first frame(s) after open seems to help timing on some platforms. + int drop_frames; + + // Backend timestamp of first acquired frame, so we can keep these meaningful regardless of epoch. + Uint64 base_timestamp; + + // SDL timestamp of first acquired frame, so we can roughly convert to SDL ticks. + Uint64 adjust_timestamp; + + // Pixel data flows from the driver into these, then gets converted for the app if necessary. + SDL_Surface *acquire_surface; + + // acquire_surface converts or scales to this surface before landing in output_surfaces, if necessary. + SDL_Surface *conversion_surface; + + // A queue of surfaces that buffer converted/scaled frames of video until the app claims them. + SurfaceList output_surfaces[8]; + SurfaceList filled_output_surfaces; // this is FIFO + SurfaceList empty_output_surfaces; // this is LIFO + SurfaceList app_held_output_surfaces; + + // A fake video frame we allocate if the camera fails/disconnects. + Uint8 *zombie_pixels; + + // 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; + + // Current state flags + SDL_AtomicInt shutdown; + SDL_AtomicInt zombie; + + // A thread to feed the camera device + SDL_Thread *thread; + + // Optional properties. + SDL_PropertiesID props; + + // -1: user denied permission, 0: waiting for user response, 1: user approved permission. + int permission; + + // Data private to this driver, used when device is opened and running. + struct SDL_PrivateCameraData *hidden; +}; + +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() + void (*Deinitialize)(void); + + SDL_bool ProvidesOwnCallbackThread; +} SDL_CameraDriverImpl; + +typedef struct SDL_PendingCameraDeviceEvent +{ + Uint32 type; + SDL_CameraDeviceID devid; + struct SDL_PendingCameraDeviceEvent *next; +} SDL_PendingCameraDeviceEvent; + +typedef struct SDL_CameraDriver +{ + const char *name; // The name of this camera driver + const char *desc; // The description of this camera driver + SDL_CameraDriverImpl 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 camera devices + SDL_PendingCameraDeviceEvent pending_events; + SDL_PendingCameraDeviceEvent *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. +} SDL_CameraDriver; + +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. +} CameraBootStrap; + +// Not all of these are available in a given build. Use #ifdefs, etc. +extern CameraBootStrap DUMMYCAMERA_bootstrap; +extern CameraBootStrap V4L2_bootstrap; +extern CameraBootStrap COREMEDIA_bootstrap; +extern CameraBootStrap ANDROIDCAMERA_bootstrap; +extern CameraBootStrap EMSCRIPTENCAMERA_bootstrap; +extern CameraBootStrap MEDIAFOUNDATION_bootstrap; + +#endif // SDL_syscamera_h_ diff --git a/src/camera/android/SDL_camera_android.c b/src/camera/android/SDL_camera_android.c new file mode 100644 index 00000000..f96990ee --- /dev/null +++ b/src/camera/android/SDL_camera_android.c @@ -0,0 +1,891 @@ +/* + 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_syscamera.h" +#include "../SDL_camera_c.h" +#include "../../video/SDL_pixels_c.h" +#include "../../thread/SDL_systhread.h" + +#ifdef SDL_CAMERA_DRIVER_ANDROID + +/* + * AndroidManifest.xml: + * + * + * + * Very likely SDL must be build with YUV support (done by default) + * + * https://developer.android.com/reference/android/hardware/camera2/CameraManager + * "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler), + * before configuring sessions on any of the camera devices." + */ + +// this is kinda gross, but on older NDK headers all the camera stuff is +// gated behind __ANDROID_API__. We'll dlopen() it at runtime, so we'll do +// the right thing on pre-Android 7.0 devices, but we still +// need the struct declarations and such in those headers. +// The other option is to make a massive jump in minimum Android version we +// support--going from ancient to merely really old--but this seems less +// distasteful and using dlopen matches practices on other SDL platforms. +// We'll see if it works out. +#if __ANDROID_API__ < 24 +#undef __ANDROID_API__ +#define __ANDROID_API__ 24 +#endif + +#include +#include +#include +#include +#include + +#include "../../core/android/SDL_android.h" + +static void *libcamera2ndk = NULL; +typedef ACameraManager* (*pfnACameraManager_create)(void); +typedef camera_status_t (*pfnACameraManager_registerAvailabilityCallback)(ACameraManager*, const ACameraManager_AvailabilityCallbacks*); +typedef camera_status_t (*pfnACameraManager_unregisterAvailabilityCallback)(ACameraManager*, const ACameraManager_AvailabilityCallbacks*); +typedef camera_status_t (*pfnACameraManager_getCameraIdList)(ACameraManager*, ACameraIdList**); +typedef void (*pfnACameraManager_deleteCameraIdList)(ACameraIdList*); +typedef void (*pfnACameraCaptureSession_close)(ACameraCaptureSession*); +typedef void (*pfnACaptureRequest_free)(ACaptureRequest*); +typedef void (*pfnACameraOutputTarget_free)(ACameraOutputTarget*); +typedef camera_status_t (*pfnACameraDevice_close)(ACameraDevice*); +typedef void (*pfnACameraManager_delete)(ACameraManager*); +typedef void (*pfnACaptureSessionOutputContainer_free)(ACaptureSessionOutputContainer*); +typedef void (*pfnACaptureSessionOutput_free)(ACaptureSessionOutput*); +typedef camera_status_t (*pfnACameraManager_openCamera)(ACameraManager*, const char*, ACameraDevice_StateCallbacks*, ACameraDevice**); +typedef camera_status_t (*pfnACameraDevice_createCaptureRequest)(const ACameraDevice*, ACameraDevice_request_template, ACaptureRequest**); +typedef camera_status_t (*pfnACameraDevice_createCaptureSession)(ACameraDevice*, const ACaptureSessionOutputContainer*, const ACameraCaptureSession_stateCallbacks*,ACameraCaptureSession**); +typedef camera_status_t (*pfnACameraManager_getCameraCharacteristics)(ACameraManager*, const char*, ACameraMetadata**); +typedef void (*pfnACameraMetadata_free)(ACameraMetadata*); +typedef camera_status_t (*pfnACameraMetadata_getConstEntry)(const ACameraMetadata*, uint32_t tag, ACameraMetadata_const_entry*); +typedef camera_status_t (*pfnACameraCaptureSession_setRepeatingRequest)(ACameraCaptureSession*, ACameraCaptureSession_captureCallbacks*, int numRequests, ACaptureRequest**, int*); +typedef camera_status_t (*pfnACameraOutputTarget_create)(ACameraWindowType*,ACameraOutputTarget**); +typedef camera_status_t (*pfnACaptureRequest_addTarget)(ACaptureRequest*, const ACameraOutputTarget*); +typedef camera_status_t (*pfnACaptureSessionOutputContainer_add)(ACaptureSessionOutputContainer*, const ACaptureSessionOutput*); +typedef camera_status_t (*pfnACaptureSessionOutputContainer_create)(ACaptureSessionOutputContainer**); +typedef camera_status_t (*pfnACaptureSessionOutput_create)(ACameraWindowType*, ACaptureSessionOutput**); +static pfnACameraManager_create pACameraManager_create = NULL; +static pfnACameraManager_registerAvailabilityCallback pACameraManager_registerAvailabilityCallback = NULL; +static pfnACameraManager_unregisterAvailabilityCallback pACameraManager_unregisterAvailabilityCallback = NULL; +static pfnACameraManager_getCameraIdList pACameraManager_getCameraIdList = NULL; +static pfnACameraManager_deleteCameraIdList pACameraManager_deleteCameraIdList = NULL; +static pfnACameraCaptureSession_close pACameraCaptureSession_close = NULL; +static pfnACaptureRequest_free pACaptureRequest_free = NULL; +static pfnACameraOutputTarget_free pACameraOutputTarget_free = NULL; +static pfnACameraDevice_close pACameraDevice_close = NULL; +static pfnACameraManager_delete pACameraManager_delete = NULL; +static pfnACaptureSessionOutputContainer_free pACaptureSessionOutputContainer_free = NULL; +static pfnACaptureSessionOutput_free pACaptureSessionOutput_free = NULL; +static pfnACameraManager_openCamera pACameraManager_openCamera = NULL; +static pfnACameraDevice_createCaptureRequest pACameraDevice_createCaptureRequest = NULL; +static pfnACameraDevice_createCaptureSession pACameraDevice_createCaptureSession = NULL; +static pfnACameraManager_getCameraCharacteristics pACameraManager_getCameraCharacteristics = NULL; +static pfnACameraMetadata_free pACameraMetadata_free = NULL; +static pfnACameraMetadata_getConstEntry pACameraMetadata_getConstEntry = NULL; +static pfnACameraCaptureSession_setRepeatingRequest pACameraCaptureSession_setRepeatingRequest = NULL; +static pfnACameraOutputTarget_create pACameraOutputTarget_create = NULL; +static pfnACaptureRequest_addTarget pACaptureRequest_addTarget = NULL; +static pfnACaptureSessionOutputContainer_add pACaptureSessionOutputContainer_add = NULL; +static pfnACaptureSessionOutputContainer_create pACaptureSessionOutputContainer_create = NULL; +static pfnACaptureSessionOutput_create pACaptureSessionOutput_create = NULL; + +static void *libmediandk = NULL; +typedef void (*pfnAImage_delete)(AImage*); +typedef media_status_t (*pfnAImage_getTimestamp)(const AImage*, int64_t*); +typedef media_status_t (*pfnAImage_getNumberOfPlanes)(const AImage*, int32_t*); +typedef media_status_t (*pfnAImage_getPlaneRowStride)(const AImage*, int, int32_t*); +typedef media_status_t (*pfnAImage_getPlaneData)(const AImage*, int, uint8_t**, int*); +typedef media_status_t (*pfnAImageReader_acquireNextImage)(AImageReader*, AImage**); +typedef void (*pfnAImageReader_delete)(AImageReader*); +typedef media_status_t (*pfnAImageReader_setImageListener)(AImageReader*, AImageReader_ImageListener*); +typedef media_status_t (*pfnAImageReader_getWindow)(AImageReader*, ANativeWindow**); +typedef media_status_t (*pfnAImageReader_new)(int32_t, int32_t, int32_t, int32_t, AImageReader**); +static pfnAImage_delete pAImage_delete = NULL; +static pfnAImage_getTimestamp pAImage_getTimestamp = NULL; +static pfnAImage_getNumberOfPlanes pAImage_getNumberOfPlanes = NULL; +static pfnAImage_getPlaneRowStride pAImage_getPlaneRowStride = NULL; +static pfnAImage_getPlaneData pAImage_getPlaneData = NULL; +static pfnAImageReader_acquireNextImage pAImageReader_acquireNextImage = NULL; +static pfnAImageReader_delete pAImageReader_delete = NULL; +static pfnAImageReader_setImageListener pAImageReader_setImageListener = NULL; +static pfnAImageReader_getWindow pAImageReader_getWindow = NULL; +static pfnAImageReader_new pAImageReader_new = NULL; + +typedef media_status_t (*pfnAImage_getWidth)(const AImage*, int32_t*); +typedef media_status_t (*pfnAImage_getHeight)(const AImage*, int32_t*); +static pfnAImage_getWidth pAImage_getWidth = NULL; +static pfnAImage_getHeight pAImage_getHeight = NULL; + +struct SDL_PrivateCameraData +{ + ACameraDevice *device; + AImageReader *reader; + ANativeWindow *window; + ACaptureSessionOutput *sessionOutput; + ACaptureSessionOutputContainer *sessionOutputContainer; + ACameraOutputTarget *outputTarget; + ACaptureRequest *request; + ACameraCaptureSession *session; + SDL_CameraSpec requested_spec; +}; + +static int SetErrorStr(const char *what, const char *errstr, const int rc) +{ + char errbuf[128]; + if (!errstr) { + SDL_snprintf(errbuf, sizeof (errbuf), "Unknown error #%d", rc); + errstr = errbuf; + } + return SDL_SetError("%s: %s", what, errstr); +} + +static const char *CameraStatusStr(const camera_status_t rc) +{ + switch (rc) { + case ACAMERA_OK: return "no error"; + case ACAMERA_ERROR_UNKNOWN: return "unknown error"; + case ACAMERA_ERROR_INVALID_PARAMETER: return "invalid parameter"; + case ACAMERA_ERROR_CAMERA_DISCONNECTED: return "camera disconnected"; + case ACAMERA_ERROR_NOT_ENOUGH_MEMORY: return "not enough memory"; + case ACAMERA_ERROR_METADATA_NOT_FOUND: return "metadata not found"; + case ACAMERA_ERROR_CAMERA_DEVICE: return "camera device error"; + case ACAMERA_ERROR_CAMERA_SERVICE: return "camera service error"; + case ACAMERA_ERROR_SESSION_CLOSED: return "session closed"; + case ACAMERA_ERROR_INVALID_OPERATION: return "invalid operation"; + case ACAMERA_ERROR_STREAM_CONFIGURE_FAIL: return "configure failure"; + case ACAMERA_ERROR_CAMERA_IN_USE: return "camera in use"; + case ACAMERA_ERROR_MAX_CAMERA_IN_USE: return "max cameras in use"; + case ACAMERA_ERROR_CAMERA_DISABLED: return "camera disabled"; + case ACAMERA_ERROR_PERMISSION_DENIED: return "permission denied"; + case ACAMERA_ERROR_UNSUPPORTED_OPERATION: return "unsupported operation"; + default: break; + } + + return NULL; // unknown error +} + +static int SetCameraError(const char *what, const camera_status_t rc) +{ + return SetErrorStr(what, CameraStatusStr(rc), (int) rc); +} + +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_RECLAIMED: return "reclaimed"; + case AMEDIA_ERROR_UNKNOWN: return "unknown error"; + case AMEDIA_ERROR_MALFORMED: return "malformed"; + case AMEDIA_ERROR_UNSUPPORTED: return "unsupported"; + case AMEDIA_ERROR_INVALID_OBJECT: return "invalid object"; + case AMEDIA_ERROR_INVALID_PARAMETER: return "invalid parameter"; + case AMEDIA_ERROR_INVALID_OPERATION: return "invalid operation"; + case AMEDIA_ERROR_END_OF_STREAM: return "end of stream"; + case AMEDIA_ERROR_IO: return "i/o error"; + case AMEDIA_ERROR_WOULD_BLOCK: return "operation would block"; + case AMEDIA_DRM_NOT_PROVISIONED: return "DRM not provisioned"; + case AMEDIA_DRM_RESOURCE_BUSY: return "DRM resource busy"; + case AMEDIA_DRM_DEVICE_REVOKED: return "DRM device revoked"; + case AMEDIA_DRM_SHORT_BUFFER: return "DRM short buffer"; + case AMEDIA_DRM_SESSION_NOT_OPENED: return "DRM session not opened"; + case AMEDIA_DRM_TAMPER_DETECTED: return "DRM tampering detected"; + case AMEDIA_DRM_VERIFY_FAILED: return "DRM verify failed"; + case AMEDIA_DRM_NEED_KEY: return "DRM need key"; + case AMEDIA_DRM_LICENSE_EXPIRED: return "DRM license expired"; + case AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE: return "no buffer available"; + case AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED: return "maximum images acquired"; + case AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE: return "cannot lock image"; + case AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE: return "cannot unlock image"; + case AMEDIA_IMGREADER_IMAGE_NOT_LOCKED: return "image not locked"; + default: break; + } + + return NULL; // unknown error +} + +static int SetMediaError(const char *what, const media_status_t rc) +{ + return SetErrorStr(what, MediaStatusStr(rc), (int) rc); +} + + +static ACameraManager *cameraMgr = NULL; + +static int CreateCameraManager(void) +{ + SDL_assert(cameraMgr == NULL); + + cameraMgr = pACameraManager_create(); + if (!cameraMgr) { + return SDL_SetError("Error creating ACameraManager"); + } + return 0; +} + +static void DestroyCameraManager(void) +{ + if (cameraMgr) { + pACameraManager_delete(cameraMgr); + cameraMgr = NULL; + } +} + +static Uint32 format_android_to_sdl(Uint32 fmt) +{ + 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); + #undef CASE + default: break; + } + + #if DEBUG_CAMERA + //SDL_Log("Unknown format AIMAGE_FORMAT '%d'", fmt); + #endif + + return SDL_PIXELFORMAT_UNKNOWN; +} + +static Uint32 format_sdl_to_android(Uint32 fmt) +{ + switch (fmt) { + #define CASE(x, y) case y: return x + 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); + #undef CASE + default: + return 0; + } +} + +static int ANDROIDCAMERA_WaitDevice(SDL_CameraDevice *device) +{ + return 0; // 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) +{ + int retval = 1; + media_status_t res; + AImage *image = NULL; + + res = pAImageReader_acquireNextImage(device->hidden->reader, &image); + // We could also use this one: + //res = AImageReader_acquireLatestImage(device->hidden->reader, &image); + + 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); + } + + int64_t atimestamp = 0; + if (pAImage_getTimestamp(image, &atimestamp) == AMEDIA_OK) { + *timestampNS = (Uint64) atimestamp; + } else { + *timestampNS = 0; + } + + // !!! 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... + int32_t num_planes = 0; + pAImage_getNumberOfPlanes(image, &num_planes); + + if ((num_planes == 3) && (device->spec.format == SDL_PIXELFORMAT_NV12)) { + num_planes--; // treat the interleaved planes as one. + } + + // !!! 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 < num_planes) && (i < 3); i++) { + uint8_t *data = NULL; + int32_t datalen = 0; + pAImage_getPlaneData(image, i, &data, &datalen); + buflen += (int) datalen; + } + + frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + if (frame->pixels == NULL) { + retval = -1; + } else { + int32_t row_stride = 0; + Uint8 *dst = frame->pixels; + pAImage_getPlaneRowStride(image, 0, &row_stride); + frame->pitch = (int) row_stride; // this is what SDL3 currently expects, probably incorrectly. + + for (int i = 0; (i < num_planes) && (i < 3); i++) { + uint8_t *data = NULL; + int32_t datalen = 0; + pAImage_getPlaneData(image, i, &data, &datalen); + const void *src = data; + SDL_memcpy(dst, src, datalen); + dst += datalen; + } + } + + pAImage_delete(image); + + return retval; +} + +static void ANDROIDCAMERA_ReleaseFrame(SDL_CameraDevice *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); +} + +static void onImageAvailable(void *context, AImageReader *reader) +{ + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onImageAvailable"); + #endif + SDL_CameraDevice *device = (SDL_CameraDevice *) context; + SDL_CameraThreadIterate(device); +} + +static void onDisconnected(void *context, ACameraDevice *device) +{ + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onDisconnected"); + #endif + SDL_CameraDeviceDisconnected((SDL_CameraDevice *) context); +} + +static void onError(void *context, ACameraDevice *device, int error) +{ + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onError"); + #endif + SDL_CameraDeviceDisconnected((SDL_CameraDevice *) context); +} + +static void onClosed(void* context, ACameraCaptureSession *session) +{ + // SDL_CameraDevice *_this = (SDL_CameraDevice *) context; + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onClosed"); + #endif +} + +static void onReady(void* context, ACameraCaptureSession *session) +{ + // SDL_CameraDevice *_this = (SDL_CameraDevice *) context; + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onReady"); + #endif +} + +static void onActive(void* context, ACameraCaptureSession *session) +{ + // SDL_CameraDevice *_this = (SDL_CameraDevice *) context; + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onActive"); + #endif +} + +static void ANDROIDCAMERA_CloseDevice(SDL_CameraDevice *device) +{ + if (device && device->hidden) { + struct SDL_PrivateCameraData *hidden = device->hidden; + device->hidden = NULL; + + if (hidden->reader) { + pAImageReader_setImageListener(hidden->reader, NULL); + } + + if (hidden->session) { + pACameraCaptureSession_close(hidden->session); + } + + if (hidden->request) { + pACaptureRequest_free(hidden->request); + } + + if (hidden->outputTarget) { + pACameraOutputTarget_free(hidden->outputTarget); + } + + if (hidden->sessionOutputContainer) { + pACaptureSessionOutputContainer_free(hidden->sessionOutputContainer); + } + + if (hidden->sessionOutput) { + pACaptureSessionOutput_free(hidden->sessionOutput); + } + + // we don't free hidden->window here, it'll be cleaned up by AImageReader_delete. + + if (hidden->reader) { + pAImageReader_delete(hidden->reader); + } + + if (hidden->device) { + pACameraDevice_close(hidden->device); + } + + SDL_free(hidden); + } +} + +// this is where the "opening" of the camera happens, after permission is granted. +static int PrepareCamera(SDL_CameraDevice *device) +{ + SDL_assert(device->hidden != NULL); + + camera_status_t res; + media_status_t res2; + + ACameraDevice_StateCallbacks dev_callbacks; + SDL_zero(dev_callbacks); + dev_callbacks.context = device; + dev_callbacks.onDisconnected = onDisconnected; + dev_callbacks.onError = onError; + + ACameraCaptureSession_stateCallbacks capture_callbacks; + SDL_zero(capture_callbacks); + capture_callbacks.context = device; + capture_callbacks.onClosed = onClosed; + capture_callbacks.onReady = onReady; + capture_callbacks.onActive = onActive; + + AImageReader_ImageListener imglistener; + SDL_zero(imglistener); + imglistener.context = device; + imglistener.onImageAvailable = onImageAvailable; + + // just in case SDL_OpenCameraDevice 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) { + return SetCameraError("Failed to open camera", res); + } else if ((res2 = pAImageReader_new(spec->width, spec->height, format_sdl_to_android(spec->format), 10 /* nb buffers */, &device->hidden->reader)) != AMEDIA_OK) { + return SetMediaError("Error AImageReader_new", res2); + } else if ((res2 = pAImageReader_getWindow(device->hidden->reader, &device->hidden->window)) != AMEDIA_OK) { + return SetMediaError("Error AImageReader_getWindow", res2); + } else if ((res = pACaptureSessionOutput_create(device->hidden->window, &device->hidden->sessionOutput)) != ACAMERA_OK) { + return SetCameraError("Error ACaptureSessionOutput_create", res); + } else if ((res = pACaptureSessionOutputContainer_create(&device->hidden->sessionOutputContainer)) != ACAMERA_OK) { + return SetCameraError("Error ACaptureSessionOutputContainer_create", res); + } else if ((res = pACaptureSessionOutputContainer_add(device->hidden->sessionOutputContainer, device->hidden->sessionOutput)) != ACAMERA_OK) { + return SetCameraError("Error ACaptureSessionOutputContainer_add", res); + } else if ((res = pACameraOutputTarget_create(device->hidden->window, &device->hidden->outputTarget)) != ACAMERA_OK) { + return SetCameraError("Error ACameraOutputTarget_create", res); + } else if ((res = pACameraDevice_createCaptureRequest(device->hidden->device, TEMPLATE_RECORD, &device->hidden->request)) != ACAMERA_OK) { + return SetCameraError("Error ACameraDevice_createCaptureRequest", res); + } else if ((res = pACaptureRequest_addTarget(device->hidden->request, device->hidden->outputTarget)) != ACAMERA_OK) { + return SetCameraError("Error ACaptureRequest_addTarget", res); + } else if ((res = pACameraDevice_createCaptureSession(device->hidden->device, device->hidden->sessionOutputContainer, &capture_callbacks, &device->hidden->session)) != ACAMERA_OK) { + return SetCameraError("Error ACameraDevice_createCaptureSession", res); + } else if ((res = pACameraCaptureSession_setRepeatingRequest(device->hidden->session, NULL, 1, &device->hidden->request, NULL)) != ACAMERA_OK) { + return SetCameraError("Error ACameraCaptureSession_setRepeatingRequest", res); + } else if ((res2 = pAImageReader_setImageListener(device->hidden->reader, &imglistener)) != AMEDIA_OK) { + return SetMediaError("Error AImageReader_setImageListener", res2); + } + + return 0; +} + +static void SDLCALL CameraPermissionCallback(void *userdata, const char *permission, SDL_bool granted) +{ + SDL_CameraDevice *device = (SDL_CameraDevice *) 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. + // 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); + } 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! + } + } + + UnrefPhysicalCameraDevice(device); // we ref'd this in OpenDevice, release the extra reference. +} + + +static int ANDROIDCAMERA_OpenDevice(SDL_CameraDevice *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. + * If you want to play several camera, they must all be opened first, then played. + * + * https://developer.android.com/reference/android/hardware/camera2/CameraManager + * "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler), + * before configuring sessions on any of the camera devices. * " + * + */ + if (CheckDevicePlaying()) { + return SDL_SetError("A camera is already playing"); + } +#endif + + device->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); + if (device->hidden == NULL) { + return -1; + } + + RefPhysicalCameraDevice(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. + SDL_copyp(&device->hidden->requested_spec, spec); + if (SDL_AndroidRequestPermission("android.permission.CAMERA", CameraPermissionCallback, device) < 0) { + UnrefPhysicalCameraDevice(device); + return -1; + } + + return 0; // we don't open the camera until permission is granted, so always succeed for now. +} + +static void ANDROIDCAMERA_FreeDeviceHandle(SDL_CameraDevice *device) +{ + if (device) { + SDL_free(device->handle); + } +} + +static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data, char **fullname, SDL_CameraPosition *position) +{ + SDL_zerop(add_data); + + ACameraMetadata *metadata = NULL; + ACameraMetadata_const_entry cfgentry; + ACameraMetadata_const_entry durentry; + ACameraMetadata_const_entry infoentry; + + // This can fail with an "unknown error" (with `adb logcat` reporting "no such file or directory") + // for "LEGACY" level cameras. I saw this happen on a 30-dollar budget phone I have for testing + // (but a different brand budget phone worked, so it's not strictly the low-end of Android devices). + // LEGACY devices are seen by onCameraAvailable, but are not otherwise accessible through + // libcamera2ndk. The Java camera2 API apparently _can_ access these cameras, but we're going on + // without them here for now, in hopes that such hardware is a dying breed. + if (pACameraManager_getCameraCharacteristics(cameraMgr, devid, &metadata) != ACAMERA_OK) { + return; // oh well. + } else if (pACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &cfgentry) != ACAMERA_OK) { + pACameraMetadata_free(metadata); + return; // oh well. + } else if (pACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, &durentry) != ACAMERA_OK) { + pACameraMetadata_free(metadata); + return; // oh well. + } + + *fullname = NULL; + if (pACameraMetadata_getConstEntry(metadata, ACAMERA_INFO_VERSION, &infoentry) == ACAMERA_OK) { + *fullname = (char *) SDL_malloc(infoentry.count + 1); + if (*fullname) { + SDL_strlcpy(*fullname, (const char *) infoentry.data.u8, infoentry.count + 1); + } + } + + ACameraMetadata_const_entry posentry; + if (pACameraMetadata_getConstEntry(metadata, ACAMERA_LENS_FACING, &posentry) == ACAMERA_OK) { // ignore this if it fails. + if (*posentry.data.u8 == ACAMERA_LENS_FACING_FRONT) { + *position = SDL_CAMERA_POSITION_FRONT_FACING; + if (!*fullname) { + *fullname = SDL_strdup("Front-facing camera"); + } + } else if (*posentry.data.u8 == ACAMERA_LENS_FACING_BACK) { + *position = SDL_CAMERA_POSITION_BACK_FACING; + if (!*fullname) { + *fullname = SDL_strdup("Back-facing camera"); + } + } + } + + if (!*fullname) { + *fullname = SDL_strdup("Generic camera"); // we tried. + } + + const int32_t *i32ptr = cfgentry.data.i32; + for (int i = 0; i < cfgentry.count; i++, i32ptr += 4) { + const int32_t fmt = i32ptr[0]; + const int w = (int) i32ptr[1]; + const int h = (int) i32ptr[2]; + const int32_t type = i32ptr[3]; + Uint32 sdlfmt; + + 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; + } + +#if 0 // !!! FIXME: these all come out with 0 durations on my test phone. :( + const int64_t *i64ptr = durentry.data.i64; + for (int j = 0; j < durentry.count; j++, i64ptr += 4) { + const int32_t fpsfmt = (int32_t) i64ptr[0]; + 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); + if ((duration > 0) && (fpsfmt == fmt) && (fpsw == w) && (fpsh == h)) { + SDL_AddCameraFormat(add_data, sdlfmt, w, h, duration, 1000000000); + } + } +#else + SDL_AddCameraFormat(add_data, sdlfmt, w, h, 1, 30); +#endif + } + + pACameraMetadata_free(metadata); +} + +static SDL_bool FindAndroidCameraDeviceByID(SDL_CameraDevice *device, void *userdata) +{ + const char *devid = (const char *) userdata; + return (SDL_strcmp(devid, (const char *) device->handle) == 0); +} + +static void MaybeAddDevice(const char *devid) +{ + #if DEBUG_CAMERA + SDL_Log("CAMERA: MaybeAddDevice('%s')", devid); + #endif + + if (SDL_FindPhysicalCameraDeviceByCallback(FindAndroidCameraDeviceByID, (void *) devid)) { + return; // already have this one. + } + + SDL_CameraPosition position = SDL_CAMERA_POSITION_UNKNOWN; + char *fullname = NULL; + CameraFormatAddData add_data; + GatherCameraSpecs(devid, &add_data, &fullname, &position); + 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); + if (!device) { + SDL_free(namecpy); + } + } + } + + SDL_free(fullname); + SDL_free(add_data.specs); +} + +// note that camera "availability" covers both hotplugging and whether another +// has the device opened, but for something like Android, it's probably fine +// to treat both unplugging and loss of access as disconnection events. When +// the other app closes the camera, we get an available event as if it was +// just plugged back in. + +static void onCameraAvailable(void *context, const char *cameraId) +{ + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onCameraAvailable('%s')", cameraId); + #endif + SDL_assert(cameraId != NULL); + MaybeAddDevice(cameraId); +} + +static void onCameraUnavailable(void *context, const char *cameraId) +{ + #if DEBUG_CAMERA + SDL_Log("CAMERA: CB onCameraUnvailable('%s')", cameraId); + #endif + + SDL_assert(cameraId != NULL); + + // 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); + if (device && !device->hidden) { + SDL_CameraDeviceDisconnected(device); + } +} + +static const ACameraManager_AvailabilityCallbacks camera_availability_listener = { + NULL, + onCameraAvailable, + onCameraUnavailable +}; + +static void ANDROIDCAMERA_DetectDevices(void) +{ + ACameraIdList *list = NULL; + camera_status_t res = pACameraManager_getCameraIdList(cameraMgr, &list); + + if ((res == ACAMERA_OK) && list) { + const int total = list->numCameras; + for (int i = 0; i < total; i++) { + MaybeAddDevice(list->cameraIds[i]); + } + + pACameraManager_deleteCameraIdList(list); + } + + pACameraManager_registerAvailabilityCallback(cameraMgr, &camera_availability_listener); +} + +static void ANDROIDCAMERA_Deinitialize(void) +{ + pACameraManager_unregisterAvailabilityCallback(cameraMgr, &camera_availability_listener); + DestroyCameraManager(); + + dlclose(libcamera2ndk); + libcamera2ndk = NULL; + pACameraManager_create = NULL; + pACameraManager_registerAvailabilityCallback = NULL; + pACameraManager_unregisterAvailabilityCallback = NULL; + pACameraManager_getCameraIdList = NULL; + pACameraManager_deleteCameraIdList = NULL; + pACameraCaptureSession_close = NULL; + pACaptureRequest_free = NULL; + pACameraOutputTarget_free = NULL; + pACameraDevice_close = NULL; + pACameraManager_delete = NULL; + pACaptureSessionOutputContainer_free = NULL; + pACaptureSessionOutput_free = NULL; + pACameraManager_openCamera = NULL; + pACameraDevice_createCaptureRequest = NULL; + pACameraDevice_createCaptureSession = NULL; + pACameraManager_getCameraCharacteristics = NULL; + pACameraMetadata_free = NULL; + pACameraMetadata_getConstEntry = NULL; + pACameraCaptureSession_setRepeatingRequest = NULL; + pACameraOutputTarget_create = NULL; + pACaptureRequest_addTarget = NULL; + pACaptureSessionOutputContainer_add = NULL; + pACaptureSessionOutputContainer_create = NULL; + pACaptureSessionOutput_create = NULL; + + dlclose(libmediandk); + libmediandk = NULL; + pAImage_delete = NULL; + pAImage_getTimestamp = NULL; + pAImage_getNumberOfPlanes = NULL; + pAImage_getPlaneRowStride = NULL; + pAImage_getPlaneData = NULL; + pAImageReader_acquireNextImage = NULL; + pAImageReader_delete = NULL; + pAImageReader_setImageListener = NULL; + pAImageReader_getWindow = NULL; + pAImageReader_new = NULL; +} + +static SDL_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; + } + + 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; + } + + 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; } } + //#define LOADSYM(lib, fn) p##fn = (pfn##fn) fn + LOADSYM(libcamera2, ACameraManager_create); + LOADSYM(libcamera2, ACameraManager_registerAvailabilityCallback); + LOADSYM(libcamera2, ACameraManager_unregisterAvailabilityCallback); + LOADSYM(libcamera2, ACameraManager_getCameraIdList); + LOADSYM(libcamera2, ACameraManager_deleteCameraIdList); + LOADSYM(libcamera2, ACameraCaptureSession_close); + LOADSYM(libcamera2, ACaptureRequest_free); + LOADSYM(libcamera2, ACameraOutputTarget_free); + LOADSYM(libcamera2, ACameraDevice_close); + LOADSYM(libcamera2, ACameraManager_delete); + LOADSYM(libcamera2, ACaptureSessionOutputContainer_free); + LOADSYM(libcamera2, ACaptureSessionOutput_free); + LOADSYM(libcamera2, ACameraManager_openCamera); + LOADSYM(libcamera2, ACameraDevice_createCaptureRequest); + LOADSYM(libcamera2, ACameraDevice_createCaptureSession); + LOADSYM(libcamera2, ACameraManager_getCameraCharacteristics); + LOADSYM(libcamera2, ACameraMetadata_free); + LOADSYM(libcamera2, ACameraMetadata_getConstEntry); + LOADSYM(libcamera2, ACameraCaptureSession_setRepeatingRequest); + LOADSYM(libcamera2, ACameraOutputTarget_create); + LOADSYM(libcamera2, ACaptureRequest_addTarget); + LOADSYM(libcamera2, ACaptureSessionOutputContainer_add); + LOADSYM(libcamera2, ACaptureSessionOutputContainer_create); + LOADSYM(libcamera2, ACaptureSessionOutput_create); + LOADSYM(libmedia, AImage_delete); + LOADSYM(libmedia, AImage_getTimestamp); + LOADSYM(libmedia, AImage_getNumberOfPlanes); + LOADSYM(libmedia, AImage_getPlaneRowStride); + LOADSYM(libmedia, AImage_getPlaneData); + LOADSYM(libmedia, AImageReader_acquireNextImage); + LOADSYM(libmedia, AImageReader_delete); + LOADSYM(libmedia, AImageReader_setImageListener); + LOADSYM(libmedia, AImageReader_getWindow); + LOADSYM(libmedia, AImageReader_new); + LOADSYM(libmedia, AImage_getWidth); + LOADSYM(libmedia, AImage_getHeight); + + #undef LOADSYM + + if (!okay) { + dlclose(libmedia); + dlclose(libcamera2); + } + + if (CreateCameraManager() < 0) { + dlclose(libmedia); + dlclose(libcamera2); + return SDL_FALSE; + } + + libcamera2ndk = libcamera2; + libmediandk = libmedia; + + impl->DetectDevices = ANDROIDCAMERA_DetectDevices; + impl->OpenDevice = ANDROIDCAMERA_OpenDevice; + impl->CloseDevice = ANDROIDCAMERA_CloseDevice; + impl->WaitDevice = ANDROIDCAMERA_WaitDevice; + impl->AcquireFrame = ANDROIDCAMERA_AcquireFrame; + impl->ReleaseFrame = ANDROIDCAMERA_ReleaseFrame; + impl->FreeDeviceHandle = ANDROIDCAMERA_FreeDeviceHandle; + impl->Deinitialize = ANDROIDCAMERA_Deinitialize; + + impl->ProvidesOwnCallbackThread = SDL_TRUE; + + return SDL_TRUE; +} + +CameraBootStrap ANDROIDCAMERA_bootstrap = { + "android", "SDL Android camera driver", ANDROIDCAMERA_Init, SDL_FALSE +}; + +#endif diff --git a/src/camera/coremedia/SDL_camera_coremedia.m b/src/camera/coremedia/SDL_camera_coremedia.m new file mode 100644 index 00000000..049c4a40 --- /dev/null +++ b/src/camera/coremedia/SDL_camera_coremedia.m @@ -0,0 +1,479 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 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_CAMERA_DRIVER_COREMEDIA + +#include "../SDL_syscamera.h" +#include "../SDL_camera_c.h" +#include "../../thread/SDL_systhread.h" + +#import +#import + +/* + * Need to link with:: CoreMedia CoreVideo + * + * Add in pInfo.list: + * NSCameraUsageDescription Access camera + * + * + * MACOSX: + * Add to the Code Sign Entitlement file: + * com.apple.security.device.camera + */ + +static Uint32 CoreMediaFormatToSDL(FourCharCode fmt) +{ + switch (fmt) { + #define CASE(x, y) case x: return y + // 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); + #undef CASE + default: + #if DEBUG_CAMERA + SDL_Log("CAMERA: Unknown format FourCharCode '%d'", (int) fmt); + #endif + break; + } + return SDL_PIXELFORMAT_UNKNOWN; +} + +@class SDLCaptureVideoDataOutputSampleBufferDelegate; + +// just a simple wrapper to help ARC manage memory... +@interface SDLPrivateCameraData : NSObject +@property(nonatomic, retain) AVCaptureSession *session; +@property(nonatomic, retain) SDLCaptureVideoDataOutputSampleBufferDelegate *delegate; +@property(nonatomic, assign) CMSampleBufferRef current_sample; +@end + +@implementation SDLPrivateCameraData +@end + + +static SDL_bool CheckCameraPermissions(SDL_CameraDevice *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); + } + } else { + SDL_CameraDevicePermissionOutcome(device, SDL_TRUE); // always allowed (or just unqueryable...?) on older macOS. + } + } + + return (device->permission > 0); +} + +// 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; + -(void) captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection; +@end + +@implementation SDLCaptureVideoDataOutputSampleBufferDelegate + + -(id) init:(SDL_CameraDevice *) dev { + if ( self = [super init] ) { + _device = dev; + } + return self; + } + + - (void) captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection + { + SDL_CameraDevice *device = self.device; + if (!device || !device->hidden) { + return; // oh well. + } + + if (!CheckCameraPermissions(device)) { + return; // nothing to do right now, dump what is probably a completely black frame. + } + + SDLPrivateCameraData *hidden = (__bridge SDLPrivateCameraData *) device->hidden; + hidden.current_sample = sampleBuffer; + SDL_CameraThreadIterate(device); + hidden.current_sample = NULL; + } + + - (void)captureOutput:(AVCaptureOutput *)output didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection + { + #if DEBUG_CAMERA + SDL_Log("CAMERA: Drop frame."); + #endif + } +@end + +static int COREMEDIA_WaitDevice(SDL_CameraDevice *device) +{ + return 0; // 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) +{ + int retval = 1; + SDLPrivateCameraData *hidden = (__bridge SDLPrivateCameraData *) device->hidden; + CMSampleBufferRef sample_buffer = hidden.current_sample; + hidden.current_sample = NULL; + SDL_assert(sample_buffer != NULL); // should only have been called from our delegate with a new frame. + + CMSampleTimingInfo timinginfo; + if (CMSampleBufferGetSampleTimingInfo(sample_buffer, 0, &timinginfo) == noErr) { + *timestampNS = (Uint64) (CMTimeGetSeconds(timinginfo.presentationTimeStamp) * ((Float64) SDL_NS_PER_SECOND)); + } else { + SDL_assert(!"this shouldn't happen, I think."); + *timestampNS = 0; + } + + CVImageBufferRef image = CMSampleBufferGetImageBuffer(sample_buffer); // does not retain `image` (and we don't want it to). + const int numPlanes = (int) CVPixelBufferGetPlaneCount(image); + const int planar = (int) CVPixelBufferIsPlanar(image); + + #if DEBUG_CAMERA + const int w = (int) CVPixelBufferGetWidth(image); + const int h = (int) CVPixelBufferGetHeight(image); + const int sz = (int) CVPixelBufferGetDataSize(image); + const int pitch = (int) CVPixelBufferGetBytesPerRow(image); + SDL_Log("CAMERA: buffer planar=%d numPlanes=%d %d x %d sz=%d pitch=%d", planar, numPlanes, w, h, sz, pitch); + #endif + + // !!! 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); + + 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); + if (frame->pixels == NULL) { + retval = -1; + } else { + frame->pitch = pitch; + SDL_memcpy(frame->pixels, CVPixelBufferGetBaseAddress(image), buflen); + } + } 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); + } + buflen *= frame->h; + + frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + if (frame->pixels == NULL) { + retval = -1; + } 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++) { + const void *src = CVPixelBufferGetBaseAddressOfPlane(image, i); + const size_t pitch = CVPixelBufferGetBytesPerRowOfPlane(image, i); + SDL_memcpy(dst, src, pitch * frame->h); + dst += pitch * frame->h; + } + } + } + + CVPixelBufferUnlockBaseAddress(image, 0); + + return retval; +} + +static void COREMEDIA_ReleaseFrame(SDL_CameraDevice *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) +{ + if (device && device->hidden) { + SDLPrivateCameraData *hidden = (SDLPrivateCameraData *) CFBridgingRelease(device->hidden); + device->hidden = NULL; + + AVCaptureSession *session = hidden.session; + if (session) { + hidden.session = nil; + [session stopRunning]; + [session removeInput:[session.inputs objectAtIndex:0]]; + [session removeOutput:(AVCaptureVideoDataOutput*)[session.outputs objectAtIndex:0]]; + session = nil; + } + + hidden.delegate = NULL; + hidden.current_sample = NULL; + } +} + +static int COREMEDIA_OpenDevice(SDL_CameraDevice *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; + AVCaptureDeviceFormat *spec_format = nil; + NSArray *formats = [avdevice formats]; + for (AVCaptureDeviceFormat *format in formats) { + CMFormatDescriptionRef formatDescription = [format formatDescription]; + if (CoreMediaFormatToSDL(CMFormatDescriptionGetMediaSubType(formatDescription)) != sdlfmt) { + continue; + } + + const CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription); + if ( ((int) dim.width != w) || (((int) dim.height) != h) ) { + continue; + } + + for (AVFrameRateRange *framerate in format.videoSupportedFrameRateRanges) { + if ((rate == (int) SDL_ceil((double) framerate.minFrameRate)) || (rate == (int) SDL_floor((double) framerate.maxFrameRate))) { + spec_format = format; + break; + } + } + + if (spec_format != nil) { + break; + } + } + + if (spec_format == nil) { + return SDL_SetError("camera spec format not available"); + } else if (![avdevice lockForConfiguration:NULL]) { + return SDL_SetError("Cannot lockForConfiguration"); + } + + avdevice.activeFormat = spec_format; + [avdevice unlockForConfiguration]; + + AVCaptureSession *session = [[AVCaptureSession alloc] init]; + if (session == nil) { + return SDL_SetError("Failed to allocate/init AVCaptureSession"); + } + + session.sessionPreset = AVCaptureSessionPresetHigh; + + NSError *error = nil; + AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:avdevice error:&error]; + if (!input) { + return SDL_SetError("Cannot create AVCaptureDeviceInput"); + } + + AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init]; + if (!output) { + return SDL_SetError("Cannot create AVCaptureVideoDataOutput"); + } + + char threadname[64]; + SDL_GetCameraThreadName(device, threadname, sizeof (threadname)); + dispatch_queue_t queue = dispatch_queue_create(threadname, NULL); + //dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + if (!queue) { + return SDL_SetError("dispatch_queue_create() failed"); + } + + SDLCaptureVideoDataOutputSampleBufferDelegate *delegate = [[SDLCaptureVideoDataOutputSampleBufferDelegate alloc] init:device]; + if (delegate == nil) { + return SDL_SetError("Cannot create SDLCaptureVideoDataOutputSampleBufferDelegate"); + } + [output setSampleBufferDelegate:delegate queue:queue]; + + if (![session canAddInput:input]) { + return SDL_SetError("Cannot add AVCaptureDeviceInput"); + } + [session addInput:input]; + + if (![session canAddOutput:output]) { + return SDL_SetError("Cannot add AVCaptureVideoDataOutput"); + } + [session addOutput:output]; + + [session commitConfiguration]; + + SDLPrivateCameraData *hidden = [[SDLPrivateCameraData alloc] init]; + if (hidden == nil) { + return SDL_SetError("Cannot create SDLPrivateCameraData"); + } + + hidden.session = session; + hidden.delegate = delegate; + hidden.current_sample = NULL; + device->hidden = (struct SDL_PrivateCameraData *)CFBridgingRetain(hidden); + + [session startRunning]; // !!! FIXME: docs say this can block while camera warms up and shouldn't be done on main thread. Maybe push through `queue`? + + CheckCameraPermissions(device); // check right away, in case the process is already granted permission. + + return 0; +} + +static void COREMEDIA_FreeDeviceHandle(SDL_CameraDevice *device) +{ + if (device && device->handle) { + CFBridgingRelease(device->handle); + } +} + +static void GatherCameraSpecs(AVCaptureDevice *device, CameraFormatAddData *add_data) +{ + SDL_zerop(add_data); + + for (AVCaptureDeviceFormat *fmt in device.formats) { + if (CMFormatDescriptionGetMediaType(fmt.formatDescription) != kCMMediaType_Video) { + continue; + } + + const Uint32 sdlfmt = CoreMediaFormatToSDL(CMFormatDescriptionGetMediaSubType(fmt.formatDescription)); + if (sdlfmt == SDL_PIXELFORMAT_UNKNOWN) { + continue; + } + + const CMVideoDimensions dims = CMVideoFormatDescriptionGetDimensions(fmt.formatDescription); + 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); + } + } + } +} + +static SDL_bool FindCoreMediaCameraDeviceByUniqueID(SDL_CameraDevice *device, void *userdata) +{ + NSString *uniqueid = (__bridge NSString *) userdata; + AVCaptureDevice *avdev = (__bridge AVCaptureDevice *) device->handle; + return ([uniqueid isEqualToString:avdev.uniqueID]) ? SDL_TRUE : SDL_FALSE; +} + +static void MaybeAddDevice(AVCaptureDevice *avdevice) +{ + if (!avdevice.connected) { + return; // not connected. + } else if (![avdevice hasMediaType:AVMediaTypeVideo]) { + return; // not a camera. + } else if (SDL_FindPhysicalCameraDeviceByCallback(FindCoreMediaCameraDeviceByUniqueID, (__bridge void *) avdevice.uniqueID)) { + return; // already have this one. + } + + CameraFormatAddData add_data; + GatherCameraSpecs(avdevice, &add_data); + if (add_data.num_specs > 0) { + SDL_CameraPosition position = SDL_CAMERA_POSITION_UNKNOWN; + if (avdevice.position == AVCaptureDevicePositionFront) { + position = SDL_CAMERA_POSITION_FRONT_FACING; + } 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_free(add_data.specs); +} + +static void COREMEDIA_DetectDevices(void) +{ + NSArray *devices = nil; + + if (@available(macOS 10.15, iOS 13, *)) { + // kind of annoying that there isn't a "give me anything that looks like a camera" option, + // so this list will need to be updated when Apple decides to add + // AVCaptureDeviceTypeBuiltInQuadrupleCamera some day. + NSArray *device_types = @[ + #ifdef SDL_PLATFORM_IOS + AVCaptureDeviceTypeBuiltInTelephotoCamera, + AVCaptureDeviceTypeBuiltInDualCamera, + AVCaptureDeviceTypeBuiltInDualWideCamera, + AVCaptureDeviceTypeBuiltInTripleCamera, + AVCaptureDeviceTypeBuiltInUltraWideCamera, + #else + AVCaptureDeviceTypeExternalUnknown, + #endif + AVCaptureDeviceTypeBuiltInWideAngleCamera + ]; + + AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession + discoverySessionWithDeviceTypes:device_types + mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionUnspecified]; + + devices = discoverySession.devices; + // !!! FIXME: this can use Key Value Observation to get hotplug events. + } else { + // this is deprecated but works back to macOS 10.7; 10.15 added AVCaptureDeviceDiscoverySession as a replacement. + devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; + // !!! FIXME: this can use AVCaptureDeviceWasConnectedNotification and AVCaptureDeviceWasDisconnectedNotification with NSNotificationCenter to get hotplug events. + } + + for (AVCaptureDevice *device in devices) { + MaybeAddDevice(device); + } +} + +static void COREMEDIA_Deinitialize(void) +{ + // !!! FIXME: disable hotplug. +} + +static SDL_bool COREMEDIA_Init(SDL_CameraDriverImpl *impl) +{ + impl->DetectDevices = COREMEDIA_DetectDevices; + impl->OpenDevice = COREMEDIA_OpenDevice; + impl->CloseDevice = COREMEDIA_CloseDevice; + impl->WaitDevice = COREMEDIA_WaitDevice; + impl->AcquireFrame = COREMEDIA_AcquireFrame; + impl->ReleaseFrame = COREMEDIA_ReleaseFrame; + impl->FreeDeviceHandle = COREMEDIA_FreeDeviceHandle; + impl->Deinitialize = COREMEDIA_Deinitialize; + + impl->ProvidesOwnCallbackThread = SDL_TRUE; + + return SDL_TRUE; +} + +CameraBootStrap COREMEDIA_bootstrap = { + "coremedia", "SDL Apple CoreMedia camera driver", COREMEDIA_Init, SDL_FALSE +}; + +#endif // SDL_CAMERA_DRIVER_COREMEDIA + diff --git a/src/camera/dummy/SDL_camera_dummy.c b/src/camera/dummy/SDL_camera_dummy.c new file mode 100644 index 00000000..b93eecbb --- /dev/null +++ b/src/camera/dummy/SDL_camera_dummy.c @@ -0,0 +1,80 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 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_CAMERA_DRIVER_DUMMY + +#include "../SDL_syscamera.h" + +static int DUMMYCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +{ + return SDL_Unsupported(); +} + +static void DUMMYCAMERA_CloseDevice(SDL_CameraDevice *device) +{ +} + +static int DUMMYCAMERA_WaitDevice(SDL_CameraDevice *device) +{ + return SDL_Unsupported(); +} + +static int DUMMYCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +{ + return SDL_Unsupported(); +} + +static void DUMMYCAMERA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +{ +} + +static void DUMMYCAMERA_DetectDevices(void) +{ +} + +static void DUMMYCAMERA_FreeDeviceHandle(SDL_CameraDevice *device) +{ +} + +static void DUMMYCAMERA_Deinitialize(void) +{ +} + +static SDL_bool DUMMYCAMERA_Init(SDL_CameraDriverImpl *impl) +{ + impl->DetectDevices = DUMMYCAMERA_DetectDevices; + impl->OpenDevice = DUMMYCAMERA_OpenDevice; + impl->CloseDevice = DUMMYCAMERA_CloseDevice; + impl->WaitDevice = DUMMYCAMERA_WaitDevice; + impl->AcquireFrame = DUMMYCAMERA_AcquireFrame; + impl->ReleaseFrame = DUMMYCAMERA_ReleaseFrame; + impl->FreeDeviceHandle = DUMMYCAMERA_FreeDeviceHandle; + impl->Deinitialize = DUMMYCAMERA_Deinitialize; + + return SDL_TRUE; +} + +CameraBootStrap DUMMYCAMERA_bootstrap = { + "dummy", "SDL dummy camera driver", DUMMYCAMERA_Init, SDL_TRUE +}; + +#endif // SDL_CAMERA_DRIVER_DUMMY diff --git a/src/camera/emscripten/SDL_camera_emscripten.c b/src/camera/emscripten/SDL_camera_emscripten.c new file mode 100644 index 00000000..9a605a75 --- /dev/null +++ b/src/camera/emscripten/SDL_camera_emscripten.c @@ -0,0 +1,265 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 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_CAMERA_DRIVER_EMSCRIPTEN + +#include "../SDL_syscamera.h" +#include "../SDL_camera_c.h" +#include "../../video/SDL_pixels_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 */ + +EM_JS_DEPS(sdlcamera, "$dynCall"); + +static int EMSCRIPTENCAMERA_WaitDevice(SDL_CameraDevice *device) +{ + SDL_assert(!"This shouldn't be called"); // we aren't using SDL's internal thread. + return -1; +} + +static int EMSCRIPTENCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +{ + void *rgba = SDL_malloc(device->actual_spec.width * device->actual_spec.height * 4); + if (!rgba) { + return SDL_OutOfMemory(); + } + + *timestampNS = SDL_GetTicksNS(); // best we can do here. + + const int rc = MAIN_THREAD_EM_ASM_INT({ + const w = $0; + const h = $1; + const rgba = $2; + const SDL3 = Module['SDL3']; + if ((typeof(SDL3) === 'undefined') || (typeof(SDL3.camera) === 'undefined') || (typeof(SDL3.camera.ctx2d) === 'undefined')) { + return 0; // don't have something we need, oh well. + } + + SDL3.camera.ctx2d.drawImage(SDL3.camera.video, 0, 0, w, h); + const imgrgba = SDL3.camera.ctx2d.getImageData(0, 0, w, h).data; + Module.HEAPU8.set(imgrgba, rgba); + + return 1; + }, device->actual_spec.width, device->actual_spec.height, rgba); + + if (!rc) { + SDL_free(rgba); + return 0; // something went wrong, maybe shutting down; just don't return a frame. + } + + frame->pixels = rgba; + frame->pitch = device->actual_spec.width * 4; + + return 1; +} + +static void EMSCRIPTENCAMERA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +{ + SDL_free(frame->pixels); +} + +static void EMSCRIPTENCAMERA_CloseDevice(SDL_CameraDevice *device) +{ + if (device) { + MAIN_THREAD_EM_ASM({ + const SDL3 = Module['SDL3']; + if ((typeof(SDL3) === 'undefined') || (typeof(SDL3.camera) === 'undefined') || (typeof(SDL3.camera.stream) === 'undefined')) { + 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); + device->hidden = NULL; + } +} + +static void SDLEmscriptenCameraDevicePermissionOutcome(SDL_CameraDevice *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); +} + +static int EMSCRIPTENCAMERA_OpenDevice(SDL_CameraDevice *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 + // permission, we don't list any specs for the device and wrangle it during device open. + const device = $0; + const w = $1; + const h = $2; + const interval_numerator = $3; + const interval_denominator = $4; + const outcome = $5; + const iterate = $6; + + const constraints = {}; + if ((w <= 0) || (h <= 0)) { + constraints.video = true; // didn't ask for anything, let the system choose. + } else { + constraints.video = {}; // asked for a specific thing: request it as "ideal" but take closest hardware will offer. + constraints.video.width = w; + constraints.video.height = h; + } + + if ((interval_numerator > 0) && (interval_denominator > 0)) { + var fps = interval_denominator / interval_numerator; + constraints.video.frameRate = { ideal: fps }; + } + + function grabNextCameraFrame() { // !!! FIXME: this (currently) runs as a requestAnimationFrame callback, for lack of a better option. + const SDL3 = Module['SDL3']; + if ((typeof(SDL3) === 'undefined') || (typeof(SDL3.camera) === 'undefined') || (typeof(SDL3.camera.stream) === 'undefined')) { + return; // camera was closed and/or subsystem was shut down, stop iterating here. + } + + // time for a new frame from the camera? + const nextframems = SDL3.camera.next_frame_time; + const now = performance.now(); + if (now >= nextframems) { + dynCall('vi', iterate, [device]); // calls SDL_CameraThreadIterate, which will call our AcquireFrame implementation. + + // bump ahead but try to stay consistent on timing, in case we dropped frames. + while (SDL3.camera.next_frame_time < now) { + SDL3.camera.next_frame_time += SDL3.camera.fpsincrms; + } + } + + requestAnimationFrame(grabNextCameraFrame); // run this function again at the display framerate. (!!! FIXME: would this be better as requestIdleCallback?) + } + + navigator.mediaDevices.getUserMedia(constraints) + .then((stream) => { + const settings = stream.getVideoTracks()[0].getSettings(); + const actualw = settings.width; + const actualh = settings.height; + const actualfps = settings.frameRate; + console.log("Camera is opened! Actual spec: (" + actualw + "x" + actualh + "), fps=" + actualfps); + + dynCall('viiiii', outcome, [device, 1, actualw, actualh, actualfps]); + + const video = document.createElement("video"); + video.width = actualw; + video.height = actualh; + video.style.display = 'none'; // we need to attach this to a hidden video node so we can read it as pixels. + video.srcObject = stream; + + const canvas = document.createElement("canvas"); + canvas.width = actualw; + canvas.height = actualh; + canvas.style.display = 'none'; // we need to attach this to a hidden video node so we can read it as pixels. + + const ctx2d = canvas.getContext('2d'); + + const SDL3 = Module['SDL3']; + SDL3.camera.width = actualw; + SDL3.camera.height = actualh; + SDL3.camera.fps = actualfps; + SDL3.camera.fpsincrms = 1000.0 / actualfps; + SDL3.camera.stream = stream; + 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(); + video.addEventListener('loadedmetadata', () => { + grabNextCameraFrame(); // start this loop going. + }); + }) + .catch((err) => { + 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); + + return 0; // the real work waits until the user approves a camera. +} + +static void EMSCRIPTENCAMERA_FreeDeviceHandle(SDL_CameraDevice *device) +{ + // no-op. +} + +static void EMSCRIPTENCAMERA_Deinitialize(void) +{ + MAIN_THREAD_EM_ASM({ + if (typeof(Module['SDL3']) !== 'undefined') { + Module['SDL3'].camera = undefined; + } + }); +} + +static void EMSCRIPTENCAMERA_DetectDevices(void) +{ + // `navigator.mediaDevices` is not defined if unsupported or not in a secure context! + const int supported = MAIN_THREAD_EM_ASM_INT({ return (navigator.mediaDevices === undefined) ? 0 : 1; }); + + // if we have support at all, report a single generic camera with no specs. + // We'll find out if there really _is_ a camera when we try to open it, but querying it for real here + // 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); + } +} + +static SDL_bool EMSCRIPTENCAMERA_Init(SDL_CameraDriverImpl *impl) +{ + MAIN_THREAD_EM_ASM({ + if (typeof(Module['SDL3']) === 'undefined') { + Module['SDL3'] = {}; + } + Module['SDL3'].camera = {}; + }); + + impl->DetectDevices = EMSCRIPTENCAMERA_DetectDevices; + impl->OpenDevice = EMSCRIPTENCAMERA_OpenDevice; + impl->CloseDevice = EMSCRIPTENCAMERA_CloseDevice; + impl->WaitDevice = EMSCRIPTENCAMERA_WaitDevice; + impl->AcquireFrame = EMSCRIPTENCAMERA_AcquireFrame; + impl->ReleaseFrame = EMSCRIPTENCAMERA_ReleaseFrame; + impl->FreeDeviceHandle = EMSCRIPTENCAMERA_FreeDeviceHandle; + impl->Deinitialize = EMSCRIPTENCAMERA_Deinitialize; + + impl->ProvidesOwnCallbackThread = SDL_TRUE; + + return SDL_TRUE; +} + +CameraBootStrap EMSCRIPTENCAMERA_bootstrap = { + "emscripten", "SDL Emscripten MediaStream camera driver", EMSCRIPTENCAMERA_Init, SDL_FALSE +}; + +/* *INDENT-ON* */ /* clang-format on */ + +#endif // SDL_CAMERA_DRIVER_EMSCRIPTEN + diff --git a/src/camera/mediafoundation/SDL_camera_mediafoundation.c b/src/camera/mediafoundation/SDL_camera_mediafoundation.c new file mode 100644 index 00000000..86d50059 --- /dev/null +++ b/src/camera/mediafoundation/SDL_camera_mediafoundation.c @@ -0,0 +1,933 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 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 Windows Media Foundation API + +#ifdef SDL_CAMERA_DRIVER_MEDIAFOUNDATION + +#define COBJMACROS + +// this seems to be a bug in mfidl.h, just define this to avoid the problem section. +#define __IMFVideoProcessorControl3_INTERFACE_DEFINED__ + +#include "../../core/windows/SDL_windows.h" + +#include +#include +#include + +#include "../SDL_syscamera.h" +#include "../SDL_camera_c.h" + +static const IID SDL_IID_IMFMediaSource = { 0x279a808d, 0xaec7, 0x40c8, { 0x9c, 0x6b, 0xa6, 0xb4, 0x92, 0xc7, 0x8a, 0x66 } }; +static const IID SDL_IID_IMF2DBuffer = { 0x7dc9d5f9, 0x9ed9, 0x44ec, { 0x9b, 0xbf, 0x06, 0x00, 0xbb, 0x58, 0x9f, 0xbb } }; +static const IID SDL_IID_IMF2DBuffer2 = { 0x33ae5ea6, 0x4316, 0x436f, { 0x8d, 0xdd, 0xd7, 0x3d, 0x22, 0xf8, 0x29, 0xec } }; +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_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 } }; + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmultichar" +#endif + +#define SDL_DEFINE_MEDIATYPE_GUID(name, fmt) static const GUID SDL_##name = { fmt, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB555, 24); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB565, 23); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB24, 20); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB32, 22); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_ARGB32, 21); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_A2R10G10B10, 31); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_YV12, FCC('YV12')); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_IYUV, FCC('IYUV')); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_YUY2, FCC('YUY2')); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_UYVY, FCC('UYVY')); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_YVYU, FCC('YVYU')); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV12, FCC('NV12')); +SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV21, FCC('NV21')); +#undef SDL_DEFINE_MEDIATYPE_GUID + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +static const struct +{ + const GUID *guid; + const SDL_PixelFormatEnum sdlfmt; +} 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 } +}; + +static SDL_PixelFormatEnum MFVidFmtGuidToSDLFmt(const GUID *guid) +{ + for (size_t i = 0; i < SDL_arraysize(fmtmappings); i++) { + if (WIN_IsEqualGUID(guid, fmtmappings[i].guid)) { + return fmtmappings[i].sdlfmt; + } + } + return SDL_PIXELFORMAT_UNKNOWN; +} + +static const GUID *SDLFmtToMFVidFmtGuid(SDL_PixelFormatEnum sdlfmt) +{ + for (size_t i = 0; i < SDL_arraysize(fmtmappings); i++) { + if (fmtmappings[i].sdlfmt == sdlfmt) { + return fmtmappings[i].guid; + } + } + return NULL; +} + + +// handle to Media Foundation libs--Vista and later!--for access to the Media Foundation API. + +// mf.dll ... +static HMODULE libmf = NULL; +typedef HRESULT(WINAPI *pfnMFEnumDeviceSources)(IMFAttributes *,IMFActivate ***,UINT32 *); +typedef HRESULT(WINAPI *pfnMFCreateDeviceSource)(IMFAttributes *, IMFMediaSource **); +static pfnMFEnumDeviceSources pMFEnumDeviceSources = NULL; +static pfnMFCreateDeviceSource pMFCreateDeviceSource = NULL; + +// mfplat.dll ... +static HMODULE libmfplat = NULL; +typedef HRESULT(WINAPI *pfnMFStartup)(ULONG, DWORD); +typedef HRESULT(WINAPI *pfnMFShutdown)(void); +typedef HRESULT(WINAPI *pfnMFCreateAttributes)(IMFAttributes **, UINT32); +typedef HRESULT(WINAPI *pfnMFCreateMediaType)(IMFMediaType **); +typedef HRESULT(WINAPI *pfnMFGetStrideForBitmapInfoHeader)(DWORD, DWORD, LONG *); + +static pfnMFStartup pMFStartup = NULL; +static pfnMFShutdown pMFShutdown = NULL; +static pfnMFCreateAttributes pMFCreateAttributes = NULL; +static pfnMFCreateMediaType pMFCreateMediaType = NULL; +static pfnMFGetStrideForBitmapInfoHeader pMFGetStrideForBitmapInfoHeader = NULL; + +// mfreadwrite.dll ... +static HMODULE libmfreadwrite = NULL; +typedef HRESULT(WINAPI *pfnMFCreateSourceReaderFromMediaSource)(IMFMediaSource *, IMFAttributes *, IMFSourceReader **); +static pfnMFCreateSourceReaderFromMediaSource pMFCreateSourceReaderFromMediaSource = NULL; + + +typedef struct SDL_PrivateCameraData +{ + IMFSourceReader *srcreader; + IMFSample *current_sample; + int pitch; +} SDL_PrivateCameraData; + +static int MEDIAFOUNDATION_WaitDevice(SDL_CameraDevice *device) +{ + SDL_assert(device->hidden->current_sample == NULL); + + IMFSourceReader *srcreader = device->hidden->srcreader; + IMFSample *sample = NULL; + + while (!SDL_AtomicGet(&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. + } + + // 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 + // 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. :/ + } + + // otherwise, there was some minor burp, probably; just try again. + } + + device->hidden->current_sample = sample; + + return 0; +} + + +#ifdef KEEP_ACQUIRED_BUFFERS_LOCKED + +#define PROP_SURFACE_IMFOBJS_POINTER "SDL.camera.mediafoundation.imfobjs" + +typedef struct SDL_IMFObjects +{ + IMF2DBuffer2 *buffer2d2; + IMF2DBuffer *buffer2d; + IMFMediaBuffer *buffer; + IMFSample *sample; +} SDL_IMFObjects; + +static void SDLCALL CleanupIMF2DBuffer2(void *userdata, void *value) +{ + SDL_IMFObjects *objs = (SDL_IMFObjects *)value; + IMF2DBuffer2_Unlock2D(objs->buffer2d2); + IMF2DBuffer2_Release(objs->buffer2d2); + IMFMediaBuffer_Release(objs->buffer); + IMFSample_Release(objs->sample); + SDL_free(objs); +} + +static void SDLCALL CleanupIMF2DBuffer(void *userdata, void *value) +{ + SDL_IMFObjects *objs = (SDL_IMFObjects *)value; + IMF2DBuffer_Unlock2D(objs->buffer2d); + IMF2DBuffer_Release(objs->buffer2d); + IMFMediaBuffer_Release(objs->buffer); + IMFSample_Release(objs->sample); + SDL_free(objs); +} + +static void SDLCALL CleanupIMFMediaBuffer(void *userdata, void *value) +{ + SDL_IMFObjects *objs = (SDL_IMFObjects *)value; + IMFMediaBuffer_Unlock(objs->buffer); + IMFMediaBuffer_Release(objs->buffer); + IMFSample_Release(objs->sample); + SDL_free(objs); +} + +static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +{ + SDL_assert(device->hidden->current_sample != NULL); + + int retval = 1; + HRESULT ret; + LONGLONG timestamp100NS = 0; + SDL_IMFObjects *objs = (SDL_IMFObjects *) SDL_calloc(1, sizeof (SDL_IMFObjects)); + + if (objs == NULL) { + return -1; + } + + objs->sample = device->hidden->current_sample; + device->hidden->current_sample = NULL; + + const SDL_PropertiesID surfprops = SDL_GetSurfaceProperties(frame); + if (!surfprops) { + retval = -1; + } else { + ret = IMFSample_GetSampleTime(objs->sample, ×tamp100NS); + if (FAILED(ret)) { + retval = -1; + } + + *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);*/ + + if (FAILED(ret)) { + SDL_free(objs); + retval = -1; + } else { + BYTE *pixels = NULL; + LONG pitch = 0; + + if (SUCCEEDED(IMFMediaBuffer_QueryInterface(objs->buffer, &SDL_IID_IMF2DBuffer2, (void **)&objs->buffer2d2))) { + BYTE *bufstart = NULL; + DWORD buflen = 0; + ret = IMF2DBuffer2_Lock2DSize(objs->buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen); + if (FAILED(ret)) { + retval = -1; + 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; + } + } + } 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; + } 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; + } + } + } else { + DWORD maxlen = 0, currentlen = 0; + ret = IMFMediaBuffer_Lock(objs->buffer, &pixels, &maxlen, ¤tlen); + if (FAILED(ret)) { + CleanupIMFMediaBuffer(NULL, objs); + retval = -1; + } else { + pitch = (LONG) device->hidden->pitch; + if (pitch < 0) { // image rows are reversed. + pixels += -pitch * (frame->h - 1); + } + 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 (retval < 0) { + *timestampNS = 0; + } + + return retval; +} + +static void MEDIAFOUNDATION_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +{ + const SDL_PropertiesID surfprops = SDL_GetSurfaceProperties(frame); + if (surfprops) { + // this will release the IMFBuffer and IMFSample objects for this frame. + SDL_ClearProperty(surfprops, PROP_SURFACE_IMFOBJS_POINTER); + } +} + +#else + +static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +{ + SDL_assert(device->hidden->current_sample != NULL); + + int retval = 1; + HRESULT ret; + LONGLONG timestamp100NS = 0; + + IMFSample *sample = device->hidden->current_sample; + device->hidden->current_sample = NULL; + + const SDL_PropertiesID surfprops = SDL_GetSurfaceProperties(frame); + if (!surfprops) { + retval = -1; + } else { + ret = IMFSample_GetSampleTime(sample, ×tamp100NS); + if (FAILED(ret)) { + retval = -1; + } + + *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);*/ + + if (FAILED(ret)) { + retval = -1; + } else { + IMF2DBuffer *buffer2d = NULL; + IMF2DBuffer2 *buffer2d2 = NULL; + BYTE *pixels = NULL; + LONG pitch = 0; + + if (SUCCEEDED(IMFMediaBuffer_QueryInterface(buffer, &SDL_IID_IMF2DBuffer2, (void **)&buffer2d2))) { + BYTE *bufstart = NULL; + DWORD buflen = 0; + ret = IMF2DBuffer2_Lock2DSize(buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen); + if (FAILED(ret)) { + retval = -1; + } else { + frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + if (frame->pixels == NULL) { + retval = -1; + } else { + SDL_memcpy(frame->pixels, pixels, buflen); + frame->pitch = (int)pitch; + } + IMF2DBuffer2_Unlock2D(buffer2d2); + } + IMF2DBuffer2_Release(buffer2d2); + } else if (SUCCEEDED(IMFMediaBuffer_QueryInterface(buffer, &SDL_IID_IMF2DBuffer, (void **)&buffer2d))) { + ret = IMF2DBuffer_Lock2D(buffer2d, &pixels, &pitch); + if (FAILED(ret)) { + retval = -1; + } 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); + if (frame->pixels == NULL) { + retval = -1; + } else { + SDL_memcpy(frame->pixels, bufstart, buflen); + frame->pitch = (int)pitch; + } + IMF2DBuffer_Unlock2D(buffer2d); + } + IMF2DBuffer_Release(buffer2d); + } else { + DWORD maxlen = 0, currentlen = 0; + ret = IMFMediaBuffer_Lock(buffer, &pixels, &maxlen, ¤tlen); + if (FAILED(ret)) { + retval = -1; + } else { + BYTE *bufstart = pixels; + pitch = (LONG)device->hidden->pitch; + 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); + if (frame->pixels == NULL) { + retval = -1; + } else { + SDL_memcpy(frame->pixels, bufstart, buflen); + frame->pitch = (int)pitch; + } + IMFMediaBuffer_Unlock(buffer); + } + } + IMFMediaBuffer_Release(buffer); + } + + IMFSample_Release(sample); + + if (retval < 0) { + *timestampNS = 0; + } + + return retval; +} + +static void MEDIAFOUNDATION_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +{ + SDL_aligned_free(frame->pixels); +} + +#endif + +static void MEDIAFOUNDATION_CloseDevice(SDL_CameraDevice *device) +{ + if (device && device->hidden) { + if (device->hidden->srcreader) { + IMFSourceReader_Release(device->hidden->srcreader); + } + if (device->hidden->current_sample) { + IMFSample_Release(device->hidden->current_sample); + } + SDL_free(device->hidden); + device->hidden = NULL; + } +} + +// this function is from https://learn.microsoft.com/en-us/windows/win32/medfound/uncompressed-video-buffers +static HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride) +{ + LONG lStride = 0; + + // Try to get the default stride from the media type. + HRESULT ret = IMFMediaType_GetUINT32(pType, &SDL_MF_MT_DEFAULT_STRIDE, (UINT32*)&lStride); + if (FAILED(ret)) { + // Attribute not set. Try to calculate the default stride. + + GUID subtype = GUID_NULL; + UINT32 width = 0; + /* UINT32 height = 0; */ + UINT64 val = 0; + + // Get the subtype and the image size. + ret = IMFMediaType_GetGUID(pType, &SDL_MF_MT_SUBTYPE, &subtype); + if (FAILED(ret)) { + goto done; + } + + ret = IMFMediaType_GetUINT64(pType, &SDL_MF_MT_FRAME_SIZE, &val); + if (FAILED(ret)) { + goto done; + } + + width = (UINT32) (val >> 32); + /* height = (UINT32) val; */ + + ret = pMFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride); + if (FAILED(ret)) { + goto done; + } + + // Set the attribute for later reference. + IMFMediaType_SetUINT32(pType, &SDL_MF_MT_DEFAULT_STRIDE, (UINT32) lStride); + } + + if (SUCCEEDED(ret)) { + *plStride = lStride; + } + +done: + return ret; +} + + +static int MEDIAFOUNDATION_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +{ + const char *utf8symlink = (const char *) device->handle; + IMFAttributes *attrs = NULL; + LPWSTR wstrsymlink = NULL; + IMFMediaSource *source = NULL; + IMFMediaType *mediatype = NULL; + IMFSourceReader *srcreader = NULL; +#if 0 + DWORD num_streams = 0; +#endif + LONG lstride = 0; + //PROPVARIANT var; + HRESULT ret; + + #if 0 + IMFStreamDescriptor *streamdesc = NULL; + IMFPresentationDescriptor *presentdesc = NULL; + IMFMediaTypeHandler *handler = NULL; + #endif + + #if DEBUG_CAMERA + SDL_Log("CAMERA: opening device with symlink of '%s'", utf8symlink); + #endif + + wstrsymlink = WIN_UTF8ToString(utf8symlink); + if (!wstrsymlink) { + goto failed; + } + + #define CHECK_HRESULT(what, r) if (FAILED(r)) { WIN_SetErrorFromHRESULT(what " failed", r); goto failed; } + + ret = pMFCreateAttributes(&attrs, 1); + CHECK_HRESULT("MFCreateAttributes", ret); + + ret = IMFAttributes_SetGUID(attrs, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, &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); + CHECK_HRESULT("IMFAttributes_SetString(symlink)", ret); + + ret = pMFCreateDeviceSource(attrs, &source); + CHECK_HRESULT("MFCreateDeviceSource", ret); + + IMFAttributes_Release(attrs); + SDL_free(wstrsymlink); + attrs = NULL; + wstrsymlink = NULL; + + // !!! FIXME: I think it'd be nice to do this without an IMFSourceReader, + // since it's just utility code that has to handle more complex media streams + // than we're dealing with, but this will do for now. The docs are slightly + // insistent that you should use one, though...Maybe it's extremely hard + // to handle directly at the IMFMediaSource layer...? + ret = pMFCreateSourceReaderFromMediaSource(source, NULL, &srcreader); + CHECK_HRESULT("MFCreateSourceReaderFromMediaSource", ret); + + // !!! FIXME: do we actually have to find the media type object in the source reader or can we just roll our own like this? + ret = pMFCreateMediaType(&mediatype); + CHECK_HRESULT("MFCreateMediaType", ret); + + ret = IMFMediaType_SetGUID(mediatype, &SDL_MF_MT_MAJOR_TYPE, &SDL_MFMediaType_Video); + CHECK_HRESULT("IMFMediaType_SetGUID(major_type)", ret); + + ret = IMFMediaType_SetGUID(mediatype, &SDL_MF_MT_SUBTYPE, SDLFmtToMFVidFmtGuid(spec->format)); + CHECK_HRESULT("IMFMediaType_SetGUID(subtype)", ret); + + 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)); + CHECK_HRESULT("MFSetAttributeRatio(frame_rate)", ret); + + ret = IMFSourceReader_SetCurrentMediaType(srcreader, (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, mediatype); + CHECK_HRESULT("IMFSourceReader_SetCurrentMediaType", ret); + + #if 0 // this (untested thing) is what we would do to get started with a IMFMediaSource that _doesn't_ use IMFSourceReader... + ret = IMFMediaSource_CreatePresentationDescriptor(source, &presentdesc); + CHECK_HRESULT("IMFMediaSource_CreatePresentationDescriptor", ret); + + ret = IMFPresentationDescriptor_GetStreamDescriptorCount(presentdesc, &num_streams); + CHECK_HRESULT("IMFPresentationDescriptor_GetStreamDescriptorCount", ret); + + for (DWORD i = 0; i < num_streams; i++) { + BOOL selected = FALSE; + ret = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentdesc, i, &selected, &streamdesc); + CHECK_HRESULT("IMFPresentationDescriptor_GetStreamDescriptorByIndex", ret); + + if (selected) { + ret = IMFStreamDescriptor_GetMediaTypeHandler(streamdesc, &handler); + CHECK_HRESULT("IMFStreamDescriptor_GetMediaTypeHandler", ret); + IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype); + IMFMediaTypeHandler_Release(handler); + handler = NULL; + } + + IMFStreamDescriptor_Release(streamdesc); + streamdesc = NULL; + } + + PropVariantInit(&var); + var.vt = VT_EMPTY; + ret = IMFMediaSource_Start(source, presentdesc, NULL, &var); + PropVariantClear(&var); + CHECK_HRESULT("IMFMediaSource_Start", ret); + + IMFPresentationDescriptor_Release(presentdesc); + presentdesc = NULL; + #endif + + ret = GetDefaultStride(mediatype, &lstride); + CHECK_HRESULT("GetDefaultStride", ret); + + IMFMediaType_Release(mediatype); + mediatype = NULL; + + device->hidden = (SDL_PrivateCameraData *) SDL_calloc(1, sizeof (SDL_PrivateCameraData)); + if (!device->hidden) { + goto failed; + } + + device->hidden->pitch = (int) lstride; + device->hidden->srcreader = srcreader; + 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); + + #undef CHECK_HRESULT + + return 0; + +failed: + + if (srcreader) { + IMFSourceReader_Release(srcreader); + } + + #if 0 + if (handler) { + IMFMediaTypeHandler_Release(handler); + } + + if (streamdesc) { + IMFStreamDescriptor_Release(streamdesc); + } + + if (presentdesc) { + IMFPresentationDescriptor_Release(presentdesc); + } + #endif + + if (source) { + IMFMediaSource_Shutdown(source); + IMFMediaSource_Release(source); + } + + if (mediatype) { + IMFMediaType_Release(mediatype); + } + + if (attrs) { + IMFAttributes_Release(attrs); + } + SDL_free(wstrsymlink); + + return -1; +} + +static void MEDIAFOUNDATION_FreeDeviceHandle(SDL_CameraDevice *device) +{ + if (device) { + SDL_free(device->handle); // the device's symlink string. + } +} + +static char *QueryActivationObjectString(IMFActivate *activation, const GUID *pguid) +{ + LPWSTR wstr = NULL; + UINT32 wlen = 0; + HRESULT ret = IMFActivate_GetAllocatedString(activation, pguid, &wstr, &wlen); + if (FAILED(ret)) { + return NULL; + } + + char *utf8str = WIN_StringToUTF8(wstr); + CoTaskMemFree(wstr); + return utf8str; +} + +static void GatherCameraSpecs(IMFMediaSource *source, CameraFormatAddData *add_data) +{ + HRESULT ret; + + // this has like a thousand steps. :/ + + SDL_zerop(add_data); + + IMFPresentationDescriptor *presentdesc = NULL; + ret = IMFMediaSource_CreatePresentationDescriptor(source, &presentdesc); + if (FAILED(ret) || !presentdesc) { + return; + } + + DWORD num_streams = 0; + ret = IMFPresentationDescriptor_GetStreamDescriptorCount(presentdesc, &num_streams); + if (FAILED(ret)) { + num_streams = 0; + } + + for (DWORD i = 0; i < num_streams; i++) { + IMFStreamDescriptor *streamdesc = NULL; + BOOL selected = FALSE; + ret = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentdesc, i, &selected, &streamdesc); + if (FAILED(ret) || !streamdesc) { + continue; + } + + if (selected) { + IMFMediaTypeHandler *handler = NULL; + ret = IMFStreamDescriptor_GetMediaTypeHandler(streamdesc, &handler); + if (SUCCEEDED(ret) && handler) { + DWORD num_mediatype = 0; + ret = IMFMediaTypeHandler_GetMediaTypeCount(handler, &num_mediatype); + if (FAILED(ret)) { + num_mediatype = 0; + } + + for (DWORD j = 0; j < num_mediatype; j++) { + IMFMediaType *mediatype = NULL; + ret = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, j, &mediatype); + if (SUCCEEDED(ret) && mediatype) { + 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. + } + } + } + } + } + IMFMediaType_Release(mediatype); + } + } + IMFMediaTypeHandler_Release(handler); + } + } + IMFStreamDescriptor_Release(streamdesc); + } + + IMFPresentationDescriptor_Release(presentdesc); +} + +static SDL_bool FindMediaFoundationCameraDeviceBySymlink(SDL_CameraDevice *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); + + if (SDL_FindPhysicalCameraDeviceByCallback(FindMediaFoundationCameraDeviceBySymlink, symlink)) { + SDL_free(symlink); + return; // already have this one. + } + + char *name = QueryActivationObjectString(activation, &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. + HRESULT ret = IMFActivate_ActivateObject(activation, &SDL_IID_IMFMediaSource, (void**)&source); + if (SUCCEEDED(ret) && source) { + 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_free(add_data.specs); + IMFActivate_ShutdownObject(activation); + IMFMediaSource_Release(source); + } + } + + SDL_free(name); +} + +static void MEDIAFOUNDATION_DetectDevices(void) +{ + // !!! FIXME: use CM_Register_Notification (Win8+) to get device notifications. + // !!! FIXME: Earlier versions can use RegisterDeviceNotification, but I'm not bothering: no hotplug for you! + HRESULT ret; + + IMFAttributes *attrs = NULL; + ret = pMFCreateAttributes(&attrs, 1); + if (FAILED(ret)) { + 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); + if (FAILED(ret)) { + IMFAttributes_Release(attrs); + return; // oh well, no cameras for you. + } + + IMFActivate **activations = NULL; + UINT32 total = 0; + ret = pMFEnumDeviceSources(attrs, &activations, &total); + IMFAttributes_Release(attrs); + if (FAILED(ret)) { + return; // oh well, no cameras for you. + } + + for (UINT32 i = 0; i < total; i++) { + MaybeAddDevice(activations[i]); + IMFActivate_Release(activations[i]); + } + + CoTaskMemFree(activations); +} + +static void MEDIAFOUNDATION_Deinitialize(void) +{ + pMFShutdown(); + + FreeLibrary(libmfreadwrite); + libmfreadwrite = NULL; + FreeLibrary(libmfplat); + libmfplat = NULL; + FreeLibrary(libmf); + libmf = NULL; + + pMFEnumDeviceSources = NULL; + pMFCreateDeviceSource = NULL; + pMFStartup = NULL; + pMFShutdown = NULL; + pMFCreateAttributes = NULL; + pMFCreateMediaType = NULL; + pMFCreateSourceReaderFromMediaSource = NULL; + pMFGetStrideForBitmapInfoHeader = NULL; +} + +static SDL_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; + } + + 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; + } + + 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; + } + + SDL_bool okay = SDL_TRUE; + #define LOADSYM(lib, fn) if (okay) { p##fn = (pfn##fn) GetProcAddress(lib, #fn); if (!p##fn) { okay = SDL_FALSE; } } + LOADSYM(mf, MFEnumDeviceSources); + LOADSYM(mf, MFCreateDeviceSource); + LOADSYM(mfplat, MFStartup); + LOADSYM(mfplat, MFShutdown); + LOADSYM(mfplat, MFCreateAttributes); + LOADSYM(mfplat, MFCreateMediaType); + LOADSYM(mfplat, MFGetStrideForBitmapInfoHeader); + LOADSYM(mfreadwrite, MFCreateSourceReaderFromMediaSource); + #undef LOADSYM + + if (!okay) { + FreeLibrary(mfreadwrite); + FreeLibrary(mfplat); + FreeLibrary(mf); + } + + 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; + impl->WaitDevice = MEDIAFOUNDATION_WaitDevice; + impl->AcquireFrame = MEDIAFOUNDATION_AcquireFrame; + impl->ReleaseFrame = MEDIAFOUNDATION_ReleaseFrame; + impl->FreeDeviceHandle = MEDIAFOUNDATION_FreeDeviceHandle; + impl->Deinitialize = MEDIAFOUNDATION_Deinitialize; + + return SDL_TRUE; +} + +CameraBootStrap MEDIAFOUNDATION_bootstrap = { + "mediafoundation", "SDL Windows Media Foundation camera driver", MEDIAFOUNDATION_Init, SDL_FALSE +}; + +#endif // SDL_CAMERA_DRIVER_MEDIAFOUNDATION + diff --git a/src/camera/v4l2/SDL_camera_v4l2.c b/src/camera/v4l2/SDL_camera_v4l2.c new file mode 100644 index 00000000..8d061c96 --- /dev/null +++ b/src/camera/v4l2/SDL_camera_v4l2.c @@ -0,0 +1,890 @@ +/* + 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_CAMERA_DRIVER_V4L2 + +#include +#include +#include +#include // low-level i/o +#include +#include +#include +#include + +#ifndef V4L2_CAP_DEVICE_CAPS +// device_caps was added to struct v4l2_capability as of kernel 3.4. +#define device_caps reserved[0] +SDL_COMPILE_TIME_ASSERT(v4l2devicecaps, offsetof(struct v4l2_capability,device_caps) == offsetof(struct v4l2_capability,capabilities) + 4); +#endif + +#include "../SDL_syscamera.h" +#include "../SDL_camera_c.h" +#include "../../video/SDL_pixels_c.h" +#include "../../thread/SDL_systhread.h" +#include "../../core/linux/SDL_evdev_capabilities.h" +#include "../../core/linux/SDL_udev.h" + +#ifndef SDL_USE_LIBUDEV +#include +#endif + +typedef struct V4L2DeviceHandle +{ + char *bus_info; + char *path; +} V4L2DeviceHandle; + + +typedef enum io_method { + IO_METHOD_INVALID, + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR +} io_method; + +struct buffer { + void *start; + size_t length; + int available; // Is available in userspace +}; + +struct SDL_PrivateCameraData +{ + int fd; + io_method io; + int nb_buffers; + struct buffer *buffers; + int driver_pitch; +}; + +static int xioctl(int fh, int request, void *arg) +{ + int r; + + do { + r = ioctl(fh, request, arg); + } while ((r == -1) && (errno == EINTR)); + + return r; +} + +static int V4L2_WaitDevice(SDL_CameraDevice *device) +{ + const int fd = device->hidden->fd; + + int retval; + + do { + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd, &fds); + + struct timeval tv; + 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. + } + } while (retval == 0); + + return retval; +} + +static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +{ + const int fd = device->hidden->fd; + const io_method io = device->hidden->io; + size_t size = device->hidden->buffers[0].length; + struct v4l2_buffer buf; + + switch (io) { + case IO_METHOD_READ: + if (read(fd, device->hidden->buffers[0].start, size) == -1) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + // Could ignore EIO, see spec. + // fall through + + default: + return SDL_SetError("read"); + } + } + + *timestampNS = SDL_GetTicksNS(); // oh well, close enough. + frame->pixels = device->hidden->buffers[0].start; + frame->pitch = device->hidden->driver_pitch; + break; + + case IO_METHOD_MMAP: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + // Could ignore EIO, see spec. + // fall through + + default: + return SDL_SetError("VIDIOC_DQBUF: %d", errno); + } + } + + if ((int)buf.index < 0 || (int)buf.index >= device->hidden->nb_buffers) { + return SDL_SetError("invalid buffer index"); + } + + frame->pixels = device->hidden->buffers[buf.index].start; + frame->pitch = device->hidden->driver_pitch; + device->hidden->buffers[buf.index].available = 1; + + *timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec); + + #if DEBUG_CAMERA + SDL_Log("CAMERA: debug mmap: image %d/%d data[0]=%p", buf.index, device->hidden->nb_buffers, (void*)frame->pixels); + #endif + break; + + case IO_METHOD_USERPTR: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + + if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + // Could ignore EIO, see spec. + + // fall through + + default: + return SDL_SetError("VIDIOC_DQBUF"); + } + } + + int i; + for (i = 0; i < device->hidden->nb_buffers; ++i) { + if (buf.m.userptr == (unsigned long)device->hidden->buffers[i].start && buf.length == size) { + break; + } + } + + if (i >= device->hidden->nb_buffers) { + return SDL_SetError("invalid buffer index"); + } + + frame->pixels = (void*)buf.m.userptr; + frame->pitch = device->hidden->driver_pitch; + device->hidden->buffers[i].available = 1; + + *timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec); + + #if DEBUG_CAMERA + SDL_Log("CAMERA: debug userptr: image %d/%d data[0]=%p", buf.index, device->hidden->nb_buffers, (void*)frame->pixels); + #endif + break; + + case IO_METHOD_INVALID: + SDL_assert(!"Shouldn't have hit this"); + break; + } + + return 1; +} + +static void V4L2_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +{ + struct v4l2_buffer buf; + const int fd = device->hidden->fd; + const io_method io = device->hidden->io; + int i; + + for (i = 0; i < device->hidden->nb_buffers; ++i) { + if (frame->pixels == device->hidden->buffers[i].start) { + break; + } + } + + if (i >= device->hidden->nb_buffers) { + return; // oh well, we didn't own this. + } + + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + // !!! FIXME: disconnect the device. + return; //SDL_SetError("VIDIOC_QBUF"); + } + device->hidden->buffers[i].available = 0; + break; + + case IO_METHOD_USERPTR: + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.userptr = (unsigned long)frame->pixels; + buf.length = (int) device->hidden->buffers[i].length; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + // !!! FIXME: disconnect the device. + return; //SDL_SetError("VIDIOC_QBUF"); + } + device->hidden->buffers[i].available = 0; + break; + + case IO_METHOD_INVALID: + SDL_assert(!"Shouldn't have hit this"); + break; + } +} + +static int EnqueueBuffers(SDL_CameraDevice *device) +{ + const int fd = device->hidden->fd; + const io_method io = device->hidden->io; + switch (io) { + case IO_METHOD_READ: + break; + + case IO_METHOD_MMAP: + for (int i = 0; i < device->hidden->nb_buffers; ++i) { + if (device->hidden->buffers[i].available == 0) { + struct v4l2_buffer buf; + + SDL_zero(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QBUF"); + } + } + } + break; + + case IO_METHOD_USERPTR: + for (int i = 0; i < device->hidden->nb_buffers; ++i) { + if (device->hidden->buffers[i].available == 0) { + struct v4l2_buffer buf; + + SDL_zero(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.userptr = (unsigned long)device->hidden->buffers[i].start; + buf.length = (int) device->hidden->buffers[i].length; + + if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QBUF"); + } + } + } + break; + + case IO_METHOD_INVALID: SDL_assert(!"Shouldn't have hit this"); break; + } + return 0; +} + +static int AllocBufferRead(SDL_CameraDevice *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; +} + +static int AllocBufferMmap(SDL_CameraDevice *device) +{ + const int fd = device->hidden->fd; + int i; + for (i = 0; i < device->hidden->nb_buffers; ++i) { + struct v4l2_buffer buf; + + SDL_zero(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (xioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { + return SDL_SetError("VIDIOC_QUERYBUF"); + } + + device->hidden->buffers[i].length = buf.length; + device->hidden->buffers[i].start = + mmap(NULL /* start anywhere */, + buf.length, + PROT_READ | PROT_WRITE /* required */, + MAP_SHARED /* recommended */, + fd, buf.m.offset); + + if (MAP_FAILED == device->hidden->buffers[i].start) { + return SDL_SetError("mmap"); + } + } + return 0; +} + +static int AllocBufferUserPtr(SDL_CameraDevice *device, size_t buffer_size) +{ + int i; + for (i = 0; i < device->hidden->nb_buffers; ++i) { + device->hidden->buffers[i].length = buffer_size; + device->hidden->buffers[i].start = SDL_calloc(1, buffer_size); + + if (!device->hidden->buffers[i].start) { + return -1; + } + } + return 0; +} + +static Uint32 format_v4l2_to_sdl(Uint32 fmt) +{ + 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; + } +} + +static Uint32 format_sdl_to_v4l2(Uint32 fmt) +{ + switch (fmt) { + #define CASE(y, x) case x: return y + CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2); + CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); + #undef CASE + default: + return 0; + } +} + +static void V4L2_CloseDevice(SDL_CameraDevice *device) +{ + if (!device) { + return; + } + + if (device->hidden) { + const io_method io = device->hidden->io; + const int fd = device->hidden->fd; + + if ((io == IO_METHOD_MMAP) || (io == IO_METHOD_USERPTR)) { + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + xioctl(fd, VIDIOC_STREAMOFF, &type); + } + + if (device->hidden->buffers) { + switch (io) { + case IO_METHOD_INVALID: + break; + + case IO_METHOD_READ: + SDL_free(device->hidden->buffers[0].start); + break; + + case IO_METHOD_MMAP: + for (int i = 0; i < device->hidden->nb_buffers; ++i) { + if (munmap(device->hidden->buffers[i].start, device->hidden->buffers[i].length) == -1) { + SDL_SetError("munmap"); + } + } + break; + + case IO_METHOD_USERPTR: + for (int i = 0; i < device->hidden->nb_buffers; ++i) { + SDL_free(device->hidden->buffers[i].start); + } + break; + } + + SDL_free(device->hidden->buffers); + } + + if (fd != -1) { + close(fd); + } + SDL_free(device->hidden); + + device->hidden = NULL; + } +} + +static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +{ + const V4L2DeviceHandle *handle = (const V4L2DeviceHandle *) device->handle; + struct stat st; + struct v4l2_capability cap; + const int fd = open(handle->path, O_RDWR /* required */ | O_NONBLOCK, 0); + + // most of this probably shouldn't fail unless the filesystem node changed out from under us since MaybeAddDevice(). + if (fd == -1) { + return SDL_SetError("Cannot open '%s': %d, %s", handle->path, errno, strerror(errno)); + } else if (fstat(fd, &st) == -1) { + close(fd); + return SDL_SetError("Cannot identify '%s': %d, %s", handle->path, errno, strerror(errno)); + } else if (!S_ISCHR(st.st_mode)) { + close(fd); + return SDL_SetError("%s is not a character device", handle->path); + } else if (xioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) { + const int err = errno; + close(fd); + if (err == EINVAL) { + return SDL_SetError("%s is unexpectedly not a V4L2 device", handle->path); + } + return SDL_SetError("Error VIDIOC_QUERYCAP errno=%d device%s is no V4L2 device", err, handle->path); + } else if ((cap.device_caps & V4L2_CAP_VIDEO_CAPTURE) == 0) { + close(fd); + return SDL_SetError("%s is unexpectedly not a video capture device", handle->path); + } + + device->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); + if (device->hidden == NULL) { + close(fd); + return -1; + } + + device->hidden->fd = fd; + device->hidden->io = IO_METHOD_INVALID; + + // Select video input, video standard and tune here. + // errors in the crop code are not fatal. + struct v4l2_cropcap cropcap; + SDL_zero(cropcap); + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0) { + struct v4l2_crop crop; + SDL_zero(crop); + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; // reset to default + xioctl(fd, VIDIOC_S_CROP, &crop); + } + + struct v4l2_format fmt; + SDL_zero(fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = spec->width; + fmt.fmt.pix.height = spec->height; + fmt.fmt.pix.pixelformat = format_sdl_to_v4l2(spec->format); + //fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + + #if DEBUG_CAMERA + SDL_Log("CAMERA: set SDL format %s", SDL_GetPixelFormatName(spec->format)); + { const Uint32 f = fmt.fmt.pix.pixelformat; SDL_Log("CAMERA: set format V4L2_format=%d %c%c%c%c", f, (f >> 0) & 0xff, (f >> 8) & 0xff, (f >> 16) & 0xff, (f >> 24) & 0xff); } + #endif + + if (xioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { + return SDL_SetError("Error VIDIOC_S_FMT"); + } + + if (spec->interval_numerator && spec->interval_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) ) { + setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + setfps.parm.capture.timeperframe.numerator = spec->interval_numerator; + setfps.parm.capture.timeperframe.denominator = spec->interval_denominator; + if (xioctl(fd, VIDIOC_S_PARM, &setfps) == -1) { + return SDL_SetError("Error VIDIOC_S_PARM"); + } + } + } + } + + SDL_zero(fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(fd, VIDIOC_G_FMT, &fmt) == -1) { + return SDL_SetError("Error VIDIOC_G_FMT"); + } + device->hidden->driver_pitch = fmt.fmt.pix.bytesperline; + + io_method io = IO_METHOD_INVALID; + if ((io == IO_METHOD_INVALID) && (cap.device_caps & V4L2_CAP_STREAMING)) { + struct v4l2_requestbuffers req; + SDL_zero(req); + req.count = 8; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + if ((xioctl(fd, VIDIOC_REQBUFS, &req) == 0) && (req.count >= 2)) { + io = IO_METHOD_MMAP; + device->hidden->nb_buffers = req.count; + } else { // mmap didn't work out? Try USERPTR. + SDL_zero(req); + req.count = 8; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + if (xioctl(fd, VIDIOC_REQBUFS, &req) == 0) { + io = IO_METHOD_USERPTR; + device->hidden->nb_buffers = 8; + } + } + } + + if ((io == IO_METHOD_INVALID) && (cap.device_caps & V4L2_CAP_READWRITE)) { + io = IO_METHOD_READ; + device->hidden->nb_buffers = 1; + } + + if (io == IO_METHOD_INVALID) { + return SDL_SetError("Don't have a way to talk to this device"); + } + + device->hidden->io = io; + + device->hidden->buffers = SDL_calloc(device->hidden->nb_buffers, sizeof(*device->hidden->buffers)); + if (!device->hidden->buffers) { + return -1; + } + + size_t size, pitch; + SDL_CalculateSurfaceSize(device->spec.format, device->spec.width, device->spec.height, &size, &pitch, SDL_FALSE); + + int rc = 0; + switch (io) { + case IO_METHOD_READ: + rc = AllocBufferRead(device, size); + break; + + case IO_METHOD_MMAP: + rc = AllocBufferMmap(device); + break; + + case IO_METHOD_USERPTR: + rc = AllocBufferUserPtr(device, size); + break; + + case IO_METHOD_INVALID: + SDL_assert(!"Shouldn't have hit this"); + break; + } + + if (rc < 0) { + return -1; + } else if (EnqueueBuffers(device) < 0) { + return -1; + } else if (io != IO_METHOD_READ) { + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(fd, VIDIOC_STREAMON, &type) == -1) { + return SDL_SetError("VIDIOC_STREAMON"); + } + } + + // 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); + + return 0; +} + +static SDL_bool FindV4L2CameraDeviceByBusInfoCallback(SDL_CameraDevice *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) +{ + struct v4l2_frmivalenum frmivalenum; + SDL_zero(frmivalenum); + frmivalenum.pixel_format = v4l2fmt; + frmivalenum.width = (Uint32) w; + frmivalenum.height = (Uint32) h; + + while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) == 0) { + if (frmivalenum.type == V4L2_FRMIVAL_TYPE_DISCRETE) { + const int numerator = (int) frmivalenum.discrete.numerator; + const int denominator = (int) frmivalenum.discrete.denominator; + #if DEBUG_CAMERA + 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. + } + frmivalenum.index++; // set up for the next one. + } else if ((frmivalenum.type == V4L2_FRMIVAL_TYPE_STEPWISE) || (frmivalenum.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) { + int d = frmivalenum.stepwise.min.denominator; + // !!! FIXME: should we step by the numerator...? + for (int n = (int) frmivalenum.stepwise.min.numerator; n <= (int) frmivalenum.stepwise.max.numerator; n += (int) frmivalenum.stepwise.step.numerator) { + #if DEBUG_CAMERA + 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. + } + d += (int) frmivalenum.stepwise.step.denominator; + } + break; + } + } + + return 0; +} + + +static void MaybeAddDevice(const char *path) +{ + if (!path) { + return; + } + + struct stat st; + const int fd = open(path, O_RDWR /* required */ | O_NONBLOCK, 0); + if (fd == -1) { + return; // can't open it? skip it. + } else if (fstat(fd, &st) == -1) { + close(fd); + return; // can't stat it? skip it. + } else if (!S_ISCHR(st.st_mode)) { + close(fd); + return; // not a character device. + } + + struct v4l2_capability vcap; + const int rc = ioctl(fd, VIDIOC_QUERYCAP, &vcap); + if (rc != 0) { + close(fd); + return; // probably not a v4l2 device at all. + } 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)) { + close(fd); + return; // already have it. + } + + #if DEBUG_CAMERA + SDL_Log("CAMERA: V4L2 camera path='%s' bus_info='%s' name='%s'", path, (const char *) vcap.bus_info, vcap.card); + #endif + + CameraFormatAddData add_data; + SDL_zero(add_data); + + struct v4l2_fmtdesc fmtdesc; + 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); + + #if DEBUG_CAMERA + SDL_Log("CAMERA: - Has format '%s'%s%s", SDL_GetPixelFormatName(sdlfmt), + (fmtdesc.flags & V4L2_FMT_FLAG_EMULATED) ? " [EMULATED]" : "", + (fmtdesc.flags & V4L2_FMT_FLAG_COMPRESSED) ? " [COMPRESSED]" : ""); + #endif + + fmtdesc.index++; // prepare for next iteration. + + if (sdlfmt == SDL_PIXELFORMAT_UNKNOWN) { + continue; // unsupported by SDL atm. + } + + struct v4l2_frmsizeenum frmsizeenum; + SDL_zero(frmsizeenum); + frmsizeenum.pixel_format = fmtdesc.pixelformat; + + while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == 0) { + if (frmsizeenum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + const int w = (int) frmsizeenum.discrete.width; + const int h = (int) frmsizeenum.discrete.height; + #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) { + break; // Probably out of memory; we'll go with what we have, if anything. + } + frmsizeenum.index++; // set up for the next one. + } else if ((frmsizeenum.type == V4L2_FRMSIZE_TYPE_STEPWISE) || (frmsizeenum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS)) { + const int minw = (int) frmsizeenum.stepwise.min_width; + const int minh = (int) frmsizeenum.stepwise.min_height; + const int maxw = (int) frmsizeenum.stepwise.max_width; + const int maxh = (int) frmsizeenum.stepwise.max_height; + const int stepw = (int) frmsizeenum.stepwise.step_width; + const int steph = (int) frmsizeenum.stepwise.step_height; + for (int w = minw; w <= maxw; w += stepw) { + for (int h = minh; w <= maxh; w += steph) { + #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) { + break; // Probably out of memory; we'll go with what we have, if anything. + } + } + } + break; + } + } + } + + close(fd); + + #if DEBUG_CAMERA + SDL_Log("CAMERA: (total specs: %d)", add_data.num_specs); + #endif + + if (add_data.num_specs > 0) { + V4L2DeviceHandle *handle = (V4L2DeviceHandle *) SDL_calloc(1, sizeof (V4L2DeviceHandle)); + if (handle) { + handle->path = SDL_strdup(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)) { + SDL_free(add_data.specs); + return; // good to go. + } + SDL_free(handle->bus_info); + } + SDL_free(handle->path); + } + SDL_free(handle); + } + } + SDL_free(add_data.specs); +} + +static void V4L2_FreeDeviceHandle(SDL_CameraDevice *device) +{ + if (device) { + V4L2DeviceHandle *handle = (V4L2DeviceHandle *) device->handle; + SDL_free(handle->path); + SDL_free(handle->bus_info); + SDL_free(handle); + } +} + +#ifdef SDL_USE_LIBUDEV +static SDL_bool FindV4L2CameraDeviceByPathCallback(SDL_CameraDevice *device, void *userdata) +{ + const V4L2DeviceHandle *handle = (const V4L2DeviceHandle *) device->handle; + return (SDL_strcmp(handle->path, (const char *) userdata) == 0); +} + +static void MaybeRemoveDevice(const char *path) +{ + if (path) { + SDL_CameraDeviceDisconnected(SDL_FindPhysicalCameraDeviceByCallback(FindV4L2CameraDeviceByPathCallback, (void *) path)); + } +} + +static void CameraUdevCallback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) +{ + if (devpath && (udev_class & SDL_UDEV_DEVICE_VIDEO_CAPTURE)) { + if (udev_type == SDL_UDEV_DEVICEADDED) { + MaybeAddDevice(devpath); + } else if (udev_type == SDL_UDEV_DEVICEREMOVED) { + MaybeRemoveDevice(devpath); + } + } +} +#endif // SDL_USE_LIBUDEV + +static void V4L2_Deinitialize(void) +{ +#ifdef SDL_USE_LIBUDEV + SDL_UDEV_DelCallback(CameraUdevCallback); + SDL_UDEV_Quit(); +#endif // SDL_USE_LIBUDEV +} + +static void V4L2_DetectDevices(void) +{ +#ifdef SDL_USE_LIBUDEV + if (SDL_UDEV_Init() == 0) { + if (SDL_UDEV_AddCallback(CameraUdevCallback) == 0) { + SDL_UDEV_Scan(); // Force a scan to build the initial device list + } + } +#else + DIR *dirp = opendir("/dev"); + if (dirp) { + struct dirent *dent; + while ((dent = readdir(dirp)) != NULL) { + int num = 0; + if (SDL_sscanf(dent->d_name, "video%d", &num) == 1) { + char fullpath[64]; + SDL_snprintf(fullpath, sizeof (fullpath), "/dev/video%d", num); + MaybeAddDevice(fullpath); + } + } + closedir(dirp); + } +#endif // SDL_USE_LIBUDEV +} + +static SDL_bool V4L2_Init(SDL_CameraDriverImpl *impl) +{ + impl->DetectDevices = V4L2_DetectDevices; + impl->OpenDevice = V4L2_OpenDevice; + impl->CloseDevice = V4L2_CloseDevice; + impl->WaitDevice = V4L2_WaitDevice; + impl->AcquireFrame = V4L2_AcquireFrame; + impl->ReleaseFrame = V4L2_ReleaseFrame; + impl->FreeDeviceHandle = V4L2_FreeDeviceHandle; + impl->Deinitialize = V4L2_Deinitialize; + + return SDL_TRUE; +} + +CameraBootStrap V4L2_bootstrap = { + "v4l2", "SDL Video4Linux2 camera driver", V4L2_Init, SDL_FALSE +}; + +#endif // SDL_CAMERA_DRIVER_V4L2 + diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c index b9e33974..2196aa40 100644 --- a/src/core/SDL_core_unsupported.c +++ b/src/core/SDL_core_unsupported.c @@ -28,7 +28,7 @@ DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userd #endif -#ifndef __LINUX__ +#ifndef SDL_PLATFORM_LINUX DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority); int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority) @@ -49,7 +49,7 @@ int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int sc #endif -#ifndef __GDK__ +#ifndef SDL_PLATFORM_GDK DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); void SDL_GDKSuspendComplete(void) @@ -65,7 +65,7 @@ int SDL_GDKGetDefaultUser(void *outUserHandle) #endif -#if !(defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)) +#if !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK)) DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); int SDL_RegisterApp(const char *name, Uint32 style, void *hInst) @@ -92,7 +92,7 @@ void SDL_UnregisterApp(void) #endif -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT /* Returns SDL_WinRT_DeviceFamily enum */ DECLSPEC int SDLCALL SDL_WinRTGetDeviceFamily(void); @@ -119,7 +119,7 @@ const char *SDL_WinRTGetFSPathUTF8(int pathType) } #endif -#ifndef __ANDROID__ +#ifndef SDL_PLATFORM_ANDROID DECLSPEC void SDLCALL SDL_AndroidBackButton(void); void SDL_AndroidBackButton() @@ -161,12 +161,14 @@ void *SDL_AndroidGetJNIEnv() return NULL; } -DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission); -SDL_bool SDL_AndroidRequestPermission(const char *permission) +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) { (void)permission; - SDL_Unsupported(); - return SDL_FALSE; + (void)cb; + (void)userdata; + return SDL_Unsupported(); } DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); @@ -225,7 +227,7 @@ Sint32 JNI_OnLoad(void *vm, void *reserved) } #endif -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) char *SDL_GetUserFolder(SDL_Folder folder) { (void)folder; diff --git a/src/core/SDL_runapp.c b/src/core/SDL_runapp.c index 52c7ede1..753dafbc 100644 --- a/src/core/SDL_runapp.c +++ b/src/core/SDL_runapp.c @@ -22,7 +22,7 @@ /* Most platforms that use/need SDL_main have their own SDL_RunApp() implementation. * If not, you can special case it here by appending || defined(__YOUR_PLATFORM__) */ -#if ( !defined(SDL_MAIN_NEEDED) && !defined(SDL_MAIN_AVAILABLE) ) || defined(__ANDROID__) +#if ( !defined(SDL_MAIN_NEEDED) && !defined(SDL_MAIN_AVAILABLE) ) || defined(SDL_PLATFORM_ANDROID) DECLSPEC int SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index b4ee8b7a..01e03bde 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID #include "SDL_android.h" @@ -269,7 +269,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)( JNIEXPORT jint 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, - jboolean is_accelerometer, jint button_mask, jint naxes, jint axis_mask, jint nhats); + jint button_mask, jint naxes, jint axis_mask, jint nhats); JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)( JNIEnv *env, jclass jcls, @@ -289,7 +289,7 @@ static JNINativeMethod SDLControllerManager_tab[] = { { "onNativePadUp", "(II)I", 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;IIZIIII)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) }, + { "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) } @@ -381,9 +381,6 @@ static SDL_bool bHasNewData; static SDL_bool bHasEnvironmentVariables; -static SDL_AtomicInt bPermissionRequestPending; -static SDL_bool bPermissionRequestResult; - /* Android AssetManager */ static void Internal_Android_Create_AssetManager(void); static void Internal_Android_Destroy_AssetManager(void); @@ -823,7 +820,7 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls, 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://bitbucket.org/MartinFelis/love-android-sdl2/issue/23/release-build-crash-on-start + https://github.com/love2d/love-android/issues/24 */ argv[argc++] = SDL_strdup("app_process"); for (i = 0; i < len; ++i) { @@ -997,14 +994,6 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)( (*env)->ReleaseStringUTFChars(env, name, utfname); } -JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePermissionResult)( - JNIEnv *env, jclass cls, - jint requestCode, jboolean result) -{ - bPermissionRequestResult = result; - SDL_AtomicSet(&bPermissionRequestPending, SDL_FALSE); -} - JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, jstring name, jint device_id) @@ -1068,14 +1057,14 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)( JNIEXPORT jint 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, jboolean is_accelerometer, + jint vendor_id, jint product_id, jint button_mask, jint naxes, jint axis_mask, jint nhats) { int retval; 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, is_accelerometer, button_mask, naxes, axis_mask, nhats); + retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats); (*env)->ReleaseStringUTFChars(env, device_name, name); (*env)->ReleaseStringUTFChars(env, device_desc, desc); @@ -1967,11 +1956,12 @@ static void Internal_Android_Destroy_AssetManager() } } -int Android_JNI_FileOpen(SDL_RWops *ctx, - const char *fileName, const char *mode) +int Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode) { + SDL_assert(puserdata != NULL); + AAsset *asset = NULL; - ctx->hidden.androidio.asset = NULL; + *puserdata = NULL; if (!asset_manager) { Internal_Android_Create_AssetManager(); @@ -1986,14 +1976,13 @@ int Android_JNI_FileOpen(SDL_RWops *ctx, return SDL_SetError("Couldn't open asset '%s'", fileName); } - ctx->hidden.androidio.asset = (void *)asset; + *puserdata = (void *)asset; return 0; } -size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size) +size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status) { - AAsset *asset = (AAsset *)ctx->hidden.androidio.asset; - int bytes = AAsset_read(asset, buffer, size); + const int bytes = AAsset_read((AAsset *)userdata, buffer, size); if (bytes < 0) { SDL_SetError("AAsset_read() failed"); return 0; @@ -2001,31 +1990,24 @@ size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size) return (size_t)bytes; } -size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size) +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"); } -Sint64 Android_JNI_FileSize(SDL_RWops *ctx) +Sint64 Android_JNI_FileSize(void *userdata) { - off64_t result; - AAsset *asset = (AAsset *)ctx->hidden.androidio.asset; - result = AAsset_getLength64(asset); - return result; + return (Sint64) AAsset_getLength64((AAsset *)userdata); } -Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence) +Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, int whence) { - off64_t result; - AAsset *asset = (AAsset *)ctx->hidden.androidio.asset; - result = AAsset_seek64(asset, offset, whence); - return result; + return (Sint64) AAsset_seek64((AAsset *)userdata, offset, whence); } -int Android_JNI_FileClose(SDL_RWops *ctx) +int Android_JNI_FileClose(void *userdata) { - AAsset *asset = (AAsset *)ctx->hidden.androidio.asset; - AAsset_close(asset); + AAsset_close((AAsset *)userdata); return 0; } @@ -2264,7 +2246,7 @@ SDL_bool Android_JNI_IsScreenKeyboardShown(void) return is_shown; } -int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) { JNIEnv *env; jclass clazz; @@ -2304,7 +2286,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu temp = sdlButton->flags; (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp); - temp = sdlButton->buttonid; + temp = sdlButton->buttonID; (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp); text = (*env)->NewStringUTF(env, sdlButton->text); (*env)->SetObjectArrayElement(env, button_texts, i, text); @@ -2333,7 +2315,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu mid = (*env)->GetMethodID(env, clazz, "messageboxShowMessageBox", "(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I"); - *buttonid = (*env)->CallIntMethod(env, context, mid, + *buttonID = (*env)->CallIntMethod(env, context, mid, messageboxdata->flags, title, message, @@ -2568,11 +2550,6 @@ const char *SDL_AndroidGetExternalStoragePath(void) return s_AndroidExternalFilesPath; } -SDL_bool SDL_AndroidRequestPermission(const char *permission) -{ - return Android_JNI_RequestPermission(permission); -} - int SDL_AndroidShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset) { return Android_JNI_ShowToast(message, duration, gravity, xOffset, yOffset); @@ -2640,27 +2617,75 @@ SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled) return (*env)->CallStaticBooleanMethod(env, mActivityClass, midSetRelativeMouseEnabled, (enabled == 1)); } -SDL_bool Android_JNI_RequestPermission(const char *permission) +typedef struct NativePermissionRequestInfo { - JNIEnv *env = Android_JNI_GetEnv(); - jstring jpermission; - const int requestCode = 1; + int request_code; + char *permission; + SDL_AndroidRequestPermissionCallback callback; + void *userdata; + struct NativePermissionRequestInfo *next; +} NativePermissionRequestInfo; - /* Wait for any pending request on another thread */ - while (SDL_AtomicGet(&bPermissionRequestPending) == SDL_TRUE) { - SDL_Delay(10); +static NativePermissionRequestInfo pending_permissions; + +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePermissionResult)( + JNIEnv *env, jclass cls, + jint requestCode, jboolean result) +{ + SDL_LockMutex(Android_ActivityMutex); + NativePermissionRequestInfo *prev = &pending_permissions; + for (NativePermissionRequestInfo *info = prev->next; info != NULL; info = info->next) { + 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); + SDL_free(info->permission); + SDL_free(info); + return; + } + prev = info; } - SDL_AtomicSet(&bPermissionRequestPending, SDL_TRUE); - jpermission = (*env)->NewStringUTF(env, permission); - (*env)->CallStaticVoidMethod(env, mActivityClass, midRequestPermission, jpermission, requestCode); + 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) +{ + if (!permission) { + return SDL_InvalidParamError("permission"); + } else if (!cb) { + return SDL_InvalidParamError("cb"); + } + + NativePermissionRequestInfo *info = (NativePermissionRequestInfo *) SDL_calloc(1, sizeof (NativePermissionRequestInfo)); + if (!info) { + return -1; + } + + info->permission = SDL_strdup(permission); + if (!info->permission) { + SDL_free(info); + return -1; + } + + static SDL_AtomicInt next_request_code; + info->request_code = SDL_AtomicAdd(&next_request_code, 1); + + info->callback = cb; + info->userdata = userdata; + + SDL_LockMutex(Android_ActivityMutex); + info->next = pending_permissions.next; + pending_permissions.next = info; + SDL_UnlockMutex(Android_ActivityMutex); + + JNIEnv *env = Android_JNI_GetEnv(); + jstring jpermission = (*env)->NewStringUTF(env, permission); + (*env)->CallStaticVoidMethod(env, mActivityClass, midRequestPermission, jpermission, info->request_code); (*env)->DeleteLocalRef(env, jpermission); - /* Wait for the request to complete */ - while (SDL_AtomicGet(&bPermissionRequestPending) == SDL_TRUE) { - SDL_Delay(10); - } - return bPermissionRequestResult; + return 0; } /* Show toast notification */ @@ -2741,4 +2766,4 @@ int Android_JNI_OpenURL(const char *url) return ret; } -#endif /* __ANDROID__ */ +#endif /* SDL_PLATFORM_ANDROID */ diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index af8ed1d4..b323722e 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -66,12 +66,12 @@ extern void Android_JNI_CloseAudioDevice(const int iscapture); extern SDL_bool Android_IsDeXMode(void); extern SDL_bool Android_IsChromebook(void); -int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode); -Sint64 Android_JNI_FileSize(SDL_RWops *ctx); -Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence); -size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size); -size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size); -int Android_JNI_FileClose(SDL_RWops *ctx); +int 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); +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); /* Environment support */ void Android_JNI_GetManifestEnvironmentVariables(void); @@ -113,7 +113,7 @@ int Android_JNI_SendMessage(int command, int param); JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv *mEnv, jclass cls); /* MessageBox */ -int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); +int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID); /* Cursor support */ int Android_JNI_CreateCustomCursor(SDL_Surface *surface, int hot_x, int hot_y); @@ -125,9 +125,6 @@ SDL_bool Android_JNI_SetSystemCursor(int cursorID); SDL_bool Android_JNI_SupportsRelativeMouse(void); SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled); -/* Request permission */ -SDL_bool Android_JNI_RequestPermission(const char *permission); - /* Show toast notification */ int Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset); diff --git a/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/src/core/freebsd/SDL_evdev_kbd_freebsd.c index 2c1df4a8..22d02bf5 100644 --- a/src/core/freebsd/SDL_evdev_kbd_freebsd.c +++ b/src/core/freebsd/SDL_evdev_kbd_freebsd.c @@ -542,6 +542,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, if (down == 0) { chg_vc_kbd_led(kbd, ALKED); } + SDL_FALLTHROUGH; case LSH: /* left shift */ case RSH: /* right shift */ k_shift(kbd, 0, down == 0); @@ -551,6 +552,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, if (down == 0) { chg_vc_kbd_led(kbd, ALKED); } + SDL_FALLTHROUGH; case LCTR: /* left ctrl */ case RCTR: /* right ctrl */ k_shift(kbd, 1, down == 0); @@ -560,6 +562,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, if (down == 0) { chg_vc_kbd_led(kbd, ALKED); } + SDL_FALLTHROUGH; case LALT: /* left alt */ case RALT: /* right alt */ k_shift(kbd, 2, down == 0); diff --git a/src/core/gdk/SDL_gdk.cpp b/src/core/gdk/SDL_gdk.cpp index 2c4469b4..af018d36 100644 --- a/src/core/gdk/SDL_gdk.cpp +++ b/src/core/gdk/SDL_gdk.cpp @@ -190,7 +190,7 @@ SDL_RunApp(int, char**, SDL_main_func mainFunction, void *reserved) XGameRuntimeUninitialize(); } else { -#ifdef __WINGDK__ +#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"); diff --git a/src/core/haiku/SDL_BApp.h b/src/core/haiku/SDL_BApp.h index 39fec778..8af12eec 100644 --- a/src/core/haiku/SDL_BApp.h +++ b/src/core/haiku/SDL_BApp.h @@ -46,6 +46,7 @@ extern "C" { #include + /* Forward declarations */ class SDL_BLooper; class SDL_BWin; @@ -248,12 +249,12 @@ class SDL_BLooper : public BLooper SDL_GetWindowPosition(win, &winPosX, &winPosY); int dx = x - (winWidth / 2); int dy = y - (winHeight / 2); - SDL_SendMouseMotion(0, win, 0, SDL_GetMouse()->relative_mode, (float)dx, (float)dy); + SDL_SendMouseMotion(0, win, SDL_DEFAULT_MOUSE_ID, SDL_GetMouse()->relative_mode, (float)dx, (float)dy); set_mouse_position((winPosX + winWidth / 2), (winPosY + winHeight / 2)); if (!be_app->IsCursorHidden()) be_app->HideCursor(); } else { - SDL_SendMouseMotion(0, win, 0, 0, (float)x, (float)y); + SDL_SendMouseMotion(0, win, SDL_DEFAULT_MOUSE_ID, SDL_FALSE, (float)x, (float)y); if (SDL_CursorVisible() && be_app->IsCursorHidden()) be_app->ShowCursor(); } @@ -271,7 +272,7 @@ class SDL_BLooper : public BLooper return; } win = GetSDLWindow(winID); - SDL_SendMouseButton(0, win, 0, state, button); + SDL_SendMouseButton(0, win, SDL_DEFAULT_MOUSE_ID, state, button); } void _HandleMouseWheel(BMessage *msg) @@ -286,7 +287,7 @@ class SDL_BLooper : public BLooper return; } win = GetSDLWindow(winID); - SDL_SendMouseWheel(0, win, 0, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL); + SDL_SendMouseWheel(0, win, SDL_DEFAULT_MOUSE_ID, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL); } void _HandleKey(BMessage *msg) @@ -303,13 +304,13 @@ class SDL_BLooper : public BLooper return; } HAIKU_SetKeyState(scancode, state); - SDL_SendKeyboardKey(0, state, HAIKU_GetScancodeFromBeKey(scancode)); + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, state, HAIKU_GetScancodeFromBeKey(scancode)); - if (state == SDL_PRESSED && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (state == SDL_PRESSED && SDL_TextInputActive()) { const int8 *keyUtf8; ssize_t count; if (msg->FindData("key-utf8", B_INT8_TYPE, (const void **)&keyUtf8, &count) == B_OK) { - char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; + char text[64]; SDL_zeroa(text); SDL_memcpy(text, keyUtf8, count); SDL_SendKeyboardText(text); diff --git a/src/core/haiku/SDL_BeApp.cc b/src/core/haiku/SDL_BeApp.cc index ccb9a4db..68a79f4e 100644 --- a/src/core/haiku/SDL_BeApp.cc +++ b/src/core/haiku/SDL_BeApp.cc @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#ifdef __HAIKU__ +#ifdef SDL_PLATFORM_HAIKU /* Handle the BeApp specific portions of the application */ @@ -192,4 +192,4 @@ void SDL_BLooper::ClearID(SDL_BWin *bwin) { } } -#endif /* __HAIKU__ */ +#endif /* SDL_PLATFORM_HAIKU */ diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index f7f5b6d6..9e6a56b6 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -53,6 +53,7 @@ static int LoadDBUSSyms(void) SDL_DBUS_SYM(void (*)(DBusConnection *, dbus_bool_t), connection_set_exit_on_disconnect); SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *), connection_get_is_connected); SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, DBusHandleMessageFunction, void *, DBusFreeFunction), connection_add_filter); + SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, DBusHandleMessageFunction, void *), connection_remove_filter); SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, const char *, const DBusObjectPathVTable *, void *, DBusError *), connection_try_register_object_path); SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, DBusMessage *, dbus_uint32_t *), connection_send); SDL_DBUS_SYM(DBusMessage *(*)(DBusConnection *, DBusMessage *, int, DBusError *), connection_send_with_reply_and_block); @@ -63,6 +64,7 @@ static int LoadDBUSSyms(void) SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, int), connection_read_write); SDL_DBUS_SYM(DBusDispatchStatus (*)(DBusConnection *), connection_dispatch); SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, const char *, const char *), message_is_signal); + SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, const char *), message_has_path); SDL_DBUS_SYM(DBusMessage *(*)(const char *, const char *, const char *, const char *), message_new_method_call); SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, int, ...), message_append_args); SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, int, va_list), message_append_args_valist); @@ -168,9 +170,9 @@ static void SDL_DBus_Init_Spinlocked(void) void SDL_DBus_Init(void) { - SDL_AtomicLock(&spinlock_dbus_init); /* make sure two threads can't init at same time, since this can happen before SDL_Init. */ + 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_AtomicUnlock(&spinlock_dbus_init); + SDL_UnlockSpinlock(&spinlock_dbus_init); } void SDL_DBus_Quit(void) diff --git a/src/core/linux/SDL_dbus.h b/src/core/linux/SDL_dbus.h index c37de56a..0be866b3 100644 --- a/src/core/linux/SDL_dbus.h +++ b/src/core/linux/SDL_dbus.h @@ -31,6 +31,9 @@ #ifndef DBUS_TIMEOUT_USE_DEFAULT #define DBUS_TIMEOUT_USE_DEFAULT -1 #endif +#ifndef DBUS_TIMEOUT_INFINITE +#define DBUS_TIMEOUT_INFINITE ((int) 0x7fffffff) +#endif typedef struct SDL_DBusContext { @@ -44,6 +47,7 @@ typedef struct SDL_DBusContext void (*connection_set_exit_on_disconnect)(DBusConnection *, dbus_bool_t); dbus_bool_t (*connection_get_is_connected)(DBusConnection *); dbus_bool_t (*connection_add_filter)(DBusConnection *, DBusHandleMessageFunction, void *, DBusFreeFunction); + dbus_bool_t (*connection_remove_filter)(DBusConnection *, DBusHandleMessageFunction, void *); dbus_bool_t (*connection_try_register_object_path)(DBusConnection *, const char *, const DBusObjectPathVTable *, void *, DBusError *); dbus_bool_t (*connection_send)(DBusConnection *, DBusMessage *, dbus_uint32_t *); @@ -55,6 +59,7 @@ typedef struct SDL_DBusContext dbus_bool_t (*connection_read_write)(DBusConnection *, int); DBusDispatchStatus (*connection_dispatch)(DBusConnection *); dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *); + dbus_bool_t (*message_has_path)(DBusMessage *, const char *); DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *); dbus_bool_t (*message_append_args)(DBusMessage *, int, ...); dbus_bool_t (*message_append_args_valist)(DBusMessage *, int, va_list); diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index f7e26b12..0f464e30 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -375,9 +375,9 @@ void SDL_EVDEV_Poll(void) 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_RELEASED, scan_code); + 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_PRESSED, scan_code); + SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, SDL_PRESSED, scan_code); } } SDL_EVDEV_kbd_keycode(_this->kbd, event->code, event->value); @@ -395,7 +395,7 @@ void SDL_EVDEV_Poll(void) break; } if (event->value >= 0) { - item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = event->value; + item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = event->value + 1; item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN; } else { item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP; @@ -551,7 +551,7 @@ void SDL_EVDEV_Poll(void) 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); - item->touchscreen_data->slots[j].tracking_id = -1; + item->touchscreen_data->slots[j].tracking_id = 0; item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE; break; case EVDEV_TOUCH_SLOTDELTA_MOVE: @@ -605,11 +605,34 @@ static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode) return scancode; } +static int 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); + + return 0; +} + +static void SDL_EVDEV_destroy_keyboard(SDL_evdevlist_item *item) +{ + SDL_RemoveKeyboard((SDL_KeyboardID)item->fd); +} + static int SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class) { + char name[128]; int ret; struct input_absinfo abs_info; + name[0] = '\0'; + ioctl(item->fd, EVIOCGNAME(sizeof(name)), name); + + SDL_AddMouse((SDL_MouseID)item->fd, name, SDL_TRUE); + ret = ioctl(item->fd, EVIOCGABS(ABS_X), &abs_info); if (ret < 0) { // no absolute mode info, continue @@ -631,9 +654,14 @@ static int SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class) return 0; } +static void SDL_EVDEV_destroy_mouse(SDL_evdevlist_item *item) +{ + SDL_RemoveMouse((SDL_MouseID)item->fd); +} + static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) { - int ret, i; + int ret; unsigned long xreq, yreq; char name[64]; struct input_absinfo abs_info; @@ -715,10 +743,6 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) return -1; } - for (i = 0; i < item->touchscreen_data->max_slots; i++) { - item->touchscreen_data->slots[i].tracking_id = -1; - } - 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); @@ -792,13 +816,13 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) * SDL_EVDEV_Poll to tell SDL, the current structure of this code doesn't * allow it. Lets just pray to God it doesn't happen. */ - if (item->touchscreen_data->slots[i].tracking_id < 0 && + if (item->touchscreen_data->slots[i].tracking_id == 0 && mt_req_values[i] >= 0) { - item->touchscreen_data->slots[i].tracking_id = mt_req_values[i]; + item->touchscreen_data->slots[i].tracking_id = mt_req_values[i] + 1; item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN; - } else if (item->touchscreen_data->slots[i].tracking_id >= 0 && + } else if (item->touchscreen_data->slots[i].tracking_id != 0 && mt_req_values[i] < 0) { - item->touchscreen_data->slots[i].tracking_id = -1; + item->touchscreen_data->slots[i].tracking_id = 0; item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP; } } @@ -810,7 +834,7 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) return; } for (i = 0; i < item->touchscreen_data->max_slots; i++) { - if (item->touchscreen_data->slots[i].tracking_id >= 0 && + if (item->touchscreen_data->slots[i].tracking_id != 0 && item->touchscreen_data->slots[i].x != mt_req_values[i]) { item->touchscreen_data->slots[i].x = mt_req_values[i]; if (item->touchscreen_data->slots[i].delta == @@ -828,7 +852,7 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) return; } for (i = 0; i < item->touchscreen_data->max_slots; i++) { - if (item->touchscreen_data->slots[i].tracking_id >= 0 && + if (item->touchscreen_data->slots[i].tracking_id != 0 && item->touchscreen_data->slots[i].y != mt_req_values[i]) { item->touchscreen_data->slots[i].y = mt_req_values[i]; if (item->touchscreen_data->slots[i].delta == @@ -846,7 +870,7 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) return; } for (i = 0; i < item->touchscreen_data->max_slots; i++) { - if (item->touchscreen_data->slots[i].tracking_id >= 0 && + if (item->touchscreen_data->slots[i].tracking_id != 0 && item->touchscreen_data->slots[i].pressure != mt_req_values[i]) { item->touchscreen_data->slots[i].pressure = mt_req_values[i]; if (item->touchscreen_data->slots[i].delta == @@ -926,6 +950,14 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) SDL_free(item); return ret; } + } else if (udev_class & SDL_UDEV_DEVICE_KEYBOARD) { + int ret = SDL_EVDEV_init_keyboard(item, udev_class); + if (ret < 0) { + close(item->fd); + SDL_free(item->path); + SDL_free(item); + return ret; + } } if (!_this->last) { @@ -961,6 +993,10 @@ static int SDL_EVDEV_device_removed(const char *dev_path) } if (item->is_touchscreen) { SDL_EVDEV_destroy_touchscreen(item); + } else if (item->udev_class & SDL_UDEV_DEVICE_MOUSE) { + SDL_EVDEV_destroy_mouse(item); + } else if (item->udev_class & SDL_UDEV_DEVICE_KEYBOARD) { + SDL_EVDEV_destroy_keyboard(item); } close(item->fd); SDL_free(item->path); diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index 7c81b544..bf483298 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -416,7 +416,7 @@ static void kbd_vt_update(SDL_EVDEV_keyboard_state *state) } ioctl(state->console_fd, VT_RELDISP, VT_ACKACQ); } - SDL_AtomicCAS(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE); + SDL_AtomicCompareAndSwap(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE); } } diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index a3de3c68..808054a0 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -54,15 +54,15 @@ static FcitxClient fcitx_client; static char *GetAppName(void) { -#if defined(__LINUX__) || defined(__FREEBSD__) +#if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_FREEBSD) char *spot; char procfile[1024]; char linkfile[1024]; int linksize; -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX (void)SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/exe", getpid()); -#elif defined(__FREEBSD__) +#elif defined(SDL_PLATFORM_FREEBSD) (void)SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/file", getpid()); #endif linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1); @@ -75,7 +75,7 @@ static char *GetAppName(void) return SDL_strdup(linkfile); } } -#endif /* __LINUX__ || __FREEBSD__ */ +#endif /* SDL_PLATFORM_LINUX || SDL_PLATFORM_FREEBSD */ return SDL_strdup("SDL_App"); } @@ -191,17 +191,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m dbus->message_iter_init(msg, &iter); dbus->message_iter_get_basic(&iter, &text); - if (text && *text) { - char buf[SDL_TEXTINPUTEVENT_TEXT_SIZE]; - size_t text_bytes = SDL_strlen(text), i = 0; - - while (i < text_bytes) { - size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - SDL_SendKeyboardText(buf); - - i += sz; - } - } + SDL_SendKeyboardText(text); return DBUS_HANDLER_RESULT_HANDLED; } @@ -428,9 +418,9 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) #ifdef SDL_VIDEO_DRIVER_X11 { SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, NULL); - int x_screen = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER, 0); - Window x_win = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, 0); + Display *x_disp = (Display *)SDL_GetProperty(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; if (x_disp && x_win) { X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused); diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index a919735e..9e514c30 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -228,17 +228,7 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * dbus->message_iter_init(msg, &iter); text = IBus_GetVariantText(conn, &iter, dbus); - if (text && *text) { - char buf[SDL_TEXTINPUTEVENT_TEXT_SIZE]; - size_t text_bytes = SDL_strlen(text), i = 0; - - while (i < text_bytes) { - size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf)); - SDL_SendKeyboardText(buf); - - i += sz; - } - } + SDL_SendKeyboardText(text); return DBUS_HANDLER_RESULT_HANDLED; } @@ -705,9 +695,9 @@ void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) #ifdef SDL_VIDEO_DRIVER_X11 { SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROPERTY_WINDOW_X11_DISPLAY_POINTER, NULL); - int x_screen = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_SCREEN_NUMBER, 0); - Window x_win = SDL_GetNumberProperty(props, SDL_PROPERTY_WINDOW_X11_WINDOW_NUMBER, 0); + Display *x_disp = (Display *)SDL_GetProperty(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; if (x_disp && x_win) { diff --git a/src/core/linux/SDL_system_theme.c b/src/core/linux/SDL_system_theme.c index 20b24122..1623775a 100644 --- a/src/core/linux/SDL_system_theme.c +++ b/src/core/linux/SDL_system_theme.c @@ -22,7 +22,7 @@ #include "SDL_dbus.h" #include "SDL_system_theme.h" -#include "../SDL_sysvideo.h" +#include "../../video/SDL_sysvideo.h" #include diff --git a/src/core/linux/SDL_threadprio.c b/src/core/linux/SDL_threadprio.c index cc8d6e47..10689494 100644 --- a/src/core/linux/SDL_threadprio.c +++ b/src/core/linux/SDL_threadprio.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX #ifndef SDL_THREADS_DISABLED #include @@ -342,4 +342,4 @@ int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int sc #endif } -#endif /* __LINUX__ */ +#endif /* SDL_PLATFORM_LINUX */ diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index aa12289e..fb992138 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -31,6 +31,7 @@ #ifdef SDL_USE_LIBUDEV #include +#include #include "SDL_evdev_capabilities.h" #include "../unix/SDL_poll.h" @@ -223,61 +224,59 @@ int SDL_UDEV_Scan(void) SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class) { - struct udev_enumerate *enumerate = NULL; - struct udev_list_entry *devs = NULL; - struct udev_list_entry *item = NULL; - SDL_bool found = SDL_FALSE; + struct stat statbuf; + char type; + struct udev_device *dev; + const char* val; + int class_temp; if (!_this) { return SDL_FALSE; } - enumerate = _this->syms.udev_enumerate_new(_this->udev); - if (!enumerate) { - SDL_SetError("udev_enumerate_new() failed"); + if (stat(device_path, &statbuf) == -1) { return SDL_FALSE; } - _this->syms.udev_enumerate_scan_devices(enumerate); - devs = _this->syms.udev_enumerate_get_list_entry(enumerate); - for (item = devs; item && !found; item = _this->syms.udev_list_entry_get_next(item)) { - const char *path = _this->syms.udev_list_entry_get_name(item); - struct udev_device *dev = _this->syms.udev_device_new_from_syspath(_this->udev, path); - if (dev) { - const char *val = NULL; - const char *existing_path; - - existing_path = _this->syms.udev_device_get_devnode(dev); - if (existing_path && SDL_strcmp(device_path, existing_path) == 0) { - int class_temp; - found = SDL_TRUE; - - val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID"); - if (val) { - *vendor = (Uint16)SDL_strtol(val, NULL, 16); - } - - val = _this->syms.udev_device_get_property_value(dev, "ID_MODEL_ID"); - if (val) { - *product = (Uint16)SDL_strtol(val, NULL, 16); - } - - val = _this->syms.udev_device_get_property_value(dev, "ID_REVISION"); - if (val) { - *version = (Uint16)SDL_strtol(val, NULL, 16); - } - - class_temp = device_class(dev); - if (class_temp) { - *class = class_temp; - } - } - _this->syms.udev_device_unref(dev); - } + if (S_ISBLK(statbuf.st_mode)) { + type = 'b'; + } + else if (S_ISCHR(statbuf.st_mode)) { + type = 'c'; + } + else { + return SDL_FALSE; } - _this->syms.udev_enumerate_unref(enumerate); - return found; + dev = _this->syms.udev_device_new_from_devnum(_this->udev, type, statbuf.st_rdev); + + if (!dev) { + return SDL_FALSE; + } + + val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID"); + if (val) { + *vendor = (Uint16)SDL_strtol(val, NULL, 16); + } + + val = _this->syms.udev_device_get_property_value(dev, "ID_MODEL_ID"); + if (val) { + *product = (Uint16)SDL_strtol(val, NULL, 16); + } + + val = _this->syms.udev_device_get_property_value(dev, "ID_REVISION"); + if (val) { + *version = (Uint16)SDL_strtol(val, NULL, 16); + } + + class_temp = device_class(dev); + if (class_temp) { + *class = class_temp; + } + + _this->syms.udev_device_unref(dev); + + return SDL_TRUE; } void SDL_UDEV_UnloadLibrary(void) @@ -429,9 +428,8 @@ static int device_class(struct udev_device *dev) } val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER"); - if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE) && - val && SDL_strcmp(val, "1") == 0) { - devclass |= SDL_UDEV_DEVICE_JOYSTICK; + if (val && SDL_strcmp(val, "1") == 0) { + devclass |= SDL_UDEV_DEVICE_ACCELEROMETER; } val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE"); diff --git a/src/core/n3ds/SDL_n3ds.c b/src/core/n3ds/SDL_n3ds.c index 46610d19..ac404675 100644 --- a/src/core/n3ds/SDL_n3ds.c +++ b/src/core/n3ds/SDL_n3ds.c @@ -21,7 +21,7 @@ #include "SDL_internal.h" -#ifdef __3DS__ +#ifdef SDL_PLATFORM_3DS #include <3ds.h> diff --git a/src/core/ngage/SDL_ngage_runapp.cpp b/src/core/ngage/SDL_ngage_runapp.cpp index b2eca988..6b7f3f82 100644 --- a/src/core/ngage/SDL_ngage_runapp.cpp +++ b/src/core/ngage/SDL_ngage_runapp.cpp @@ -4,7 +4,7 @@ #include "SDL_internal.h" -#ifdef __NGAGE__ +#ifdef SDL_PLATFORM_NGAGE #include #include @@ -75,4 +75,4 @@ cleanup: return ret; } -#endif // __NGAGE__ +#endif // SDL_PLATFORM_NGAGE diff --git a/src/core/openbsd/SDL_wscons_kbd.c b/src/core/openbsd/SDL_wscons_kbd.c index 6832cc83..81f94448 100644 --- a/src/core/openbsd/SDL_wscons_kbd.c +++ b/src/core/openbsd/SDL_wscons_kbd.c @@ -33,8 +33,9 @@ #include #include "../../events/SDL_events_c.h" +#include "../../events/SDL_keyboard_c.h" -#ifdef __NetBSD__ +#ifdef SDL_PLATFORM_NETBSD #define KS_GROUP_Ascii KS_GROUP_Plain #define KS_Cmd_ScrollBack KS_Cmd_ScrollFastUp #define KS_Cmd_ScrollFwd KS_Cmd_ScrollFastDown @@ -224,7 +225,7 @@ static struct SDL_wscons_compose_tab_s { { KS_asciicircum, KS_u }, KS_ucircumflex }, { { KS_grave, KS_u }, KS_ugrave }, { { KS_acute, KS_y }, KS_yacute }, -#ifndef __NetBSD__ +#ifndef SDL_PLATFORM_NETBSD { { KS_dead_caron, KS_space }, KS_L2_caron }, { { KS_dead_caron, KS_S }, KS_L2_Scaron }, { { KS_dead_caron, KS_Z }, KS_L2_Zcaron }, @@ -319,7 +320,7 @@ static struct wscons_keycode_to_SDL { KS_f18, SDL_SCANCODE_F18 }, { KS_f19, SDL_SCANCODE_F19 }, { KS_f20, SDL_SCANCODE_F20 }, -#ifndef __NetBSD__ +#ifndef SDL_PLATFORM_NETBSD { KS_f21, SDL_SCANCODE_F21 }, { KS_f22, SDL_SCANCODE_F22 }, { KS_f23, SDL_SCANCODE_F23 }, @@ -388,6 +389,7 @@ static struct wscons_keycode_to_SDL typedef struct { int fd; + SDL_KeyboardID keyboardID; struct wskbd_map_data keymap; int ledstate; int origledstate; @@ -420,14 +422,19 @@ static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev) SDL_WSCONS_input_data *input = (SDL_WSCONS_input_data *)SDL_calloc(1, sizeof(SDL_WSCONS_input_data)); if (!input) { - return input; + return NULL; } + input->fd = open(dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); if (input->fd == -1) { SDL_free(input); input = NULL; return NULL; } + + input->keyboardID = SDL_GetNextObjectID(); + SDL_AddKeyboard(input->keyboardID, NULL, SDL_FALSE); + input->keymap.map = SDL_calloc(sizeof(struct wscons_keymap), KS_NUMKEYCODES); if (!input->keymap.map) { SDL_free(input); @@ -553,22 +560,22 @@ static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_ switch (keyDesc.command) { case KS_Cmd_ScrollBack: { - SDL_SendKeyboardKey(0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP); + SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP); return; } case KS_Cmd_ScrollFwd: { - SDL_SendKeyboardKey(0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN); + SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN); 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, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey); + SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey); return; } } - SDL_SendKeyboardKey(0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN); + SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN); } static void updateKeyboard(SDL_WSCONS_input_data *input) @@ -620,7 +627,7 @@ static void updateKeyboard(SDL_WSCONS_input_data *input) input->lockheldstate[2] = 1; break; } -#ifndef __NetBSD__ +#ifndef SDL_PLATFORM_NETBSD case KS_Mode_Lock: { if (input->lockheldstate[3] >= 1) { @@ -728,7 +735,7 @@ static void updateKeyboard(SDL_WSCONS_input_data *input) input->lockheldstate[2] = 0; } } break; -#ifndef __NetBSD__ +#ifndef SDL_PLATFORM_NETBSD case KS_Mode_Lock: { if (input->lockheldstate[3]) { @@ -802,13 +809,13 @@ 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, SDL_RELEASED, i); + SDL_SendKeyboardKey(0, input->keyboardID, SDL_RELEASED, i); } break; } if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7) - SDL_SendKeyboardKey(0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)events[i].value); + SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)events[i].value); else Translate_to_keycode(input, type, events[i].value); diff --git a/src/core/openbsd/SDL_wscons_mouse.c b/src/core/openbsd/SDL_wscons_mouse.c index 3d3de955..6b0c9626 100644 --- a/src/core/openbsd/SDL_wscons_mouse.c +++ b/src/core/openbsd/SDL_wscons_mouse.c @@ -32,6 +32,7 @@ typedef struct SDL_WSCONS_mouse_input_data { int fd; + SDL_MouseID mouseID; } SDL_WSCONS_mouse_input_data; SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse() @@ -39,32 +40,36 @@ SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse() #ifdef WSMOUSEIO_SETVERSION int version = WSMOUSE_EVENT_VERSION; #endif - SDL_WSCONS_mouse_input_data *mouseInputData = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data)); + SDL_WSCONS_mouse_input_data *input = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data)); - if (!mouseInputData) { + if (!input) { return NULL; } - mouseInputData->fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_CLOEXEC); - if (mouseInputData->fd == -1) { - SDL_free(mouseInputData); + input->fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_CLOEXEC); + if (input->fd == -1) { + SDL_free(input); return NULL; } + + input->mouseID = SDL_GetNextObjectID(); + SDL_AddMouse(input->mouseID, NULL, SDL_FALSE); + #ifdef WSMOUSEIO_SETMODE - ioctl(mouseInputData->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT); + ioctl(input->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT); #endif #ifdef WSMOUSEIO_SETVERSION - ioctl(mouseInputData->fd, WSMOUSEIO_SETVERSION, &version); + ioctl(input->fd, WSMOUSEIO_SETVERSION, &version); #endif - return mouseInputData; + return input; } -void updateMouse(SDL_WSCONS_mouse_input_data *inputData) +void updateMouse(SDL_WSCONS_mouse_input_data *input) { struct wscons_event events[64]; int n; SDL_Mouse *mouse = SDL_GetMouse(); - if ((n = read(inputData->fd, events, sizeof(events))) > 0) { + if ((n = read(input->fd, events, sizeof(events))) > 0) { int i; n /= sizeof(struct wscons_event); for (i = 0; i < n; i++) { @@ -74,13 +79,13 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData) { switch (events[i].value) { case 0: /* Left Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_LEFT); + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_LEFT); break; case 1: /* Middle Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_MIDDLE); + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_MIDDLE); break; case 2: /* Right Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_RIGHT); + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_RIGHT); break; } } break; @@ -88,34 +93,34 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData) { switch (events[i].value) { case 0: /* Left Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_LEFT); + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_LEFT); break; case 1: /* Middle Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_MIDDLE); + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_MIDDLE); break; case 2: /* Right Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_RIGHT); + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_RIGHT); break; } } break; case WSCONS_EVENT_MOUSE_DELTA_X: { - SDL_SendMouseMotion(0, mouse->focus, mouse->mouseID, 1, (float)events[i].value, 0.0f); + SDL_SendMouseMotion(0, mouse->focus, input->mouseID, 1, (float)events[i].value, 0.0f); break; } case WSCONS_EVENT_MOUSE_DELTA_Y: { - SDL_SendMouseMotion(0, mouse->focus, mouse->mouseID, 1, 0.0f, -(float)events[i].value); + SDL_SendMouseMotion(0, mouse->focus, input->mouseID, 1, 0.0f, -(float)events[i].value); break; } case WSCONS_EVENT_MOUSE_DELTA_W: { - SDL_SendMouseWheel(0, mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL); + SDL_SendMouseWheel(0, mouse->focus, input->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL); break; } case WSCONS_EVENT_MOUSE_DELTA_Z: { - SDL_SendMouseWheel(0, mouse->focus, mouse->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL); + SDL_SendMouseWheel(0, mouse->focus, input->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL); break; } } @@ -123,11 +128,11 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData) } } -void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *inputData) +void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *input) { - if (!inputData) { + if (!input) { return; } - close(inputData->fd); - SDL_free(inputData); + close(input->fd); + SDL_free(input); } diff --git a/src/core/ps2/SDL_ps2.c b/src/core/ps2/SDL_ps2.c index b0a6f549..6be9a2ad 100644 --- a/src/core/ps2/SDL_ps2.c +++ b/src/core/ps2/SDL_ps2.c @@ -21,7 +21,7 @@ #include "SDL_internal.h" -#ifdef __PS2__ +#ifdef SDL_PLATFORM_PS2 /* SDL_RunApp() code for PS2 based on SDL_ps2_main.c, fjtrujy@gmail.com */ @@ -82,4 +82,4 @@ SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved) return res; } -#endif /* __PS2__ */ +#endif /* SDL_PLATFORM_PS2 */ diff --git a/src/core/psp/SDL_psp.c b/src/core/psp/SDL_psp.c index 2b47c5b1..2350e88e 100644 --- a/src/core/psp/SDL_psp.c +++ b/src/core/psp/SDL_psp.c @@ -21,7 +21,7 @@ #include "SDL_internal.h" -#ifdef __PSP__ +#ifdef SDL_PLATFORM_PSP /* SDL_RunApp() for PSP based on SDL_psp_main.c, placed in the public domain by Sam Lantinga 3/13/14 */ @@ -79,4 +79,4 @@ SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved) return mainFunction(argc, argv); } -#endif /* __PSP__ */ +#endif /* SDL_PLATFORM_PSP */ diff --git a/src/core/unix/SDL_appid.c b/src/core/unix/SDL_appid.c index fd2f2dc3..67a44330 100644 --- a/src/core/unix/SDL_appid.c +++ b/src/core/unix/SDL_appid.c @@ -30,15 +30,15 @@ const char *SDL_GetExeName() /* TODO: Use a fallback if BSD has no mounted procfs (OpenBSD has no procfs at all) */ if (!proc_name) { -#if defined(__LINUX__) || defined(__FREEBSD__) || defined (__NETBSD__) +#if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_FREEBSD) || defined (SDL_PLATFORM_NETBSD) static char linkfile[1024]; int linksize; -#if defined(__LINUX__) +#if defined(SDL_PLATFORM_LINUX) const char *proc_path = "/proc/self/exe"; -#elif defined(__FREEBSD__) +#elif defined(SDL_PLATFORM_FREEBSD) const char *proc_path = "/proc/curproc/file"; -#elif defined(__NETBSD__) +#elif defined(SDL_PLATFORM_NETBSD) const char *proc_path = "/proc/curproc/exe"; #endif linksize = readlink(proc_path, linkfile, sizeof(linkfile) - 1); diff --git a/src/core/windows/SDL_hid.c b/src/core/windows/SDL_hid.c index 6cea5344..0e42bb66 100644 --- a/src/core/windows/SDL_hid.c +++ b/src/core/windows/SDL_hid.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT #include "SDL_hid.h" @@ -35,6 +35,7 @@ HidP_GetData_t SDL_HidP_GetData; static HMODULE s_pHIDDLL = 0; static int s_HIDDLLRefCount = 0; + int WIN_LoadHIDDLL(void) { if (s_pHIDDLL) { @@ -81,4 +82,175 @@ void WIN_UnloadHIDDLL(void) } } -#endif /* !__WINRT__ */ +#endif /* !SDL_PLATFORM_WINRT */ + +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) + +/* CM_Register_Notification definitions */ + +#define CR_SUCCESS 0 + +DECLARE_HANDLE(HCMNOTIFICATION); +typedef HCMNOTIFICATION *PHCMNOTIFICATION; + +typedef enum _CM_NOTIFY_FILTER_TYPE +{ + CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE = 0, + CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE, + CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE, + CM_NOTIFY_FILTER_TYPE_MAX +} CM_NOTIFY_FILTER_TYPE, *PCM_NOTIFY_FILTER_TYPE; + +typedef struct _CM_NOTIFY_FILTER +{ + DWORD cbSize; + DWORD Flags; + CM_NOTIFY_FILTER_TYPE FilterType; + DWORD Reserved; + union + { + struct + { + GUID ClassGuid; + } DeviceInterface; + struct + { + HANDLE hTarget; + } DeviceHandle; + struct + { + WCHAR InstanceId[200]; + } DeviceInstance; + } u; +} CM_NOTIFY_FILTER, *PCM_NOTIFY_FILTER; + +typedef enum _CM_NOTIFY_ACTION +{ + CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL = 0, + CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL, + CM_NOTIFY_ACTION_DEVICEQUERYREMOVE, + CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED, + CM_NOTIFY_ACTION_DEVICEREMOVEPENDING, + CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE, + CM_NOTIFY_ACTION_DEVICECUSTOMEVENT, + CM_NOTIFY_ACTION_DEVICEINSTANCEENUMERATED, + CM_NOTIFY_ACTION_DEVICEINSTANCESTARTED, + CM_NOTIFY_ACTION_DEVICEINSTANCEREMOVED, + CM_NOTIFY_ACTION_MAX +} CM_NOTIFY_ACTION, *PCM_NOTIFY_ACTION; + +typedef struct _CM_NOTIFY_EVENT_DATA +{ + CM_NOTIFY_FILTER_TYPE FilterType; + DWORD Reserved; + union + { + struct + { + GUID ClassGuid; + WCHAR SymbolicLink[ANYSIZE_ARRAY]; + } DeviceInterface; + struct + { + GUID EventGuid; + LONG NameOffset; + DWORD DataSize; + BYTE Data[ANYSIZE_ARRAY]; + } DeviceHandle; + struct + { + WCHAR InstanceId[ANYSIZE_ARRAY]; + } DeviceInstance; + } u; +} CM_NOTIFY_EVENT_DATA, *PCM_NOTIFY_EVENT_DATA; + +typedef DWORD (CALLBACK *PCM_NOTIFY_CALLBACK)(HCMNOTIFICATION hNotify, PVOID Context, CM_NOTIFY_ACTION Action, PCM_NOTIFY_EVENT_DATA EventData, DWORD EventDataSize); + +typedef DWORD (WINAPI *CM_Register_NotificationFunc)(PCM_NOTIFY_FILTER pFilter, PVOID pContext, PCM_NOTIFY_CALLBACK pCallback, PHCMNOTIFICATION pNotifyContext); +typedef DWORD (WINAPI *CM_Unregister_NotificationFunc)(HCMNOTIFICATION NotifyContext); + +static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; + +static int s_DeviceNotificationsRequested; +static HMODULE cfgmgr32_lib_handle; +static CM_Register_NotificationFunc CM_Register_Notification; +static CM_Unregister_NotificationFunc CM_Unregister_Notification; +static HCMNOTIFICATION s_DeviceNotificationFuncHandle; +static Uint64 s_LastDeviceNotification = 1; + +static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size) +{ + if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL || + action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) { + s_LastDeviceNotification = SDL_GetTicksNS(); + } + return ERROR_SUCCESS; +} + +void WIN_InitDeviceNotification(void) +{ + ++s_DeviceNotificationsRequested; + if (s_DeviceNotificationsRequested > 1) { + return; + } + + cfgmgr32_lib_handle = LoadLibraryA("cfgmgr32.dll"); + if (cfgmgr32_lib_handle) { + CM_Register_Notification = (CM_Register_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Register_Notification"); + CM_Unregister_Notification = (CM_Unregister_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Unregister_Notification"); + if (CM_Register_Notification && CM_Unregister_Notification) { + CM_NOTIFY_FILTER notify_filter; + + SDL_zero(notify_filter); + notify_filter.cbSize = sizeof(notify_filter); + notify_filter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; + notify_filter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_HID; + if (CM_Register_Notification(¬ify_filter, NULL, SDL_DeviceNotificationFunc, &s_DeviceNotificationFuncHandle) == CR_SUCCESS) { + return; + } + } + } + + // FIXME: Should we log errors? +} + +Uint64 WIN_GetLastDeviceNotification(void) +{ + return s_LastDeviceNotification; +} + +void WIN_QuitDeviceNotification(void) +{ + if (--s_DeviceNotificationsRequested > 0) { + return; + } + /* Make sure we have balanced calls to init/quit */ + SDL_assert(s_DeviceNotificationsRequested == 0); + + if (cfgmgr32_lib_handle) { + if (s_DeviceNotificationFuncHandle && CM_Unregister_Notification) { + CM_Unregister_Notification(s_DeviceNotificationFuncHandle); + s_DeviceNotificationFuncHandle = NULL; + } + + FreeLibrary(cfgmgr32_lib_handle); + cfgmgr32_lib_handle = NULL; + } +} + +#else + +void WIN_InitDeviceNotification(void) +{ +} + +Uint64 WIN_GetLastDeviceNotification( void ) +{ + return 0; +} + +void WIN_QuitDeviceNotification(void) +{ +} + +#endif // !SDL_PLATFORM_WINRT && !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES diff --git a/src/core/windows/SDL_hid.h b/src/core/windows/SDL_hid.h index 4dbdd757..3d782112 100644 --- a/src/core/windows/SDL_hid.h +++ b/src/core/windows/SDL_hid.h @@ -25,7 +25,7 @@ #include "SDL_windows.h" -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT typedef LONG NTSTATUS; typedef USHORT USAGE; @@ -193,12 +193,12 @@ typedef struct extern int WIN_LoadHIDDLL(void); extern void WIN_UnloadHIDDLL(void); -typedef BOOLEAN(WINAPI *HidD_GetString_t)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); -typedef NTSTATUS(WINAPI *HidP_GetCaps_t)(PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities); -typedef NTSTATUS(WINAPI *HidP_GetButtonCaps_t)(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData); -typedef NTSTATUS(WINAPI *HidP_GetValueCaps_t)(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData); -typedef ULONG(WINAPI *HidP_MaxDataListLength_t)(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData); -typedef NTSTATUS(WINAPI *HidP_GetData_t)(HIDP_REPORT_TYPE ReportType, PHIDP_DATA DataList, PULONG DataLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); +typedef BOOLEAN (WINAPI *HidD_GetString_t)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); +typedef NTSTATUS (WINAPI *HidP_GetCaps_t)(PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities); +typedef NTSTATUS (WINAPI *HidP_GetButtonCaps_t)(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData); +typedef NTSTATUS (WINAPI *HidP_GetValueCaps_t)(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData); +typedef ULONG (WINAPI *HidP_MaxDataListLength_t)(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData); +typedef NTSTATUS (WINAPI *HidP_GetData_t)(HIDP_REPORT_TYPE ReportType, PHIDP_DATA DataList, PULONG DataLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); extern HidD_GetString_t SDL_HidD_GetManufacturerString; extern HidD_GetString_t SDL_HidD_GetProductString; @@ -208,6 +208,11 @@ extern HidP_GetValueCaps_t SDL_HidP_GetValueCaps; extern HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength; extern HidP_GetData_t SDL_HidP_GetData; -#endif /* !__WINRT__ */ +#endif /* !SDL_PLATFORM_WINRT */ + + +void WIN_InitDeviceNotification(void); +Uint64 WIN_GetLastDeviceNotification(void); +void WIN_QuitDeviceNotification(void); #endif /* SDL_hid_h_ */ diff --git a/src/core/windows/SDL_immdevice.c b/src/core/windows/SDL_immdevice.c index 2e956b47..77911e64 100644 --- a/src/core/windows/SDL_immdevice.c +++ b/src/core/windows/SDL_immdevice.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if (defined(__WIN32__) || defined(__GDK__)) && defined(HAVE_MMDEVICEAPI_H) +#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && defined(HAVE_MMDEVICEAPI_H) #include "SDL_windows.h" #include "SDL_immdevice.h" @@ -147,7 +147,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char * if (!device) { // handle is freed by SDL_IMMDevice_FreeDeviceHandle! - SDL_IMMDevice_HandleData *handle = SDL_malloc(sizeof(SDL_IMMDevice_HandleData)); + SDL_IMMDevice_HandleData *handle = (SDL_IMMDevice_HandleData *)SDL_malloc(sizeof(SDL_IMMDevice_HandleData)); if (!handle) { return NULL; } @@ -429,4 +429,4 @@ void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_Audi IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)¬ification_client); } -#endif /* (defined(__WIN32__) || defined(__GDK__)) && defined(HAVE_MMDEVICEAPI_H) */ +#endif /* (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && defined(HAVE_MMDEVICEAPI_H) */ diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index 0e6b474e..bc06f4d5 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) #include "SDL_windows.h" @@ -49,6 +49,10 @@ typedef enum RO_INIT_TYPE #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 #endif +#ifndef WC_ERR_INVALID_CHARS +#define WC_ERR_INVALID_CHARS 0x00000080 +#endif + /* Sets an error message based on an HRESULT */ int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) { @@ -86,14 +90,14 @@ WIN_CoInitialize(void) If you need multi-threaded mode, call CoInitializeEx() before SDL_Init() */ -#ifdef __WINRT__ +#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(__XBOXONE__) || defined(__XBOXSERIES__) +#elif 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 @@ -114,13 +118,13 @@ WIN_CoInitialize(void) void WIN_CoUninitialize(void) { -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT CoUninitialize(); #endif } -#ifndef __WINRT__ -void *WIN_LoadComBaseFunction(const char *name) +#ifndef SDL_PLATFORM_WINRT +FARPROC WIN_LoadComBaseFunction(const char *name) { static SDL_bool s_bLoaded; static HMODULE s_hComBase; @@ -140,7 +144,7 @@ void *WIN_LoadComBaseFunction(const char *name) HRESULT WIN_RoInitialize(void) { -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT return S_OK; #else typedef HRESULT(WINAPI * RoInitialize_t)(RO_INIT_TYPE initType); @@ -167,7 +171,7 @@ WIN_RoInitialize(void) void WIN_RoUninitialize(void) { -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT typedef void(WINAPI * RoUninitialize_t)(void); RoUninitialize_t RoUninitializeFunc = (RoUninitialize_t)WIN_LoadComBaseFunction("RoUninitialize"); if (RoUninitializeFunc) { @@ -176,7 +180,7 @@ void WIN_RoUninitialize(void) #endif } -#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) { OSVERSIONINFOEXW osvi; @@ -197,33 +201,47 @@ 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) + #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; \ + if (!checked) { \ + retval = (test); \ + checked = SDL_TRUE; \ + } \ + return retval; +#endif + +// this is the oldest thing we run on (and we may lose support for this in SDL3 at any time!), +// so there's no "OrGreater" as that would always be TRUE. The other functions are here to +// ask "can we support a specific feature?" but this function is here to ask "do we need to do +// something different for an OS version we probably should abandon?" :) +BOOL WIN_IsWindowsXP(void) +{ + CHECKWINVER(FALSE, !WIN_IsWindowsVistaOrGreater() && IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0)); +} + BOOL WIN_IsWindowsVistaOrGreater(void) { -#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__) - return TRUE; -#else - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0); -#endif + CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0)); } BOOL WIN_IsWindows7OrGreater(void) { -#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__) - return TRUE; -#else - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0); -#endif + CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0)); } BOOL WIN_IsWindows8OrGreater(void) { -#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__) - return TRUE; -#else - return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0); -#endif + CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)); } +#undef CHECKWINVER + + /* WAVExxxCAPS gives you 31 bytes for the device name, and just truncates if it's longer. However, since WinXP, you can use the WAVExxxCAPS2 structure, which @@ -247,7 +265,7 @@ WASAPI doesn't need this. This is just for DirectSound/WinMM. */ char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid) { -#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__) +#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. */ #else static const GUID nullguid = { 0 }; @@ -300,7 +318,7 @@ char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid) retval = WIN_StringToUTF8(strw); SDL_free(strw); return retval ? retval : WIN_StringToUTF8(name); -#endif /* if __WINRT__ / else */ +#endif /* if SDL_PLATFORM_WINRT / else */ } BOOL WIN_IsEqualGUID(const GUID *a, const GUID *b) @@ -362,9 +380,19 @@ SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat) return 0; } + +int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar) +{ + if (WIN_IsWindowsXP()) { + dwFlags &= ~WC_ERR_INVALID_CHARS; // not supported before Vista. Without this flag, it will just replace bogus chars with U+FFFD. You're on your own, WinXP. + } + 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 __WIN32__ +#ifdef SDL_PLATFORM_WIN32 #include /* CommandLineToArgvW() */ @@ -433,51 +461,6 @@ DECLSPEC int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_fu return result; } -#endif /* __WIN32__ */ +#endif /* SDL_PLATFORM_WIN32 */ -#endif /* defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) */ - -/* - * Public APIs - */ -#ifndef SDL_VIDEO_DRIVER_WINDOWS - -#if defined(__WIN32__) || defined(__GDK__) -int SDL_RegisterApp(const char *name, Uint32 style, void *hInst) -{ - (void)name; - (void)style; - (void)hInst; - return 0; -} - -void SDL_UnregisterApp(void) -{ -} - -void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata) -{ -} -#endif /* __WIN32__ || __GDK__ */ - -#if defined(__WIN32__) || defined(__WINGDK__) -int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID) -{ - (void)displayID; - return 0; /* D3DADAPTER_DEFAULT */ -} - -SDL_bool SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex) -{ - (void)displayID; - if (adapterIndex) { - *adapterIndex = -1; - } - if (outputIndex) { - *outputIndex = -1; - } - return SDL_FALSE; -} -#endif /* __WIN32__ || __WINGDK__ */ - -#endif /* !SDL_VIDEO_DRIVER_WINDOWS */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) */ diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 61044956..e4a25f95 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -24,7 +24,7 @@ #ifndef _INCLUDED_WINDOWS_H #define _INCLUDED_WINDOWS_H -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif @@ -36,7 +36,7 @@ #endif #undef WINVER #undef _WIN32_WINNT -#ifdef SDL_VIDEO_RENDER_D3D12 +#if SDL_VIDEO_RENDER_D3D12 #define _WIN32_WINNT 0xA00 /* For D3D12, 0xA00 is required */ #elif defined(HAVE_SHELLSCALINGAPI_H) #define _WIN32_WINNT 0x603 /* For DPI support */ @@ -45,7 +45,7 @@ #endif #define WINVER _WIN32_WINNT -#elif defined(__WINGDK__) +#elif defined(SDL_PLATFORM_WINGDK) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif @@ -60,7 +60,7 @@ #define _WIN32_WINNT 0xA00 #define WINVER _WIN32_WINNT -#elif defined(__XBOXONE__) || defined(__XBOXSERIES__) +#elif defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif @@ -93,16 +93,6 @@ #include /* for REFIID with broken mingw.org headers */ #include -/* Older Visual C++ headers don't have the Win64-compatible typedefs... */ -#if defined(_MSC_VER) && (_MSC_VER <= 1200) -#ifndef DWORD_PTR -#define DWORD_PTR DWORD -#endif -#ifndef LONG_PTR -#define LONG_PTR LONG -#endif -#endif - /* 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) @@ -132,9 +122,9 @@ extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr); /* Sets an error message based on GetLastError(). Always return -1. */ extern int WIN_SetError(const char *prefix); -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT /* Load a function from combase.dll */ -void *WIN_LoadComBaseFunction(const char *name); +FARPROC WIN_LoadComBaseFunction(const char *name); #endif /* Wrap up the oddities of CoInitialize() into a common function. */ @@ -145,6 +135,9 @@ extern void WIN_CoUninitialize(void); 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"! */ +extern BOOL WIN_IsWindowsXP(void); + /* Returns SDL_TRUE if we're running on Windows Vista and newer */ extern BOOL WIN_IsWindowsVistaOrGreater(void); @@ -170,6 +163,9 @@ extern BOOL WIN_IsRectEmpty(const RECT *rect); extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat); +/* WideCharToMultiByte, but with some WinXP manangement. */ +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++ */ #ifdef __cplusplus } diff --git a/src/core/windows/SDL_xinput.c b/src/core/windows/SDL_xinput.c index 36c9d818..13c06bde 100644 --- a/src/core/windows/SDL_xinput.c +++ b/src/core/windows/SDL_xinput.c @@ -37,7 +37,7 @@ DWORD SDL_XInputVersion = 0; static HMODULE s_pXInputDLL = NULL; static int s_XInputDLLRefCount = 0; -#if defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) int WIN_LoadXInputDLL(void) { @@ -68,7 +68,7 @@ void WIN_UnloadXInputDLL(void) { } -#else /* !(defined(__WINRT__) || defined(__XBOXONE__) || defined(__XBOXSERIES__)) */ +#else /* !(defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) */ int WIN_LoadXInputDLL(void) { @@ -136,7 +136,7 @@ void WIN_UnloadXInputDLL(void) } } -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/core/windows/SDL_xinput.h b/src/core/windows/SDL_xinput.h index d9c840db..200c8b6f 100644 --- a/src/core/windows/SDL_xinput.h +++ b/src/core/windows/SDL_xinput.h @@ -26,7 +26,7 @@ #include "SDL_windows.h" #ifdef HAVE_XINPUT_H -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#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... */ #include @@ -212,7 +212,7 @@ typedef struct #endif /* HAVE_XINPUT_H */ /* This struct is not defined in XInput headers. */ -typedef struct _XINPUT_CAPABILITIES_EX +typedef struct { XINPUT_CAPABILITIES Capabilities; WORD VendorId; @@ -220,7 +220,7 @@ typedef struct _XINPUT_CAPABILITIES_EX WORD ProductVersion; WORD unk1; DWORD unk2; -} XINPUT_CAPABILITIES_EX, *PXINPUT_CAPABILITIES_EX; +} SDL_XINPUT_CAPABILITIES_EX; /* Forward decl's for XInput API's we load dynamically and use if available */ typedef DWORD(WINAPI *XInputGetState_t)( @@ -244,7 +244,7 @@ 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 */ - XINPUT_CAPABILITIES_EX *pCapabilitiesEx /* [out] Receives the capabilities */ + SDL_XINPUT_CAPABILITIES_EX *pCapabilitiesEx /* [out] Receives the capabilities */ ); typedef DWORD(WINAPI *XInputGetBatteryInformation_t)( diff --git a/src/core/windows/version.rc b/src/core/windows/version.rc index 84869e1c..d2201682 100644 --- a/src/core/windows/version.rc +++ b/src/core/windows/version.rc @@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,0,0,0 - PRODUCTVERSION 3,0,0,0 + FILEVERSION 3,1,0,0 + PRODUCTVERSION 3,1,0,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -23,12 +23,12 @@ BEGIN BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "SDL\0" - VALUE "FileVersion", "3, 0, 0, 0\0" + VALUE "FileVersion", "3, 1, 0, 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, 0, 0, 0\0" + VALUE "ProductVersion", "3, 1, 0, 0\0" END END BLOCK "VarFileInfo" diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index 404fa736..013d03e2 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -20,12 +20,6 @@ */ #include "SDL_internal.h" -/* Standard C++11 includes */ -#include -#include -#include -using namespace std; - /* Windows includes */ #include "ppltasks.h" using namespace concurrency; @@ -59,7 +53,7 @@ extern "C" { #include "SDL_winrtapp_common.h" #include "SDL_winrtapp_direct3d.h" -#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) +#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. */ @@ -544,7 +538,7 @@ void SDL_WinRTApp::OnWindowActivated(CoreWindow ^ sender, WindowActivatedEventAr */ #if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION >= NTDDI_WINBLUE Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize); - SDL_SendMouseMotion(0, window, 0, 0, cursorPos.X, cursorPos.Y); + 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) */ @@ -615,7 +609,7 @@ void SDL_WinRTApp::OnSuspending(Platform::Object ^ sender, SuspendingEventArgs ^ // 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 defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D11 if (WINRT_GlobalSDLWindow) { SDL_Renderer *renderer = SDL_GetRenderer(WINRT_GlobalSDLWindow); if (renderer && (SDL_strcmp(renderer->info.name, "direct3d11") == 0)) { @@ -730,8 +724,8 @@ void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, W template static void WINRT_OnBackButtonPressed(BackButtonEventArgs ^ args) { - SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_AC_BACK); - SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_AC_BACK); + 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; diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index 2f0dc1e5..2270956e 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -18,9 +18,10 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ + #include "SDL_internal.h" -#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) #include "../core/windows/SDL_windows.h" #endif @@ -33,13 +34,13 @@ #include #include #endif -#if defined(__MACOS__) && (defined(__ppc__) || defined(__ppc64__)) +#if defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__)) #include /* For AltiVec check */ -#elif defined(__OpenBSD__) && defined(__powerpc__) +#elif defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__) #include #include /* For AltiVec check */ #include -#elif defined(__FreeBSD__) && defined(__powerpc__) +#elif defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__) #include #include #elif defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) @@ -47,7 +48,7 @@ #include #endif -#if (defined(__LINUX__) || defined(__ANDROID__)) && defined(__arm__) +#if (defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)) && defined(__arm__) #include #include #include @@ -66,7 +67,7 @@ #endif #endif -#if defined(__ANDROID__) && defined(__arm__) && !defined(HAVE_GETAUXVAL) +#if defined(SDL_PLATFORM_ANDROID) && defined(__arm__) && !defined(HAVE_GETAUXVAL) #include #endif @@ -74,16 +75,16 @@ #include #endif -#ifdef __RISCOS__ +#ifdef SDL_PLATFORM_RISCOS #include #include #endif -#ifdef __PS2__ +#ifdef SDL_PLATFORM_PS2 #include #endif -#ifdef __HAIKU__ +#ifdef SDL_PLATFORM_HAIKU #include #endif @@ -106,7 +107,7 @@ #define CPU_CFG2_LSX (1 << 6) #define CPU_CFG2_LASX (1 << 7) -#if defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) && !defined(__MACOS__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) +#if defined(SDL_ALTIVEC_BLITTERS) && defined(HAVE_SETJMP) && !defined(SDL_PLATFORM_MACOS) && !defined(SDL_PLATFORM_OPENBSD) && !defined(SDL_PLATFORM_FREEBSD) /* This is the brute force way of detecting instruction sets... the idea is borrowed from the libmpeg2 library - thanks! */ @@ -122,7 +123,7 @@ static int CPU_haveCPUID(void) int has_CPUID = 0; /* *INDENT-OFF* */ /* clang-format off */ -#ifndef SDL_CPUINFO_DISABLED +#ifndef SDL_PLATFORM_EMSCRIPTEN #if (defined(__GNUC__) || defined(__llvm__)) && defined(__i386__) __asm__ ( " pushfl # Get original EFLAGS \n" @@ -209,7 +210,7 @@ done: "1: \n" ); #endif -#endif +#endif /* !SDL_PLATFORM_EMSCRIPTEN */ /* *INDENT-ON* */ /* clang-format on */ return has_CPUID; } @@ -318,8 +319,8 @@ static int CPU_haveAltiVec(void) { volatile int altivec = 0; #ifndef SDL_CPUINFO_DISABLED -#if (defined(__MACOS__) && (defined(__ppc__) || defined(__ppc64__))) || (defined(__OpenBSD__) && defined(__powerpc__)) -#ifdef __OpenBSD__ +#if (defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__))) || (defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__)) +#ifdef SDL_PLATFORM_OPENBSD int selectors[2] = { CTL_MACHDEP, CPU_ALTIVEC }; #else int selectors[2] = { CTL_HW, HW_VECTORUNIT }; @@ -330,7 +331,7 @@ static int CPU_haveAltiVec(void) if (0 == error) { altivec = (hasVectorUnit != 0); } -#elif defined(__FreeBSD__) && defined(__powerpc__) +#elif defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__) unsigned long cpufeatures = 0; elf_aux_info(AT_HWCAP, &cpufeatures, sizeof(cpufeatures)); altivec = cpufeatures & PPC_FEATURE_HAS_ALTIVEC; @@ -361,7 +362,7 @@ static int CPU_haveARMSIMD(void) return 0; } -#elif defined(__LINUX__) +#elif defined(SDL_PLATFORM_LINUX) static int CPU_haveARMSIMD(void) { int arm_simd = 0; @@ -384,7 +385,7 @@ static int CPU_haveARMSIMD(void) return arm_simd; } -#elif defined(__RISCOS__) +#elif defined(SDL_PLATFORM_RISCOS) static int CPU_haveARMSIMD(void) { _kernel_swi_regs regs; @@ -414,7 +415,7 @@ static int CPU_haveARMSIMD(void) } #endif -#if defined(__LINUX__) && defined(__arm__) && !defined(HAVE_GETAUXVAL) +#if defined(SDL_PLATFORM_LINUX) && defined(__arm__) && !defined(HAVE_GETAUXVAL) static int readProcAuxvForNeon(void) { int neon = 0; @@ -439,9 +440,7 @@ 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. :/ */ -#ifdef SDL_CPUINFO_DISABLED - return 0; /* disabled */ -#elif (defined(__WINDOWS__) || defined(__WINRT__) || defined(__GDK__)) && (defined(_M_ARM) || defined(_M_ARM64)) +#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 */ #ifndef PF_ARM_NEON_INSTRUCTIONS_AVAILABLE @@ -451,18 +450,18 @@ static int CPU_haveNEON(void) 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. */ -#elif defined(__VITA__) +#elif defined(SDL_PLATFORM_VITA) return 1; -#elif defined(__3DS__) +#elif defined(SDL_PLATFORM_3DS) return 0; -#elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7) +#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. */ -#elif defined(__APPLE__) +#elif defined(SDL_PLATFORM_APPLE) return 0; /* assume anything else from Apple doesn't have NEON. */ #elif !defined(__arm__) return 0; /* not an ARM CPU at all. */ -#elif defined(__OpenBSD__) +#elif defined(SDL_PLATFORM_OPENBSD) return 1; /* OpenBSD only supports ARMv7 CPUs that have NEON. */ #elif defined(HAVE_ELF_AUX_INFO) unsigned long hasneon = 0; @@ -470,11 +469,11 @@ static int CPU_haveNEON(void) return 0; } return (hasneon & HWCAP_NEON) == HWCAP_NEON; -#elif (defined(__LINUX__) || defined(__ANDROID__)) && defined(HAVE_GETAUXVAL) +#elif (defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_ANDROID)) && defined(HAVE_GETAUXVAL) return (getauxval(AT_HWCAP) & HWCAP_NEON) == HWCAP_NEON; -#elif defined(__LINUX__) +#elif defined(SDL_PLATFORM_LINUX) return readProcAuxvForNeon(); -#elif defined(__ANDROID__) +#elif defined(SDL_PLATFORM_ANDROID) /* Use NDK cpufeatures to read either /proc/self/auxv or /proc/cpuinfo */ { AndroidCpuFamily cpu_family = android_getCpuFamily(); @@ -486,7 +485,7 @@ static int CPU_haveNEON(void) } return 0; } -#elif defined(__RISCOS__) +#elif defined(SDL_PLATFORM_RISCOS) /* Use the VFPSupport_Features SWI to access the MVFR registers */ { _kernel_swi_regs regs; @@ -498,6 +497,8 @@ static int CPU_haveNEON(void) } return 0; } +#elif defined(SDL_PLATFORM_EMSCRIPTEN) + return 0; #else #warning SDL_HasNEON is not implemented for this ARM platform. Write me. return 0; @@ -618,7 +619,6 @@ static int SDL_CPUCount = 0; int SDL_GetCPUCount(void) { if (!SDL_CPUCount) { -#ifndef SDL_CPUINFO_DISABLED #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) if (SDL_CPUCount <= 0) { SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN); @@ -630,13 +630,12 @@ int SDL_GetCPUCount(void) sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0); } #endif -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) if (SDL_CPUCount <= 0) { SYSTEM_INFO info; GetSystemInfo(&info); SDL_CPUCount = info.dwNumberOfProcessors; } -#endif #endif /* There has to be at least 1, right? :) */ if (SDL_CPUCount <= 0) { @@ -857,12 +856,88 @@ int SDL_GetCPUCacheLineSize(void) } } -static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; +#define SDL_CPUFEATURES_RESET_VALUE 0xFFFFFFFF + +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) { + 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] == ','); +} + +static Uint32 SDLCALL SDL_CPUFeatureMaskFromHint(void) +{ + Uint32 result_mask = SDL_CPUFEATURES_RESET_VALUE; + + const char *hint = SDL_GetHint(SDL_HINT_CPU_FEATURE_MASK); + + if (hint) { + 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; + if (end) { + next = end + 1; + } else { + size_t len = SDL_strlen(spot); + end = spot + len; + next = end; + } + if (spot[0] == '+') { + add_spot_mask = SDL_TRUE; + spot += 1; + } else if (spot[0] == '-') { + add_spot_mask = SDL_FALSE; + spot += 1; + } + if (ref_string_equals("all", spot, end)) { + spot_mask = SDL_CPUFEATURES_RESET_VALUE; + } else if (ref_string_equals("altivec", spot, end)) { + spot_mask= CPU_HAS_ALTIVEC; + } else if (ref_string_equals("mmx", spot, end)) { + spot_mask = CPU_HAS_MMX; + } else if (ref_string_equals("sse", spot, end)) { + spot_mask = CPU_HAS_SSE; + } else if (ref_string_equals("sse2", spot, end)) { + spot_mask = CPU_HAS_SSE2; + } else if (ref_string_equals("sse3", spot, end)) { + spot_mask = CPU_HAS_SSE3; + } else if (ref_string_equals("sse41", spot, end)) { + spot_mask = CPU_HAS_SSE41; + } else if (ref_string_equals("sse42", spot, end)) { + spot_mask = CPU_HAS_SSE42; + } else if (ref_string_equals("avx", spot, end)) { + spot_mask = CPU_HAS_AVX; + } else if (ref_string_equals("avx2", spot, end)) { + spot_mask = CPU_HAS_AVX2; + } else if (ref_string_equals("avx512f", spot, end)) { + spot_mask = CPU_HAS_AVX512F; + } else if (ref_string_equals("arm-simd", spot, end)) { + spot_mask = CPU_HAS_ARM_SIMD; + } else if (ref_string_equals("neon", spot, end)) { + spot_mask = CPU_HAS_NEON; + } else if (ref_string_equals("lsx", spot, end)) { + spot_mask = CPU_HAS_LSX; + } else if (ref_string_equals("lasx", spot, end)) { + spot_mask = CPU_HAS_LASX; + } else { + /* Ignore unknown/incorrect cpu feature(s) */ + continue; + } + if (add_spot_mask) { + result_mask |= spot_mask; + } else { + result_mask &= ~spot_mask; + } + } + } + return result_mask; +} + static Uint32 SDL_GetCPUFeatures(void) { - if (SDL_CPUFeatures == 0xFFFFFFFF) { + if (SDL_CPUFeatures == SDL_CPUFEATURES_RESET_VALUE) { CPU_calcCPUIDFeatures(); SDL_CPUFeatures = 0; SDL_SIMDAlignment = sizeof(void *); /* a good safe base value */ @@ -922,10 +997,15 @@ static Uint32 SDL_GetCPUFeatures(void) SDL_CPUFeatures |= CPU_HAS_LASX; SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 32); } + SDL_CPUFeatures &= SDL_CPUFeatureMaskFromHint(); } return SDL_CPUFeatures; } +void SDL_QuitCPUInfo(void) { + SDL_CPUFeatures = SDL_CPUFEATURES_RESET_VALUE; +} + #define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & (f)) ? SDL_TRUE : SDL_FALSE) SDL_bool SDL_HasAltiVec(void) @@ -1003,7 +1083,6 @@ static int SDL_SystemRAM = 0; int SDL_GetSystemRAM(void) { if (!SDL_SystemRAM) { -#ifndef SDL_CPUINFO_DISABLED #if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) if (SDL_SystemRAM <= 0) { SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024 * 1024)); @@ -1032,7 +1111,7 @@ int SDL_GetSystemRAM(void) } } #endif -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) if (SDL_SystemRAM <= 0) { MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); @@ -1041,7 +1120,7 @@ int SDL_GetSystemRAM(void) } } #endif -#ifdef __RISCOS__ +#ifdef SDL_PLATFORM_RISCOS if (SDL_SystemRAM <= 0) { _kernel_swi_regs regs; regs.r[0] = 0x108; @@ -1050,20 +1129,20 @@ int SDL_GetSystemRAM(void) } } #endif -#ifdef __VITA__ +#ifdef SDL_PLATFORM_VITA if (SDL_SystemRAM <= 0) { /* Vita has 512MiB on SoC, that's split into 256MiB(+109MiB in extended memory mode) for app +26MiB of physically continuous memory, +112MiB of CDRAM(VRAM) + system reserved memory. */ SDL_SystemRAM = 536870912; } #endif -#ifdef __PS2__ +#ifdef SDL_PLATFORM_PS2 if (SDL_SystemRAM <= 0) { /* PlayStation 2 has 32MiB however there are some special models with 64 and 128 */ SDL_SystemRAM = GetMemorySize(); } #endif -#ifdef __HAIKU__ +#ifdef SDL_PLATFORM_HAIKU if (SDL_SystemRAM <= 0) { system_info info; if (get_system_info(&info) == B_OK) { @@ -1072,7 +1151,6 @@ int SDL_GetSystemRAM(void) SDL_SystemRAM = (int)SDL_round((info.max_pages + info.ignored_pages > 0 ? info.ignored_pages : 0) * B_PAGE_SIZE / 1048576.0); } } -#endif #endif } return SDL_SystemRAM; diff --git a/src/cpuinfo/SDL_cpuinfo_c.h b/src/cpuinfo/SDL_cpuinfo_c.h new file mode 100644 index 00000000..c64a091e --- /dev/null +++ b/src/cpuinfo/SDL_cpuinfo_c.h @@ -0,0 +1,27 @@ +/* + 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_cpuinfo_c_h_ +#define SDL_cpuinfo_c_h_ + +extern void SDL_QuitCPUInfo(void); + +#endif /* SDL_cpuinfo_c_h_ */ diff --git a/src/dialog/cocoa/SDL_cocoadialog.m b/src/dialog/cocoa/SDL_cocoadialog.m new file mode 100644 index 00000000..3d4a8a59 --- /dev/null +++ b/src/dialog/cocoa/SDL_cocoadialog.m @@ -0,0 +1,169 @@ +/* + 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: Macro? */ + +#import + +typedef enum +{ + FDT_SAVE, + FDT_OPEN, + 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) +{ + /* NSOpenPanel inherits from NSSavePanel */ + NSSavePanel *dialog; + NSOpenPanel *dialog_as_open; + + switch (type) { + case FDT_SAVE: + dialog = [NSSavePanel savePanel]; + break; + case FDT_OPEN: + dialog_as_open = [NSOpenPanel openPanel]; + [dialog_as_open setAllowsMultipleSelection:((allow_many == SDL_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 = dialog_as_open; + break; + }; + + int n = -1; + while (filters[++n].name && filters[n].pattern); + NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:n ]; + + int has_all_files = 0; + for (int i = 0; i < n; i++) { + char *pattern = SDL_strdup(filters[i].pattern); + char *pattern_ptr = pattern; + + if (!pattern_ptr) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + for (char *c = pattern; *c; c++) { + if (*c == ';') { + *c = '\0'; + [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; + 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; + } + } + [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; + + SDL_free(pattern); + } + + if (!has_all_files) { + if (@available(macOS 11.0, *)) { + [dialog setAllowedContentTypes:types]; + } else { + [dialog setAllowedFileTypes:types]; + } + } + + /* Keep behavior consistent with other platforms */ + [dialog setAllowsOtherFileTypes:YES]; + + if (default_location) { + [dialog setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:default_location]]]; + } + + NSWindow *w = NULL; + + if (window) { + w = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL); + } + + if (w) { + // [dialog beginWithCompletionHandler:^(NSInteger result) { + [dialog beginSheetModalForWindow:w completionHandler:^(NSInteger result) { + // NSModalResponseOK for >= 10.13 + if (result == NSFileHandlingPanelOKButton) { + if (dialog_as_open) { + NSArray* urls = [dialog_as_open URLs]; + const char *files[[urls count] + 1]; + for (int i = 0; i < [urls count]; i++) { + files[i] = [[[urls objectAtIndex:i] path] UTF8String]; + } + files[[urls count]] = NULL; + callback(userdata, files, -1); + } else { + const char *files[2] = { [[[dialog URL] path] UTF8String], NULL }; + callback(userdata, files, -1); + } + } else if (result == NSModalResponseCancel) { + const char *files[1] = { NULL }; + callback(userdata, files, -1); + } + }]; + } else { + // NSModalResponseOK for >= 10.10 + if ([dialog runModal] == NSOKButton) { + if (dialog_as_open) { + NSArray* urls = [dialog_as_open URLs]; + const char *files[[urls count] + 1]; + for (int i = 0; i < [urls count]; i++) { + files[i] = [[[urls objectAtIndex:i] path] UTF8String]; + } + files[[urls count]] = NULL; + callback(userdata, files, -1); + } else { + const char *files[2] = { [[[dialog URL] path] UTF8String], NULL }; + callback(userdata, files, -1); + } + } else { + const char *files[1] = { NULL }; + callback(userdata, files, -1); + } + } +} + +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +{ + show_file_dialog(FDT_OPEN, callback, userdata, window, filters, default_location, allow_many); +} + +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +{ + show_file_dialog(FDT_SAVE, callback, userdata, window, filters, default_location, 0); +} + +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +{ + show_file_dialog(FDT_OPENFOLDER, callback, userdata, window, NULL, default_location, allow_many); +} diff --git a/src/dialog/dummy/SDL_dummydialog.c b/src/dialog/dummy/SDL_dummydialog.c new file mode 100644 index 00000000..8740f2f2 --- /dev/null +++ b/src/dialog/dummy/SDL_dummydialog.c @@ -0,0 +1,41 @@ +/* + 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: Macro? */ + +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_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) +{ + 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) +{ + SDL_Unsupported(); + callback(userdata, NULL, -1); +} diff --git a/src/dialog/haiku/SDL_haikudialog.cc b/src/dialog/haiku/SDL_haikudialog.cc new file mode 100644 index 00000000..3e63fc80 --- /dev/null +++ b/src/dialog/haiku/SDL_haikudialog.cc @@ -0,0 +1,233 @@ +/* + 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/haiku/SDL_BeApp.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +bool StringEndsWith(const std::string& str, const std::string& end) +{ + return str.size() >= end.size() && !str.compare(str.size() - end.size(), end.size(), end); +} + +std::vector StringSplit(const std::string& str, const std::string& split) +{ + std::vector retval; + std::string s = str; + size_t pos = 0; + + while ((pos = s.find(split)) != std::string::npos) { + retval.push_back(s.substr(0, pos)); + s = s.substr(pos + split.size()); + } + + retval.push_back(s); + + return retval; +} + +class SDLBRefFilter : public BRefFilter +{ +public: + SDLBRefFilter(const SDL_DialogFileFilter *filters) : + BRefFilter(), + m_filters(filters) + { + } + + virtual bool Filter(const entry_ref *ref, BNode *node, struct stat_beos *stat, const char *mimeType) override + { + BEntry entry(ref); + BPath path; + entry.GetPath(&path); + std::string result = path.Path(); + + if (!m_filters) + return true; + + struct stat info; + node->GetStat(&info); + 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, ";")) { + if (StringEndsWith(result, std::string(".") + suffix)) { + return true; + } + } + filter++; + } + + return false; + } + +private: + const SDL_DialogFileFilter * const m_filters; +}; + +class CallbackLooper : public BLooper +{ +public: + CallbackLooper(SDL_DialogFileCallback callback, void *userdata) : + m_callback(callback), + m_userdata(userdata), + m_files(), + m_messenger(), + m_panel(), + m_filter() + { + } + + ~CallbackLooper() + { + delete m_messenger; + delete m_panel; + delete m_filter; + } + + void SetToBeFreed(BMessenger *messenger, BFilePanel *panel, SDLBRefFilter *filter) + { + m_messenger = messenger; + m_panel = panel; + m_filter = filter; + } + + virtual void MessageReceived(BMessage *msg) override + { + entry_ref file; + BPath path; + BEntry entry; + std::string result; + const char *filename; + int32 nFiles = 0; + + switch (msg->what) + { + case B_REFS_RECEIVED: // Open + msg->GetInfo("refs", NULL, &nFiles); + for (int i = 0; i < nFiles; i++) { + msg->FindRef("refs", i, &file); + entry.SetTo(&file); + entry.GetPath(&path); + result = path.Path(); + m_files.push_back(result); + } + break; + + case B_SAVE_REQUESTED: // Save + msg->FindRef("directory", &file); + entry.SetTo(&file); + entry.GetPath(&path); + result = path.Path(); + result += "/"; + msg->FindString("name", &filename); + result += filename; + m_files.push_back(result); + break; + + case B_CANCEL: // Whenever the dialog is closed (Cancel but also after Open and Save) + { + nFiles = m_files.size(); + const char* files[nFiles + 1]; + for (int i = 0; i < nFiles; i++) { + files[i] = m_files[i].c_str(); + } + files[nFiles] = NULL; + m_callback(m_userdata, files, -1); + Quit(); + SDL_QuitBeApp(); + delete this; + } + break; + + default: + BHandler::MessageReceived(msg); + break; + } + } + +private: + SDL_DialogFileCallback m_callback; + void *m_userdata; + std::vector m_files; + + // Only to free stuff later + BMessenger *m_messenger; + BFilePanel *m_panel; + 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) +{ + if (SDL_InitBeApp()) { + char* err = SDL_strdup(SDL_GetError()); + SDL_SetError("Couldn't init Be app: %s", err); + SDL_free(err); + 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); + + BEntry entry; + entry_ref entryref; + if (location) { + entry.SetTo(location); + entry.GetRef(&entryref); + } + + BFilePanel *panel = new BFilePanel(save ? B_SAVE_PANEL : B_OPEN_PANEL, messenger, location ? &entryref : NULL, folder ? B_DIRECTORY_NODE : B_FILE_NODE, many, NULL, filter, modal); + looper->SetToBeFreed(messenger, panel, filter); + looper->Run(); + 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) +{ + ShowDialog(false, callback, userdata, allow_many == SDL_TRUE, !!window, filters, false, default_location); +} + +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location) +{ + ShowDialog(true, callback, userdata, false, !!window, filters, false, default_location); +} + +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char* default_location, SDL_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); +} diff --git a/src/dialog/unix/SDL_portaldialog.c b/src/dialog/unix/SDL_portaldialog.c new file mode 100644 index 00000000..e56478bb --- /dev/null +++ b/src/dialog/unix/SDL_portaldialog.c @@ -0,0 +1,492 @@ +/* + 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.h" + +#include "../../core/linux/SDL_dbus.h" + +#ifdef SDL_USE_LIBDBUS + +#include +#include +#include +#include + +#define PORTAL_DESTINATION "org.freedesktop.portal.Desktop" +#define PORTAL_PATH "/org/freedesktop/portal/desktop" +#define PORTAL_INTERFACE "org.freedesktop.portal.FileChooser" + +#define SIGNAL_SENDER "org.freedesktop.portal.Desktop" +#define SIGNAL_INTERFACE "org.freedesktop.portal.Request" +#define SIGNAL_NAME "Response" +#define SIGNAL_FILTER "type='signal', sender='"SIGNAL_SENDER"', interface='"SIGNAL_INTERFACE"', member='"SIGNAL_NAME"', path='" + +#define HANDLE_LEN 10 + +#define WAYLAND_HANDLE_PREFIX "wayland:" +#define X11_HANDLE_PREFIX "x11:" + +typedef struct { + SDL_DialogFileCallback callback; + void *userdata; + const char *path; +} SignalCallback; + +static void DBus_AppendStringOption(SDL_DBusContext *dbus, DBusMessageIter *options, const char *key, const char *value) +{ + DBusMessageIter options_pair, options_value; + + dbus->message_iter_open_container(options, DBUS_TYPE_DICT_ENTRY, NULL, &options_pair); + dbus->message_iter_append_basic(&options_pair, DBUS_TYPE_STRING, &key); + dbus->message_iter_open_container(&options_pair, DBUS_TYPE_VARIANT, "s", &options_value); + dbus->message_iter_append_basic(&options_value, DBUS_TYPE_STRING, &value); + dbus->message_iter_close_container(&options_pair, &options_value); + dbus->message_iter_close_container(options, &options_pair); +} + +static void DBus_AppendBoolOption(SDL_DBusContext *dbus, DBusMessageIter *options, const char *key, int value) +{ + DBusMessageIter options_pair, options_value; + + dbus->message_iter_open_container(options, DBUS_TYPE_DICT_ENTRY, NULL, &options_pair); + dbus->message_iter_append_basic(&options_pair, DBUS_TYPE_STRING, &key); + dbus->message_iter_open_container(&options_pair, DBUS_TYPE_VARIANT, "b", &options_value); + dbus->message_iter_append_basic(&options_value, DBUS_TYPE_BOOLEAN, &value); + dbus->message_iter_close_container(&options_pair, &options_value); + dbus->message_iter_close_container(options, &options_pair); +} + +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_open_container(&filter_entry, DBUS_TYPE_ARRAY, "(us)", &filter_array); + + patterns = SDL_strdup(filter->pattern); + if (!patterns) { + SDL_OutOfMemory(); + goto cleanup; + } + + pattern = SDL_strtok_r(patterns, ";", &state); + while (pattern) { + size_t max_len = SDL_strlen(pattern) + 3; + + 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); + if (!glob_pattern) { + SDL_OutOfMemory(); + goto cleanup; + } + glob_pattern[0] = '*'; + /* Special case: The '*' filter doesn't need to be rewritten */ + if (pattern[0] != '*' || pattern[1]) { + glob_pattern[1] = '.'; + SDL_strlcat(glob_pattern + 2, pattern, max_len); + } + dbus->message_iter_append_basic(&filter_array_entry, DBUS_TYPE_STRING, &glob_pattern); + SDL_free(glob_pattern); + + dbus->message_iter_close_container(&filter_array, &filter_array_entry); + pattern = SDL_strtok_r(NULL, ";", &state); + } + +cleanup: + SDL_free(patterns); + + dbus->message_iter_close_container(&filter_entry, &filter_array); + dbus->message_iter_close_container(parent, &filter_entry); +} + +static void DBus_AppendFilters(SDL_DBusContext *dbus, DBusMessageIter *options, const SDL_DialogFileFilter *filters) +{ + DBusMessageIter options_pair, options_value, options_value_array; + static const char *filters_name = "filters"; + + dbus->message_iter_open_container(options, DBUS_TYPE_DICT_ENTRY, NULL, &options_pair); + 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); + } + dbus->message_iter_close_container(&options_value, &options_value_array); + dbus->message_iter_close_container(&options_pair, &options_value); + dbus->message_iter_close_container(options, &options_pair); +} + +static void DBus_AppendByteArray(SDL_DBusContext *dbus, DBusMessageIter *options, const char *key, const char *value) +{ + DBusMessageIter options_pair, options_value, options_array; + + dbus->message_iter_open_container(options, DBUS_TYPE_DICT_ENTRY, NULL, &options_pair); + dbus->message_iter_append_basic(&options_pair, DBUS_TYPE_STRING, &key); + dbus->message_iter_open_container(&options_pair, DBUS_TYPE_VARIANT, "ay", &options_value); + dbus->message_iter_open_container(&options_value, DBUS_TYPE_ARRAY, "y", &options_array); + do { + dbus->message_iter_append_basic(&options_array, DBUS_TYPE_BYTE, value); + } while (*value++); + dbus->message_iter_close_container(&options_value, &options_array); + dbus->message_iter_close_container(&options_pair, &options_value); + dbus->message_iter_close_container(options, &options_pair); +} + +static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data) { + SDL_DBusContext *dbus = SDL_DBus_GetContext(); + SignalCallback *signal_data = (SignalCallback *)data; + + if (dbus->message_is_signal(msg, SIGNAL_INTERFACE, SIGNAL_NAME) + && dbus->message_has_path(msg, signal_data->path)) { + DBusMessageIter signal_iter, result_array, array_entry, value_entry, uri_entry; + uint32_t result; + size_t length = 2, current = 0; + const char **path; + + dbus->message_iter_init(msg, &signal_iter); + /* 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 */ + const char *result_data[] = { NULL }; + 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 */ + signal_data->callback(signal_data->userdata, NULL, -1); + goto handled; + } + + if (!dbus->message_iter_next(&signal_iter)) + goto not_our_signal; + + if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_ARRAY) + goto not_our_signal; + dbus->message_iter_recurse(&signal_iter, &result_array); + + while (dbus->message_iter_get_arg_type(&result_array) == DBUS_TYPE_DICT_ENTRY) + { + const char *method; + + dbus->message_iter_recurse(&result_array, &array_entry); + if (dbus->message_iter_get_arg_type(&array_entry) != DBUS_TYPE_STRING) + goto not_our_signal; + + dbus->message_iter_get_basic(&array_entry, &method); + if (!SDL_strcmp(method, "uris")) { + /* we only care about the selected file paths */ + break; + } + + if (!dbus->message_iter_next(&result_array)) + goto not_our_signal; + } + + if (!dbus->message_iter_next(&array_entry)) + goto not_our_signal; + + if (dbus->message_iter_get_arg_type(&array_entry) != DBUS_TYPE_VARIANT) + goto not_our_signal; + dbus->message_iter_recurse(&array_entry, &value_entry); + + if (dbus->message_iter_get_arg_type(&value_entry) != DBUS_TYPE_ARRAY) + goto not_our_signal; + dbus->message_iter_recurse(&value_entry, &uri_entry); + + 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) + { + 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_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 */ +cleanup: + dbus->connection_remove_filter(conn, &DBus_MessageFilter, signal_data); + + SDL_free(path); + SDL_free((void *)signal_data->path); + SDL_free(signal_data); +handled: + return DBUS_HANDLER_RESULT_HANDLED; + } +not_our_signal: + 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) +{ + SDL_DBusContext *dbus = SDL_DBus_GetContext(); + DBusMessage *msg; + DBusMessageIter params, options; + const char *signal_id = NULL; + char *handle_str, *filter; + int filter_len; + static uint32_t handle_id = 0; + static char *default_parent_window = ""; + SDL_PropertiesID props = SDL_GetWindowProperties(window); + + if (dbus == NULL) { + SDL_SetError("Failed to connect to DBus"); + 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"); + return; + } + + dbus->message_iter_init_append(msg, ¶ms); + + handle_str = default_parent_window; + if (props) { + const char *parent_handle = SDL_GetStringProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_STRING, NULL); + if (parent_handle) { + size_t len = SDL_strlen(parent_handle); + len += sizeof(WAYLAND_HANDLE_PREFIX) + 1; + handle_str = SDL_malloc(len * sizeof(char)); + if (!handle_str) { + return; + } + + SDL_snprintf(handle_str, len, "%s%s", WAYLAND_HANDLE_PREFIX, parent_handle); + } 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. */ + handle_str = SDL_malloc(len * sizeof(char)); + if (!handle_str) { + return; + } + + /* The portal wants X11 window ID numbers in hex. */ + SDL_snprintf(handle_str, len, "%s%" SDL_PRIx64, X11_HANDLE_PREFIX, xid); + } + } + } + + dbus->message_iter_append_basic(¶ms, DBUS_TYPE_STRING, &handle_str); + if (handle_str != default_parent_window) { + SDL_free(handle_str); + } + + dbus->message_iter_append_basic(¶ms, DBUS_TYPE_STRING, &method_title); + dbus->message_iter_open_container(¶ms, DBUS_TYPE_ARRAY, "{sv}", &options); + + handle_str = SDL_malloc(sizeof(char) * (HANDLE_LEN + 1)); + if (!handle_str) { + return; + } + SDL_snprintf(handle_str, HANDLE_LEN, "%u", ++handle_id); + DBus_AppendStringOption(dbus, &options, "handle_token", handle_str); + SDL_free(handle_str); + + DBus_AppendBoolOption(dbus, &options, "modal", !!window); + if (allow_many == SDL_TRUE) { + DBus_AppendBoolOption(dbus, &options, "multiple", 1); + } + if (open_folders) { + DBus_AppendBoolOption(dbus, &options, "directory", 1); + } + if (filters) { + DBus_AppendFilters(dbus, &options, filters); + } + if (default_location) { + DBus_AppendByteArray(dbus, &options, "current_folder", default_location); + } + dbus->message_iter_close_container(¶ms, &options); + + DBusMessage *reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, DBUS_TIMEOUT_INFINITE, NULL); + if (reply) { + DBusMessageIter reply_iter; + dbus->message_iter_init(reply, &reply_iter); + + if (dbus->message_iter_get_arg_type(&reply_iter) == DBUS_TYPE_OBJECT_PATH) { + dbus->message_iter_get_basic(&reply_iter, &signal_id); + } + } + + if (!signal_id) { + SDL_SetError("Invalid response received by DBus"); + goto incorrect_type; + } + + dbus->message_unref(msg); + + filter_len = SDL_strlen(SIGNAL_FILTER) + SDL_strlen(signal_id) + 2; + filter = SDL_malloc(sizeof(char) * filter_len); + if (!filter) { + goto incorrect_type; + } + + SDL_snprintf(filter, filter_len, SIGNAL_FILTER"%s'", signal_id); + dbus->bus_add_match(dbus->session_conn, filter, NULL); + SDL_free(filter); + + SignalCallback *data = SDL_malloc(sizeof(SignalCallback)); + if (!data) { + goto incorrect_type; + } + data->callback = callback; + data->userdata = userdata; + data->path = SDL_strdup(signal_id); + if (!data->path) { + SDL_free(data); + goto incorrect_type; + } + + /* TODO: This should be registered before opening the portal, or the filter will not catch + the message if it is sent before we register the filter. + */ + dbus->connection_add_filter(dbus->session_conn, + &DBus_MessageFilter, data, NULL); + dbus->connection_flush(dbus->session_conn); + +incorrect_type: + 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) +{ + DBus_OpenDialog("OpenFile", "Open File", callback, userdata, window, filters, 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) +{ + DBus_OpenDialog("SaveFile", "Save File", callback, userdata, window, filters, default_location, 0, 0); +} + +void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +{ + DBus_OpenDialog("OpenFile", "Open Folder", callback, userdata, window, NULL, default_location, allow_many, 1); +} + +int SDL_Portal_detect(void) +{ + SDL_DBusContext *dbus = SDL_DBus_GetContext(); + DBusMessage *msg = NULL, *reply = NULL; + char *reply_str = NULL; + DBusMessageIter reply_iter; + static int portal_present = -1; + + /* No need for this if the result is cached. */ + if (portal_present != -1) { + return portal_present; + } + + portal_present = 0; + + if (!dbus) { + SDL_SetError("%s", "Failed to connect to DBus!"); + return 0; + } + + /* 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; + } + + reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, DBUS_TIMEOUT_INFINITE, NULL); + dbus->message_unref(msg); + if (!reply) { + goto done; + } + + if (!dbus->message_iter_init(reply, &reply_iter)) { + goto done; + } + + if (dbus->message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_STRING) { + goto done; + } + + /* Introspection gives us a dump of all the services on the destination in XML format, so search the + * giant string for the file chooser protocol. + */ + dbus->message_iter_get_basic(&reply_iter, &reply_str); + if (SDL_strstr(reply_str, PORTAL_INTERFACE)) { + portal_present = 1; /* Found it! */ + } + +done: + if (reply) { + dbus->message_unref(reply); + } + + return portal_present; +} + +#else + +/* 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) +{ + 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) +{ + 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) +{ + SDL_Unsupported(); + callback(userdata, NULL, -1); +} + +int SDL_Portal_detect(void) +{ + return 0; +} + +#endif /* SDL_USE_LIBDBUS */ diff --git a/src/dialog/unix/SDL_portaldialog.h b/src/dialog/unix/SDL_portaldialog.h new file mode 100644 index 00000000..71ed3cbe --- /dev/null +++ b/src/dialog/unix/SDL_portaldialog.h @@ -0,0 +1,29 @@ +/* + 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" + +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); + +/** @returns non-zero if available, zero if unavailable */ +int SDL_Portal_detect(void); diff --git a/src/dialog/unix/SDL_unixdialog.c b/src/dialog/unix/SDL_unixdialog.c new file mode 100644 index 00000000..29ce2eef --- /dev/null +++ b/src/dialog/unix/SDL_unixdialog.c @@ -0,0 +1,85 @@ +/* + 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_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; + +/* Returns non-zero on success, 0 on failure */ +static int detect_available_methods(void) +{ + 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; + } + + SDL_SetError("No supported method for file dialogs"); + 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) +{ + /* Call detect_available_methods() again each time in case the situation changed */ + if (!detected_open && !detect_available_methods()) { + /* SetError() done by detect_available_methods() */ + callback(userdata, NULL, -1); + return; + } + + detected_open(callback, userdata, window, filters, default_location, allow_many); +} + +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, 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() */ + callback(userdata, NULL, -1); + return; + } + + detected_save(callback, userdata, window, filters, default_location); +} + +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_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() */ + callback(userdata, NULL, -1); + return; + } + + detected_folder(callback, userdata, window, default_location, allow_many); +} diff --git a/src/dialog/unix/SDL_zenitydialog.c b/src/dialog/unix/SDL_zenitydialog.c new file mode 100644 index 00000000..5ba8e8dc --- /dev/null +++ b/src/dialog/unix/SDL_zenitydialog.c @@ -0,0 +1,488 @@ +/* + 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.h" + +#include +#include +#include +#include + +typedef enum +{ + ZENITY_MULTIPLE = 0x1, + ZENITY_DIRECTORY = 0x2, + ZENITY_SAVE = 0x4 +} zenityFlags; + +typedef struct +{ + SDL_DialogFileCallback callback; + void* userdata; + const char* filename; + const SDL_DialogFileFilter *filters; + Uint32 flags; +} zenityArgs; + +#define CLEAR_AND_RETURN() \ + { \ + while (--nextarg >= 0) { \ + SDL_free(argv[nextarg]); \ + } \ + SDL_free(argv); \ + return NULL; \ + } + +#define CHECK_OOM() \ + { \ + if (!argv[nextarg - 1]) { \ + SDL_OutOfMemory(); \ + CLEAR_AND_RETURN() \ + } \ + \ + if (nextarg > argc) { \ + SDL_SetError("Zenity dialog problem: argc (%d) < nextarg (%d)", \ + argc, nextarg); \ + CLEAR_AND_RETURN() \ + } \ + } + +/* Exec call format: + * + * /usr/bin/env zenity --file-selection --separator=\n [--multiple] + * [--directory] [--save] [--filename FILENAME] + * [--file-filter=Filter Name | *.filt *.fn ...]... + */ +static char** generate_args(const zenityArgs* info) +{ + int argc = 4; + int nextarg = 0; + char **argv = NULL; + + /* ARGC PASS */ + if (info->flags & ZENITY_MULTIPLE) { + argc++; + } + + if (info->flags & ZENITY_DIRECTORY) { + argc++; + } + + if (info->flags & ZENITY_SAVE) { + argc++; + } + + if (info->filename) { + argc += 2; + } + + if (info->filters) { + const SDL_DialogFileFilter *filter_ptr = info->filters; + + while (filter_ptr->name && filter_ptr->pattern) { + argc++; + filter_ptr++; + } + } + + argv = SDL_malloc(sizeof(char *) * argc + 1); + + if (!argv) { + SDL_OutOfMemory(); + return NULL; + } + + argv[nextarg++] = SDL_strdup("/usr/bin/env"); + CHECK_OOM() + argv[nextarg++] = SDL_strdup("zenity"); + CHECK_OOM() + argv[nextarg++] = SDL_strdup("--file-selection"); + CHECK_OOM() + argv[nextarg++] = SDL_strdup("--separator=\n"); + CHECK_OOM() + + /* ARGV PASS */ + if (info->flags & ZENITY_MULTIPLE) { + argv[nextarg++] = SDL_strdup("--multiple"); + CHECK_OOM() + } + + if (info->flags & ZENITY_DIRECTORY) { + argv[nextarg++] = SDL_strdup("--directory"); + CHECK_OOM() + } + + if (info->flags & ZENITY_SAVE) { + argv[nextarg++] = SDL_strdup("--save"); + CHECK_OOM() + } + + if (info->filename) { + argv[nextarg++] = SDL_strdup("--filename"); + CHECK_OOM() + + argv[nextarg++] = SDL_strdup(info->filename); + CHECK_OOM() + } + + 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 (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); + CLEAR_AND_RETURN() + } + + buffer[i_buf] = '\0'; + + argv[nextarg++] = SDL_strdup(buffer); + CHECK_OOM() + + filter_ptr++; + } + } + + argv[nextarg++] = NULL; + + return argv; +} + +void free_args(char **argv) +{ + char **ptr = argv; + + while (*ptr) { + SDL_free(*ptr); + ptr++; + } + + SDL_free(argv); +} + +/* 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; + int status = -1; + + if (pipe(out) < 0) { + SDL_SetError("Could not create pipe: %s", strerror(errno)); + callback(userdata, NULL, -1); + return; + } + + /* 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); + + if (!args) { + /* SDL_SetError will have been called already */ + callback(userdata, NULL, -1); + return; + } + + process = fork(); + + 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; + } + 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; + } + + 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; + } + } + } + + /* 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); + } + + SDL_free(array); + SDL_free(container); + } +} + +static int run_zenity_thread(void* ptr) +{ + run_zenity(ptr); + SDL_free(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) +{ + zenityArgs *args; + SDL_Thread *thread; + + args = SDL_malloc(sizeof(*args)); + if (!args) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + args->callback = callback; + args->userdata = userdata; + args->filename = default_location; + args->filters = filters; + args->flags = (allow_many == SDL_TRUE) ? ZENITY_MULTIPLE : 0; + + thread = SDL_CreateThread(run_zenity_thread, "SDL_ShowOpenFileDialog", (void *) args); + + if (thread == NULL) { + callback(userdata, NULL, -1); + return; + } + + SDL_DetachThread(thread); +} + +void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +{ + zenityArgs *args; + SDL_Thread *thread; + + args = SDL_malloc(sizeof(zenityArgs)); + if (args == NULL) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + args->callback = callback; + args->userdata = userdata; + args->filename = default_location; + args->filters = filters; + args->flags = ZENITY_SAVE; + + thread = SDL_CreateThread(run_zenity_thread, "SDL_ShowSaveFileDialog", (void *) args); + + if (thread == NULL) { + callback(userdata, NULL, -1); + return; + } + + SDL_DetachThread(thread); +} + +void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +{ + zenityArgs *args; + SDL_Thread *thread; + + args = SDL_malloc(sizeof(zenityArgs)); + if (args == NULL) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + args->callback = callback; + args->userdata = userdata; + args->filename = default_location; + args->filters = NULL; + args->flags = ((allow_many == SDL_TRUE) ? ZENITY_MULTIPLE : 0) | ZENITY_DIRECTORY; + + thread = SDL_CreateThread(run_zenity_thread, "SDL_ShowOpenFolderDialog", (void *) args); + + if (thread == NULL) { + callback(userdata, NULL, -1); + return; + } + + SDL_DetachThread(thread); +} + +int SDL_Zenity_detect(void) +{ + pid_t process; + 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; + } +} diff --git a/src/dialog/unix/SDL_zenitydialog.h b/src/dialog/unix/SDL_zenitydialog.h new file mode 100644 index 00000000..9d7203b6 --- /dev/null +++ b/src/dialog/unix/SDL_zenitydialog.h @@ -0,0 +1,29 @@ +/* + 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" + +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); + +/** @returns non-zero if available, zero if unavailable */ +int SDL_Zenity_detect(void); diff --git a/src/dialog/windows/SDL_windowsdialog.c b/src/dialog/windows/SDL_windowsdialog.c new file mode 100644 index 00000000..57bfe8b6 --- /dev/null +++ b/src/dialog/windows/SDL_windowsdialog.c @@ -0,0 +1,489 @@ +/* + 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: Macro? */ + +/* TODO: Better includes? */ +#include +#include +#include "../../core/windows/SDL_windows.h" +#include "../../thread/SDL_systhread.h" + +typedef struct +{ + int is_save; + const SDL_DialogFileFilter *filters; + const char* default_file; + const char* default_folder; + SDL_Window* parent; + DWORD flags; + SDL_DialogFileCallback callback; + void* userdata; +} winArgs; + +typedef struct +{ + SDL_Window* parent; + SDL_DialogFileCallback callback; + const char* default_folder; + void* userdata; +} winFArgs; + +/** Converts dialog.nFilterIndex to SDL-compatible value */ +int getFilterIndex(int as_reported_by_windows, const SDL_DialogFileFilter *filters) +{ + 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; +} + +/* 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; + 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; + void* userdata = args->userdata; + + /* GetOpenFileName and GetSaveFileName have the same signature + (yes, LPOPENFILENAMEW even for the save dialog) */ + typedef BOOL (WINAPI *pfnGetAnyFileNameW)(LPOPENFILENAMEW); + typedef DWORD (WINAPI *pfnCommDlgExtendedError)(void); + HMODULE lib = LoadLibraryW(L"Comdlg32.dll"); + pfnGetAnyFileNameW pGetAnyFileName = NULL; + pfnCommDlgExtendedError pCommDlgExtendedError = NULL; + + if (lib) { + pGetAnyFileName = (pfnGetAnyFileNameW) GetProcAddress(lib, is_save ? "GetSaveFileNameW" : "GetOpenFileNameW"); + pCommDlgExtendedError = (pfnCommDlgExtendedError) GetProcAddress(lib, "CommDlgExtendedError"); + } else { + SDL_SetError("Couldn't load Comdlg32.dll"); + callback(userdata, NULL, -1); + return; + } + + if (!pGetAnyFileName) { + SDL_SetError("Couldn't load GetOpenFileName/GetSaveFileName from library"); + callback(userdata, NULL, -1); + return; + } + + if (!pCommDlgExtendedError) { + SDL_SetError("Couldn't load CommDlgExtendedError from library"); + callback(userdata, NULL, -1); + return; + } + + HWND window = NULL; + + if (parent) { + window = (HWND) SDL_GetProperty(SDL_GetWindowProperties(parent), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); + } + + wchar_t filebuffer[MAX_PATH] = L""; + wchar_t initfolder[MAX_PATH] = L""; + + /* Necessary for the return code below */ + SDL_memset(filebuffer, 0, MAX_PATH * sizeof(wchar_t)); + + if (default_file) { + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, default_file, -1, filebuffer, MAX_PATH); + } + + if (default_folder) { + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, default_folder, -1, filebuffer, MAX_PATH); + } + + 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; + } + pattern_ptr++; + } + } + wchar_t *filterlist = SDL_malloc((len + 1) * sizeof(wchar_t)); + + if (!filterlist) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + 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++; + } + pattern_ptr++; + } + *filter_ptr++ = '\0'; + } + *filter_ptr = '\0'; + + + OPENFILENAMEW dialog; + dialog.lStructSize = sizeof(OPENFILENAME); + dialog.hwndOwner = window; + dialog.hInstance = 0; + dialog.lpstrFilter = filterlist; + 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.lpstrInitialDir = *initfolder ? initfolder : NULL; + dialog.lpstrTitle = NULL; + dialog.Flags = flags | OFN_EXPLORER | OFN_HIDEREADONLY; + dialog.nFileOffset = 0; + dialog.nFileExtension = 0; + dialog.lpstrDefExt = NULL; + dialog.lCustData = 0; + dialog.lpfnHook = NULL; + dialog.lpTemplateName = NULL; + /* Skipped many mac-exclusive and reserved members */ + dialog.FlagsEx = 0; + + BOOL result = pGetAnyFileName(&dialog); + + SDL_free(filterlist); + + if (result) { + if (!(flags & OFN_ALLOWMULTISELECT)) { + /* 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)); + SDL_free(chosen_file); + } else { + /* File is either a C string if the user chose a single file, else + it's a series of strings formatted like: + + "C:\\path\\to\\folder\0filename1.ext\0filename2.ext\0\0" + + The code below will only stop on a double NULL in all cases, so + it is important that the rest of the buffer has been zeroed. */ + char chosen_folder[MAX_PATH]; + char chosen_file[MAX_PATH]; + wchar_t *file_ptr = dialog.lpstrFile; + size_t nfiles = 0; + size_t chosen_folder_size; + char **chosen_files_list = (char **) SDL_malloc(sizeof(char *) * (nfiles + 1)); + + if (!chosen_files_list) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + chosen_files_list[nfiles] = NULL; + + if (WideCharToMultiByte(CP_UTF8, 0, file_ptr, -1, chosen_folder, MAX_PATH, NULL, NULL) >= MAX_PATH) { + SDL_SetError("Path too long or invalid character in path"); + SDL_free(chosen_files_list); + callback(userdata, NULL, -1); + return; + } + + chosen_folder_size = SDL_strlen(chosen_folder); + SDL_strlcpy(chosen_file, chosen_folder, MAX_PATH); + chosen_file[chosen_folder_size] = '\\'; + + file_ptr += SDL_strlen(chosen_folder) + 1; + + while (*file_ptr) { + nfiles++; + 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); + return; + } + + chosen_files_list = new_cfl; + chosen_files_list[nfiles] = NULL; + + int diff = ((int) chosen_folder_size) + 1; + + if (WideCharToMultiByte(CP_UTF8, 0, file_ptr, -1, chosen_file + diff, MAX_PATH - diff, NULL, NULL) >= MAX_PATH - diff) { + SDL_SetError("Path too long or invalid character in path"); + + for (size_t i = 0; i < nfiles - 1; i++) { + SDL_free(chosen_files_list[i]); + } + + SDL_free(chosen_files_list); + callback(userdata, NULL, -1); + return; + } + + file_ptr += SDL_strlen(chosen_file) + 1 - diff; + + 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); + return; + } + } + + callback(userdata, (const char * const*) chosen_files_list, getFilterIndex(dialog.nFilterIndex, filters)); + + for (size_t i = 0; i < nfiles; i++) { + SDL_free(chosen_files_list[i]); + } + + SDL_free(chosen_files_list); + } + } else { + DWORD error = pCommDlgExtendedError(); + /* 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)); + } else { + SDL_SetError("Windows error, CommDlgExtendedError: %ld", pCommDlgExtendedError()); + callback(userdata, NULL, -1); + } + } +} + +int windows_file_dialog_thread(void* ptr) +{ + windows_ShowFileDialog(ptr); + SDL_free(ptr); + return 0; +} + +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); + } + break; + case BFFM_SELCHANGED : + break; + case BFFM_VALIDATEFAILED : + break; + default: + break; + } + return 0; +} + +void windows_ShowFolderDialog(void* ptr) +{ + winFArgs *args = (winFArgs *) 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); + } + + wchar_t buffer[MAX_PATH]; + + BROWSEINFOW dialog; + dialog.hwndOwner = parent; + dialog.pidlRoot = NULL; + /* Windows docs say this is `LPTSTR` - apparently it's actually `LPWSTR`*/ + dialog.pszDisplayName = buffer; + dialog.lpszTitle = NULL; + dialog.ulFlags = BIF_USENEWUI; + dialog.lpfn = browse_callback_proc; + dialog.lParam = (LPARAM)args->default_folder; + dialog.iImage = 0; + + LPITEMIDLIST lpItem = SHBrowseForFolderW(&dialog); + if (lpItem != NULL) { + SHGetPathFromIDListW(lpItem, buffer); + char *chosen_file = WIN_StringToUTF8W(buffer); + const char *files[2] = { chosen_file, NULL }; + callback(userdata, (const char * const*) files, -1); + SDL_free(chosen_file); + } else { + const char *files[1] = { NULL }; + callback(userdata, (const char * const*) files, -1); + } +} + +int windows_folder_dialog_thread(void* ptr) +{ + windows_ShowFolderDialog(ptr); + SDL_free(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) +{ + winArgs *args; + SDL_Thread *thread; + + args = SDL_malloc(sizeof(winArgs)); + if (args == NULL) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + args->is_save = 0; + args->filters = filters; + args->default_file = default_location; + args->default_folder = NULL; + args->parent = window; + args->flags = (allow_many == SDL_TRUE) ? OFN_ALLOWMULTISELECT : 0; + args->callback = callback; + args->userdata = userdata; + + thread = SDL_CreateThreadInternal(windows_file_dialog_thread, "SDL_ShowOpenFileDialog", 0, (void *) args); + + if (thread == NULL) { + callback(userdata, NULL, -1); + return; + } + + SDL_DetachThread(thread); +} + +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +{ + winArgs *args; + SDL_Thread *thread; + + args = SDL_malloc(sizeof(winArgs)); + if (args == NULL) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + args->is_save = 1; + args->filters = filters; + 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); + + if (thread == NULL) { + callback(userdata, NULL, -1); + return; + } + + SDL_DetachThread(thread); +} + +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +{ + winFArgs *args; + SDL_Thread *thread; + + args = SDL_malloc(sizeof(winFArgs)); + if (args == NULL) { + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } + + args->parent = window; + args->callback = callback; + args->default_folder = default_location; + args->userdata = userdata; + + thread = SDL_CreateThreadInternal(windows_folder_dialog_thread, "SDL_ShowOpenFolderDialog", 0, (void *) args); + + if (thread == NULL) { + callback(userdata, NULL, -1); + return; + } + + SDL_DetachThread(thread); +} diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c index 3900b6ca..8a46fe1f 100644 --- a/src/dynapi/SDL_dynapi.c +++ b/src/dynapi/SDL_dynapi.c @@ -26,6 +26,9 @@ #if SDL_DYNAMIC_API #define SDL_DYNAMIC_API_ENVVAR "SDL3_DYNAMIC_API" +#define SDL_SLOW_MEMCPY +#define SDL_SLOW_MEMMOVE +#define SDL_SLOW_MEMSET #ifdef HAVE_STDIO_H #include @@ -143,13 +146,13 @@ static void SDL_InitDynamicAPI(void); va_end(ap); \ return retval; \ } \ - _static size_t SDLCALL SDL_RWprintf##name(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ + _static size_t SDLCALL SDL_IOprintf##name(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ size_t retval; \ va_list ap; \ initcall; \ va_start(ap, fmt); \ - retval = jump_table.SDL_RWvprintf(context, fmt, ap); \ + retval = jump_table.SDL_IOvprintf(context, fmt, ap); \ va_end(ap); \ return retval; \ } \ @@ -294,13 +297,13 @@ static int SDLCALL SDL_swprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) wchar_t *buf, va_end(ap); return retval; } -_static size_t SDLCALL SDL_RWprintf_LOGSDLCALLS(SDL_RWops *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; va_list ap; - SDL_Log_REAL("SDL3CALL SDL_RWprintf"); + SDL_Log_REAL("SDL3CALL SDL_IOprintf"); va_start(ap, fmt); - retval = SDL_RWvprintf_REAL(context, fmt, ap); + retval = SDL_IOvprintf_REAL(context, fmt, ap); va_end(ap); return retval; } @@ -407,7 +410,7 @@ Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize) /* Obviously we can't use SDL_LoadObject() to load SDL. :) */ /* Also obviously, we never close the loaded library. */ -#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) +#if defined(WIN32) || defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif @@ -425,7 +428,7 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) return retval; } -#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) +#elif defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE) || defined(SDL_PLATFORM_HAIKU) #include static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) { @@ -449,7 +452,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. */ -#if (defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#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) fprintf(stderr, "\n\n%s\n%s\n\n", caption, msg); @@ -535,22 +538,15 @@ static void SDL_InitDynamicAPI(void) */ static SDL_bool already_initialized = SDL_FALSE; - /* SDL_AtomicLock calls SDL mutex functions to emulate if - SDL_ATOMIC_DISABLED, which we can't do here, so in such a - configuration, you're on your own. */ - #ifndef SDL_ATOMIC_DISABLED static SDL_SpinLock lock = 0; - SDL_AtomicLock_REAL(&lock); - #endif + SDL_LockSpinlock_REAL(&lock); if (!already_initialized) { SDL_InitDynamicAPILocked(); already_initialized = SDL_TRUE; } - #ifndef SDL_ATOMIC_DISABLED - SDL_AtomicUnlock_REAL(&lock); - #endif + SDL_UnlockSpinlock_REAL(&lock); } #else /* SDL_DYNAMIC_API */ diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 579cdf49..43a64241 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -39,31 +39,31 @@ #error Nope, you have to edit this file to force this off. #endif -#ifdef __APPLE__ +#ifdef SDL_PLATFORM_APPLE #include "TargetConditionals.h" #endif #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE /* probably not useful on iOS. */ #define SDL_DYNAMIC_API 0 -#elif defined(__ANDROID__) /* probably not useful on Android. */ +#elif defined(SDL_PLATFORM_ANDROID) /* probably not useful on Android. */ #define SDL_DYNAMIC_API 0 -#elif defined(__EMSCRIPTEN__) && __EMSCRIPTEN__ /* probably not useful on Emscripten. */ +#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 */ #define SDL_DYNAMIC_API 0 -#elif defined(__PS2__) && __PS2__ +#elif defined(SDL_PLATFORM_PS2) && SDL_PLATFORM_PS2 #define SDL_DYNAMIC_API 0 -#elif defined(__PSP__) && __PSP__ +#elif defined(SDL_PLATFORM_PSP) && SDL_PLATFORM_PSP #define SDL_DYNAMIC_API 0 -#elif defined(__riscos__) && __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(__VITA__) +#elif defined(SDL_PLATFORM_VITA) #define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */ -#elif defined(__NGAGE__) +#elif defined(SDL_PLATFORM_NGAGE) #define SDL_DYNAMIC_API 0 /* The N-Gage doesn't support dynamic linking either */ -#elif defined(__3DS__) +#elif defined(SDL_PLATFORM_3DS) #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.... */ diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index f8900f68..47adfb82 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -2,11 +2,15 @@ SDL3_0.0.0 { global: JNI_OnLoad; SDL_DYNAPI_entry; + SDL_AcquireCameraFrame; SDL_AddEventWatch; SDL_AddGamepadMapping; - SDL_AddGamepadMappingsFromRW; + SDL_AddGamepadMappingsFromFile; + SDL_AddGamepadMappingsFromIO; SDL_AddHintCallback; SDL_AddTimer; + SDL_AddVulkanRenderSemaphores; + SDL_AllocateEventMemory; SDL_AndroidBackButton; SDL_AndroidGetActivity; SDL_AndroidGetExternalStoragePath; @@ -17,17 +21,17 @@ SDL3_0.0.0 { SDL_AndroidSendMessage; SDL_AndroidShowToast; SDL_AtomicAdd; - SDL_AtomicCAS; - SDL_AtomicCASPtr; + SDL_AtomicCompareAndSwap; + SDL_AtomicCompareAndSwapPointer; SDL_AtomicGet; SDL_AtomicGetPtr; - SDL_AtomicLock; SDL_AtomicSet; SDL_AtomicSetPtr; - SDL_AtomicTryLock; - SDL_AtomicUnlock; SDL_AttachVirtualJoystick; SDL_AttachVirtualJoystickEx; + SDL_AudioDevicePaused; + SDL_BindAudioStream; + SDL_BindAudioStreams; SDL_BlitSurface; SDL_BlitSurfaceScaled; SDL_BlitSurfaceUnchecked; @@ -35,35 +39,52 @@ SDL3_0.0.0 { SDL_BroadcastCondition; SDL_CaptureMouse; SDL_CleanupTLS; + SDL_ClearAudioStream; + SDL_ClearClipboardData; SDL_ClearComposition; SDL_ClearError; - SDL_ClearHints; + SDL_ClearProperty; + SDL_CloseAudioDevice; + SDL_CloseCamera; SDL_CloseGamepad; + SDL_CloseHaptic; + SDL_CloseIO; SDL_CloseJoystick; SDL_CloseSensor; + SDL_CloseStorage; SDL_ComposeCustomBlendMode; + SDL_ConvertAudioSamples; SDL_ConvertEventToRenderCoordinates; SDL_ConvertPixels; + SDL_ConvertPixelsAndColorspace; SDL_ConvertSurface; SDL_ConvertSurfaceFormat; + SDL_ConvertSurfaceFormatAndColorspace; + SDL_CopyProperties; + SDL_CreateAudioStream; SDL_CreateColorCursor; SDL_CreateCondition; SDL_CreateCursor; + SDL_CreateDirectory; + SDL_CreateHapticEffect; SDL_CreateMutex; SDL_CreatePalette; SDL_CreatePixelFormat; SDL_CreatePopupWindow; - SDL_CreateRW; + SDL_CreateProperties; SDL_CreateRWLock; SDL_CreateRenderer; + SDL_CreateRendererWithProperties; SDL_CreateSemaphore; SDL_CreateSoftwareRenderer; + SDL_CreateStorageDirectory; SDL_CreateSurface; SDL_CreateSurfaceFrom; SDL_CreateSystemCursor; SDL_CreateTLS; SDL_CreateTexture; SDL_CreateTextureFromSurface; + SDL_CreateTextureWithProperties; SDL_CreateThread; SDL_CreateThreadWithStackSize; SDL_CreateWindow; @@ -71,16 +92,19 @@ SDL3_0.0.0 { SDL_CreateWindowWithProperties; SDL_CursorVisible; SDL_DXGIGetOutputInfo; + SDL_DateTimeToTime; SDL_DelEventWatch; SDL_DelHintCallback; SDL_Delay; SDL_DelayNS; + SDL_DestroyAudioStream; SDL_DestroyCondition; SDL_DestroyCursor; + SDL_DestroyHapticEffect; SDL_DestroyMutex; SDL_DestroyPalette; SDL_DestroyPixelFormat; - SDL_DestroyRW; + SDL_DestroyProperties; SDL_DestroyRWLock; SDL_DestroyRenderer; SDL_DestroySemaphore; @@ -99,15 +123,22 @@ SDL3_0.0.0 { SDL_EGL_GetWindowEGLSurface; SDL_EGL_SetEGLAttributeCallbacks; SDL_EnableScreenSaver; + SDL_EnterAppMainCallbacks; + SDL_EnumerateDirectory; + SDL_EnumerateProperties; + SDL_EnumerateStorageDirectory; SDL_Error; SDL_EventEnabled; SDL_FillSurfaceRect; SDL_FillSurfaceRects; SDL_FilterEvents; SDL_FlashWindow; + SDL_FlipSurface; + SDL_FlushAudioStream; SDL_FlushEvent; SDL_FlushEvents; SDL_FlushRenderer; + SDL_GDKGetDefaultUser; SDL_GDKGetTaskQueue; SDL_GDKSuspendComplete; SDL_GL_CreateContext; @@ -131,25 +162,51 @@ SDL3_0.0.0 { SDL_GamepadEventsEnabled; SDL_GamepadHasAxis; SDL_GamepadHasButton; - SDL_GamepadHasLED; - SDL_GamepadHasRumble; - SDL_GamepadHasRumbleTriggers; SDL_GamepadHasSensor; SDL_GamepadSensorEnabled; SDL_GetAndroidSDKVersion; SDL_GetAssertionHandler; SDL_GetAssertionReport; + SDL_GetAudioCaptureDevices; + SDL_GetAudioDeviceFormat; + SDL_GetAudioDeviceName; + SDL_GetAudioDriver; + SDL_GetAudioOutputDevices; + SDL_GetAudioStreamAvailable; + SDL_GetAudioStreamData; + SDL_GetAudioStreamDevice; + SDL_GetAudioStreamFormat; + SDL_GetAudioStreamFrequencyRatio; + 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_GetCameraPermissionState; + SDL_GetCameraProperties; SDL_GetClipboardData; SDL_GetClipboardText; SDL_GetClosestFullscreenDisplayMode; + SDL_GetCurrentAudioDriver; + SDL_GetCurrentCameraDriver; SDL_GetCurrentDisplayMode; SDL_GetCurrentDisplayOrientation; SDL_GetCurrentRenderOutputSize; + SDL_GetCurrentThreadID; + SDL_GetCurrentTime; SDL_GetCurrentVideoDriver; SDL_GetCursor; + SDL_GetDayOfWeek; + SDL_GetDayOfYear; + SDL_GetDaysInMonth; SDL_GetDefaultAssertionHandler; SDL_GetDefaultCursor; SDL_GetDesktopDisplayMode; @@ -159,10 +216,12 @@ SDL3_0.0.0 { SDL_GetDisplayForRect; SDL_GetDisplayForWindow; SDL_GetDisplayName; + SDL_GetDisplayProperties; SDL_GetDisplayUsableBounds; SDL_GetDisplays; SDL_GetError; SDL_GetEventFilter; + SDL_GetFloatProperty; SDL_GetFullscreenDisplayModes; SDL_GetGamepadAppleSFSymbolsNameForAxis; SDL_GetGamepadAppleSFSymbolsNameForButton; @@ -171,10 +230,13 @@ SDL3_0.0.0 { SDL_GetGamepadBindings; SDL_GetGamepadButton; SDL_GetGamepadButtonFromString; + SDL_GetGamepadButtonLabel; + SDL_GetGamepadButtonLabelForType; SDL_GetGamepadFirmwareVersion; SDL_GetGamepadFromInstanceID; SDL_GetGamepadFromPlayerIndex; SDL_GetGamepadInstanceGUID; + SDL_GetGamepadInstanceID; SDL_GetGamepadInstanceMapping; SDL_GetGamepadInstanceName; SDL_GetGamepadInstancePath; @@ -186,26 +248,44 @@ SDL3_0.0.0 { SDL_GetGamepadJoystick; SDL_GetGamepadMapping; SDL_GetGamepadMappingForGUID; + SDL_GetGamepadMappings; SDL_GetGamepadName; SDL_GetGamepadPath; SDL_GetGamepadPlayerIndex; + SDL_GetGamepadPowerLevel; SDL_GetGamepadProduct; SDL_GetGamepadProductVersion; + SDL_GetGamepadProperties; SDL_GetGamepadSensorData; SDL_GetGamepadSensorDataRate; SDL_GetGamepadSerial; + SDL_GetGamepadSteamHandle; SDL_GetGamepadStringForAxis; SDL_GetGamepadStringForButton; + SDL_GetGamepadStringForType; SDL_GetGamepadTouchpadFinger; SDL_GetGamepadType; + SDL_GetGamepadTypeFromString; SDL_GetGamepadVendor; SDL_GetGamepads; SDL_GetGlobalMouseState; + SDL_GetGlobalProperties; SDL_GetGrabbedWindow; + SDL_GetHapticEffectStatus; + SDL_GetHapticFeatures; + SDL_GetHapticFromInstanceID; + SDL_GetHapticInstanceID; + SDL_GetHapticInstanceName; + SDL_GetHapticName; + SDL_GetHaptics; SDL_GetHint; SDL_GetHintBoolean; + SDL_GetIOProperties; + SDL_GetIOSize; + SDL_GetIOStatus; SDL_GetJoystickAxis; SDL_GetJoystickAxisInitialState; + SDL_GetJoystickBall; SDL_GetJoystickButton; SDL_GetJoystickFirmwareVersion; SDL_GetJoystickFromInstanceID; @@ -230,6 +310,7 @@ SDL3_0.0.0 { SDL_GetJoystickPowerLevel; SDL_GetJoystickProduct; SDL_GetJoystickProductVersion; + SDL_GetJoystickProperties; SDL_GetJoystickSerial; SDL_GetJoystickType; SDL_GetJoystickVendor; @@ -238,24 +319,50 @@ SDL3_0.0.0 { SDL_GetKeyFromScancode; SDL_GetKeyName; SDL_GetKeyboardFocus; + SDL_GetKeyboardInstanceName; SDL_GetKeyboardState; + SDL_GetKeyboards; + SDL_GetLogOutputFunction; SDL_GetMasksForPixelFormatEnum; + SDL_GetMaxHapticEffects; + SDL_GetMaxHapticEffectsPlaying; SDL_GetMemoryFunctions; + SDL_GetMice; SDL_GetModState; SDL_GetMouseFocus; + SDL_GetMouseInstanceName; SDL_GetMouseState; SDL_GetNaturalDisplayOrientation; SDL_GetNumAllocations; + SDL_GetNumAudioDrivers; + SDL_GetNumCameraDrivers; SDL_GetNumGamepadTouchpadFingers; SDL_GetNumGamepadTouchpads; + SDL_GetNumHapticAxes; SDL_GetNumJoystickAxes; + SDL_GetNumJoystickBalls; SDL_GetNumJoystickButtons; SDL_GetNumJoystickHats; SDL_GetNumRenderDrivers; SDL_GetNumTouchFingers; SDL_GetNumVideoDrivers; + SDL_GetNumberProperty; SDL_GetOriginalMemoryFunctions; - SDL_GetUserFolder; + 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; @@ -266,8 +373,12 @@ SDL3_0.0.0 { SDL_GetPreferredLocales; SDL_GetPrimaryDisplay; SDL_GetPrimarySelectionText; + SDL_GetProperty; + SDL_GetPropertyType; SDL_GetRGB; SDL_GetRGBA; + SDL_GetRealGamepadInstanceType; + SDL_GetRealGamepadType; SDL_GetRectAndLineIntersection; SDL_GetRectAndLineIntersectionFloat; SDL_GetRectEnclosingPoints; @@ -279,8 +390,10 @@ SDL3_0.0.0 { SDL_GetRelativeMouseMode; SDL_GetRelativeMouseState; SDL_GetRenderClipRect; + SDL_GetRenderColorScale; SDL_GetRenderDrawBlendMode; SDL_GetRenderDrawColor; + SDL_GetRenderDrawColorFloat; SDL_GetRenderDriver; SDL_GetRenderLogicalPresentation; SDL_GetRenderMetalCommandEncoder; @@ -292,7 +405,9 @@ SDL3_0.0.0 { SDL_GetRenderViewport; SDL_GetRenderWindow; SDL_GetRenderer; + SDL_GetRendererFromTexture; SDL_GetRendererInfo; + SDL_GetRendererProperties; SDL_GetRevision; SDL_GetScancodeFromKey; SDL_GetScancodeFromName; @@ -306,26 +421,40 @@ SDL3_0.0.0 { SDL_GetSensorInstanceType; SDL_GetSensorName; SDL_GetSensorNonPortableType; + SDL_GetSensorProperties; SDL_GetSensorType; SDL_GetSensors; + SDL_GetSilenceValueForFormat; + SDL_GetStorageFileSize; + SDL_GetStoragePathInfo; + SDL_GetStorageSpaceRemaining; + SDL_GetStringProperty; SDL_GetSurfaceAlphaMod; SDL_GetSurfaceBlendMode; SDL_GetSurfaceClipRect; SDL_GetSurfaceColorKey; SDL_GetSurfaceColorMod; + SDL_GetSurfaceColorspace; + SDL_GetSurfaceProperties; SDL_GetSystemRAM; SDL_GetSystemTheme; SDL_GetTLS; SDL_GetTextureAlphaMod; + SDL_GetTextureAlphaModFloat; SDL_GetTextureBlendMode; SDL_GetTextureColorMod; + SDL_GetTextureColorModFloat; + SDL_GetTextureProperties; SDL_GetTextureScaleMode; SDL_GetThreadID; SDL_GetThreadName; SDL_GetTicks; SDL_GetTicksNS; + SDL_GetTouchDeviceName; SDL_GetTouchDeviceType; + SDL_GetTouchDevices; SDL_GetTouchFinger; + SDL_GetUserFolder; SDL_GetVersion; SDL_GetVideoDriver; SDL_GetWindowBordersSize; @@ -333,7 +462,6 @@ SDL3_0.0.0 { SDL_GetWindowFlags; SDL_GetWindowFromID; SDL_GetWindowFullscreenMode; - SDL_GetWindowGrab; SDL_GetWindowICCProfile; SDL_GetWindowID; SDL_GetWindowKeyboardGrab; @@ -346,39 +474,13 @@ SDL3_0.0.0 { SDL_GetWindowPixelDensity; SDL_GetWindowPixelFormat; SDL_GetWindowPosition; + SDL_GetWindowProperties; SDL_GetWindowSize; SDL_GetWindowSizeInPixels; SDL_GetWindowSurface; SDL_GetWindowTitle; - SDL_GetYUVConversionMode; - SDL_GetYUVConversionModeForResolution; - SDL_HapticClose; - SDL_HapticDestroyEffect; SDL_HapticEffectSupported; - SDL_HapticGetEffectStatus; - SDL_HapticIndex; - SDL_HapticName; - SDL_HapticNewEffect; - SDL_HapticNumAxes; - SDL_HapticNumEffects; - SDL_HapticNumEffectsPlaying; - SDL_HapticOpen; - SDL_HapticOpenFromJoystick; - SDL_HapticOpenFromMouse; - SDL_HapticOpened; - SDL_HapticPause; - SDL_HapticQuery; - SDL_HapticRumbleInit; - SDL_HapticRumblePlay; - SDL_HapticRumbleStop; SDL_HapticRumbleSupported; - SDL_HapticRunEffect; - SDL_HapticSetAutocenter; - SDL_HapticSetGain; - SDL_HapticStopAll; - SDL_HapticStopEffect; - SDL_HapticUnpause; - SDL_HapticUpdateEffect; SDL_HasARMSIMD; SDL_HasAVX2; SDL_HasAVX512F; @@ -388,11 +490,16 @@ SDL3_0.0.0 { SDL_HasClipboardText; SDL_HasEvent; SDL_HasEvents; + SDL_HasGamepad; + SDL_HasJoystick; + SDL_HasKeyboard; SDL_HasLASX; SDL_HasLSX; SDL_HasMMX; + SDL_HasMouse; SDL_HasNEON; SDL_HasPrimarySelectionText; + SDL_HasProperty; SDL_HasRectIntersection; SDL_HasRectIntersectionFloat; SDL_HasSSE2; @@ -401,35 +508,44 @@ SDL3_0.0.0 { SDL_HasSSE42; SDL_HasSSE; SDL_HasScreenKeyboardSupport; - SDL_HasWindowSurface; SDL_HideCursor; SDL_HideWindow; + SDL_IOFromConstMem; + SDL_IOFromDynamicMem; + SDL_IOFromFile; + SDL_IOFromMem; + SDL_IOprintf; + SDL_IOvprintf; SDL_Init; + SDL_InitHapticRumble; SDL_InitSubSystem; SDL_IsAndroidTV; SDL_IsChromebook; SDL_IsDeXMode; SDL_IsGamepad; + SDL_IsJoystickHaptic; SDL_IsJoystickVirtual; + SDL_IsMouseHaptic; SDL_IsTablet; SDL_JoystickConnected; SDL_JoystickEventsEnabled; - SDL_JoystickHasLED; - SDL_JoystickHasRumble; - SDL_JoystickHasRumbleTriggers; - SDL_JoystickIsHaptic; SDL_LinuxSetThreadPriority; SDL_LinuxSetThreadPriorityAndPolicy; SDL_LoadBMP; - SDL_LoadBMP_RW; + SDL_LoadBMP_IO; SDL_LoadFile; - SDL_LoadFile_RW; + SDL_LoadFile_IO; SDL_LoadFunction; SDL_LoadObject; + SDL_LoadWAV; + SDL_LoadWAV_IO; + SDL_LockAudioStream; SDL_LockJoysticks; SDL_LockMutex; + SDL_LockProperties; SDL_LockRWLockForReading; SDL_LockRWLockForWriting; + SDL_LockSpinlock; SDL_LockSurface; SDL_LockTexture; SDL_LockTextureToSurface; @@ -437,14 +553,12 @@ SDL3_0.0.0 { SDL_LogCritical; SDL_LogDebug; SDL_LogError; - SDL_LogGetOutputFunction; SDL_LogGetPriority; SDL_LogInfo; SDL_LogMessage; SDL_LogMessageV; SDL_LogResetPriorities; SDL_LogSetAllPriority; - SDL_LogSetOutputFunction; SDL_LogSetPriority; SDL_LogVerbose; SDL_LogWarn; @@ -457,8 +571,7 @@ SDL3_0.0.0 { SDL_Metal_DestroyView; SDL_Metal_GetLayer; SDL_MinimizeWindow; - SDL_MouseIsHaptic; - SDL_NumHaptics; + SDL_MixAudioFormat; SDL_OnApplicationDidBecomeActive; SDL_OnApplicationDidChangeStatusBarOrientation; SDL_OnApplicationDidEnterBackground; @@ -466,39 +579,62 @@ SDL3_0.0.0 { SDL_OnApplicationWillEnterForeground; SDL_OnApplicationWillResignActive; SDL_OnApplicationWillTerminate; + SDL_OpenAudioDevice; + SDL_OpenAudioDeviceStream; + SDL_OpenCameraDevice; + SDL_OpenFileStorage; SDL_OpenGamepad; + SDL_OpenHaptic; + SDL_OpenHapticFromJoystick; + SDL_OpenHapticFromMouse; + SDL_OpenIO; SDL_OpenJoystick; SDL_OpenSensor; + SDL_OpenStorage; + SDL_OpenTitleStorage; SDL_OpenURL; + SDL_OpenUserStorage; + SDL_PauseAudioDevice; + SDL_PauseHaptic; SDL_PeepEvents; + SDL_PenConnected; + SDL_PenConnected; + SDL_PlayHapticRumble; SDL_PollEvent; SDL_PostSemaphore; SDL_PremultiplyAlpha; SDL_PumpEvents; SDL_PushEvent; + SDL_PutAudioStreamData; SDL_QueryTexture; SDL_Quit; SDL_QuitSubSystem; - SDL_RWFromConstMem; - SDL_RWFromFile; - SDL_RWFromMem; - SDL_RWclose; - SDL_RWread; - SDL_RWseek; - SDL_RWsize; - SDL_RWtell; - SDL_RWwrite; SDL_RaiseWindow; + SDL_ReadIO; + SDL_ReadS16BE; + SDL_ReadS16LE; + SDL_ReadS32BE; + SDL_ReadS32LE; + SDL_ReadS64BE; + SDL_ReadS64LE; + SDL_ReadStorageFile; + SDL_ReadSurfacePixel; SDL_ReadU16BE; - SDL_ReadU32BE; - SDL_ReadU64BE; SDL_ReadU16LE; + SDL_ReadU32BE; SDL_ReadU32LE; + SDL_ReadU64BE; SDL_ReadU64LE; SDL_ReadU8; SDL_RegisterApp; SDL_RegisterEvents; + SDL_ReleaseCameraFrame; + SDL_ReloadGamepadMappings; + SDL_RemovePath; + SDL_RemoveStoragePath; SDL_RemoveTimer; + SDL_RenamePath; + SDL_RenameStoragePath; SDL_RenderClear; SDL_RenderClipEnabled; SDL_RenderCoordinatesFromWindow; @@ -507,6 +643,7 @@ SDL3_0.0.0 { SDL_RenderFillRects; SDL_RenderGeometry; SDL_RenderGeometryRaw; + SDL_RenderGeometryRawFloat; SDL_RenderLine; SDL_RenderLines; SDL_RenderPoint; @@ -517,36 +654,51 @@ SDL3_0.0.0 { SDL_RenderRects; SDL_RenderTexture; SDL_RenderTextureRotated; + SDL_RenderViewportSet; SDL_ReportAssertion; SDL_ResetAssertionReport; SDL_ResetHint; SDL_ResetHints; SDL_ResetKeyboard; SDL_RestoreWindow; + SDL_ResumeAudioDevice; + SDL_ResumeHaptic; SDL_RumbleGamepad; SDL_RumbleGamepadTriggers; SDL_RumbleJoystick; SDL_RumbleJoystickTriggers; SDL_RunApp; + SDL_RunHapticEffect; SDL_SIMDGetAlignment; SDL_SaveBMP; - SDL_SaveBMP_RW; + SDL_SaveBMP_IO; SDL_ScreenKeyboardShown; SDL_ScreenSaverEnabled; + SDL_SeekIO; SDL_SendGamepadEffect; SDL_SendJoystickEffect; SDL_SetAssertionHandler; + SDL_SetAudioPostmixCallback; SDL_SetAudioStreamFormat; + SDL_SetAudioStreamFormat; + SDL_SetAudioStreamFrequencyRatio; + SDL_SetAudioStreamGetCallback; + SDL_SetAudioStreamPutCallback; + SDL_SetBooleanProperty; SDL_SetClipboardData; SDL_SetClipboardText; SDL_SetCursor; SDL_SetError; SDL_SetEventEnabled; SDL_SetEventFilter; + SDL_SetFloatProperty; SDL_SetGamepadEventsEnabled; SDL_SetGamepadLED; + SDL_SetGamepadMapping; SDL_SetGamepadPlayerIndex; SDL_SetGamepadSensorEnabled; + SDL_SetHapticAutocenter; + SDL_SetHapticGain; SDL_SetHint; SDL_SetHintWithPriority; SDL_SetJoystickEventsEnabled; @@ -555,40 +707,50 @@ SDL3_0.0.0 { SDL_SetJoystickVirtualAxis; SDL_SetJoystickVirtualButton; SDL_SetJoystickVirtualHat; + SDL_SetLogOutputFunction; SDL_SetMainReady; SDL_SetMemoryFunctions; SDL_SetModState; + SDL_SetNumberProperty; SDL_SetPaletteColors; SDL_SetPixelFormatPalette; SDL_SetPrimarySelectionText; + SDL_SetProperty; + SDL_SetPropertyWithCleanup; SDL_SetRelativeMouseMode; SDL_SetRenderClipRect; + SDL_SetRenderColorScale; SDL_SetRenderDrawBlendMode; SDL_SetRenderDrawColor; + SDL_SetRenderDrawColorFloat; SDL_SetRenderLogicalPresentation; SDL_SetRenderScale; SDL_SetRenderTarget; SDL_SetRenderVSync; SDL_SetRenderViewport; + SDL_SetStringProperty; SDL_SetSurfaceAlphaMod; SDL_SetSurfaceBlendMode; SDL_SetSurfaceClipRect; SDL_SetSurfaceColorKey; SDL_SetSurfaceColorMod; + SDL_SetSurfaceColorspace; SDL_SetSurfacePalette; SDL_SetSurfaceRLE; SDL_SetTLS; SDL_SetTextInputRect; SDL_SetTextureAlphaMod; + SDL_SetTextureAlphaModFloat; SDL_SetTextureBlendMode; SDL_SetTextureColorMod; + SDL_SetTextureColorModFloat; SDL_SetTextureScaleMode; SDL_SetThreadPriority; SDL_SetWindowAlwaysOnTop; SDL_SetWindowBordered; + SDL_SetWindowFocusable; SDL_SetWindowFullscreen; SDL_SetWindowFullscreenMode; - SDL_SetWindowGrab; SDL_SetWindowHitTest; SDL_SetWindowIcon; SDL_SetWindowInputFocus; @@ -601,35 +763,54 @@ SDL3_0.0.0 { SDL_SetWindowOpacity; SDL_SetWindowPosition; SDL_SetWindowResizable; + SDL_SetWindowShape; SDL_SetWindowSize; SDL_SetWindowTitle; SDL_SetWindowsMessageHook; - SDL_SetYUVConversionMode; + SDL_SetX11EventHook; SDL_ShowCursor; SDL_ShowMessageBox; + SDL_ShowOpenFileDialog; + SDL_ShowOpenFolderDialog; + SDL_ShowSaveFileDialog; SDL_ShowSimpleMessageBox; SDL_ShowWindow; + SDL_ShowWindowSystemMenu; SDL_SignalCondition; SDL_SoftStretch; SDL_StartTextInput; + SDL_StopHapticEffect; + SDL_StopHapticEffects; + SDL_StopHapticRumble; SDL_StopTextInput; + SDL_StorageReady; SDL_SurfaceHasColorKey; SDL_SurfaceHasRLE; + SDL_SyncWindow; + SDL_TellIO; SDL_TextInputActive; - SDL_TextInputShown; - SDL_ThreadID; + SDL_TimeFromWindows; + SDL_TimeToDateTime; + SDL_TimeToWindows; SDL_TryLockMutex; SDL_TryLockRWLockForReading; SDL_TryLockRWLockForWriting; + SDL_TryLockSpinlock; SDL_TryWaitSemaphore; + SDL_UnbindAudioStream; + SDL_UnbindAudioStreams; SDL_UnloadObject; + SDL_UnlockAudioStream; SDL_UnlockJoysticks; SDL_UnlockMutex; + SDL_UnlockProperties; SDL_UnlockRWLock; + SDL_UnlockSpinlock; SDL_UnlockSurface; SDL_UnlockTexture; SDL_UnregisterApp; SDL_UpdateGamepads; + SDL_UpdateHapticEffect; SDL_UpdateJoysticks; SDL_UpdateNVTexture; SDL_UpdateSensors; @@ -655,11 +836,19 @@ SDL3_0.0.0 { SDL_WinRTGetDeviceFamily; SDL_WinRTGetFSPathUNICODE; SDL_WinRTGetFSPathUTF8; + SDL_WindowHasSurface; + SDL_WriteIO; + SDL_WriteS16BE; + SDL_WriteS16LE; + SDL_WriteS32BE; + SDL_WriteS32LE; + SDL_WriteS64BE; + SDL_WriteS64LE; SDL_WriteU16BE; - SDL_WriteU32BE; - SDL_WriteU64BE; SDL_WriteU16LE; + SDL_WriteU32BE; SDL_WriteU32LE; + SDL_WriteU64BE; SDL_WriteU64LE; SDL_WriteU8; SDL_abs; @@ -677,6 +866,7 @@ SDL3_0.0.0 { SDL_atof; SDL_atoi; SDL_bsearch; + SDL_bsearch_r; SDL_calloc; SDL_ceil; SDL_ceilf; @@ -756,6 +946,7 @@ SDL3_0.0.0 { SDL_pow; SDL_powf; SDL_qsort; + SDL_qsort_r; SDL_realloc; SDL_round; SDL_roundf; @@ -779,6 +970,9 @@ SDL3_0.0.0 { SDL_strlwr; SDL_strncasecmp; SDL_strncmp; + SDL_strndup; + SDL_strnlen; + SDL_strnstr; SDL_strrchr; SDL_strrev; SDL_strstr; @@ -814,154 +1008,10 @@ SDL3_0.0.0 { SDL_wcslen; SDL_wcsncasecmp; SDL_wcsncmp; + SDL_wcsnlen; + SDL_wcsnstr; SDL_wcsstr; SDL_wcstol; - SDL_ClearClipboardData; - SDL_GetGamepadInstanceID; - SDL_GetGamepadPowerLevel; - SDL_SetGamepadMapping; - SDL_strndup; - SDL_GetGamepadTypeFromString; - SDL_GetGamepadStringForType; - SDL_GetRealGamepadInstanceType; - SDL_GetRealGamepadType; - SDL_wcsnlen; - SDL_strnlen; - SDL_AddGamepadMappingsFromFile; - SDL_ReloadGamepadMappings; - SDL_GetNumAudioDrivers; - SDL_GetAudioDriver; - SDL_GetCurrentAudioDriver; - SDL_GetAudioOutputDevices; - SDL_GetAudioCaptureDevices; - SDL_GetAudioDeviceName; - SDL_GetAudioDeviceFormat; - SDL_OpenAudioDevice; - SDL_CloseAudioDevice; - SDL_BindAudioStreams; - SDL_BindAudioStream; - SDL_UnbindAudioStreams; - SDL_UnbindAudioStream; - SDL_CreateAudioStream; - SDL_GetAudioStreamFormat; - SDL_SetAudioStreamFormat; - SDL_PutAudioStreamData; - SDL_GetAudioStreamData; - SDL_GetAudioStreamAvailable; - SDL_FlushAudioStream; - SDL_ClearAudioStream; - SDL_LockAudioStream; - SDL_UnlockAudioStream; - SDL_SetAudioStreamGetCallback; - SDL_SetAudioStreamPutCallback; - SDL_DestroyAudioStream; - SDL_OpenAudioDeviceStream; - SDL_LoadWAV_RW; - SDL_LoadWAV; - SDL_MixAudioFormat; - SDL_ConvertAudioSamples; - SDL_GetSilenceValueForFormat; - SDL_PauseAudioDevice; - SDL_ResumeAudioDevice; - SDL_AudioDevicePaused; - SDL_GetAudioStreamDevice; - SDL_ShowWindowSystemMenu; - SDL_ReadS16LE; - SDL_ReadS16BE; - SDL_ReadS32LE; - SDL_ReadS32BE; - SDL_ReadS64LE; - SDL_ReadS64BE; - SDL_WriteS16LE; - SDL_WriteS16BE; - SDL_WriteS32LE; - SDL_WriteS32BE; - SDL_WriteS64LE; - SDL_WriteS64BE; - SDL_GDKGetDefaultUser; - SDL_SetWindowFocusable; - SDL_GetAudioStreamFrequencyRatio; - SDL_SetAudioStreamFrequencyRatio; - SDL_SetAudioPostmixCallback; - SDL_GetAudioStreamQueued; - SDL_CreateProperties; - SDL_LockProperties; - SDL_UnlockProperties; - SDL_SetProperty; - SDL_GetProperty; - SDL_DestroyProperties; - SDL_GetAudioStreamProperties; - SDL_GetGamepadProperties; - SDL_GetJoystickProperties; - SDL_GetRendererProperties; - SDL_GetTextureProperties; - SDL_GetRWProperties; - SDL_GetSensorProperties; - SDL_GetSurfaceProperties; - SDL_GetWindowProperties; - SDL_ClearProperty; - SDL_EnterAppMainCallbacks; - SDL_RWprintf; - SDL_RWvprintf; - SDL_AllocateEventMemory; - SDL_GetDisplayProperties; - SDL_SetPropertyWithCleanup; - SDL_SetX11EventHook; - SDL_GetGlobalProperties; - SDL_OpenVideoCapture; - SDL_SetVideoCaptureSpec; - SDL_OpenVideoCaptureWithSpec; - SDL_GetVideoCaptureDeviceName; - SDL_GetVideoCaptureSpec; - SDL_GetVideoCaptureFormat; - SDL_GetNumVideoCaptureFormats; - SDL_GetVideoCaptureFrameSize; - SDL_GetNumVideoCaptureFrameSizes; - SDL_GetVideoCaptureStatus; - SDL_StartVideoCapture; - SDL_AcquireVideoCaptureFrame; - SDL_ReleaseVideoCaptureFrame; - SDL_StopVideoCapture; - SDL_CloseVideoCapture; - SDL_GetVideoCaptureDevices; - SDL_GetGamepadButtonLabelForType; - SDL_GetGamepadButtonLabel; - SDL_GetPens; - SDL_GetPenStatus; - SDL_GetPenFromGUID; - SDL_GetPenGUID; - SDL_PenConnected; - SDL_GetPenName; - SDL_GetPenCapabilities; - SDL_GetPenType; - SDL_GetPens; - SDL_GetPenStatus; - SDL_GetPenFromGUID; - SDL_GetPenGUID; - SDL_PenConnected; - SDL_GetPenName; - SDL_GetPenCapabilities; - SDL_GetPenType; - SDL_SetStringProperty; - SDL_SetNumberProperty; - SDL_SetFloatProperty; - SDL_GetPropertyType; - SDL_GetStringProperty; - SDL_GetNumberProperty; - SDL_GetFloatProperty; - SDL_EnumerateProperties; - SDL_SetBooleanProperty; - SDL_GetBooleanProperty; - SDL_CreateTextureWithProperties; - SDL_CreateRendererWithProperties; - SDL_GetGamepadMappings; - SDL_GetTouchDevices; - SDL_GetTouchDeviceName; - SDL_strnstr; - SDL_wcsnstr; - SDL_SyncWindow; - SDL_GetGamepadSteamHandle; - SDL_GetRendererFromTexture; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index b092b19e..41f36222 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -26,11 +26,16 @@ #error You should not be here. #endif +/* New API symbols are added at the end */ +#define SDL_AcquireCameraFrame SDL_AcquireCameraFrame_REAL #define SDL_AddEventWatch SDL_AddEventWatch_REAL #define SDL_AddGamepadMapping SDL_AddGamepadMapping_REAL -#define SDL_AddGamepadMappingsFromRW SDL_AddGamepadMappingsFromRW_REAL +#define SDL_AddGamepadMappingsFromFile SDL_AddGamepadMappingsFromFile_REAL +#define SDL_AddGamepadMappingsFromIO SDL_AddGamepadMappingsFromIO_REAL #define SDL_AddHintCallback SDL_AddHintCallback_REAL #define SDL_AddTimer SDL_AddTimer_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 @@ -41,17 +46,17 @@ #define SDL_AndroidSendMessage SDL_AndroidSendMessage_REAL #define SDL_AndroidShowToast SDL_AndroidShowToast_REAL #define SDL_AtomicAdd SDL_AtomicAdd_REAL -#define SDL_AtomicCAS SDL_AtomicCAS_REAL -#define SDL_AtomicCASPtr SDL_AtomicCASPtr_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_AtomicLock SDL_AtomicLock_REAL #define SDL_AtomicSet SDL_AtomicSet_REAL #define SDL_AtomicSetPtr SDL_AtomicSetPtr_REAL -#define SDL_AtomicTryLock SDL_AtomicTryLock_REAL -#define SDL_AtomicUnlock SDL_AtomicUnlock_REAL #define SDL_AttachVirtualJoystick SDL_AttachVirtualJoystick_REAL #define SDL_AttachVirtualJoystickEx SDL_AttachVirtualJoystickEx_REAL +#define SDL_AudioDevicePaused SDL_AudioDevicePaused_REAL +#define SDL_BindAudioStream SDL_BindAudioStream_REAL +#define SDL_BindAudioStreams SDL_BindAudioStreams_REAL #define SDL_BlitSurface SDL_BlitSurface_REAL #define SDL_BlitSurfaceScaled SDL_BlitSurfaceScaled_REAL #define SDL_BlitSurfaceUnchecked SDL_BlitSurfaceUnchecked_REAL @@ -59,35 +64,52 @@ #define SDL_BroadcastCondition SDL_BroadcastCondition_REAL #define SDL_CaptureMouse SDL_CaptureMouse_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_ClearHints SDL_ClearHints_REAL +#define SDL_ClearProperty SDL_ClearProperty_REAL +#define SDL_CloseAudioDevice SDL_CloseAudioDevice_REAL +#define SDL_CloseCamera SDL_CloseCamera_REAL #define SDL_CloseGamepad SDL_CloseGamepad_REAL +#define SDL_CloseHaptic SDL_CloseHaptic_REAL +#define SDL_CloseIO SDL_CloseIO_REAL #define SDL_CloseJoystick SDL_CloseJoystick_REAL #define SDL_CloseSensor SDL_CloseSensor_REAL +#define SDL_CloseStorage SDL_CloseStorage_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_CopyProperties SDL_CopyProperties_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_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_CreateRW SDL_CreateRW_REAL +#define SDL_CreateProperties SDL_CreateProperties_REAL #define SDL_CreateRWLock SDL_CreateRWLock_REAL #define SDL_CreateRenderer SDL_CreateRenderer_REAL +#define SDL_CreateRendererWithProperties SDL_CreateRendererWithProperties_REAL #define SDL_CreateSemaphore SDL_CreateSemaphore_REAL #define SDL_CreateSoftwareRenderer SDL_CreateSoftwareRenderer_REAL +#define SDL_CreateStorageDirectory SDL_CreateStorageDirectory_REAL #define SDL_CreateSurface SDL_CreateSurface_REAL #define SDL_CreateSurfaceFrom SDL_CreateSurfaceFrom_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_CreateWindow SDL_CreateWindow_REAL @@ -95,16 +117,19 @@ #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_DestroyHapticEffect SDL_DestroyHapticEffect_REAL #define SDL_DestroyMutex SDL_DestroyMutex_REAL #define SDL_DestroyPalette SDL_DestroyPalette_REAL #define SDL_DestroyPixelFormat SDL_DestroyPixelFormat_REAL -#define SDL_DestroyRW SDL_DestroyRW_REAL +#define SDL_DestroyProperties SDL_DestroyProperties_REAL #define SDL_DestroyRWLock SDL_DestroyRWLock_REAL #define SDL_DestroyRenderer SDL_DestroyRenderer_REAL #define SDL_DestroySemaphore SDL_DestroySemaphore_REAL @@ -123,15 +148,22 @@ #define SDL_EGL_GetWindowEGLSurface SDL_EGL_GetWindowEGLSurface_REAL #define SDL_EGL_SetEGLAttributeCallbacks SDL_EGL_SetEGLAttributeCallbacks_REAL #define SDL_EnableScreenSaver SDL_EnableScreenSaver_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 #define SDL_FilterEvents SDL_FilterEvents_REAL #define SDL_FlashWindow SDL_FlashWindow_REAL +#define SDL_FlipSurface SDL_FlipSurface_REAL +#define SDL_FlushAudioStream SDL_FlushAudioStream_REAL #define SDL_FlushEvent SDL_FlushEvent_REAL #define SDL_FlushEvents SDL_FlushEvents_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_GL_CreateContext SDL_GL_CreateContext_REAL @@ -155,25 +187,51 @@ #define SDL_GamepadEventsEnabled SDL_GamepadEventsEnabled_REAL #define SDL_GamepadHasAxis SDL_GamepadHasAxis_REAL #define SDL_GamepadHasButton SDL_GamepadHasButton_REAL -#define SDL_GamepadHasLED SDL_GamepadHasLED_REAL -#define SDL_GamepadHasRumble SDL_GamepadHasRumble_REAL -#define SDL_GamepadHasRumbleTriggers SDL_GamepadHasRumbleTriggers_REAL #define SDL_GamepadHasSensor SDL_GamepadHasSensor_REAL #define SDL_GamepadSensorEnabled SDL_GamepadSensorEnabled_REAL #define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL #define SDL_GetAssertionReport SDL_GetAssertionReport_REAL +#define SDL_GetAudioCaptureDevices SDL_GetAudioCaptureDevices_REAL +#define SDL_GetAudioDeviceFormat SDL_GetAudioDeviceFormat_REAL +#define SDL_GetAudioDeviceName SDL_GetAudioDeviceName_REAL +#define SDL_GetAudioDriver SDL_GetAudioDriver_REAL +#define SDL_GetAudioOutputDevices SDL_GetAudioOutputDevices_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_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_GetCameraPermissionState SDL_GetCameraPermissionState_REAL +#define SDL_GetCameraProperties SDL_GetCameraProperties_REAL #define SDL_GetClipboardData SDL_GetClipboardData_REAL #define SDL_GetClipboardText SDL_GetClipboardText_REAL #define SDL_GetClosestFullscreenDisplayMode SDL_GetClosestFullscreenDisplayMode_REAL +#define SDL_GetCurrentAudioDriver SDL_GetCurrentAudioDriver_REAL +#define SDL_GetCurrentCameraDriver SDL_GetCurrentCameraDriver_REAL #define SDL_GetCurrentDisplayMode SDL_GetCurrentDisplayMode_REAL #define SDL_GetCurrentDisplayOrientation SDL_GetCurrentDisplayOrientation_REAL #define SDL_GetCurrentRenderOutputSize SDL_GetCurrentRenderOutputSize_REAL +#define SDL_GetCurrentThreadID SDL_GetCurrentThreadID_REAL +#define SDL_GetCurrentTime SDL_GetCurrentTime_REAL #define SDL_GetCurrentVideoDriver SDL_GetCurrentVideoDriver_REAL #define SDL_GetCursor SDL_GetCursor_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 @@ -183,10 +241,12 @@ #define SDL_GetDisplayForRect SDL_GetDisplayForRect_REAL #define SDL_GetDisplayForWindow SDL_GetDisplayForWindow_REAL #define SDL_GetDisplayName SDL_GetDisplayName_REAL +#define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL #define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL #define SDL_GetDisplays SDL_GetDisplays_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_GetGamepadAppleSFSymbolsNameForAxis SDL_GetGamepadAppleSFSymbolsNameForAxis_REAL #define SDL_GetGamepadAppleSFSymbolsNameForButton SDL_GetGamepadAppleSFSymbolsNameForButton_REAL @@ -195,10 +255,13 @@ #define SDL_GetGamepadBindings SDL_GetGamepadBindings_REAL #define SDL_GetGamepadButton SDL_GetGamepadButton_REAL #define SDL_GetGamepadButtonFromString SDL_GetGamepadButtonFromString_REAL +#define SDL_GetGamepadButtonLabel SDL_GetGamepadButtonLabel_REAL +#define SDL_GetGamepadButtonLabelForType SDL_GetGamepadButtonLabelForType_REAL #define SDL_GetGamepadFirmwareVersion SDL_GetGamepadFirmwareVersion_REAL #define SDL_GetGamepadFromInstanceID SDL_GetGamepadFromInstanceID_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 @@ -210,26 +273,44 @@ #define SDL_GetGamepadJoystick SDL_GetGamepadJoystick_REAL #define SDL_GetGamepadMapping SDL_GetGamepadMapping_REAL #define SDL_GetGamepadMappingForGUID SDL_GetGamepadMappingForGUID_REAL +#define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL #define SDL_GetGamepadName SDL_GetGamepadName_REAL #define SDL_GetGamepadPath SDL_GetGamepadPath_REAL #define SDL_GetGamepadPlayerIndex SDL_GetGamepadPlayerIndex_REAL +#define SDL_GetGamepadPowerLevel SDL_GetGamepadPowerLevel_REAL #define SDL_GetGamepadProduct SDL_GetGamepadProduct_REAL #define SDL_GetGamepadProductVersion SDL_GetGamepadProductVersion_REAL +#define SDL_GetGamepadProperties SDL_GetGamepadProperties_REAL #define SDL_GetGamepadSensorData SDL_GetGamepadSensorData_REAL #define SDL_GetGamepadSensorDataRate SDL_GetGamepadSensorDataRate_REAL #define SDL_GetGamepadSerial SDL_GetGamepadSerial_REAL +#define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL #define SDL_GetGamepadStringForAxis SDL_GetGamepadStringForAxis_REAL #define SDL_GetGamepadStringForButton SDL_GetGamepadStringForButton_REAL +#define SDL_GetGamepadStringForType SDL_GetGamepadStringForType_REAL #define SDL_GetGamepadTouchpadFinger SDL_GetGamepadTouchpadFinger_REAL #define SDL_GetGamepadType SDL_GetGamepadType_REAL +#define SDL_GetGamepadTypeFromString SDL_GetGamepadTypeFromString_REAL #define SDL_GetGamepadVendor SDL_GetGamepadVendor_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_GetHapticName SDL_GetHapticName_REAL +#define SDL_GetHaptics SDL_GetHaptics_REAL #define SDL_GetHint SDL_GetHint_REAL #define SDL_GetHintBoolean SDL_GetHintBoolean_REAL +#define SDL_GetIOProperties SDL_GetIOProperties_REAL +#define SDL_GetIOSize SDL_GetIOSize_REAL +#define SDL_GetIOStatus SDL_GetIOStatus_REAL #define SDL_GetJoystickAxis SDL_GetJoystickAxis_REAL #define SDL_GetJoystickAxisInitialState SDL_GetJoystickAxisInitialState_REAL +#define SDL_GetJoystickBall SDL_GetJoystickBall_REAL #define SDL_GetJoystickButton SDL_GetJoystickButton_REAL #define SDL_GetJoystickFirmwareVersion SDL_GetJoystickFirmwareVersion_REAL #define SDL_GetJoystickFromInstanceID SDL_GetJoystickFromInstanceID_REAL @@ -254,6 +335,7 @@ #define SDL_GetJoystickPowerLevel SDL_GetJoystickPowerLevel_REAL #define SDL_GetJoystickProduct SDL_GetJoystickProduct_REAL #define SDL_GetJoystickProductVersion SDL_GetJoystickProductVersion_REAL +#define SDL_GetJoystickProperties SDL_GetJoystickProperties_REAL #define SDL_GetJoystickSerial SDL_GetJoystickSerial_REAL #define SDL_GetJoystickType SDL_GetJoystickType_REAL #define SDL_GetJoystickVendor SDL_GetJoystickVendor_REAL @@ -262,24 +344,50 @@ #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_GetKeyboardState SDL_GetKeyboardState_REAL +#define SDL_GetKeyboards SDL_GetKeyboards_REAL +#define SDL_GetLogOutputFunction SDL_GetLogOutputFunction_REAL #define SDL_GetMasksForPixelFormatEnum SDL_GetMasksForPixelFormatEnum_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_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_GetNumGamepadTouchpadFingers SDL_GetNumGamepadTouchpadFingers_REAL #define SDL_GetNumGamepadTouchpads SDL_GetNumGamepadTouchpads_REAL +#define SDL_GetNumHapticAxes SDL_GetNumHapticAxes_REAL #define SDL_GetNumJoystickAxes SDL_GetNumJoystickAxes_REAL +#define SDL_GetNumJoystickBalls SDL_GetNumJoystickBalls_REAL #define SDL_GetNumJoystickButtons SDL_GetNumJoystickButtons_REAL #define SDL_GetNumJoystickHats SDL_GetNumJoystickHats_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_GetUserFolder SDL_GetUserFolder_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 @@ -290,8 +398,12 @@ #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_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_GetRectAndLineIntersection SDL_GetRectAndLineIntersection_REAL #define SDL_GetRectAndLineIntersectionFloat SDL_GetRectAndLineIntersectionFloat_REAL #define SDL_GetRectEnclosingPoints SDL_GetRectEnclosingPoints_REAL @@ -303,8 +415,10 @@ #define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_REAL #define SDL_GetRelativeMouseState SDL_GetRelativeMouseState_REAL #define SDL_GetRenderClipRect SDL_GetRenderClipRect_REAL +#define SDL_GetRenderColorScale SDL_GetRenderColorScale_REAL #define SDL_GetRenderDrawBlendMode SDL_GetRenderDrawBlendMode_REAL #define SDL_GetRenderDrawColor SDL_GetRenderDrawColor_REAL +#define SDL_GetRenderDrawColorFloat SDL_GetRenderDrawColorFloat_REAL #define SDL_GetRenderDriver SDL_GetRenderDriver_REAL #define SDL_GetRenderLogicalPresentation SDL_GetRenderLogicalPresentation_REAL #define SDL_GetRenderMetalCommandEncoder SDL_GetRenderMetalCommandEncoder_REAL @@ -316,7 +430,9 @@ #define SDL_GetRenderViewport SDL_GetRenderViewport_REAL #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_GetRendererProperties SDL_GetRendererProperties_REAL #define SDL_GetRevision SDL_GetRevision_REAL #define SDL_GetScancodeFromKey SDL_GetScancodeFromKey_REAL #define SDL_GetScancodeFromName SDL_GetScancodeFromName_REAL @@ -330,26 +446,40 @@ #define SDL_GetSensorInstanceType SDL_GetSensorInstanceType_REAL #define SDL_GetSensorName SDL_GetSensorName_REAL #define SDL_GetSensorNonPortableType SDL_GetSensorNonPortableType_REAL +#define SDL_GetSensorProperties SDL_GetSensorProperties_REAL #define SDL_GetSensorType SDL_GetSensorType_REAL #define SDL_GetSensors SDL_GetSensors_REAL +#define SDL_GetSilenceValueForFormat SDL_GetSilenceValueForFormat_REAL +#define SDL_GetStorageFileSize SDL_GetStorageFileSize_REAL +#define SDL_GetStoragePathInfo SDL_GetStoragePathInfo_REAL +#define SDL_GetStorageSpaceRemaining SDL_GetStorageSpaceRemaining_REAL +#define SDL_GetStringProperty SDL_GetStringProperty_REAL #define SDL_GetSurfaceAlphaMod SDL_GetSurfaceAlphaMod_REAL #define SDL_GetSurfaceBlendMode SDL_GetSurfaceBlendMode_REAL #define SDL_GetSurfaceClipRect SDL_GetSurfaceClipRect_REAL #define SDL_GetSurfaceColorKey SDL_GetSurfaceColorKey_REAL #define SDL_GetSurfaceColorMod SDL_GetSurfaceColorMod_REAL +#define SDL_GetSurfaceColorspace SDL_GetSurfaceColorspace_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_GetTextureAlphaMod SDL_GetTextureAlphaMod_REAL +#define SDL_GetTextureAlphaModFloat SDL_GetTextureAlphaModFloat_REAL #define SDL_GetTextureBlendMode SDL_GetTextureBlendMode_REAL #define SDL_GetTextureColorMod SDL_GetTextureColorMod_REAL +#define SDL_GetTextureColorModFloat SDL_GetTextureColorModFloat_REAL +#define SDL_GetTextureProperties SDL_GetTextureProperties_REAL #define SDL_GetTextureScaleMode SDL_GetTextureScaleMode_REAL #define SDL_GetThreadID SDL_GetThreadID_REAL #define SDL_GetThreadName SDL_GetThreadName_REAL #define SDL_GetTicks SDL_GetTicks_REAL #define SDL_GetTicksNS SDL_GetTicksNS_REAL +#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_GetUserFolder SDL_GetUserFolder_REAL #define SDL_GetVersion SDL_GetVersion_REAL #define SDL_GetVideoDriver SDL_GetVideoDriver_REAL #define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL @@ -357,7 +487,6 @@ #define SDL_GetWindowFlags SDL_GetWindowFlags_REAL #define SDL_GetWindowFromID SDL_GetWindowFromID_REAL #define SDL_GetWindowFullscreenMode SDL_GetWindowFullscreenMode_REAL -#define SDL_GetWindowGrab SDL_GetWindowGrab_REAL #define SDL_GetWindowICCProfile SDL_GetWindowICCProfile_REAL #define SDL_GetWindowID SDL_GetWindowID_REAL #define SDL_GetWindowKeyboardGrab SDL_GetWindowKeyboardGrab_REAL @@ -370,39 +499,13 @@ #define SDL_GetWindowPixelDensity SDL_GetWindowPixelDensity_REAL #define SDL_GetWindowPixelFormat SDL_GetWindowPixelFormat_REAL #define SDL_GetWindowPosition SDL_GetWindowPosition_REAL +#define SDL_GetWindowProperties SDL_GetWindowProperties_REAL #define SDL_GetWindowSize SDL_GetWindowSize_REAL #define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL #define SDL_GetWindowSurface SDL_GetWindowSurface_REAL #define SDL_GetWindowTitle SDL_GetWindowTitle_REAL -#define SDL_GetYUVConversionMode SDL_GetYUVConversionMode_REAL -#define SDL_GetYUVConversionModeForResolution SDL_GetYUVConversionModeForResolution_REAL -#define SDL_HapticClose SDL_HapticClose_REAL -#define SDL_HapticDestroyEffect SDL_HapticDestroyEffect_REAL #define SDL_HapticEffectSupported SDL_HapticEffectSupported_REAL -#define SDL_HapticGetEffectStatus SDL_HapticGetEffectStatus_REAL -#define SDL_HapticIndex SDL_HapticIndex_REAL -#define SDL_HapticName SDL_HapticName_REAL -#define SDL_HapticNewEffect SDL_HapticNewEffect_REAL -#define SDL_HapticNumAxes SDL_HapticNumAxes_REAL -#define SDL_HapticNumEffects SDL_HapticNumEffects_REAL -#define SDL_HapticNumEffectsPlaying SDL_HapticNumEffectsPlaying_REAL -#define SDL_HapticOpen SDL_HapticOpen_REAL -#define SDL_HapticOpenFromJoystick SDL_HapticOpenFromJoystick_REAL -#define SDL_HapticOpenFromMouse SDL_HapticOpenFromMouse_REAL -#define SDL_HapticOpened SDL_HapticOpened_REAL -#define SDL_HapticPause SDL_HapticPause_REAL -#define SDL_HapticQuery SDL_HapticQuery_REAL -#define SDL_HapticRumbleInit SDL_HapticRumbleInit_REAL -#define SDL_HapticRumblePlay SDL_HapticRumblePlay_REAL -#define SDL_HapticRumbleStop SDL_HapticRumbleStop_REAL #define SDL_HapticRumbleSupported SDL_HapticRumbleSupported_REAL -#define SDL_HapticRunEffect SDL_HapticRunEffect_REAL -#define SDL_HapticSetAutocenter SDL_HapticSetAutocenter_REAL -#define SDL_HapticSetGain SDL_HapticSetGain_REAL -#define SDL_HapticStopAll SDL_HapticStopAll_REAL -#define SDL_HapticStopEffect SDL_HapticStopEffect_REAL -#define SDL_HapticUnpause SDL_HapticUnpause_REAL -#define SDL_HapticUpdateEffect SDL_HapticUpdateEffect_REAL #define SDL_HasARMSIMD SDL_HasARMSIMD_REAL #define SDL_HasAVX SDL_HasAVX_REAL #define SDL_HasAVX2 SDL_HasAVX2_REAL @@ -412,11 +515,16 @@ #define SDL_HasClipboardText SDL_HasClipboardText_REAL #define SDL_HasEvent SDL_HasEvent_REAL #define SDL_HasEvents SDL_HasEvents_REAL +#define SDL_HasGamepad SDL_HasGamepad_REAL +#define SDL_HasJoystick SDL_HasJoystick_REAL +#define SDL_HasKeyboard SDL_HasKeyboard_REAL #define SDL_HasLASX SDL_HasLASX_REAL #define SDL_HasLSX SDL_HasLSX_REAL #define SDL_HasMMX SDL_HasMMX_REAL +#define SDL_HasMouse SDL_HasMouse_REAL #define SDL_HasNEON SDL_HasNEON_REAL #define SDL_HasPrimarySelectionText SDL_HasPrimarySelectionText_REAL +#define SDL_HasProperty SDL_HasProperty_REAL #define SDL_HasRectIntersection SDL_HasRectIntersection_REAL #define SDL_HasRectIntersectionFloat SDL_HasRectIntersectionFloat_REAL #define SDL_HasSSE SDL_HasSSE_REAL @@ -425,35 +533,44 @@ #define SDL_HasSSE41 SDL_HasSSE41_REAL #define SDL_HasSSE42 SDL_HasSSE42_REAL #define SDL_HasScreenKeyboardSupport SDL_HasScreenKeyboardSupport_REAL -#define SDL_HasWindowSurface SDL_HasWindowSurface_REAL #define SDL_HideCursor SDL_HideCursor_REAL #define SDL_HideWindow SDL_HideWindow_REAL +#define SDL_IOFromConstMem SDL_IOFromConstMem_REAL +#define SDL_IOFromDynamicMem SDL_IOFromDynamicMem_REAL +#define SDL_IOFromFile SDL_IOFromFile_REAL +#define SDL_IOFromMem SDL_IOFromMem_REAL +#define SDL_IOprintf SDL_IOprintf_REAL +#define SDL_IOvprintf SDL_IOvprintf_REAL #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_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_IsTablet SDL_IsTablet_REAL #define SDL_JoystickConnected SDL_JoystickConnected_REAL #define SDL_JoystickEventsEnabled SDL_JoystickEventsEnabled_REAL -#define SDL_JoystickHasLED SDL_JoystickHasLED_REAL -#define SDL_JoystickHasRumble SDL_JoystickHasRumble_REAL -#define SDL_JoystickHasRumbleTriggers SDL_JoystickHasRumbleTriggers_REAL -#define SDL_JoystickIsHaptic SDL_JoystickIsHaptic_REAL #define SDL_LinuxSetThreadPriority SDL_LinuxSetThreadPriority_REAL #define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_REAL #define SDL_LoadBMP SDL_LoadBMP_REAL -#define SDL_LoadBMP_RW SDL_LoadBMP_RW_REAL +#define SDL_LoadBMP_IO SDL_LoadBMP_IO_REAL #define SDL_LoadFile SDL_LoadFile_REAL -#define SDL_LoadFile_RW SDL_LoadFile_RW_REAL +#define SDL_LoadFile_IO SDL_LoadFile_IO_REAL #define SDL_LoadFunction SDL_LoadFunction_REAL #define SDL_LoadObject SDL_LoadObject_REAL +#define SDL_LoadWAV SDL_LoadWAV_REAL +#define SDL_LoadWAV_IO SDL_LoadWAV_IO_REAL +#define SDL_LockAudioStream SDL_LockAudioStream_REAL #define SDL_LockJoysticks SDL_LockJoysticks_REAL #define SDL_LockMutex SDL_LockMutex_REAL +#define SDL_LockProperties SDL_LockProperties_REAL #define SDL_LockRWLockForReading SDL_LockRWLockForReading_REAL #define SDL_LockRWLockForWriting SDL_LockRWLockForWriting_REAL +#define SDL_LockSpinlock SDL_LockSpinlock_REAL #define SDL_LockSurface SDL_LockSurface_REAL #define SDL_LockTexture SDL_LockTexture_REAL #define SDL_LockTextureToSurface SDL_LockTextureToSurface_REAL @@ -461,14 +578,12 @@ #define SDL_LogCritical SDL_LogCritical_REAL #define SDL_LogDebug SDL_LogDebug_REAL #define SDL_LogError SDL_LogError_REAL -#define SDL_LogGetOutputFunction SDL_LogGetOutputFunction_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_LogSetOutputFunction SDL_LogSetOutputFunction_REAL #define SDL_LogSetPriority SDL_LogSetPriority_REAL #define SDL_LogVerbose SDL_LogVerbose_REAL #define SDL_LogWarn SDL_LogWarn_REAL @@ -481,8 +596,7 @@ #define SDL_Metal_DestroyView SDL_Metal_DestroyView_REAL #define SDL_Metal_GetLayer SDL_Metal_GetLayer_REAL #define SDL_MinimizeWindow SDL_MinimizeWindow_REAL -#define SDL_MouseIsHaptic SDL_MouseIsHaptic_REAL -#define SDL_NumHaptics SDL_NumHaptics_REAL +#define SDL_MixAudioFormat SDL_MixAudioFormat_REAL #define SDL_OnApplicationDidBecomeActive SDL_OnApplicationDidBecomeActive_REAL #define SDL_OnApplicationDidChangeStatusBarOrientation SDL_OnApplicationDidChangeStatusBarOrientation_REAL #define SDL_OnApplicationDidEnterBackground SDL_OnApplicationDidEnterBackground_REAL @@ -490,39 +604,62 @@ #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_OpenFileStorage SDL_OpenFileStorage_REAL #define SDL_OpenGamepad SDL_OpenGamepad_REAL +#define SDL_OpenHaptic SDL_OpenHaptic_REAL +#define SDL_OpenHapticFromJoystick SDL_OpenHapticFromJoystick_REAL +#define SDL_OpenHapticFromMouse SDL_OpenHapticFromMouse_REAL +#define SDL_OpenIO SDL_OpenIO_REAL #define SDL_OpenJoystick SDL_OpenJoystick_REAL #define SDL_OpenSensor SDL_OpenSensor_REAL +#define SDL_OpenStorage SDL_OpenStorage_REAL +#define SDL_OpenTitleStorage SDL_OpenTitleStorage_REAL #define SDL_OpenURL SDL_OpenURL_REAL +#define SDL_OpenUserStorage SDL_OpenUserStorage_REAL +#define SDL_PauseAudioDevice SDL_PauseAudioDevice_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_PremultiplyAlpha SDL_PremultiplyAlpha_REAL #define SDL_PumpEvents SDL_PumpEvents_REAL #define SDL_PushEvent SDL_PushEvent_REAL +#define SDL_PutAudioStreamData SDL_PutAudioStreamData_REAL #define SDL_QueryTexture SDL_QueryTexture_REAL #define SDL_Quit SDL_Quit_REAL #define SDL_QuitSubSystem SDL_QuitSubSystem_REAL -#define SDL_RWFromConstMem SDL_RWFromConstMem_REAL -#define SDL_RWFromFile SDL_RWFromFile_REAL -#define SDL_RWFromMem SDL_RWFromMem_REAL -#define SDL_RWclose SDL_RWclose_REAL -#define SDL_RWread SDL_RWread_REAL -#define SDL_RWseek SDL_RWseek_REAL -#define SDL_RWsize SDL_RWsize_REAL -#define SDL_RWtell SDL_RWtell_REAL -#define SDL_RWwrite SDL_RWwrite_REAL #define SDL_RaiseWindow SDL_RaiseWindow_REAL +#define SDL_ReadIO SDL_ReadIO_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_ReadStorageFile SDL_ReadStorageFile_REAL +#define SDL_ReadSurfacePixel SDL_ReadSurfacePixel_REAL #define SDL_ReadU16BE SDL_ReadU16BE_REAL -#define SDL_ReadU32BE SDL_ReadU32BE_REAL -#define SDL_ReadU64BE SDL_ReadU64BE_REAL #define SDL_ReadU16LE SDL_ReadU16LE_REAL +#define SDL_ReadU32BE SDL_ReadU32BE_REAL #define SDL_ReadU32LE SDL_ReadU32LE_REAL +#define SDL_ReadU64BE SDL_ReadU64BE_REAL #define SDL_ReadU64LE SDL_ReadU64LE_REAL #define SDL_ReadU8 SDL_ReadU8_REAL #define SDL_RegisterApp SDL_RegisterApp_REAL #define SDL_RegisterEvents SDL_RegisterEvents_REAL +#define SDL_ReleaseCameraFrame SDL_ReleaseCameraFrame_REAL +#define SDL_ReloadGamepadMappings SDL_ReloadGamepadMappings_REAL +#define SDL_RemovePath SDL_RemovePath_REAL +#define SDL_RemoveStoragePath SDL_RemoveStoragePath_REAL #define SDL_RemoveTimer SDL_RemoveTimer_REAL +#define SDL_RenamePath SDL_RenamePath_REAL +#define SDL_RenameStoragePath SDL_RenameStoragePath_REAL #define SDL_RenderClear SDL_RenderClear_REAL #define SDL_RenderClipEnabled SDL_RenderClipEnabled_REAL #define SDL_RenderCoordinatesFromWindow SDL_RenderCoordinatesFromWindow_REAL @@ -531,6 +668,7 @@ #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 @@ -541,35 +679,50 @@ #define SDL_RenderRects SDL_RenderRects_REAL #define SDL_RenderTexture SDL_RenderTexture_REAL #define SDL_RenderTextureRotated SDL_RenderTextureRotated_REAL +#define SDL_RenderViewportSet SDL_RenderViewportSet_REAL #define SDL_ReportAssertion SDL_ReportAssertion_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_RestoreWindow SDL_RestoreWindow_REAL +#define SDL_ResumeAudioDevice SDL_ResumeAudioDevice_REAL +#define SDL_ResumeHaptic SDL_ResumeHaptic_REAL #define SDL_RumbleGamepad SDL_RumbleGamepad_REAL #define SDL_RumbleGamepadTriggers SDL_RumbleGamepadTriggers_REAL #define SDL_RumbleJoystick SDL_RumbleJoystick_REAL #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_RW SDL_SaveBMP_RW_REAL +#define SDL_SaveBMP_IO SDL_SaveBMP_IO_REAL #define SDL_ScreenKeyboardShown SDL_ScreenKeyboardShown_REAL #define SDL_ScreenSaverEnabled SDL_ScreenSaverEnabled_REAL +#define SDL_SeekIO SDL_SeekIO_REAL #define SDL_SendGamepadEffect SDL_SendGamepadEffect_REAL #define SDL_SendJoystickEffect SDL_SendJoystickEffect_REAL #define SDL_SetAssertionHandler SDL_SetAssertionHandler_REAL +#define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL +#define SDL_SetAudioStreamFormat SDL_SetAudioStreamFormat_REAL +#define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL +#define SDL_SetAudioStreamGetCallback SDL_SetAudioStreamGetCallback_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_SetCursor SDL_SetCursor_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_SetGamepadEventsEnabled SDL_SetGamepadEventsEnabled_REAL #define SDL_SetGamepadLED SDL_SetGamepadLED_REAL +#define SDL_SetGamepadMapping SDL_SetGamepadMapping_REAL #define SDL_SetGamepadPlayerIndex SDL_SetGamepadPlayerIndex_REAL #define SDL_SetGamepadSensorEnabled SDL_SetGamepadSensorEnabled_REAL +#define SDL_SetHapticAutocenter SDL_SetHapticAutocenter_REAL +#define SDL_SetHapticGain SDL_SetHapticGain_REAL #define SDL_SetHint SDL_SetHint_REAL #define SDL_SetHintWithPriority SDL_SetHintWithPriority_REAL #define SDL_SetJoystickEventsEnabled SDL_SetJoystickEventsEnabled_REAL @@ -578,40 +731,50 @@ #define SDL_SetJoystickVirtualAxis SDL_SetJoystickVirtualAxis_REAL #define SDL_SetJoystickVirtualButton SDL_SetJoystickVirtualButton_REAL #define SDL_SetJoystickVirtualHat SDL_SetJoystickVirtualHat_REAL +#define SDL_SetLogOutputFunction SDL_SetLogOutputFunction_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_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 #define SDL_SetRenderDrawColor SDL_SetRenderDrawColor_REAL +#define SDL_SetRenderDrawColorFloat SDL_SetRenderDrawColorFloat_REAL #define SDL_SetRenderLogicalPresentation SDL_SetRenderLogicalPresentation_REAL #define SDL_SetRenderScale SDL_SetRenderScale_REAL #define SDL_SetRenderTarget SDL_SetRenderTarget_REAL #define SDL_SetRenderVSync SDL_SetRenderVSync_REAL #define SDL_SetRenderViewport SDL_SetRenderViewport_REAL +#define SDL_SetStringProperty SDL_SetStringProperty_REAL #define SDL_SetSurfaceAlphaMod SDL_SetSurfaceAlphaMod_REAL #define SDL_SetSurfaceBlendMode SDL_SetSurfaceBlendMode_REAL #define SDL_SetSurfaceClipRect SDL_SetSurfaceClipRect_REAL #define SDL_SetSurfaceColorKey SDL_SetSurfaceColorKey_REAL #define SDL_SetSurfaceColorMod SDL_SetSurfaceColorMod_REAL +#define SDL_SetSurfaceColorspace SDL_SetSurfaceColorspace_REAL #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_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_SetWindowBordered SDL_SetWindowBordered_REAL +#define SDL_SetWindowFocusable SDL_SetWindowFocusable_REAL #define SDL_SetWindowFullscreen SDL_SetWindowFullscreen_REAL #define SDL_SetWindowFullscreenMode SDL_SetWindowFullscreenMode_REAL -#define SDL_SetWindowGrab SDL_SetWindowGrab_REAL #define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL #define SDL_SetWindowIcon SDL_SetWindowIcon_REAL #define SDL_SetWindowInputFocus SDL_SetWindowInputFocus_REAL @@ -624,35 +787,54 @@ #define SDL_SetWindowOpacity SDL_SetWindowOpacity_REAL #define SDL_SetWindowPosition SDL_SetWindowPosition_REAL #define SDL_SetWindowResizable SDL_SetWindowResizable_REAL +#define SDL_SetWindowShape SDL_SetWindowShape_REAL #define SDL_SetWindowSize SDL_SetWindowSize_REAL #define SDL_SetWindowTitle SDL_SetWindowTitle_REAL #define SDL_SetWindowsMessageHook SDL_SetWindowsMessageHook_REAL -#define SDL_SetYUVConversionMode SDL_SetYUVConversionMode_REAL +#define SDL_SetX11EventHook SDL_SetX11EventHook_REAL #define SDL_ShowCursor SDL_ShowCursor_REAL #define SDL_ShowMessageBox SDL_ShowMessageBox_REAL +#define SDL_ShowOpenFileDialog SDL_ShowOpenFileDialog_REAL +#define SDL_ShowOpenFolderDialog SDL_ShowOpenFolderDialog_REAL +#define SDL_ShowSaveFileDialog SDL_ShowSaveFileDialog_REAL #define SDL_ShowSimpleMessageBox SDL_ShowSimpleMessageBox_REAL #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_StartTextInput SDL_StartTextInput_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_SurfaceHasColorKey SDL_SurfaceHasColorKey_REAL #define SDL_SurfaceHasRLE SDL_SurfaceHasRLE_REAL +#define SDL_SyncWindow SDL_SyncWindow_REAL +#define SDL_TellIO SDL_TellIO_REAL #define SDL_TextInputActive SDL_TextInputActive_REAL -#define SDL_TextInputShown SDL_TextInputShown_REAL -#define SDL_ThreadID SDL_ThreadID_REAL +#define SDL_TimeFromWindows SDL_TimeFromWindows_REAL +#define SDL_TimeToDateTime SDL_TimeToDateTime_REAL +#define SDL_TimeToWindows SDL_TimeToWindows_REAL #define SDL_TryLockMutex SDL_TryLockMutex_REAL #define SDL_TryLockRWLockForReading SDL_TryLockRWLockForReading_REAL #define SDL_TryLockRWLockForWriting SDL_TryLockRWLockForWriting_REAL +#define SDL_TryLockSpinlock SDL_TryLockSpinlock_REAL #define SDL_TryWaitSemaphore SDL_TryWaitSemaphore_REAL +#define SDL_UnbindAudioStream SDL_UnbindAudioStream_REAL +#define SDL_UnbindAudioStreams SDL_UnbindAudioStreams_REAL #define SDL_UnloadObject SDL_UnloadObject_REAL +#define SDL_UnlockAudioStream SDL_UnlockAudioStream_REAL #define SDL_UnlockJoysticks SDL_UnlockJoysticks_REAL #define SDL_UnlockMutex SDL_UnlockMutex_REAL +#define SDL_UnlockProperties SDL_UnlockProperties_REAL #define SDL_UnlockRWLock SDL_UnlockRWLock_REAL +#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_UpdateGamepads SDL_UpdateGamepads_REAL +#define SDL_UpdateHapticEffect SDL_UpdateHapticEffect_REAL #define SDL_UpdateJoysticks SDL_UpdateJoysticks_REAL #define SDL_UpdateNVTexture SDL_UpdateNVTexture_REAL #define SDL_UpdateSensors SDL_UpdateSensors_REAL @@ -678,11 +860,19 @@ #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_WriteIO SDL_WriteIO_REAL +#define SDL_WriteS16BE SDL_WriteS16BE_REAL +#define SDL_WriteS16LE SDL_WriteS16LE_REAL +#define SDL_WriteS32BE SDL_WriteS32BE_REAL +#define SDL_WriteS32LE SDL_WriteS32LE_REAL +#define SDL_WriteS64BE SDL_WriteS64BE_REAL +#define SDL_WriteS64LE SDL_WriteS64LE_REAL #define SDL_WriteU16BE SDL_WriteU16BE_REAL -#define SDL_WriteU32BE SDL_WriteU32BE_REAL -#define SDL_WriteU64BE SDL_WriteU64BE_REAL #define SDL_WriteU16LE SDL_WriteU16LE_REAL +#define SDL_WriteU32BE SDL_WriteU32BE_REAL #define SDL_WriteU32LE SDL_WriteU32LE_REAL +#define SDL_WriteU64BE SDL_WriteU64BE_REAL #define SDL_WriteU64LE SDL_WriteU64LE_REAL #define SDL_WriteU8 SDL_WriteU8_REAL #define SDL_abs SDL_abs_REAL @@ -700,6 +890,7 @@ #define SDL_atof SDL_atof_REAL #define SDL_atoi SDL_atoi_REAL #define SDL_bsearch SDL_bsearch_REAL +#define SDL_bsearch_r SDL_bsearch_r_REAL #define SDL_calloc SDL_calloc_REAL #define SDL_ceil SDL_ceil_REAL #define SDL_ceilf SDL_ceilf_REAL @@ -779,6 +970,7 @@ #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_realloc SDL_realloc_REAL #define SDL_round SDL_round_REAL #define SDL_roundf SDL_roundf_REAL @@ -802,6 +994,9 @@ #define SDL_strlwr SDL_strlwr_REAL #define SDL_strncasecmp SDL_strncasecmp_REAL #define SDL_strncmp SDL_strncmp_REAL +#define SDL_strndup SDL_strndup_REAL +#define SDL_strnlen SDL_strnlen_REAL +#define SDL_strnstr SDL_strnstr_REAL #define SDL_strrchr SDL_strrchr_REAL #define SDL_strrev SDL_strrev_REAL #define SDL_strstr SDL_strstr_REAL @@ -837,153 +1032,7 @@ #define SDL_wcslen SDL_wcslen_REAL #define SDL_wcsncasecmp SDL_wcsncasecmp_REAL #define SDL_wcsncmp SDL_wcsncmp_REAL +#define SDL_wcsnlen SDL_wcsnlen_REAL +#define SDL_wcsnstr SDL_wcsnstr_REAL #define SDL_wcsstr SDL_wcsstr_REAL #define SDL_wcstol SDL_wcstol_REAL - -/* New API symbols are added at the end */ -#define SDL_ClearClipboardData SDL_ClearClipboardData_REAL -#define SDL_GetGamepadInstanceID SDL_GetGamepadInstanceID_REAL -#define SDL_GetGamepadPowerLevel SDL_GetGamepadPowerLevel_REAL -#define SDL_SetGamepadMapping SDL_SetGamepadMapping_REAL -#define SDL_strndup SDL_strndup_REAL -#define SDL_GetGamepadTypeFromString SDL_GetGamepadTypeFromString_REAL -#define SDL_GetGamepadStringForType SDL_GetGamepadStringForType_REAL -#define SDL_GetRealGamepadInstanceType SDL_GetRealGamepadInstanceType_REAL -#define SDL_GetRealGamepadType SDL_GetRealGamepadType_REAL -#define SDL_wcsnlen SDL_wcsnlen_REAL -#define SDL_strnlen SDL_strnlen_REAL -#define SDL_AddGamepadMappingsFromFile SDL_AddGamepadMappingsFromFile_REAL -#define SDL_ReloadGamepadMappings SDL_ReloadGamepadMappings_REAL -#define SDL_GetNumAudioDrivers SDL_GetNumAudioDrivers_REAL -#define SDL_GetAudioDriver SDL_GetAudioDriver_REAL -#define SDL_GetCurrentAudioDriver SDL_GetCurrentAudioDriver_REAL -#define SDL_GetAudioOutputDevices SDL_GetAudioOutputDevices_REAL -#define SDL_GetAudioCaptureDevices SDL_GetAudioCaptureDevices_REAL -#define SDL_GetAudioDeviceName SDL_GetAudioDeviceName_REAL -#define SDL_GetAudioDeviceFormat SDL_GetAudioDeviceFormat_REAL -#define SDL_OpenAudioDevice SDL_OpenAudioDevice_REAL -#define SDL_CloseAudioDevice SDL_CloseAudioDevice_REAL -#define SDL_BindAudioStreams SDL_BindAudioStreams_REAL -#define SDL_BindAudioStream SDL_BindAudioStream_REAL -#define SDL_UnbindAudioStreams SDL_UnbindAudioStreams_REAL -#define SDL_UnbindAudioStream SDL_UnbindAudioStream_REAL -#define SDL_CreateAudioStream SDL_CreateAudioStream_REAL -#define SDL_GetAudioStreamFormat SDL_GetAudioStreamFormat_REAL -#define SDL_SetAudioStreamFormat SDL_SetAudioStreamFormat_REAL -#define SDL_PutAudioStreamData SDL_PutAudioStreamData_REAL -#define SDL_GetAudioStreamData SDL_GetAudioStreamData_REAL -#define SDL_GetAudioStreamAvailable SDL_GetAudioStreamAvailable_REAL -#define SDL_FlushAudioStream SDL_FlushAudioStream_REAL -#define SDL_ClearAudioStream SDL_ClearAudioStream_REAL -#define SDL_LockAudioStream SDL_LockAudioStream_REAL -#define SDL_UnlockAudioStream SDL_UnlockAudioStream_REAL -#define SDL_SetAudioStreamGetCallback SDL_SetAudioStreamGetCallback_REAL -#define SDL_SetAudioStreamPutCallback SDL_SetAudioStreamPutCallback_REAL -#define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL -#define SDL_OpenAudioDeviceStream SDL_OpenAudioDeviceStream_REAL -#define SDL_LoadWAV_RW SDL_LoadWAV_RW_REAL -#define SDL_LoadWAV SDL_LoadWAV_REAL -#define SDL_MixAudioFormat SDL_MixAudioFormat_REAL -#define SDL_ConvertAudioSamples SDL_ConvertAudioSamples_REAL -#define SDL_GetSilenceValueForFormat SDL_GetSilenceValueForFormat_REAL -#define SDL_PauseAudioDevice SDL_PauseAudioDevice_REAL -#define SDL_ResumeAudioDevice SDL_ResumeAudioDevice_REAL -#define SDL_AudioDevicePaused SDL_AudioDevicePaused_REAL -#define SDL_GetAudioStreamDevice SDL_GetAudioStreamDevice_REAL -#define SDL_ShowWindowSystemMenu SDL_ShowWindowSystemMenu_REAL -#define SDL_ReadS16LE SDL_ReadS16LE_REAL -#define SDL_ReadS16BE SDL_ReadS16BE_REAL -#define SDL_ReadS32LE SDL_ReadS32LE_REAL -#define SDL_ReadS32BE SDL_ReadS32BE_REAL -#define SDL_ReadS64LE SDL_ReadS64LE_REAL -#define SDL_ReadS64BE SDL_ReadS64BE_REAL -#define SDL_WriteS16LE SDL_WriteS16LE_REAL -#define SDL_WriteS16BE SDL_WriteS16BE_REAL -#define SDL_WriteS32LE SDL_WriteS32LE_REAL -#define SDL_WriteS32BE SDL_WriteS32BE_REAL -#define SDL_WriteS64LE SDL_WriteS64LE_REAL -#define SDL_WriteS64BE SDL_WriteS64BE_REAL -#define SDL_GDKGetDefaultUser SDL_GDKGetDefaultUser_REAL -#define SDL_SetWindowFocusable SDL_SetWindowFocusable_REAL -#define SDL_GetAudioStreamFrequencyRatio SDL_GetAudioStreamFrequencyRatio_REAL -#define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL -#define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL -#define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL -#define SDL_CreateProperties SDL_CreateProperties_REAL -#define SDL_LockProperties SDL_LockProperties_REAL -#define SDL_UnlockProperties SDL_UnlockProperties_REAL -#define SDL_SetProperty SDL_SetProperty_REAL -#define SDL_GetProperty SDL_GetProperty_REAL -#define SDL_DestroyProperties SDL_DestroyProperties_REAL -#define SDL_GetAudioStreamProperties SDL_GetAudioStreamProperties_REAL -#define SDL_GetGamepadProperties SDL_GetGamepadProperties_REAL -#define SDL_GetJoystickProperties SDL_GetJoystickProperties_REAL -#define SDL_GetRendererProperties SDL_GetRendererProperties_REAL -#define SDL_GetTextureProperties SDL_GetTextureProperties_REAL -#define SDL_GetRWProperties SDL_GetRWProperties_REAL -#define SDL_GetSensorProperties SDL_GetSensorProperties_REAL -#define SDL_GetSurfaceProperties SDL_GetSurfaceProperties_REAL -#define SDL_GetWindowProperties SDL_GetWindowProperties_REAL -#define SDL_ClearProperty SDL_ClearProperty_REAL -#define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL -#define SDL_RWprintf SDL_RWprintf_REAL -#define SDL_RWvprintf SDL_RWvprintf_REAL -#define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL -#define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL -#define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL -#define SDL_SetX11EventHook SDL_SetX11EventHook_REAL -#define SDL_GetGlobalProperties SDL_GetGlobalProperties_REAL -#define SDL_OpenVideoCapture SDL_OpenVideoCapture_REAL -#define SDL_SetVideoCaptureSpec SDL_SetVideoCaptureSpec_REAL -#define SDL_OpenVideoCaptureWithSpec SDL_OpenVideoCaptureWithSpec_REAL -#define SDL_GetVideoCaptureDeviceName SDL_GetVideoCaptureDeviceName_REAL -#define SDL_GetVideoCaptureSpec SDL_GetVideoCaptureSpec_REAL -#define SDL_GetVideoCaptureFormat SDL_GetVideoCaptureFormat_REAL -#define SDL_GetNumVideoCaptureFormats SDL_GetNumVideoCaptureFormats_REAL -#define SDL_GetVideoCaptureFrameSize SDL_GetVideoCaptureFrameSize_REAL -#define SDL_GetNumVideoCaptureFrameSizes SDL_GetNumVideoCaptureFrameSizes_REAL -#define SDL_GetVideoCaptureStatus SDL_GetVideoCaptureStatus_REAL -#define SDL_StartVideoCapture SDL_StartVideoCapture_REAL -#define SDL_AcquireVideoCaptureFrame SDL_AcquireVideoCaptureFrame_REAL -#define SDL_ReleaseVideoCaptureFrame SDL_ReleaseVideoCaptureFrame_REAL -#define SDL_StopVideoCapture SDL_StopVideoCapture_REAL -#define SDL_CloseVideoCapture SDL_CloseVideoCapture_REAL -#define SDL_GetVideoCaptureDevices SDL_GetVideoCaptureDevices_REAL -#define SDL_GetGamepadButtonLabelForType SDL_GetGamepadButtonLabelForType_REAL -#define SDL_GetGamepadButtonLabel SDL_GetGamepadButtonLabel_REAL -#define SDL_GetPens SDL_GetPens_REAL -#define SDL_GetPenStatus SDL_GetPenStatus_REAL -#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL -#define SDL_GetPenGUID SDL_GetPenGUID_REAL -#define SDL_PenConnected SDL_PenConnected_REAL -#define SDL_GetPenName SDL_GetPenName_REAL -#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL -#define SDL_GetPenType SDL_GetPenType_REAL -#define SDL_GetPens SDL_GetPens_REAL -#define SDL_GetPenStatus SDL_GetPenStatus_REAL -#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL -#define SDL_GetPenGUID SDL_GetPenGUID_REAL -#define SDL_PenConnected SDL_PenConnected_REAL -#define SDL_GetPenName SDL_GetPenName_REAL -#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL -#define SDL_GetPenType SDL_GetPenType_REAL -#define SDL_SetStringProperty SDL_SetStringProperty_REAL -#define SDL_SetNumberProperty SDL_SetNumberProperty_REAL -#define SDL_SetFloatProperty SDL_SetFloatProperty_REAL -#define SDL_GetPropertyType SDL_GetPropertyType_REAL -#define SDL_GetStringProperty SDL_GetStringProperty_REAL -#define SDL_GetNumberProperty SDL_GetNumberProperty_REAL -#define SDL_GetFloatProperty SDL_GetFloatProperty_REAL -#define SDL_EnumerateProperties SDL_EnumerateProperties_REAL -#define SDL_SetBooleanProperty SDL_SetBooleanProperty_REAL -#define SDL_GetBooleanProperty SDL_GetBooleanProperty_REAL -#define SDL_CreateTextureWithProperties SDL_CreateTextureWithProperties_REAL -#define SDL_CreateRendererWithProperties SDL_CreateRendererWithProperties_REAL -#define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL -#define SDL_GetTouchDevices SDL_GetTouchDevices_REAL -#define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL -#define SDL_strnstr SDL_strnstr_REAL -#define SDL_wcsnstr SDL_wcsnstr_REAL -#define SDL_SyncWindow SDL_SyncWindow_REAL -#define SDL_GetGamepadSteamHandle SDL_GetGamepadSteamHandle_REAL -#define SDL_GetRendererFromTexture SDL_GetRendererFromTexture_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 42245686..5218b1cb 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -30,6 +30,7 @@ /* 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),) SDL_DYNAPI_PROC(void,SDL_LogCritical,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) SDL_DYNAPI_PROC(void,SDL_LogDebug,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) @@ -41,16 +42,15 @@ SDL_DYNAPI_PROC(void,SDL_LogWarn,(int a, SDL_PRINTF_FORMAT_STRING const char *b, SDL_DYNAPI_PROC(int,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_swprintf,(SDL_OUT_Z_CAP(b) wchar_t *a, size_t b, SDL_PRINTF_FORMAT_STRING const wchar_t *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(size_t,SDL_RWprintf,(SDL_RWops *a, SDL_PRINTF_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(__WIN32__) || defined(__GDK__) +#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) @@ -60,64 +60,43 @@ SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThread,(SDL_ThreadFunction a, const char * #undef SDL_CreateThreadWithStackSize #endif -#if defined(__WIN32__) || defined(__GDK__) +#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 -SDL_DYNAPI_PROC(int,SDL_RegisterApp,(const char *a, Uint32 b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(void,SDL_SetWindowsMessageHook,(SDL_WindowsMessageHook a, void *b),(a,b),) -SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) - -SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(SDL_DisplayID a, int *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_Direct3D9GetAdapterIndex,(SDL_DisplayID a),(a),return) - -SDL_DYNAPI_PROC(int,SDL_GDKGetTaskQueue,(XTaskQueueHandle *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),) - -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(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(void,SDL_OnApplicationDidChangeStatusBarOrientation,(void),(),) -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),) - +/* 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(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(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(SDL_bool,SDL_AndroidRequestPermission,(const char *a),(a),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_GetAndroidSDKVersion,(void),(),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(int,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_AddGamepadMappingsFromRW,(SDL_RWops *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(SDL_TimerID,SDL_AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_AtomicAdd,(SDL_AtomicInt *a, int b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_AtomicCAS,(SDL_AtomicInt *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_AtomicCASPtr,(void **a, void *b, void *c),(a,b,c),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(void,SDL_AtomicLock,(SDL_SpinLock *a),(a),) 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_bool,SDL_AtomicTryLock,(SDL_SpinLock *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_AtomicUnlock,(SDL_SpinLock *a),(a),) 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) @@ -125,49 +104,70 @@ SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const SDL_Re 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(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(void,SDL_ClearHints,(void),(),) +SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),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(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(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, Uint32 c, const void *d, int e, Uint32 f, void *g, int h),(a,b,c,d,e,f,g,h),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, Uint32 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(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(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,(Uint32 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_RWops*,SDL_CreateRW,(void),(),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_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(SDL_Surface*,SDL_CreateSurface,(int a, int b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurfaceFrom,(void *a, int b, int c, int d, Uint32 e),(a,b,c,d,e),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(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, Uint32 b, int c, int d, int e),(a,b,c,d,e),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_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_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(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_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_DestroyRW,(SDL_RWops *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),) SDL_DYNAPI_PROC(void,SDL_DestroySemaphore,(SDL_Semaphore *a),(a),) @@ -177,6 +177,7 @@ SDL_DYNAPI_PROC(void,SDL_DestroyWindow,(SDL_Window *a),(a),) SDL_DYNAPI_PROC(int,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(SDL_Surface*,SDL_DuplicateSurface,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(SDL_EGLConfig,SDL_EGL_GetCurrentEGLConfig,(void),(),return) @@ -185,15 +186,24 @@ SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_EGL_GetProcAddress,(const char *a),(a),r 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(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(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(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(void,SDL_GDKSuspendComplete,(void),(),) 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) @@ -215,24 +225,51 @@ 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_GamepadHasLED,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadHasRumble,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadHasRumbleTriggers,(SDL_Gamepad *a),(a),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(int,SDL_GetAndroidSDKVersion,(void),(),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(const char*,SDL_GetAudioDriver,(int a),(a),return) +SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(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(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a),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(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(int,SDL_GetCameraPermissionState,(SDL_Camera *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetCameraProperties,(SDL_Camera *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetClipboardData,(const char *a, size_t *b),(a,b),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(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(SDL_ThreadID,SDL_GetCurrentThreadID,(void),(),return) +SDL_DYNAPI_PROC(int,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(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) @@ -242,10 +279,12 @@ SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetDisplayForPoint,(const SDL_Point *a),(a),re 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(SDL_DisplayID*,SDL_GetDisplays,(int *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(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(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) @@ -254,10 +293,13 @@ SDL_DYNAPI_PROC(SDL_GamepadAxis,SDL_GetGamepadAxisFromString,(const char *a),(a) 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_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(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_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) @@ -269,26 +311,44 @@ SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceVendor,(SDL_JoystickID a),(a),retur 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(const char*,SDL_GetGamepadName,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadPath,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetGamepadPlayerIndex,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_GetGamepadPowerLevel,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadProduct,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadProductVersion,(SDL_Gamepad *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(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(SDL_GamepadType,SDL_GetGamepadType,(SDL_Gamepad *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(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_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(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(const char*,SDL_GetHapticName,(SDL_Haptic *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(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(Uint16,SDL_GetJoystickFirmwareVersion,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetJoystickFromInstanceID,(SDL_JoystickID a),(a),return) @@ -313,6 +373,7 @@ SDL_DYNAPI_PROC(int,SDL_GetJoystickPlayerIndex,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_GetJoystickPowerLevel,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProduct,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProductVersion,(SDL_Joystick *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(Uint16,SDL_GetJoystickVendor,(SDL_Joystick *a),(a),return) @@ -321,36 +382,59 @@ 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(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_bool,SDL_GetMasksForPixelFormatEnum,(Uint32 a, int *b, Uint32 *c, Uint32 *d, Uint32 *e, Uint32 *f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(SDL_MouseID*,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(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(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_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) 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_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(char*,SDL_GetUserFolder,(SDL_Folder a),(a),return) +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(Uint64,SDL_GetPerformanceCounter,(void),(),return) SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceFrequency,(void),(),return) -SDL_DYNAPI_PROC(Uint32,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,(Uint32 a),(a),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 char*,SDL_GetPlatform,(void),(),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_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_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(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) @@ -362,8 +446,10 @@ SDL_DYNAPI_PROC(int,SDL_GetRectUnionFloat,(const SDL_FRect *a, const SDL_FRect * 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(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(void*,SDL_GetRenderMetalCommandEncoder,(SDL_Renderer *a),(a),return) @@ -375,7 +461,9 @@ 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(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(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(SDL_Scancode,SDL_GetScancodeFromName,(const char *a),(a),return) @@ -389,34 +477,47 @@ SDL_DYNAPI_PROC(int,SDL_GetSensorInstanceNonPortableType,(SDL_SensorID a),(a),re SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorInstanceType,(SDL_SensorID a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetSensorName,(SDL_Sensor *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetSensorNonPortableType,(SDL_Sensor *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_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(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(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(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(SDL_threadID,SDL_GetThreadID,(SDL_Thread *a),(a),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) 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(int,SDL_GetVersion,(SDL_version *a),(a),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(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(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(const SDL_DisplayMode*,SDL_GetWindowFullscreenMode,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetWindowGrab,(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) @@ -429,39 +530,13 @@ 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_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(SDL_Surface*,SDL_GetWindowSurface,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetWindowTitle,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionMode,(void),(),return) -SDL_DYNAPI_PROC(SDL_YUV_CONVERSION_MODE,SDL_GetYUVConversionModeForResolution,(int a, int b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_HapticClose,(SDL_Haptic *a),(a),) -SDL_DYNAPI_PROC(void,SDL_HapticDestroyEffect,(SDL_Haptic *a, int b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_HapticEffectSupported,(SDL_Haptic *a, SDL_HapticEffect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_HapticGetEffectStatus,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_HapticIndex,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_HapticName,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticNewEffect,(SDL_Haptic *a, SDL_HapticEffect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_HapticNumAxes,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticNumEffects,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticNumEffectsPlaying,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(SDL_Haptic*,SDL_HapticOpen,(int a),(a),return) -SDL_DYNAPI_PROC(SDL_Haptic*,SDL_HapticOpenFromJoystick,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_Haptic*,SDL_HapticOpenFromMouse,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_HapticOpened,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticPause,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(unsigned int,SDL_HapticQuery,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticRumbleInit,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticRumblePlay,(SDL_Haptic *a, float b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_HapticRumbleStop,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticRumbleSupported,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticRunEffect,(SDL_Haptic *a, int b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_HapticSetAutocenter,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_HapticSetGain,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_HapticStopAll,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticStopEffect,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_HapticUnpause,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_HapticUpdateEffect,(SDL_Haptic *a, int b, SDL_HapticEffect *c),(a,b,c),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) @@ -471,11 +546,16 @@ 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) @@ -484,39 +564,50 @@ 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(SDL_bool,SDL_HasWindowSurface,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_HideCursor,(void),(),return) SDL_DYNAPI_PROC(int,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(SDL_bool,SDL_JoystickHasLED,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickHasRumble,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickHasRumbleTriggers,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_JoystickIsHaptic,(SDL_Joystick *a),(a),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(SDL_Surface*,SDL_LoadBMP,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP_RW,(SDL_RWops *a, SDL_bool b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP_IO,(SDL_IOStream *a, SDL_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_RW,(SDL_RWops *a, size_t *b, SDL_bool c),(a,b,c),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_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(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(void,SDL_LogGetOutputFunction,(SDL_LogOutputFunction *a, void **b),(a,b),) SDL_DYNAPI_PROC(SDL_LogPriority,SDL_LogGetPriority,(int a),(a),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_LogSetOutputFunction,(SDL_LogOutputFunction a, void *b),(a,b),) 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) @@ -527,46 +618,69 @@ 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_MouseIsHaptic,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_NumHaptics,(void),(),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(void,SDL_OnApplicationDidChangeStatusBarOrientation,(void),(),) SDL_DYNAPI_PROC(void,SDL_OnApplicationDidEnterBackground,(void),(),) SDL_DYNAPI_PROC(void,SDL_OnApplicationDidReceiveMemoryWarning,(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_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) +SDL_DYNAPI_PROC(SDL_Haptic*,SDL_OpenHapticFromJoystick,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(SDL_Haptic*,SDL_OpenHapticFromMouse,(void),(),return) +SDL_DYNAPI_PROC(SDL_IOStream*,SDL_OpenIO,(const SDL_IOStreamInterface *a, void *b),(a,b),return) 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(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, Uint32 c, const void *d, int e, Uint32 f, void *g, int h),(a,b,c,d,e,f,g,h),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(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, Uint32 *b, int *c, int *d, int *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void,SDL_Quit,(void),(),) SDL_DYNAPI_PROC(void,SDL_QuitSubSystem,(Uint32 a),(a),) -SDL_DYNAPI_PROC(SDL_RWops*,SDL_RWFromConstMem,(const void *a, size_t b),(a,b),return) -SDL_DYNAPI_PROC(SDL_RWops*,SDL_RWFromFile,(const char *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_RWops*,SDL_RWFromMem,(void *a, size_t b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_RWclose,(SDL_RWops *a),(a),return) -SDL_DYNAPI_PROC(size_t,SDL_RWread,(SDL_RWops *a, void *b, size_t c),(a,b,c),return) -SDL_DYNAPI_PROC(Sint64,SDL_RWseek,(SDL_RWops *a, Sint64 b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(Sint64,SDL_RWsize,(SDL_RWops *a),(a),return) -SDL_DYNAPI_PROC(Sint64,SDL_RWtell,(SDL_RWops *a),(a),return) -SDL_DYNAPI_PROC(size_t,SDL_RWwrite,(SDL_RWops *a, const void *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_RaiseWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16BE,(SDL_RWops *a, Uint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32BE,(SDL_RWops *a, Uint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64BE,(SDL_RWops *a, Uint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16LE,(SDL_RWops *a, Uint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32LE,(SDL_RWops *a, Uint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64LE,(SDL_RWops *a, Uint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU8,(SDL_RWops *a, Uint8 *b),(a,b),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(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) @@ -575,44 +689,60 @@ SDL_DYNAPI_PROC(int,SDL_RenderFillRect,(SDL_Renderer *a, const SDL_FRect *b),(a, 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(int,SDL_RenderReadPixels,(SDL_Renderer *a, const SDL_Rect *b, Uint32 c, void *d, int e),(a,b,c,d,e),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_RendererFlip g),(a,b,c,d,e,f,g),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(SDL_AssertState,SDL_ReportAssertion,(SDL_AssertData *a, const char *b, const char *c, int d),(a,b,c,d),return) SDL_DYNAPI_PROC(void,SDL_ResetAssertionReport,(void),(),) SDL_DYNAPI_PROC(SDL_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(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_RW,(SDL_Surface *a, SDL_RWops *b, SDL_bool c),(a,b,c),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(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(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),) @@ -621,40 +751,50 @@ SDL_DYNAPI_PROC(int,SDL_SetJoystickPlayerIndex,(SDL_Joystick *a, int b),(a,b),re 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(void,SDL_SetLogOutputFunction,(SDL_LogOutputFunction a, void *b),(a,b),) 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(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_SetWindowGrab,(SDL_Window *a, SDL_bool 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) @@ -667,33 +807,54 @@ SDL_DYNAPI_PROC(int,SDL_SetWindowMouseRect,(SDL_Window *a, const SDL_Rect *b),(a 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(void,SDL_SetYUVConversionMode,(SDL_YUV_CONVERSION_MODE a),(a),) +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(Sint64,SDL_TellIO,(SDL_IOStream *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_TextInputActive,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_TextInputShown,(void),(),return) -SDL_DYNAPI_PROC(SDL_threadID,SDL_ThreadID,(void),(),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(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(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_UnlockJoysticks,(void),(),) SDL_DYNAPI_PROC(void,SDL_UnlockMutex,(SDL_Mutex *a),(a),) +SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) 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_UnregisterApp,(void),(),) 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(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(void,SDL_UpdateSensors,(void),(),) @@ -716,13 +877,24 @@ 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(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_bool,SDL_WriteU16BE,(SDL_RWops *a, Uint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32BE,(SDL_RWops *a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64BE,(SDL_RWops *a, Uint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16LE,(SDL_RWops *a, Uint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32LE,(SDL_RWops *a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64LE,(SDL_RWops *a, Uint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU8,(SDL_RWops *a, Uint8 b),(a,b),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(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(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) @@ -737,6 +909,7 @@ 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_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) @@ -778,6 +951,8 @@ 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) @@ -814,6 +989,7 @@ SDL_DYNAPI_PROC(float,SDL_modff,(float a, float *b),(a,b),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_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) @@ -835,6 +1011,9 @@ SDL_DYNAPI_PROC(size_t,SDL_strlen,(const char *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_strlwr,(char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_strncasecmp,(const char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_strncmp,(const char *a, const char *b, size_t c),(a,b,c),return) +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_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) @@ -869,146 +1048,7 @@ SDL_DYNAPI_PROC(size_t,SDL_wcslcpy,(SDL_OUT_Z_CAP(c) wchar_t *a, const wchar_t * SDL_DYNAPI_PROC(size_t,SDL_wcslen,(const wchar_t *a),(a),return) SDL_DYNAPI_PROC(int,SDL_wcsncasecmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) +SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *a, size_t b),(a,b),return) +SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return) SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return) - -/* New API symbols are added at the end */ -SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return) -SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetGamepadInstanceID,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_GetGamepadPowerLevel,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetGamepadMapping,(SDL_JoystickID a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(char*,SDL_strndup,(const char *a, size_t b),(a,b),return) -SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadTypeFromString,(const char *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetGamepadStringForType,(SDL_GamepadType a),(a),return) -SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadInstanceType,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadType,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *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(int,SDL_AddGamepadMappingsFromFile,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ReloadGamepadMappings,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetNumAudioDrivers,(void),(),return) -SDL_DYNAPI_PROC(const char*,SDL_GetAudioDriver,(int a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetCurrentAudioDriver,(void),(),return) -SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return) -SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return) -SDL_DYNAPI_PROC(char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_OpenAudioDevice,(SDL_AudioDeviceID a, const SDL_AudioSpec *b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_CloseAudioDevice,(SDL_AudioDeviceID a),(a),) -SDL_DYNAPI_PROC(int,SDL_BindAudioStreams,(SDL_AudioDeviceID a, SDL_AudioStream **b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_BindAudioStream,(SDL_AudioDeviceID a, SDL_AudioStream *b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_UnbindAudioStreams,(SDL_AudioStream **a, int b),(a,b),) -SDL_DYNAPI_PROC(void,SDL_UnbindAudioStream,(SDL_AudioStream *a),(a),) -SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_CreateAudioStream,(const SDL_AudioSpec *a, const SDL_AudioSpec *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioSpec *b, SDL_AudioSpec *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_PutAudioStreamData,(SDL_AudioStream *a, const void *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioStreamData,(SDL_AudioStream *a, void *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_FlushAudioStream,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_LockAudioStream,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_UnlockAudioStream,(SDL_AudioStream *a),(a),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(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),) -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(int,SDL_LoadWAV_RW,(SDL_RWops *a, SDL_bool b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),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_MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),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_GetSilenceValueForFormat,(SDL_AudioFormat a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PauseAudioDevice,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ResumeAudioDevice,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_AudioDevicePaused,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetAudioStreamDevice,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ShowWindowSystemMenu,(SDL_Window *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16LE,(SDL_RWops *a, Sint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16BE,(SDL_RWops *a, Sint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32LE,(SDL_RWops *a, Sint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32BE,(SDL_RWops *a, Sint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64LE,(SDL_RWops *a, Sint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64BE,(SDL_RWops *a, Sint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16LE,(SDL_RWops *a, Sint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16BE,(SDL_RWops *a, Sint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32LE,(SDL_RWops *a, Sint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32BE,(SDL_RWops *a, Sint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64LE,(SDL_RWops *a, Sint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64BE,(SDL_RWops *a, Sint64 b),(a,b),return) - -SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return) - -SDL_DYNAPI_PROC(int,SDL_SetWindowFocusable,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return) -SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) -SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGamepadProperties,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetJoystickProperties,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRendererProperties,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetTextureProperties,(SDL_Texture *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRWProperties,(SDL_RWops *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSensorProperties,(SDL_Sensor *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) -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(size_t,SDL_RWvprintf,(SDL_RWops *a, SDL_PRINTF_FORMAT_STRING const char *b, va_list c),(a,b,c),return) -SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),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(void,SDL_SetX11EventHook,(SDL_X11EventHook a, void *b),(a,b),) -SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGlobalProperties,(void),(),return) -SDL_DYNAPI_PROC(SDL_VideoCaptureDevice*,SDL_OpenVideoCapture,(SDL_VideoCaptureDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetVideoCaptureSpec,(SDL_VideoCaptureDevice *a, const SDL_VideoCaptureSpec *b, SDL_VideoCaptureSpec *c, int d),(a,b,c,d),return) -SDL_DYNAPI_PROC(SDL_VideoCaptureDevice*,SDL_OpenVideoCaptureWithSpec,(SDL_VideoCaptureDeviceID a, const SDL_VideoCaptureSpec *b, SDL_VideoCaptureSpec *c, int d),(a,b,c,d),return) -SDL_DYNAPI_PROC(const char*,SDL_GetVideoCaptureDeviceName,(SDL_VideoCaptureDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureSpec,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureSpec *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureFormat,(SDL_VideoCaptureDevice *a, int b, Uint32 *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetNumVideoCaptureFormats,(SDL_VideoCaptureDevice *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureFrameSize,(SDL_VideoCaptureDevice *a, Uint32 b, int c, int *d, int *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_GetNumVideoCaptureFrameSizes,(SDL_VideoCaptureDevice *a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_VideoCaptureStatus,SDL_GetVideoCaptureStatus,(SDL_VideoCaptureDevice *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_StartVideoCapture,(SDL_VideoCaptureDevice *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_AcquireVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureFrame *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_ReleaseVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureFrame *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_StopVideoCapture,(SDL_VideoCaptureDevice *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_CloseVideoCapture,(SDL_VideoCaptureDevice *a),(a),) -SDL_DYNAPI_PROC(SDL_VideoCaptureDeviceID*,SDL_GetVideoCaptureDevices,(int *a),(a),return) -SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabelForType,(SDL_GamepadType a, SDL_GamepadButton b),(a,b),return) -SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabel,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) -SDL_DYNAPI_PROC(SDL_PenID*,SDL_GetPens,(int *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_PenID,SDL_GetPenFromGUID,(SDL_GUID a),(a),return) -SDL_DYNAPI_PROC(SDL_GUID,SDL_GetPenGUID,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),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_SetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_PropertyType,SDL_GetPropertyType,(SDL_PropertiesID a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(const char*,SDL_GetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return) -SDL_DYNAPI_PROC(Sint64,SDL_GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) -SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float 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_SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureWithProperties,(SDL_Renderer *a, SDL_PropertiesID b),(a,b),return) -SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID a),(a),return) -SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return) -SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) -SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return) -SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetRendererFromTexture,(SDL_Texture *a),(a),return) diff --git a/src/dynapi/SDL_dynapi_unsupported.h b/src/dynapi/SDL_dynapi_unsupported.h index 5bad9e5a..af6cd5f3 100644 --- a/src/dynapi/SDL_dynapi_unsupported.h +++ b/src/dynapi/SDL_dynapi_unsupported.h @@ -23,26 +23,30 @@ #define SDL_dynapi_unsupported_h_ -#if !(defined(__WIN32__) || defined(__GDK__)) +#if !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) typedef struct ID3D12Device ID3D12Device; typedef void *SDL_WindowsMessageHook; #endif -#if !(defined(__WIN32__) || defined(__WINGDK__)) +#if !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)) typedef struct ID3D11Device ID3D11Device; typedef struct IDirect3DDevice9 IDirect3DDevice9; #endif -#ifndef __GDK__ +#ifndef SDL_PLATFORM_GDK typedef struct XTaskQueueHandle XTaskQueueHandle; #endif -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT typedef int SDL_WinRT_DeviceFamily; typedef int SDL_WinRT_Path; #endif -#ifndef __GDK__ +#ifndef SDL_PLATFORM_GDK typedef struct XUserHandle XUserHandle; #endif +#ifndef SDL_PLATFORM_ANDROID +typedef void *SDL_AndroidRequestPermissionCallback; +#endif + #endif diff --git a/src/dynapi/gendynapi.py b/src/dynapi/gendynapi.py index 6f78afc5..08b2c1dc 100755 --- a/src/dynapi/gendynapi.py +++ b/src/dynapi/gendynapi.py @@ -25,7 +25,7 @@ # It keeps the dynamic API jump table operating correctly. # # OS-specific API: -# After running the script, you have to manually add #ifdef __WIN32__ +# After running the script, you have to manually add #ifdef SDL_PLATFORM_WIN32 # or similar around the function in 'SDL_dynapi_procs.h' # diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 2a346f03..93af8aa1 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -25,6 +25,7 @@ #include "SDL_events_c.h" #include "../SDL_hints_c.h" #include "../audio/SDL_audio_c.h" +#include "../camera/SDL_camera_c.h" #include "../timer/SDL_timer_c.h" #ifndef SDL_JOYSTICK_DISABLED #include "../joystick/SDL_joystick_c.h" @@ -35,7 +36,7 @@ #include "../video/SDL_sysvideo.h" #undef SDL_PRIs64 -#if (defined(__WIN32__) || defined(__GDK__)) && !defined(__CYGWIN__) +#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && !defined(SDL_PLATFORM_CYGWIN) #define SDL_PRIs64 "I64d" #else #define SDL_PRIs64 "lld" @@ -44,8 +45,14 @@ /* An arbitrary limit so we don't have unbounded growth */ #define SDL_MAX_QUEUED_EVENTS 65535 -/* Determines how often we wake to call SDL_PumpEvents() in SDL_WaitEventTimeout_Device() */ -#define PERIODIC_POLL_INTERVAL_NS (3 * SDL_NS_PER_SECOND) +/* 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 */ +#define EVENT_POLL_INTERVAL_NS SDL_MS_TO_NS(1) + +/* 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 { @@ -282,6 +289,7 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED); 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) \ @@ -317,9 +325,18 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED); #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) + SDL_EVENT_CASE(SDL_EVENT_KEYBOARD_ADDED) + PRINT_KEYDEV_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_KEYBOARD_REMOVED) + PRINT_KEYDEV_EVENT(event); + break; +#undef PRINT_KEYDEV_EVENT + #define PRINT_KEY_EVENT(event) \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \ - (uint)event->key.timestamp, (uint)event->key.windowID, \ + (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, \ @@ -343,6 +360,15 @@ static void SDL_LogEvent(const SDL_Event *event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s')", (uint)event->text.timestamp, (uint)event->text.windowID, event->text.text); break; +#define PRINT_MOUSEDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->mdevice.timestamp, (uint)event->mdevice.which) + SDL_EVENT_CASE(SDL_EVENT_MOUSE_ADDED) + PRINT_MOUSEDEV_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_MOUSE_REMOVED) + PRINT_MOUSEDEV_EVENT(event); + break; +#undef PRINT_MOUSEDEV_EVENT + SDL_EVENT_CASE(SDL_EVENT_MOUSE_MOTION) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%u x=%g y=%g xrel=%g yrel=%g)", (uint)event->motion.timestamp, (uint)event->motion.windowID, @@ -378,6 +404,12 @@ static void SDL_LogEvent(const SDL_Event *event) (uint)event->jaxis.axis, (int)event->jaxis.value); break; + SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BALL_MOTION) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d ball=%u xrel=%d yrel=%d)", + (uint)event->jball.timestamp, (int)event->jball.which, + (uint)event->jball.ball, (int)event->jball.xrel, (int)event->jball.yrel); + break; + SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_HAT_MOTION) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d hat=%u value=%u)", (uint)event->jhat.timestamp, (int)event->jhat.which, @@ -461,9 +493,9 @@ static void SDL_LogEvent(const SDL_Event *event) break; #define PRINT_FINGER_EVENT(event) \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u touchid=%" SDL_PRIs64 " fingerid=%" SDL_PRIs64 " x=%f y=%f dx=%f dy=%f pressure=%f)", \ - (uint)event->tfinger.timestamp, (long long)event->tfinger.touchId, \ - (long long)event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u touchid=%" SDL_PRIu64 " fingerid=%" SDL_PRIu64 " x=%f y=%f dx=%f dy=%f pressure=%f)", \ + (uint)event->tfinger.timestamp, event->tfinger.touchID, \ + event->tfinger.fingerID, event->tfinger.x, event->tfinger.y, \ event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure) SDL_EVENT_CASE(SDL_EVENT_FINGER_DOWN) PRINT_FINGER_EVENT(event); @@ -553,6 +585,21 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_AUDIODEV_EVENT +#define PRINT_CAMERADEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->cdevice.timestamp, (uint)event->cdevice.which) + SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_ADDED) + PRINT_CAMERADEV_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_REMOVED) + PRINT_CAMERADEV_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_APPROVED) + PRINT_CAMERADEV_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_DENIED) + PRINT_CAMERADEV_EVENT(event); + break; +#undef PRINT_CAMERADEV_EVENT + SDL_EVENT_CASE(SDL_EVENT_SENSOR_UPDATE) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d data[0]=%f data[1]=%f data[2]=%f data[3]=%f data[4]=%f data[5]=%f)", (uint)event->sensor.timestamp, (int)event->sensor.which, @@ -682,14 +729,6 @@ int SDL_StartEventLoop(void) } #endif /* !SDL_THREADS_DISABLED */ - /* Process most event types */ - SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, SDL_FALSE); - SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, SDL_FALSE); -#if 0 /* Leave these events enabled so apps can respond to items being dragged onto them at startup */ - SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_FALSE); - SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, SDL_FALSE); -#endif - SDL_EventQ.active = SDL_TRUE; SDL_UnlockMutex(SDL_EventQ.lock); return 0; @@ -941,6 +980,10 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) SDL_UpdateAudio(); #endif +#ifndef SDL_CAMERA_DISABLED + SDL_UpdateCamera(); +#endif + #ifndef SDL_SENSOR_DISABLED /* Check for sensor state change */ if (SDL_update_sensors) { @@ -983,21 +1026,36 @@ SDL_bool SDL_PollEvent(SDL_Event *event) return SDL_WaitEventTimeoutNS(event, 0); } -static SDL_bool SDL_events_need_periodic_poll(void) +static Sint64 SDL_events_get_polling_interval(void) { - SDL_bool need_periodic_poll = SDL_FALSE; + Sint64 poll_intervalNS = SDL_MAX_SINT64; #ifndef SDL_JOYSTICK_DISABLED - need_periodic_poll = SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks; + if (SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks) { + if (SDL_JoysticksOpened()) { + /* 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 */ + poll_intervalNS = SDL_min(poll_intervalNS, ENUMERATION_POLL_INTERVAL_NS); + } + } #endif - return need_periodic_poll; +#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 */ + poll_intervalNS = SDL_min(poll_intervalNS, EVENT_POLL_INTERVAL_NS); + } +#endif + + return poll_intervalNS; } static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeup_window, SDL_Event *event, Uint64 start, Sint64 timeoutNS) { Sint64 loop_timeoutNS = timeoutNS; - SDL_bool need_periodic_poll = SDL_events_need_periodic_poll(); + Sint64 poll_intervalNS = SDL_events_get_polling_interval(); for (;;) { int status; @@ -1039,17 +1097,18 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu } loop_timeoutNS = (timeoutNS - elapsed); } - if (need_periodic_poll) { + /* 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, PERIODIC_POLL_INTERVAL_NS); + loop_timeoutNS = SDL_min(loop_timeoutNS, poll_intervalNS); } else { - loop_timeoutNS = PERIODIC_POLL_INTERVAL_NS; + loop_timeoutNS = poll_intervalNS; } } status = _this->WaitEventTimeout(_this, loop_timeoutNS); /* Set wakeup_window to NULL without holding the lock. */ _this->wakeup_window = NULL; - if (status == 0 && need_periodic_poll && loop_timeoutNS == PERIODIC_POLL_INTERVAL_NS) { + if (status == 0 && poll_intervalNS != SDL_MAX_SINT64 && loop_timeoutNS == poll_intervalNS) { /* We may have woken up to poll. Try again */ continue; } else if (status <= 0) { @@ -1062,22 +1121,6 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu return 0; } -static SDL_bool SDL_events_need_polling(void) -{ - SDL_bool need_polling = SDL_FALSE; - -#ifndef SDL_JOYSTICK_DISABLED - need_polling = SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks && SDL_JoysticksOpened(); -#endif - -#ifndef SDL_SENSOR_DISABLED - need_polling = need_polling || - (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && SDL_SensorsOpened()); -#endif - - return need_polling; -} - static SDL_Window *SDL_find_active_window(SDL_VideoDevice *_this) { SDL_Window *window; @@ -1162,7 +1205,7 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) /* We should have completely handled timeoutNS == 0 above */ SDL_assert(timeoutNS != 0); - if (_this && _this->WaitEventTimeout && _this->SendWakeupEvent && !SDL_events_need_polling()) { + 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); if (wakeup_window) { @@ -1186,7 +1229,7 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) return SDL_TRUE; } - Uint64 delay = SDL_MS_TO_NS(1); + Uint64 delay = EVENT_POLL_INTERVAL_NS; if (timeoutNS > 0) { Uint64 now = SDL_GetTicksNS(); if (now >= expiration) { @@ -1287,7 +1330,7 @@ int SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) { SDL_EventWatcher *event_watchers; - event_watchers = SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers)); + event_watchers = (SDL_EventWatcher *)SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers)); if (event_watchers) { SDL_EventWatcher *watcher; @@ -1426,13 +1469,11 @@ SDL_bool SDL_EventEnabled(Uint32 type) Uint32 SDL_RegisterEvents(int numevents) { - Uint32 event_base; + Uint32 event_base = 0; if ((numevents > 0) && (SDL_userevents + numevents <= SDL_EVENT_LAST)) { event_base = SDL_userevents; SDL_userevents += numevents; - } else { - event_base = (Uint32)-1; } return event_base; } diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index aba50237..f1b2cde8 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -40,9 +40,13 @@ typedef enum #define KEYBOARD_SOURCE_MASK (KEYBOARD_HARDWARE | KEYBOARD_AUTORELEASE) -typedef struct SDL_Keyboard SDL_Keyboard; +typedef struct SDL_KeyboardInstance +{ + SDL_KeyboardID instance_id; + char *name; +} SDL_KeyboardInstance; -struct SDL_Keyboard +typedef struct SDL_Keyboard { /* Data common to all keyboards */ SDL_Window *focus; @@ -52,15 +56,17 @@ struct SDL_Keyboard SDL_Keycode keymap[SDL_NUM_SCANCODES]; SDL_bool autorelease_pending; Uint64 hardware_timestamp; -}; +} 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 */ 0, - /* 1 */ 0, - /* 2 */ 0, - /* 3 */ 0, + /* 0 */ SDLK_UNKNOWN, + /* 1 */ SDLK_UNKNOWN, + /* 2 */ SDLK_UNKNOWN, + /* 3 */ SDLK_UNKNOWN, /* 4 */ 'a', /* 5 */ 'b', /* 6 */ 'c', @@ -157,7 +163,7 @@ static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = { /* 97 */ SDLK_KP_9, /* 98 */ SDLK_KP_0, /* 99 */ SDLK_KP_PERIOD, - /* 100 */ 0, + /* 100 */ SDLK_UNKNOWN, /* 101 */ SDLK_APPLICATION, /* 102 */ SDLK_POWER, /* 103 */ SDLK_KP_EQUALS, @@ -187,29 +193,29 @@ static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = { /* 127 */ SDLK_MUTE, /* 128 */ SDLK_VOLUMEUP, /* 129 */ SDLK_VOLUMEDOWN, - /* 130 */ 0, - /* 131 */ 0, - /* 132 */ 0, + /* 130 */ SDLK_UNKNOWN, + /* 131 */ SDLK_UNKNOWN, + /* 132 */ SDLK_UNKNOWN, /* 133 */ SDLK_KP_COMMA, /* 134 */ SDLK_KP_EQUALSAS400, - /* 135 */ 0, - /* 136 */ 0, - /* 137 */ 0, - /* 138 */ 0, - /* 139 */ 0, - /* 140 */ 0, - /* 141 */ 0, - /* 142 */ 0, - /* 143 */ 0, - /* 144 */ 0, - /* 145 */ 0, - /* 146 */ 0, - /* 147 */ 0, - /* 148 */ 0, - /* 149 */ 0, - /* 150 */ 0, - /* 151 */ 0, - /* 152 */ 0, + /* 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, @@ -222,17 +228,17 @@ static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = { /* 162 */ SDLK_CLEARAGAIN, /* 163 */ SDLK_CRSEL, /* 164 */ SDLK_EXSEL, - /* 165 */ 0, - /* 166 */ 0, - /* 167 */ 0, - /* 168 */ 0, - /* 169 */ 0, - /* 170 */ 0, - /* 171 */ 0, - /* 172 */ 0, - /* 173 */ 0, - /* 174 */ 0, - /* 175 */ 0, + /* 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, @@ -279,8 +285,8 @@ static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = { /* 219 */ SDLK_KP_OCTAL, /* 220 */ SDLK_KP_DECIMAL, /* 221 */ SDLK_KP_HEXADECIMAL, - /* 222 */ 0, - /* 223 */ 0, + /* 222 */ SDLK_UNKNOWN, + /* 223 */ SDLK_UNKNOWN, /* 224 */ SDLK_LCTRL, /* 225 */ SDLK_LSHIFT, /* 226 */ SDLK_LALT, @@ -289,31 +295,31 @@ static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = { /* 229 */ SDLK_RSHIFT, /* 230 */ SDLK_RALT, /* 231 */ SDLK_RGUI, - /* 232 */ 0, - /* 233 */ 0, - /* 234 */ 0, - /* 235 */ 0, - /* 236 */ 0, - /* 237 */ 0, - /* 238 */ 0, - /* 239 */ 0, - /* 240 */ 0, - /* 241 */ 0, - /* 242 */ 0, - /* 243 */ 0, - /* 244 */ 0, - /* 245 */ 0, - /* 246 */ 0, - /* 247 */ 0, - /* 248 */ 0, - /* 249 */ 0, - /* 250 */ 0, - /* 251 */ 0, - /* 252 */ 0, - /* 253 */ 0, - /* 254 */ 0, - /* 255 */ 0, - /* 256 */ 0, + /* 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, @@ -678,6 +684,116 @@ int SDL_InitKeyboard(void) return 0; } +SDL_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; + } + + /* Eventually we'll have a blacklist of devices that enumerate as keyboards but aren't really */ + return SDL_TRUE; +} + +static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID) +{ + for (int i = 0; i < SDL_keyboard_count; ++i) { + if (keyboardID == SDL_keyboards[i].instance_id) { + return i; + } + } + return -1; +} + +void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, SDL_bool send_event) +{ + int keyboard_index = SDL_GetKeyboardIndex(keyboardID); + if (keyboard_index >= 0) { + /* We already know about this keyboard */ + return; + } + + SDL_assert(keyboardID != 0); + + SDL_KeyboardInstance *keyboards = (SDL_KeyboardInstance *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards)); + if (!keyboards) { + return; + } + SDL_KeyboardInstance *instance = &keyboards[SDL_keyboard_count]; + instance->instance_id = keyboardID; + instance->name = SDL_strdup(name ? name : ""); + SDL_keyboards = keyboards; + ++SDL_keyboard_count; + + if (send_event) { + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_KEYBOARD_ADDED; + event.kdevice.which = keyboardID; + SDL_PushEvent(&event); + } +} + +void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID) +{ + int keyboard_index = SDL_GetKeyboardIndex(keyboardID); + if (keyboard_index < 0) { + /* We don't know about this keyboard */ + return; + } + + SDL_free(SDL_keyboards[keyboard_index].name); + + if (keyboard_index != SDL_keyboard_count - 1) { + SDL_memcpy(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index])); + } + --SDL_keyboard_count; + + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_KEYBOARD_REMOVED; + event.kdevice.which = keyboardID; + SDL_PushEvent(&event); +} + +SDL_bool SDL_HasKeyboard(void) +{ + return (SDL_keyboard_count > 0); +} + +SDL_KeyboardID *SDL_GetKeyboards(int *count) +{ + int i; + SDL_KeyboardID *keyboards; + + keyboards = (SDL_JoystickID *)SDL_malloc((SDL_keyboard_count + 1) * sizeof(*keyboards)); + if (keyboards) { + if (count) { + *count = SDL_keyboard_count; + } + + for (i = 0; i < SDL_keyboard_count; ++i) { + keyboards[i] = SDL_keyboards[i].instance_id; + } + keyboards[i] = 0; + } else { + if (count) { + *count = 0; + } + } + + return keyboards; +} + +const char *SDL_GetKeyboardInstanceName(SDL_KeyboardID instance_id) +{ + int keyboard_index = SDL_GetKeyboardIndex(instance_id); + if (keyboard_index < 0) { + return NULL; + } + return SDL_keyboards[keyboard_index].name; +} + void SDL_ResetKeyboard(void) { SDL_Keyboard *keyboard = &SDL_keyboard; @@ -688,7 +804,7 @@ void SDL_ResetKeyboard(void) #endif for (scancode = (SDL_Scancode)0; scancode < SDL_NUM_SCANCODES; ++scancode) { if (keyboard->keystate[scancode] == SDL_PRESSED) { - SDL_SendKeyboardKey(0, SDL_RELEASED, scancode); + SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, scancode); } } } @@ -796,11 +912,10 @@ int SDL_SetKeyboardFocus(SDL_Window *window) SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE)); } - SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, - 0, 0); + SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, 0, 0); /* Ensures IME compositions are committed */ - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { if (video && video->StopTextInput) { video->StopTextInput(video); } @@ -810,10 +925,9 @@ int SDL_SetKeyboardFocus(SDL_Window *window) keyboard->focus = window; if (keyboard->focus) { - SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, - 0, 0); + SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0); - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { if (video && video->StartTextInput) { video->StartTextInput(video); } @@ -822,7 +936,7 @@ int SDL_SetKeyboardFocus(SDL_Window *window) return 0; } -static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, SDL_KeyboardFlags flags, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode) +static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode) { SDL_Keyboard *keyboard = &SDL_keyboard; int posted; @@ -949,6 +1063,7 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, SDL_KeyboardFlags flags 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); } @@ -982,43 +1097,43 @@ int SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch) if (mod & SDL_KMOD_SHIFT) { /* If the character uses shift, press shift down */ - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN); + SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN); } /* Send a keydown and keyup for the character */ - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_PRESSED, code, SDLK_UNKNOWN); - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_RELEASED, code, SDLK_UNKNOWN); + 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); if (mod & SDL_KMOD_SHIFT) { /* If the character uses shift, release shift */ - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN); + SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN); } return 0; } int SDL_SendVirtualKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, state, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, state, scancode, SDLK_UNKNOWN); } -int SDL_SendKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode) +int SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, state, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, state, scancode, SDLK_UNKNOWN); } -int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode) +int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, state, scancode, keycode); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, state, scancode, keycode); } int SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_PRESSED, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, scancode, SDLK_UNKNOWN); } -int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, Uint8 state, SDL_Scancode scancode) +int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, state, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, keyboardID, state, scancode, SDLK_UNKNOWN); } void SDL_ReleaseAutoReleaseKeys(void) @@ -1029,7 +1144,7 @@ void SDL_ReleaseAutoReleaseKeys(void) if (keyboard->autorelease_pending) { for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) { if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) { - SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, SDL_RELEASED, scancode, SDLK_UNKNOWN); + SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, scancode, SDLK_UNKNOWN); } } keyboard->autorelease_pending = SDL_FALSE; @@ -1062,6 +1177,14 @@ int SDL_SendKeyboardText(const char *text) SDL_Keyboard *keyboard = &SDL_keyboard; int posted; + if (!SDL_TextInputActive()) { + return 0; + } + + if (!text || !*text) { + return 0; + } + /* Don't post text events for unprintable characters */ if (SDL_iscntrl((unsigned char)*text)) { return 0; @@ -1092,6 +1215,14 @@ int SDL_SendEditingText(const char *text, int start, int length) SDL_Keyboard *keyboard = &SDL_keyboard; int posted; + if (!SDL_TextInputActive()) { + return 0; + } + + if (!text) { + return 0; + } + /* Post the event, if desired */ posted = 0; if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING)) { @@ -1117,6 +1248,9 @@ int SDL_SendEditingText(const char *text, int start, int length) void SDL_QuitKeyboard(void) { + SDL_keyboard_count = 0; + SDL_free(SDL_keyboards); + SDL_keyboards = NULL; } const Uint8 *SDL_GetKeyboardState(int *numkeys) diff --git a/src/events/SDL_keyboard_c.h b/src/events/SDL_keyboard_c.h index 98459b1d..323b139d 100644 --- a/src/events/SDL_keyboard_c.h +++ b/src/events/SDL_keyboard_c.h @@ -23,9 +23,24 @@ #ifndef SDL_keyboard_c_h_ #define SDL_keyboard_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 */ +#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); + /* Get the default keymap */ extern void SDL_GetDefaultKeymap(SDL_Keycode *keymap); @@ -53,13 +68,13 @@ extern int SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch); extern int SDL_SendVirtualKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode); /* Send a keyboard key event */ -extern int SDL_SendKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode); +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, Uint8 state, SDL_Scancode scancode); +extern int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, 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, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode); +extern int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode); /* Release all the autorelease keys */ extern void SDL_ReleaseAutoReleaseKeys(void); diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 2f14cacf..885179c9 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -27,19 +27,27 @@ #include "SDL_events_c.h" #include "SDL_mouse_c.h" #include "SDL_pen_c.h" -#if defined(__WIN32__) || defined(__GDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) #include "../core/windows/SDL_windows.h" // For GetDoubleClickTime() #endif /* #define DEBUG_MOUSE */ +typedef struct SDL_MouseInstance +{ + SDL_MouseID instance_id; + char *name; +} SDL_MouseInstance; + /* 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; -static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y); +static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y); static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { @@ -48,7 +56,7 @@ static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char * if (hint && *hint) { mouse->double_click_time = SDL_atoi(hint); } else { -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) mouse->double_click_time = GetDoubleClickTime(); #else mouse->double_click_time = 500; @@ -107,7 +115,7 @@ static void SDLCALL SDL_TouchMouseEventsChanged(void *userdata, const char *name mouse->touch_mouse_events = SDL_GetStringBoolean(hint, SDL_TRUE); } -#ifdef __vita__ +#ifdef SDL_PLATFORM_VITA static void SDLCALL SDL_VitaTouchMouseDeviceChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; @@ -133,7 +141,7 @@ static void SDLCALL SDL_MouseTouchEventsChanged(void *userdata, const char *name SDL_Mouse *mouse = (SDL_Mouse *)userdata; SDL_bool default_value; -#if defined(__ANDROID__) || (defined(__IOS__) && !defined(__TVOS__)) +#if defined(SDL_PLATFORM_ANDROID) || (defined(SDL_PLATFORM_IOS) && !defined(SDL_PLATFORM_TVOS)) default_value = SDL_TRUE; #else default_value = SDL_FALSE; @@ -188,7 +196,7 @@ int SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS, SDL_TouchMouseEventsChanged, mouse); -#ifdef __vita__ +#ifdef SDL_PLATFORM_VITA SDL_AddHintCallback(SDL_HINT_VITA_TOUCH_MOUSE_DEVICE, SDL_VitaTouchMouseDeviceChanged, mouse); #endif @@ -227,6 +235,124 @@ void SDL_PostInitMouse(void) SDL_PenInit(); } +SDL_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; +} + +static int SDL_GetMouseIndex(SDL_MouseID mouseID) +{ + for (int i = 0; i < SDL_mouse_count; ++i) { + if (mouseID == SDL_mice[i].instance_id) { + return i; + } + } + return -1; +} + +void SDL_AddMouse(SDL_MouseID mouseID, const char *name, SDL_bool send_event) +{ + int mouse_index = SDL_GetMouseIndex(mouseID); + if (mouse_index >= 0) { + /* We already know about this mouse */ + return; + } + + SDL_assert(mouseID != 0); + + SDL_MouseInstance *mice = (SDL_MouseInstance *)SDL_realloc(SDL_mice, (SDL_mouse_count + 1) * sizeof(*mice)); + if (!mice) { + return; + } + SDL_MouseInstance *instance = &mice[SDL_mouse_count]; + instance->instance_id = mouseID; + instance->name = SDL_strdup(name ? name : ""); + SDL_mice = mice; + ++SDL_mouse_count; + + if (send_event) { + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_MOUSE_ADDED; + event.mdevice.which = mouseID; + SDL_PushEvent(&event); + } +} + +void SDL_RemoveMouse(SDL_MouseID mouseID) +{ + int mouse_index = SDL_GetMouseIndex(mouseID); + if (mouse_index < 0) { + /* We don't know about this mouse */ + return; + } + + SDL_free(SDL_mice[mouse_index].name); + + if (mouse_index != SDL_mouse_count - 1) { + SDL_memcpy(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index])); + } + --SDL_mouse_count; + + /* 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]; + if (source->mouseID == mouseID) { + if (i != mouse->num_sources - 1) { + SDL_memcpy(&mouse->sources[i], &mouse->sources[i + 1], (mouse->num_sources - i - 1) * sizeof(mouse->sources[i])); + } + --mouse->num_sources; + break; + } + } + + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_MOUSE_REMOVED; + event.mdevice.which = mouseID; + SDL_PushEvent(&event); +} + +SDL_bool SDL_HasMouse(void) +{ + return (SDL_mouse_count > 0); +} + +SDL_MouseID *SDL_GetMice(int *count) +{ + int i; + SDL_MouseID *mice; + + mice = (SDL_JoystickID *)SDL_malloc((SDL_mouse_count + 1) * sizeof(*mice)); + if (mice) { + if (count) { + *count = SDL_mouse_count; + } + + for (i = 0; i < SDL_mouse_count; ++i) { + mice[i] = SDL_mice[i].instance_id; + } + mice[i] = 0; + } else { + if (count) { + *count = 0; + } + } + + return mice; +} + +const char *SDL_GetMouseInstanceName(SDL_MouseID instance_id) +{ + int mouse_index = SDL_GetMouseIndex(instance_id); + if (mouse_index < 0) { + return NULL; + } + return SDL_mice[mouse_index].name; +} + void SDL_SetDefaultCursor(SDL_Cursor *cursor) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -276,14 +402,21 @@ SDL_Mouse *SDL_GetMouse(void) return &SDL_mouse; } -static Uint32 GetButtonState(SDL_Mouse *mouse, SDL_bool include_touch) +Uint32 SDL_GetMouseButtonState(SDL_Mouse *mouse, SDL_MouseID mouseID, SDL_bool include_touch) { int i; Uint32 buttonstate = 0; for (i = 0; i < mouse->num_sources; ++i) { - if (include_touch || mouse->sources[i].mouseID != SDL_TOUCH_MOUSEID) { - buttonstate |= mouse->sources[i].buttonstate; + if (mouseID == SDL_GLOBAL_MOUSE_ID || mouseID == SDL_TOUCH_MOUSEID) { + if (include_touch || mouse->sources[i].mouseID != SDL_TOUCH_MOUSEID) { + buttonstate |= mouse->sources[i].buttonstate; + } + } else { + if (mouseID == mouse->sources[i].mouseID) { + buttonstate |= mouse->sources[i].buttonstate; + break; + } } } return buttonstate; @@ -307,7 +440,7 @@ SDL_Window *SDL_GetMouseFocus(void) void SDL_ResetMouse(void) { SDL_Mouse *mouse = SDL_GetMouse(); - Uint32 buttonState = GetButtonState(mouse, SDL_FALSE); + Uint32 buttonState = SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_FALSE); int i; for (i = 1; i <= sizeof(buttonState)*8; ++i) { @@ -315,7 +448,7 @@ void SDL_ResetMouse(void) SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, i); } } - SDL_assert(GetButtonState(mouse, SDL_FALSE) == 0); + SDL_assert(SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_FALSE) == 0); } #endif /* 0 */ @@ -355,7 +488,7 @@ void SDL_SetMouseFocus(SDL_Window *window) SDL_SetCursor(NULL); } -SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y) +SDL_bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y) { if (!window) { return SDL_FALSE; @@ -373,7 +506,7 @@ SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, floa static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, SDL_bool send_mouse_motion) { SDL_Mouse *mouse = SDL_GetMouse(); - SDL_bool inWindow = SDL_MousePositionInWindow(window, mouse->mouseID, x, y); + SDL_bool inWindow = SDL_MousePositionInWindow(window, x, y); if (!inWindow) { if (window == mouse->focus) { @@ -381,7 +514,7 @@ 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, mouse->mouseID, 0, x, y); + SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y); } SDL_SetMouseFocus(NULL); } @@ -394,17 +527,17 @@ 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, mouse->mouseID, 0, x, y); + SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y); } } return SDL_TRUE; } -int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y) +int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y) { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); - if (!SDL_UpdateMouseFocus(window, x, y, GetButtonState(mouse, SDL_TRUE), (mouseID != SDL_TOUCH_MOUSEID))) { + if (!SDL_UpdateMouseFocus(window, x, y, SDL_GetMouseButtonState(mouse, mouseID, SDL_TRUE), (mouseID != SDL_TOUCH_MOUSEID))) { return 0; } } @@ -438,7 +571,7 @@ static float CalculateSystemScale(SDL_Mouse *mouse, SDL_Window *window, const fl scale = v[i + 1] + (coef * (v[i + 3] - v[i + 1])); } } -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 { /* On Windows the mouse speed is affected by the content scale */ SDL_VideoDisplay *display; @@ -558,20 +691,25 @@ static void ConstrainMousePosition(SDL_Mouse *mouse, SDL_Window *window, float * } } -static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y) +static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_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 */ + mouseID = SDL_GLOBAL_MOUSE_ID; + } + /* 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) { float normalized_x = x / (float)window->w; float normalized_y = y / (float)window->h; - SDL_SendTouchMotion(timestamp, SDL_MOUSE_TOUCHID, 0, window, normalized_x, normalized_y, 1.0f); + SDL_SendTouchMotion(timestamp, SDL_MOUSE_TOUCHID, SDL_BUTTON_LEFT, window, normalized_x, normalized_y, 1.0f); } } } @@ -599,7 +737,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ if (mouse->WarpMouse) { mouse->WarpMouse(window, center_x, center_y); } else { - SDL_PrivateSendMouseMotion(timestamp, window, mouseID, 0, center_x, center_y); + SDL_PrivateSendMouseMotion(timestamp, window, mouseID, SDL_FALSE, center_x, center_y); } } } @@ -629,7 +767,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ } /* Ignore relative motion positioning the first touch */ - if (mouseID == SDL_TOUCH_MOUSEID && !GetButtonState(mouse, SDL_TRUE)) { + if (mouseID == SDL_TOUCH_MOUSEID && !SDL_GetMouseButtonState(mouse, mouseID, SDL_TRUE)) { xrel = 0.0f; yrel = 0.0f; } @@ -669,7 +807,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ event.motion.which = mouseID; /* 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 = GetButtonState(mouse, SDL_TRUE); + event.motion.state = SDL_GetMouseButtonState(mouse, mouseID, SDL_TRUE); event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; @@ -687,18 +825,35 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ return posted; } -static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID mouseID) +static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID mouseID, Uint8 state, Uint8 button) { - SDL_MouseInputSource *source, *sources; + SDL_MouseInputSource *source, *match = NULL, *sources; int i; for (i = 0; i < mouse->num_sources; ++i) { source = &mouse->sources[i]; if (source->mouseID == mouseID) { - return source; + match = source; + break; } } + if (!state && (!match || !(match->buttonstate & SDL_BUTTON(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))) { + match = source; + break; + } + } + } + if (match) { + return match; + } + sources = (SDL_MouseInputSource *)SDL_realloc(mouse->sources, (mouse->num_sources + 1) * sizeof(*mouse->sources)); if (sources) { mouse->sources = sources; @@ -737,7 +892,12 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ Uint32 buttonstate; SDL_MouseInputSource *source; - source = GetMouseInputSource(mouse, mouseID); + 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 */ + mouseID = SDL_GLOBAL_MOUSE_ID; + } + + source = GetMouseInputSource(mouse, mouseID, state, button); if (!source) { return 0; } @@ -754,7 +914,7 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ if (window) { float normalized_x = mouse->x / (float)window->w; float normalized_y = mouse->y / (float)window->h; - SDL_SendTouch(timestamp, SDL_MOUSE_TOUCHID, 0, window, track_mouse_down, normalized_x, normalized_y, 1.0f); + SDL_SendTouch(timestamp, SDL_MOUSE_TOUCHID, SDL_BUTTON_LEFT, window, track_mouse_down, normalized_x, normalized_y, 1.0f); } } } @@ -823,7 +983,7 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ event.type = type; event.common.timestamp = timestamp; event.button.windowID = mouse->focus ? mouse->focus->id : 0; - event.button.which = mouseID; + event.button.which = source->mouseID; event.button.state = state; event.button.button = button; event.button.clicks = (Uint8)SDL_min(clicks, 255); @@ -879,9 +1039,9 @@ int SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID event.wheel.which = mouseID; event.wheel.x = x; event.wheel.y = y; - event.wheel.direction = (Uint32)direction; - event.wheel.mouseX = mouse->x; - event.wheel.mouseY = mouse->y; + event.wheel.direction = direction; + event.wheel.mouse_x = mouse->x; + event.wheel.mouse_y = mouse->y; posted = (SDL_PushEvent(&event) > 0); } return posted; @@ -957,6 +1117,10 @@ void SDL_QuitMouse(void) SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, SDL_MouseRelativeWarpMotionChanged, mouse); + + SDL_mouse_count = 0; + SDL_free(SDL_mice); + SDL_mice = NULL; } Uint32 SDL_GetMouseState(float *x, float *y) @@ -969,7 +1133,7 @@ Uint32 SDL_GetMouseState(float *x, float *y) if (y) { *y = mouse->y; } - return GetButtonState(mouse, SDL_TRUE); + return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_TRUE); } Uint32 SDL_GetRelativeMouseState(float *x, float *y) @@ -984,7 +1148,7 @@ Uint32 SDL_GetRelativeMouseState(float *x, float *y) } mouse->xdelta = 0.0f; mouse->ydelta = 0.0f; - return GetButtonState(mouse, SDL_TRUE); + return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_TRUE); } Uint32 SDL_GetGlobalMouseState(float *x, float *y) @@ -1051,7 +1215,7 @@ 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, mouse->mouseID, 0, x, y); + SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y); } } @@ -1161,9 +1325,9 @@ int SDL_UpdateMouseCapture(SDL_bool force_release) if (!force_release) { if (SDL_GetMessageBoxCount() == 0 && - (mouse->capture_desired || (mouse->auto_capture && GetButtonState(mouse, SDL_FALSE) != 0))) { + (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_FALSE) != 0))) { if (!mouse->relative_mode) { - capture_window = SDL_GetKeyboardFocus(); + capture_window = mouse->focus; } } } @@ -1209,7 +1373,7 @@ int SDL_CaptureMouse(SDL_bool enabled) return SDL_Unsupported(); } -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) /* Windows mouse capture is tied to the current thread, and must be called * from the thread that created the window being captured. Since we update * the mouse capture state from the event processing, any application state @@ -1218,7 +1382,7 @@ int SDL_CaptureMouse(SDL_bool enabled) if (!SDL_OnVideoThread()) { return SDL_SetError("SDL_CaptureMouse() must be called on the main thread"); } -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ if (enabled && SDL_GetKeyboardFocus() == NULL) { return SDL_SetError("No window has focus"); @@ -1238,12 +1402,12 @@ SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, const Uint32 black = 0xFF000000; const Uint32 white = 0xFFFFFFFF; const Uint32 transparent = 0x00000000; -#if defined(__WIN32__) +#if defined(SDL_PLATFORM_WIN32) /* Only Windows backend supports inverted pixels in mono cursors. */ const Uint32 inverted = 0x00FFFFFF; #else const Uint32 inverted = 0xFF000000; -#endif /* defined(__WIN32__) */ +#endif /* defined(SDL_PLATFORM_WIN32) */ /* Make sure the width is a multiple of 8 */ w = ((w + 7) & ~7); @@ -1306,7 +1470,7 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) if (mouse->CreateCursor) { cursor = mouse->CreateCursor(surface, hot_x, hot_y); } else { - cursor = SDL_calloc(1, sizeof(*cursor)); + cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); } if (cursor) { cursor->next = mouse->cursors; diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index e024534f..4dc0c111 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -23,6 +23,12 @@ #ifndef SDL_mouse_c_h_ #define SDL_mouse_c_h_ +/* 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 */ +#define SDL_DEFAULT_MOUSE_ID 1 + struct SDL_Cursor { struct SDL_Cursor *next; @@ -75,7 +81,6 @@ typedef struct Uint32 (*GetGlobalMouseState)(float *x, float *y); /* Data common to all mice */ - SDL_MouseID mouseID; SDL_Window *focus; float x; float y; @@ -98,7 +103,7 @@ typedef struct SDL_bool touch_mouse_events; SDL_bool mouse_touch_events; SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */ -#ifdef __vita__ +#ifdef SDL_PLATFORM_VITA Uint8 vita_touch_mouse_device; #endif SDL_bool auto_capture; @@ -128,8 +133,17 @@ extern int SDL_PreInitMouse(void); /* 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); + +/* 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 removed from the system */ +extern void SDL_RemoveMouse(SDL_MouseID mouseID); + /* Get the mouse state structure */ -SDL_Mouse *SDL_GetMouse(void); +extern SDL_Mouse *SDL_GetMouse(void); /* Set the default mouse cursor */ extern void SDL_SetDefaultCursor(SDL_Cursor *cursor); @@ -140,11 +154,14 @@ extern void SDL_SetMouseFocus(SDL_Window *window); /* Update the mouse capture window */ extern int SDL_UpdateMouseCapture(SDL_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 int SDL_SetMouseSystemScale(int num_values, const float *values); /* Send a mouse motion event */ -extern int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y); +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 int SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button); @@ -164,7 +181,7 @@ extern void SDL_ResetMouse(void); #endif /* 0 */ /* Check if mouse position is within window or captured by window */ -extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y); +extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y); /* Shutdown the mouse subsystem */ extern void SDL_QuitMouse(void); diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index 5907eeaf..ed15c310 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -97,8 +97,8 @@ static int SDLCALL pen_compare(const void *lhs, const void *rhs) static int SDLCALL pen_header_compare(const void *lhs, const void *rhs) { - const struct SDL_Pen_header *l = lhs; - const struct SDL_Pen_header *r = rhs; + 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; @@ -121,15 +121,13 @@ SDL_Pen *SDL_GetPenPtr(Uint32 instance_id) } if (pen_handler.sorted) { - struct SDL_Pen_header key; + SDL_PenHeader key; SDL_Pen *pen; SDL_zero(key); key.id = instance_id; - pen = SDL_bsearch(&key, pen_handler.pens, - pen_handler.pens_known, sizeof(SDL_Pen), - pen_header_compare); + pen = (SDL_Pen *)SDL_bsearch(&key, pen_handler.pens, pen_handler.pens_known, sizeof(SDL_Pen), pen_header_compare); if (pen) { return pen; } @@ -149,7 +147,7 @@ SDL_PenID *SDL_GetPens(int *count) { int i; int pens_nr = (int)pen_handler.pens_attached; - SDL_PenID *pens = SDL_calloc(pens_nr + 1, sizeof(SDL_PenID)); + SDL_PenID *pens = (SDL_PenID *)SDL_calloc(pens_nr + 1, sizeof(SDL_PenID)); if (!pens) { /* OOM */ return pens; } @@ -222,7 +220,7 @@ const char *SDL_GetPenName(SDL_PenID instance_id) SDL_PenSubtype SDL_GetPenType(SDL_PenID instance_id) { SDL_PenSubtype result; - SDL_LOAD_LOCK_PEN(pen, instance_id, 0u); + SDL_LOAD_LOCK_PEN(pen, instance_id, SDL_PEN_TYPE_UNKNOWN); result = pen->type; SDL_UNLOCK_PENS(); return result; @@ -293,11 +291,11 @@ SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id) size_t pens_to_allocate = pen_handler.pens_allocated + alloc_growth_constant; SDL_Pen *pens; if (pen_handler.pens) { - pens = SDL_realloc(pen_handler.pens, sizeof(SDL_Pen) * pens_to_allocate); + 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_calloc(sizeof(SDL_Pen), pens_to_allocate); + pens = (SDL_Pen *)SDL_calloc(sizeof(SDL_Pen), pens_to_allocate); } pen_handler.pens = pens; pen_handler.pens_allocated = pens_to_allocate; @@ -305,13 +303,13 @@ SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id) pen = &pen_handler.pens[pen_handler.pens_known]; pen_handler.pens_known += 1; - /* Default pen initialisation */ + /* 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 = SDL_calloc(1, SDL_PEN_MAX_NAME); /* Never deallocated */ + pen->name = (char *)SDL_calloc(1, SDL_PEN_MAX_NAME); /* Never deallocated */ } return pen; } @@ -359,6 +357,7 @@ void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach) attach = SDL_FALSE; } else { pen_handler.pens_known -= 1; + SDL_free(pen->name); SDL_memset(pen, 0, sizeof(SDL_Pen)); SDL_UNLOCK_PENS(); return; @@ -498,7 +497,6 @@ int SDL_SendPenMotion(Uint64 timestamp, SDL_bool window_relative, const SDL_PenStatusInfo *status) { - const SDL_Mouse *mouse = SDL_GetMouse(); int i; SDL_Pen *pen = SDL_GetPenPtr(instance_id); SDL_Event event; @@ -541,7 +539,7 @@ int SDL_SendPenMotion(Uint64 timestamp, send_mouse_update = (x != last_x) || (y != last_y); - if (!(SDL_MousePositionInWindow(window, mouse->mouseID, x, y))) { + if (!(SDL_MousePositionInWindow(window, x, y))) { return SDL_FALSE; } @@ -559,7 +557,7 @@ int SDL_SendPenMotion(Uint64 timestamp, if (send_mouse_update) { switch (pen_mouse_emulation_mode) { case PEN_MOUSE_EMULATE: - return (SDL_SendMouseMotion(0, window, SDL_PEN_MOUSEID, 0, x, y)) || posted; + return (SDL_SendMouseMotion(0, window, SDL_PEN_MOUSEID, SDL_FALSE, x, y)) || posted; case PEN_MOUSE_STATELESS: /* Report mouse event but don't update mouse state */ @@ -575,6 +573,7 @@ int SDL_SendPenMotion(Uint64 timestamp, event.motion.yrel = last_y - y; return (SDL_PushEvent(&event) > 0) || posted; } + break; default: break; @@ -585,7 +584,6 @@ int SDL_SendPenMotion(Uint64 timestamp, int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) { - SDL_Mouse *mouse = SDL_GetMouse(); SDL_Pen *pen = SDL_GetPenPtr(instance_id); SDL_Event event; SDL_bool posted = SDL_FALSE; @@ -598,7 +596,7 @@ int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) } window = pen->header.window; - if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, mouse->mouseID, last->x, last->y))) { + if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, last->x, last->y))) { return SDL_FALSE; } @@ -664,7 +662,6 @@ int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, Uint8 state, Uint8 button) { - SDL_Mouse *mouse = SDL_GetMouse(); SDL_Pen *pen = SDL_GetPenPtr(instance_id); SDL_Event event; SDL_bool posted = SDL_FALSE; @@ -677,7 +674,7 @@ int SDL_SendPenButton(Uint64 timestamp, } window = pen->header.window; - if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, mouse->mouseID, last->x, last->y))) { + if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, last->x, last->y))) { return SDL_FALSE; } @@ -798,7 +795,7 @@ int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window * static void SDLCALL SDL_PenUpdateHint(void *userdata, const char *name, const char *oldvalue, const char *newvalue) { - int *var = userdata; + int *var = (int *)userdata; if (newvalue == NULL) { return; } @@ -832,6 +829,8 @@ void SDL_PenInit(void) void SDL_PenQuit(void) { + unsigned int i; + SDL_DelHintCallback(SDL_HINT_PEN_NOT_MOUSE, SDL_PenUpdateHint, &pen_mouse_emulation_mode); @@ -841,6 +840,15 @@ void SDL_PenQuit(void) 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); + } + SDL_free(pen_handler.pens); + /* Reset static pen information */ + SDL_memset(&pen_handler, 0, sizeof(pen_handler)); + } } SDL_bool SDL_PenPerformHitTest(void) @@ -1053,7 +1061,7 @@ int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *ax wacom_devicetype_id = PEN_WACOM_ID_INVALID; /* force detection to fail */ #endif -#if defined(__LINUX__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#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. diff --git a/src/events/SDL_pen_c.h b/src/events/SDL_pen_c.h index fef9c529..a82b345d 100644 --- a/src/events/SDL_pen_c.h +++ b/src/events/SDL_pen_c.h @@ -56,6 +56,13 @@ typedef struct SDL_PenStatusInfo Uint16 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */ } SDL_PenStatusInfo; +typedef struct +{ + 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 * @@ -66,12 +73,7 @@ typedef struct SDL_PenStatusInfo typedef struct SDL_Pen { /* Backend driver MUST NOT not write to: */ - struct SDL_Pen_header - { - 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 */ - } header; + SDL_PenHeader header; SDL_PenStatusInfo last; /* Last reported status, normally read-only for backend */ diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 071fdff4..98975e9c 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -158,6 +158,8 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name SDL_Touch **touchDevices; int index; + SDL_assert(touchID != 0); + index = SDL_GetTouchIndex(touchID); if (index >= 0) { return index; @@ -196,6 +198,8 @@ static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float { SDL_Finger *finger; + SDL_assert(fingerid != 0); + if (touch->num_fingers == touch->max_fingers) { SDL_Finger **new_fingers; new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers + 1) * sizeof(*touch->fingers)); @@ -251,7 +255,7 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W /* 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 __vita__ +#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) { @@ -275,7 +279,7 @@ 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, 0, pos_x, pos_y); + 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); } } else { @@ -324,8 +328,8 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W SDL_Event event; event.type = SDL_EVENT_FINGER_DOWN; event.common.timestamp = timestamp; - event.tfinger.touchId = id; - event.tfinger.fingerId = fingerid; + event.tfinger.touchID = id; + event.tfinger.fingerID = fingerid; event.tfinger.x = x; event.tfinger.y = y; event.tfinger.dx = 0; @@ -345,8 +349,8 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W SDL_Event event; event.type = SDL_EVENT_FINGER_UP; event.common.timestamp = timestamp; - event.tfinger.touchId = id; - event.tfinger.fingerId = fingerid; + event.tfinger.touchID = id; + event.tfinger.fingerID = fingerid; /* I don't trust the coordinates passed on fingerUp */ event.tfinger.x = finger->x; event.tfinger.y = finger->y; @@ -399,7 +403,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, 0, pos_x, pos_y); + SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, SDL_FALSE, pos_x, pos_y); } } } @@ -442,8 +446,8 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Event event; event.type = SDL_EVENT_FINGER_MOTION; event.common.timestamp = timestamp; - event.tfinger.touchId = id; - event.tfinger.fingerId = fingerid; + event.tfinger.touchID = id; + event.tfinger.fingerID = fingerid; event.tfinger.x = x; event.tfinger.y = y; event.tfinger.dx = xrel; diff --git a/src/file/SDL_iostream.c b/src/file/SDL_iostream.c new file mode 100644 index 00000000..d261094f --- /dev/null +++ b/src/file/SDL_iostream.c @@ -0,0 +1,1289 @@ +/* + 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" + +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT) +#include "../core/windows/SDL_windows.h" +#endif + +#ifdef HAVE_STDIO_H +#include +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif + +/* This file provides a general interface for SDL to read and write + data sources. It can easily be extended to files, memory, etc. +*/ + +struct SDL_IOStream +{ + SDL_IOStreamInterface iface; + void *userdata; + SDL_IOStatus status; + 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 */ + +#ifdef SDL_PLATFORM_ANDROID +#include "../core/android/SDL_android.h" +#endif + +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT) + +typedef struct IOStreamWindowsData +{ + SDL_bool append; + HANDLE h; + void *data; + size_t size; + size_t left; +} IOStreamWindowsData; + + +/* 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) +{ +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT) + UINT old_error_mode; +#endif + HANDLE h; + DWORD r_right, w_right; + 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 */ + + must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0; + truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0; + r_right = (SDL_strchr(mode, '+') != NULL || must_exist) ? GENERIC_READ : 0; + a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0; + w_right = (a_mode || SDL_strchr(mode, '+') || truncate) ? GENERIC_WRITE : 0; + + if (!r_right && !w_right) { + return -1; /* inconsistent mode */ + } + /* 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); +#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, + (w_right | r_right), + (w_right) ? 0 : FILE_SHARE_READ, + NULL, + (must_exist | truncate | a_mode), + FILE_ATTRIBUTE_NORMAL, + NULL); +#endif + SDL_free(tstr); + } + +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT) + /* 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 */ +} + +static Sint64 SDLCALL windows_file_size(void *userdata) +{ + IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; + LARGE_INTEGER size; + + if (!GetFileSizeEx(iodata->h, &size)) { + return WIN_SetError("windows_file_size"); + } + + return size.QuadPart; +} + +static Sint64 SDLCALL windows_file_seek(void *userdata, Sint64 offset, int whence) +{ + IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; + DWORD windowswhence; + LARGE_INTEGER windowsoffset; + + // FIXME: We may be able to satisfy the seek within buffered data + if ((whence == SDL_IO_SEEK_CUR) && (iodata->left)) { + offset -= iodata->left; + } + iodata->left = 0; + + switch (whence) { + case SDL_IO_SEEK_SET: + windowswhence = FILE_BEGIN; + break; + case SDL_IO_SEEK_CUR: + windowswhence = FILE_CURRENT; + break; + case SDL_IO_SEEK_END: + windowswhence = FILE_END; + break; + default: + return SDL_SetError("windows_file_seek: Unknown value for 'whence'"); + } + + windowsoffset.QuadPart = offset; + if (!SetFilePointerEx(iodata->h, windowsoffset, &windowsoffset, windowswhence)) { + return WIN_SetError("windows_file_seek"); + } + return windowsoffset.QuadPart; +} + +static size_t SDLCALL windows_file_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; + size_t total_need = size; + size_t total_read = 0; + size_t read_ahead; + DWORD bytes; + + if (iodata->left > 0) { + void *data = (char *)iodata->data + + iodata->size - + iodata->left; + read_ahead = SDL_min(total_need, iodata->left); + SDL_memcpy(ptr, data, read_ahead); + iodata->left -= read_ahead; + + if (read_ahead == total_need) { + return size; + } + ptr = (char *)ptr + read_ahead; + total_need -= read_ahead; + total_read += read_ahead; + } + + if (total_need < READAHEAD_BUFFER_SIZE) { + if (!ReadFile(iodata->h, iodata->data, READAHEAD_BUFFER_SIZE, &bytes, NULL)) { + SDL_Error(SDL_EFREAD); + return 0; + } + read_ahead = SDL_min(total_need, bytes); + SDL_memcpy(ptr, iodata->data, read_ahead); + iodata->size = bytes; + iodata->left = bytes - read_ahead; + total_read += read_ahead; + } else { + if (!ReadFile(iodata->h, ptr, (DWORD)total_need, &bytes, NULL)) { + SDL_Error(SDL_EFREAD); + return 0; + } + total_read += bytes; + } + return total_read; +} + +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); + return 0; + } + iodata->left = 0; + } + + /* 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); + return 0; + } + } + + if (!WriteFile(iodata->h, ptr, (DWORD)total_bytes, &bytes, NULL)) { + SDL_Error(SDL_EFWRITE); + return 0; + } + + return bytes; +} + +static int 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 */ + } + SDL_free(iodata->data); + SDL_free(iodata); + return 0; +} +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ + +#if defined(HAVE_STDIO_H) && !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) + +/* Functions to read/write stdio file pointers. Not used for windows. */ + +typedef struct IOStreamStdioData +{ + FILE *fp; + SDL_bool autoclose; +} IOStreamStdioData; + +#ifdef HAVE_FOPEN64 +#define fopen fopen64 +#endif +#ifdef HAVE_FSEEKO64 +#define fseek_off_t off64_t +#define fseek fseeko64 +#define ftell ftello64 +#elif defined(HAVE_FSEEKO) +#if defined(OFF_MIN) && defined(OFF_MAX) +#define FSEEK_OFF_MIN OFF_MIN +#define FSEEK_OFF_MAX OFF_MAX +#elif defined(HAVE_LIMITS_H) +/* POSIX doesn't specify the minimum and maximum macros for off_t so + * we have to improvise and dance around implementation-defined + * behavior. This may fail if the off_t type has padding bits or + * is not a two's-complement representation. The compilers will detect + * and eliminate the dead code if off_t has 64 bits. + */ +#define FSEEK_OFF_MAX (((((off_t)1 << (sizeof(off_t) * CHAR_BIT - 2)) - 1) << 1) + 1) +#define FSEEK_OFF_MIN (-(FSEEK_OFF_MAX)-1) +#endif +#define fseek_off_t off_t +#define fseek fseeko +#define ftell ftello +#elif defined(HAVE__FSEEKI64) +#define fseek_off_t __int64 +#define fseek _fseeki64 +#define ftell _ftelli64 +#else +#ifdef HAVE_LIMITS_H +#define FSEEK_OFF_MIN LONG_MIN +#define FSEEK_OFF_MAX LONG_MAX +#endif +#define fseek_off_t long +#endif + +static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence) +{ + IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; + int stdiowhence; + + switch (whence) { + case SDL_IO_SEEK_SET: + stdiowhence = SEEK_SET; + break; + case SDL_IO_SEEK_CUR: + stdiowhence = SEEK_CUR; + break; + case SDL_IO_SEEK_END: + stdiowhence = SEEK_END; + break; + default: + return SDL_SetError("Unknown value for 'whence'"); + } + +#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"); + } +#endif + + if (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"); + } + return pos; + } + return SDL_Error(SDL_EFSEEK); +} + +static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; + const size_t bytes = fread(ptr, 1, size, iodata->fp); + if (bytes == 0 && ferror(iodata->fp)) { + SDL_Error(SDL_EFREAD); + } + return bytes; +} + +static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; + const size_t bytes = fwrite(ptr, 1, size, iodata->fp); + if (bytes == 0 && ferror(iodata->fp)) { + SDL_Error(SDL_EFWRITE); + } + return bytes; +} + +static int SDLCALL stdio_close(void *userdata) +{ + IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; + int status = 0; + if (iodata->autoclose) { + if (fclose(iodata->fp) != 0) { + status = SDL_Error(SDL_EFWRITE); + } + } + SDL_free(iodata); + return status; +} + +static SDL_IOStream *SDL_IOFromFP(FILE *fp, SDL_bool autoclose) +{ + IOStreamStdioData *iodata = (IOStreamStdioData *) SDL_malloc(sizeof (*iodata)); + if (!iodata) { + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_zero(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.close = stdio_close; + + iodata->fp = fp; + iodata->autoclose = autoclose; + + 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); + } + } + + return iostr; +} +#endif /* !HAVE_STDIO_H && !(SDL_PLATFORM_WIN32 || SDL_PLATFORM_GDK) */ + +/* Functions to read/write memory pointers */ + +typedef struct IOStreamMemData +{ + Uint8 *base; + Uint8 *here; + Uint8 *stop; +} IOStreamMemData; + +static Sint64 SDLCALL mem_size(void *userdata) +{ + const IOStreamMemData *iodata = (IOStreamMemData *) userdata; + return (iodata->stop - iodata->base); +} + +static Sint64 SDLCALL mem_seek(void *userdata, Sint64 offset, int whence) +{ + IOStreamMemData *iodata = (IOStreamMemData *) userdata; + Uint8 *newpos; + + switch (whence) { + case SDL_IO_SEEK_SET: + newpos = iodata->base + offset; + break; + case SDL_IO_SEEK_CUR: + newpos = iodata->here + offset; + break; + case SDL_IO_SEEK_END: + newpos = iodata->stop + offset; + break; + default: + return SDL_SetError("Unknown value for 'whence'"); + } + if (newpos < iodata->base) { + newpos = iodata->base; + } + if (newpos > iodata->stop) { + newpos = iodata->stop; + } + iodata->here = newpos; + return (Sint64)(iodata->here - iodata->base); +} + +static size_t mem_io(void *userdata, void *dst, const void *src, size_t size) +{ + IOStreamMemData *iodata = (IOStreamMemData *) userdata; + const size_t mem_available = (iodata->stop - iodata->here); + if (size > mem_available) { + size = mem_available; + } + SDL_memcpy(dst, src, size); + iodata->here += size; + return size; +} + +static size_t SDLCALL mem_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamMemData *iodata = (IOStreamMemData *) userdata; + return mem_io(userdata, ptr, iodata->here, size); +} + +static size_t SDLCALL mem_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamMemData *iodata = (IOStreamMemData *) userdata; + return mem_io(userdata, iodata->here, ptr, size); +} + +static int SDLCALL mem_close(void *userdata) +{ + SDL_free(userdata); + return 0; +} + +/* 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) +{ + #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; + } + #endif + return SDL_TRUE; +} +#endif + +SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode) +{ + SDL_IOStream *iostr = NULL; + + if (!file || !*file) { + SDL_InvalidParamError("file"); + return NULL; + } + if (!mode || !*mode) { + SDL_InvalidParamError("mode"); + return NULL; + } + +#ifdef SDL_PLATFORM_ANDROID +#ifdef HAVE_STDIO_H + /* Try to open the file on the filesystem first */ + if (*file == '/') { + FILE *fp = fopen(file, mode); + if (fp) { + if (!IsRegularFileOrPipe(fp)) { + fclose(fp); + SDL_SetError("%s is not a regular file or pipe", file); + return NULL; + } + return SDL_IOFromFP(fp, 1); + } + } 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); + if (path) { + SDL_snprintf(path, PATH_MAX, "%s/%s", + SDL_AndroidGetInternalStoragePath(), file); + FILE *fp = fopen(path, mode); + SDL_stack_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); + } + } + } +#endif /* HAVE_STDIO_H */ + + /* Try to open the file from the asset system */ + + void *iodata = NULL; + if (Android_JNI_FileOpen(&iodata, file, mode) < 0) { + SDL_CloseIO(iostr); + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_zero(iface); + iface.size = Android_JNI_FileSize; + iface.seek = Android_JNI_FileSeek; + iface.read = Android_JNI_FileRead; + iface.write = Android_JNI_FileWrite; + iface.close = Android_JNI_FileClose; + + 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_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(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) + FILE *fp = N3DS_FileOpen(file, mode); + #else + FILE *fp = fopen(file, mode); + #endif + + if (!fp) { + SDL_SetError("Couldn't open %s", file); + } 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); + } + } + +#else + SDL_SetError("SDL not compiled with stdio support"); +#endif /* !HAVE_STDIO_H */ + + return iostr; +} + +SDL_IOStream *SDL_IOFromMem(void *mem, size_t size) +{ + if (!mem) { + SDL_InvalidParamError("mem"); + return NULL; + } else if (!size) { + SDL_InvalidParamError("size"); + return NULL; + } + + IOStreamMemData *iodata = (IOStreamMemData *) SDL_malloc(sizeof (*iodata)); + if (!iodata) { + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_zero(iface); + iface.size = mem_size; + iface.seek = mem_seek; + iface.read = mem_read; + iface.write = mem_write; + iface.close = mem_close; + + iodata->base = (Uint8 *)mem; + iodata->here = iodata->base; + iodata->stop = iodata->base + size; + + SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); + if (!iostr) { + SDL_free(iodata); + } + return iostr; +} + +SDL_IOStream *SDL_IOFromConstMem(const void *mem, size_t size) +{ + if (!mem) { + SDL_InvalidParamError("mem"); + return NULL; + } else if (!size) { + SDL_InvalidParamError("size"); + return NULL; + } + + IOStreamMemData *iodata = (IOStreamMemData *) SDL_malloc(sizeof (*iodata)); + if (!iodata) { + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_zero(iface); + iface.size = mem_size; + iface.seek = mem_seek; + iface.read = mem_read; + // leave iface.write as NULL. + iface.close = mem_close; + + iodata->base = (Uint8 *)mem; + iodata->here = iodata->base; + iodata->stop = iodata->base + size; + + SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); + if (!iostr) { + SDL_free(iodata); + } + return iostr; +} + +typedef struct IOStreamDynamicMemData +{ + SDL_IOStream *stream; + IOStreamMemData data; + Uint8 *end; +} IOStreamDynamicMemData; + +static Sint64 SDLCALL dynamic_mem_size(void *userdata) +{ + IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata; + return mem_size(&iodata->data); +} + +static Sint64 SDLCALL dynamic_mem_seek(void *userdata, Sint64 offset, int whence) +{ + IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata; + return mem_seek(&iodata->data, offset, whence); +} + +static size_t SDLCALL dynamic_mem_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata; + return mem_io(&iodata->data, ptr, iodata->data.here, size); +} + +static int 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) { + chunksize = 1024; + } + + // We're intentionally allocating more memory than needed so it can be null terminated + size_t chunks = (((iodata->end - iodata->data.base) + size) / chunksize) + 1; + size_t length = (chunks * chunksize); + Uint8 *base = (Uint8 *)SDL_realloc(iodata->data.base, length); + if (!base) { + return -1; + } + + size_t here_offset = (iodata->data.here - iodata->data.base); + size_t stop_offset = (iodata->data.stop - iodata->data.base); + iodata->data.base = base; + 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); +} + +static size_t SDLCALL dynamic_mem_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) +{ + 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) { + return 0; + } + } + iodata->data.stop = iodata->data.here + size; + } + return mem_io(&iodata->data, iodata->data.here, ptr, size); +} + +static int 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); + if (mem) { + SDL_free(mem); + } + SDL_free(userdata); + return 0; +} + +SDL_IOStream *SDL_IOFromDynamicMem(void) +{ + IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) SDL_malloc(sizeof (*iodata)); + if (!iodata) { + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_zero(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; + } else { + SDL_free(iodata); + } + return iostr; +} + +SDL_IOStatus SDL_GetIOStatus(SDL_IOStream *context) +{ + if (!context) { + SDL_InvalidParamError("context"); + return SDL_IO_STATUS_ERROR; + } + return context->status; +} + +SDL_IOStream *SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata) +{ + if (!iface) { + SDL_InvalidParamError("iface"); + return NULL; + } + + SDL_IOStream *iostr = (SDL_IOStream *)SDL_calloc(1, sizeof(*iostr)); + if (iostr) { + SDL_copyp(&iostr->iface, iface); + iostr->userdata = userdata; + } + return iostr; +} + +int SDL_CloseIO(SDL_IOStream *iostr) +{ + int retval = 0; + if (iostr) { + if (iostr->iface.close) { + retval = iostr->iface.close(iostr->userdata); + } + SDL_DestroyProperties(iostr->props); + SDL_free(iostr); + } + return retval; +} + +/* Load all the data from an SDL data stream */ +void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_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; + + if (!src) { + SDL_InvalidParamError("src"); + goto done; + } + + size = SDL_GetIOSize(src); + if (size < 0) { + size = FILE_CHUNK_SIZE; + loading_chunks = SDL_TRUE; + } + if (size >= SDL_SIZE_MAX) { + goto done; + } + data = (char *)SDL_malloc((size_t)(size + 1)); + if (!data) { + goto done; + } + + size_total = 0; + for (;;) { + if (loading_chunks) { + if ((size_total + FILE_CHUNK_SIZE) > size) { + size = (size_total + FILE_CHUNK_SIZE); + if (size >= SDL_SIZE_MAX) { + newdata = NULL; + } else { + newdata = (char *)SDL_realloc(data, (size_t)(size + 1)); + } + if (!newdata) { + SDL_free(data); + data = NULL; + goto done; + } + data = newdata; + } + } + + size_read = SDL_ReadIO(src, data + size_total, (size_t)(size - size_total)); + if (size_read > 0) { + size_total += size_read; + continue; + } + + /* The stream status will remain set for the caller to check */ + break; + } + + data[size_total] = '\0'; + +done: + if (datasize) { + *datasize = (size_t)size_total; + } + if (closeio && src) { + SDL_CloseIO(src); + } + return data; +} + +void *SDL_LoadFile(const char *file, size_t *datasize) +{ + return SDL_LoadFile_IO(SDL_IOFromFile(file, "rb"), datasize, SDL_TRUE); +} + +SDL_PropertiesID SDL_GetIOProperties(SDL_IOStream *context) +{ + if (!context) { + SDL_InvalidParamError("context"); + return 0; + } + + if (context->props == 0) { + context->props = SDL_CreateProperties(); + } + return context->props; +} + +Sint64 SDL_GetIOSize(SDL_IOStream *context) +{ + if (!context) { + return SDL_InvalidParamError("context"); + } + if (!context->iface.size) { + Sint64 pos, size; + + pos = SDL_SeekIO(context, 0, SDL_IO_SEEK_CUR); + if (pos < 0) { + return -1; + } + size = SDL_SeekIO(context, 0, SDL_IO_SEEK_END); + + SDL_SeekIO(context, pos, SDL_IO_SEEK_SET); + return size; + } + return context->iface.size(context->userdata); +} + +Sint64 SDL_SeekIO(SDL_IOStream *context, Sint64 offset, int whence) +{ + if (!context) { + return SDL_InvalidParamError("context"); + } else if (!context->iface.seek) { + return SDL_Unsupported(); + } + return context->iface.seek(context->userdata, offset, whence); +} + +Sint64 SDL_TellIO(SDL_IOStream *context) +{ + return SDL_SeekIO(context, 0, SDL_IO_SEEK_CUR); +} + +size_t SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size) +{ + size_t bytes; + + if (!context) { + SDL_InvalidParamError("context"); + return 0; + } else if (!context->iface.read) { + context->status = SDL_IO_STATUS_WRITEONLY; + SDL_Unsupported(); + return 0; + } + + context->status = SDL_IO_STATUS_READY; + SDL_ClearError(); + + if (size == 0) { + return 0; + } + + bytes = context->iface.read(context->userdata, ptr, size, &context->status); + if (bytes == 0 && context->status == SDL_IO_STATUS_READY) { + if (*SDL_GetError()) { + context->status = SDL_IO_STATUS_ERROR; + } else { + context->status = SDL_IO_STATUS_EOF; + } + } + return bytes; +} + +size_t SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size) +{ + size_t bytes; + + if (!context) { + SDL_InvalidParamError("context"); + return 0; + } else if (!context->iface.write) { + context->status = SDL_IO_STATUS_READONLY; + SDL_Unsupported(); + return 0; + } + + context->status = SDL_IO_STATUS_READY; + SDL_ClearError(); + + if (size == 0) { + return 0; + } + + bytes = context->iface.write(context->userdata, ptr, size, &context->status); + if ((bytes == 0) && (context->status == SDL_IO_STATUS_READY)) { + context->status = SDL_IO_STATUS_ERROR; + } + return bytes; +} + +size_t SDL_IOprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +{ + va_list ap; + int size; + char *string; + size_t bytes; + + va_start(ap, fmt); + size = SDL_vasprintf(&string, fmt, ap); + va_end(ap); + if (size < 0) { + return 0; + } + + bytes = SDL_WriteIO(context, string, (size_t)size); + SDL_free(string); + return bytes; +} + +size_t SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) +{ + int size; + char *string; + size_t bytes; + + size = SDL_vasprintf(&string, fmt, ap); + if (size < 0) { + return 0; + } + + bytes = SDL_WriteIO(context, string, (size_t)size); + SDL_free(string); + return bytes; +} + +/* Functions for dynamically reading and writing endian-specific values */ + +SDL_bool SDL_ReadU8(SDL_IOStream *src, Uint8 *value) +{ + Uint8 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = data; + } + return result; +} + +SDL_bool SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value) +{ + Uint16 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = SDL_SwapLE16(data); + } + return result; +} + +SDL_bool SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value) +{ + return SDL_ReadU16LE(src, (Uint16 *)value); +} + +SDL_bool SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value) +{ + Uint16 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = SDL_SwapBE16(data); + } + return result; +} + +SDL_bool SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value) +{ + return SDL_ReadU16BE(src, (Uint16 *)value); +} + +SDL_bool SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value) +{ + Uint32 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = SDL_SwapLE32(data); + } + return result; +} + +SDL_bool SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value) +{ + return SDL_ReadU32LE(src, (Uint32 *)value); +} + +SDL_bool SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value) +{ + Uint32 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = SDL_SwapBE32(data); + } + return result; +} + +SDL_bool SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value) +{ + return SDL_ReadU32BE(src, (Uint32 *)value); +} + +SDL_bool SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value) +{ + Uint64 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = SDL_SwapLE64(data); + } + return result; +} + +SDL_bool SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value) +{ + return SDL_ReadU64LE(src, (Uint64 *)value); +} + +SDL_bool SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value) +{ + Uint64 data = 0; + SDL_bool result = SDL_FALSE; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = SDL_TRUE; + } + if (value) { + *value = SDL_SwapBE64(data); + } + return result; +} + +SDL_bool SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value) +{ + return SDL_ReadU64BE(src, (Uint64 *)value); +} + +SDL_bool SDL_WriteU8(SDL_IOStream *dst, Uint8 value) +{ + return (SDL_WriteIO(dst, &value, sizeof(value)) == sizeof(value)); +} + +SDL_bool SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value) +{ + const Uint16 swapped = SDL_SwapLE16(value); + return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); +} + +SDL_bool SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value) +{ + return SDL_WriteU16LE(dst, (Uint16)value); +} + +SDL_bool SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value) +{ + const Uint16 swapped = SDL_SwapBE16(value); + return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); +} + +SDL_bool SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value) +{ + return SDL_WriteU16BE(dst, (Uint16)value); +} + +SDL_bool SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value) +{ + const Uint32 swapped = SDL_SwapLE32(value); + return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); +} + +SDL_bool SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value) +{ + return SDL_WriteU32LE(dst, (Uint32)value); +} + +SDL_bool SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value) +{ + const Uint32 swapped = SDL_SwapBE32(value); + return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); +} + +SDL_bool SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value) +{ + return SDL_WriteU32BE(dst, (Uint32)value); +} + +SDL_bool SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value) +{ + const Uint64 swapped = SDL_SwapLE64(value); + return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); +} + +SDL_bool SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value) +{ + return SDL_WriteU64LE(dst, (Uint64)value); +} + +SDL_bool SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value) +{ + const Uint64 swapped = SDL_SwapBE64(value); + return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); +} + +SDL_bool SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value) +{ + return SDL_WriteU64BE(dst, (Uint64)value); +} diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c deleted file mode 100644 index dde12ded..00000000 --- a/src/file/SDL_rwops.c +++ /dev/null @@ -1,1052 +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" - -#if defined(__WIN32__) || defined(__GDK__) || defined(__WINRT__) -#include "../core/windows/SDL_windows.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif - -/* This file provides a general interface for SDL to read and write - data sources. It can easily be extended to files, memory, etc. -*/ - -#ifdef __APPLE__ -#include "cocoa/SDL_rwopsbundlesupport.h" -#endif /* __APPLE__ */ - -#ifdef __3DS__ -#include "n3ds/SDL_rwopsromfs.h" -#endif /* __3DS__ */ - -#ifdef __ANDROID__ -#include "../core/android/SDL_android.h" -#endif - -#if defined(__WIN32__) || defined(__GDK__) || defined(__WINRT__) - -/* 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(SDL_RWops *context, const char *filename, const char *mode) -{ -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) && !defined(__WINRT__) - UINT old_error_mode; -#endif - HANDLE h; - DWORD r_right, w_right; - DWORD must_exist, truncate; - int a_mode; - - context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */ - context->hidden.windowsio.buffer.data = NULL; - context->hidden.windowsio.buffer.size = 0; - context->hidden.windowsio.buffer.left = 0; - - /* "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; - r_right = (SDL_strchr(mode, '+') != NULL || must_exist) ? GENERIC_READ : 0; - a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0; - w_right = (a_mode || SDL_strchr(mode, '+') || truncate) ? GENERIC_WRITE : 0; - - if (!r_right && !w_right) { - return -1; /* inconsistent mode */ - } - /* failed (invalid call) */ - - context->hidden.windowsio.buffer.data = - (char *)SDL_malloc(READAHEAD_BUFFER_SIZE); - if (!context->hidden.windowsio.buffer.data) { - return -1; - } -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) && !defined(__WINRT__) - /* Do not open a dialog box if failure */ - old_error_mode = - SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); -#endif - - { - LPTSTR tstr = WIN_UTF8ToString(filename); -#if defined(__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, - (w_right | r_right), - (w_right) ? 0 : FILE_SHARE_READ, - NULL, - (must_exist | truncate | a_mode), - FILE_ATTRIBUTE_NORMAL, - NULL); -#endif - SDL_free(tstr); - } - -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) && !defined(__WINRT__) - /* restore old behavior */ - SetErrorMode(old_error_mode); -#endif - - if (h == INVALID_HANDLE_VALUE) { - SDL_free(context->hidden.windowsio.buffer.data); - context->hidden.windowsio.buffer.data = NULL; - SDL_SetError("Couldn't open %s", filename); - return -2; /* failed (CreateFile) */ - } - context->hidden.windowsio.h = h; - context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE; - - return 0; /* ok */ -} - -static Sint64 SDLCALL windows_file_size(SDL_RWops *context) -{ - LARGE_INTEGER size; - - if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) { - return WIN_SetError("windows_file_size"); - } - - return size.QuadPart; -} - -static Sint64 SDLCALL windows_file_seek(SDL_RWops *context, Sint64 offset, int whence) -{ - DWORD windowswhence; - LARGE_INTEGER windowsoffset; - - /* FIXME: We may be able to satisfy the seek within buffered data */ - if (whence == SDL_RW_SEEK_CUR && context->hidden.windowsio.buffer.left) { - offset -= context->hidden.windowsio.buffer.left; - } - context->hidden.windowsio.buffer.left = 0; - - switch (whence) { - case SDL_RW_SEEK_SET: - windowswhence = FILE_BEGIN; - break; - case SDL_RW_SEEK_CUR: - windowswhence = FILE_CURRENT; - break; - case SDL_RW_SEEK_END: - windowswhence = FILE_END; - break; - default: - return SDL_SetError("windows_file_seek: Unknown value for 'whence'"); - } - - windowsoffset.QuadPart = offset; - if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) { - return WIN_SetError("windows_file_seek"); - } - return windowsoffset.QuadPart; -} - -static size_t SDLCALL windows_file_read(SDL_RWops *context, void *ptr, size_t size) -{ - size_t total_need = size; - size_t total_read = 0; - size_t read_ahead; - DWORD bytes; - - if (context->hidden.windowsio.buffer.left > 0) { - void *data = (char *)context->hidden.windowsio.buffer.data + - context->hidden.windowsio.buffer.size - - context->hidden.windowsio.buffer.left; - read_ahead = SDL_min(total_need, context->hidden.windowsio.buffer.left); - SDL_memcpy(ptr, data, read_ahead); - context->hidden.windowsio.buffer.left -= read_ahead; - - if (read_ahead == total_need) { - return size; - } - ptr = (char *)ptr + read_ahead; - total_need -= read_ahead; - total_read += read_ahead; - } - - if (total_need < READAHEAD_BUFFER_SIZE) { - if (!ReadFile(context->hidden.windowsio.h, context->hidden.windowsio.buffer.data, - READAHEAD_BUFFER_SIZE, &bytes, NULL)) { - SDL_Error(SDL_EFREAD); - return 0; - } - read_ahead = SDL_min(total_need, bytes); - SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead); - context->hidden.windowsio.buffer.size = bytes; - context->hidden.windowsio.buffer.left = bytes - read_ahead; - total_read += read_ahead; - } else { - if (!ReadFile(context->hidden.windowsio.h, ptr, (DWORD)total_need, &bytes, NULL)) { - SDL_Error(SDL_EFREAD); - return 0; - } - total_read += bytes; - } - return total_read; -} - -static size_t SDLCALL windows_file_write(SDL_RWops *context, const void *ptr, size_t size) -{ - const size_t total_bytes = size; - DWORD bytes; - - if (context->hidden.windowsio.buffer.left) { - if (!SetFilePointer(context->hidden.windowsio.h, - -(LONG)context->hidden.windowsio.buffer.left, NULL, - FILE_CURRENT)) { - SDL_Error(SDL_EFSEEK); - return 0; - } - context->hidden.windowsio.buffer.left = 0; - } - - /* if in append mode, we must go to the EOF before write */ - if (context->hidden.windowsio.append) { - LARGE_INTEGER windowsoffset; - windowsoffset.QuadPart = 0; - if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, FILE_END)) { - SDL_Error(SDL_EFSEEK); - return 0; - } - } - - if (!WriteFile(context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &bytes, NULL)) { - SDL_Error(SDL_EFWRITE); - return 0; - } - - return bytes; -} - -static int SDLCALL windows_file_close(SDL_RWops *context) -{ - if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) { - CloseHandle(context->hidden.windowsio.h); - context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */ - } - if (context->hidden.windowsio.buffer.data) { - SDL_free(context->hidden.windowsio.buffer.data); - context->hidden.windowsio.buffer.data = NULL; - } - SDL_DestroyRW(context); - return 0; -} -#endif /* defined(__WIN32__) || defined(__GDK__) */ - -#if defined(HAVE_STDIO_H) && !(defined(__WIN32__) || defined(__GDK__)) - -/* Functions to read/write stdio file pointers. Not used for windows. */ - -#ifdef HAVE_FOPEN64 -#define fopen fopen64 -#endif -#ifdef HAVE_FSEEKO64 -#define fseek_off_t off64_t -#define fseek fseeko64 -#define ftell ftello64 -#elif defined(HAVE_FSEEKO) -#if defined(OFF_MIN) && defined(OFF_MAX) -#define FSEEK_OFF_MIN OFF_MIN -#define FSEEK_OFF_MAX OFF_MAX -#elif defined(HAVE_LIMITS_H) -/* POSIX doesn't specify the minimum and maximum macros for off_t so - * we have to improvise and dance around implementation-defined - * behavior. This may fail if the off_t type has padding bits or - * is not a two's-complement representation. The compilers will detect - * and eliminate the dead code if off_t has 64 bits. - */ -#define FSEEK_OFF_MAX (((((off_t)1 << (sizeof(off_t) * CHAR_BIT - 2)) - 1) << 1) + 1) -#define FSEEK_OFF_MIN (-(FSEEK_OFF_MAX)-1) -#endif -#define fseek_off_t off_t -#define fseek fseeko -#define ftell ftello -#elif defined(HAVE__FSEEKI64) -#define fseek_off_t __int64 -#define fseek _fseeki64 -#define ftell _ftelli64 -#else -#ifdef HAVE_LIMITS_H -#define FSEEK_OFF_MIN LONG_MIN -#define FSEEK_OFF_MAX LONG_MAX -#endif -#define fseek_off_t long -#endif - -static Sint64 SDLCALL stdio_seek(SDL_RWops *context, Sint64 offset, int whence) -{ - int stdiowhence; - - switch (whence) { - case SDL_RW_SEEK_SET: - stdiowhence = SEEK_SET; - break; - case SDL_RW_SEEK_CUR: - stdiowhence = SEEK_CUR; - break; - case SDL_RW_SEEK_END: - stdiowhence = SEEK_END; - break; - default: - return SDL_SetError("Unknown value for 'whence'"); - } - -#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"); - } -#endif - - if (fseek((FILE *)context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) { - Sint64 pos = ftell((FILE *)context->hidden.stdio.fp); - if (pos < 0) { - return SDL_SetError("Couldn't get stream offset"); - } - return pos; - } - return SDL_Error(SDL_EFSEEK); -} - -static size_t SDLCALL stdio_read(SDL_RWops *context, void *ptr, size_t size) -{ - size_t bytes; - - bytes = fread(ptr, 1, size, (FILE *)context->hidden.stdio.fp); - if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { - SDL_Error(SDL_EFREAD); - } - return bytes; -} - -static size_t SDLCALL stdio_write(SDL_RWops *context, const void *ptr, size_t size) -{ - size_t bytes; - - bytes = fwrite(ptr, 1, size, (FILE *)context->hidden.stdio.fp); - if (bytes == 0 && ferror((FILE *)context->hidden.stdio.fp)) { - SDL_Error(SDL_EFWRITE); - } - return bytes; -} - -static int SDLCALL stdio_close(SDL_RWops *context) -{ - int status = 0; - if (context->hidden.stdio.autoclose) { - if (fclose((FILE *)context->hidden.stdio.fp) != 0) { - status = SDL_Error(SDL_EFWRITE); - } - } - SDL_DestroyRW(context); - return status; -} - -static SDL_RWops *SDL_RWFromFP(void *fp, SDL_bool autoclose) -{ - SDL_RWops *rwops = NULL; - - rwops = SDL_CreateRW(); - if (rwops) { - rwops->seek = stdio_seek; - rwops->read = stdio_read; - rwops->write = stdio_write; - rwops->close = stdio_close; - rwops->hidden.stdio.fp = fp; - rwops->hidden.stdio.autoclose = autoclose; - rwops->type = SDL_RWOPS_STDFILE; - } - return rwops; -} -#endif /* !HAVE_STDIO_H && !(__WIN32__ || __GDK__) */ - -/* Functions to read/write memory pointers */ - -static Sint64 SDLCALL mem_size(SDL_RWops *context) -{ - return (context->hidden.mem.stop - context->hidden.mem.base); -} - -static Sint64 SDLCALL mem_seek(SDL_RWops *context, Sint64 offset, int whence) -{ - Uint8 *newpos; - - switch (whence) { - case SDL_RW_SEEK_SET: - newpos = context->hidden.mem.base + offset; - break; - case SDL_RW_SEEK_CUR: - newpos = context->hidden.mem.here + offset; - break; - case SDL_RW_SEEK_END: - newpos = context->hidden.mem.stop + offset; - break; - default: - return SDL_SetError("Unknown value for 'whence'"); - } - if (newpos < context->hidden.mem.base) { - newpos = context->hidden.mem.base; - } - if (newpos > context->hidden.mem.stop) { - newpos = context->hidden.mem.stop; - } - context->hidden.mem.here = newpos; - return (Sint64)(context->hidden.mem.here - context->hidden.mem.base); -} - -static size_t mem_io(SDL_RWops *context, void *dst, const void *src, size_t size) -{ - const size_t mem_available = (context->hidden.mem.stop - context->hidden.mem.here); - if (size > mem_available) { - size = mem_available; - } - SDL_memcpy(dst, src, size); - context->hidden.mem.here += size; - return size; -} - -static size_t SDLCALL mem_read(SDL_RWops *context, void *ptr, size_t size) -{ - return mem_io(context, ptr, context->hidden.mem.here, size); -} - -static size_t SDLCALL mem_write(SDL_RWops *context, const void *ptr, size_t size) -{ - return mem_io(context, context->hidden.mem.here, ptr, size); -} - -/* Functions to create SDL_RWops structures from various data sources */ - -SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) -{ - SDL_RWops *rwops = NULL; - if (!file || !*file || !mode || !*mode) { - SDL_SetError("SDL_RWFromFile(): No file or no mode specified"); - return NULL; - } -#ifdef __ANDROID__ -#ifdef HAVE_STDIO_H - /* Try to open the file on the filesystem first */ - if (*file == '/') { - FILE *fp = fopen(file, mode); - if (fp) { - return SDL_RWFromFP(fp, 1); - } - } else { - /* Try opening it from internal storage if it's a relative path */ - char *path; - FILE *fp; - - /* !!! FIXME: why not just "char path[PATH_MAX];" ? */ - path = SDL_stack_alloc(char, PATH_MAX); - if (path) { - SDL_snprintf(path, PATH_MAX, "%s/%s", - SDL_AndroidGetInternalStoragePath(), file); - fp = fopen(path, mode); - SDL_stack_free(path); - if (fp) { - return SDL_RWFromFP(fp, 1); - } - } - } -#endif /* HAVE_STDIO_H */ - - /* Try to open the file from the asset system */ - rwops = SDL_CreateRW(); - if (!rwops) { - return NULL; /* SDL_SetError already setup by SDL_CreateRW() */ - } - - if (Android_JNI_FileOpen(rwops, file, mode) < 0) { - SDL_DestroyRW(rwops); - return NULL; - } - rwops->size = Android_JNI_FileSize; - rwops->seek = Android_JNI_FileSeek; - rwops->read = Android_JNI_FileRead; - rwops->write = Android_JNI_FileWrite; - rwops->close = Android_JNI_FileClose; - rwops->type = SDL_RWOPS_JNIFILE; - -#elif defined(__WIN32__) || defined(__GDK__) || defined(__WINRT__) - rwops = SDL_CreateRW(); - if (!rwops) { - return NULL; /* SDL_SetError already setup by SDL_CreateRW() */ - } - - if (windows_file_open(rwops, file, mode) < 0) { - SDL_DestroyRW(rwops); - return NULL; - } - rwops->size = windows_file_size; - rwops->seek = windows_file_seek; - rwops->read = windows_file_read; - rwops->write = windows_file_write; - rwops->close = windows_file_close; - rwops->type = SDL_RWOPS_WINFILE; -#elif defined(HAVE_STDIO_H) - { -#if defined(__APPLE__) && !defined(SDL_FILE_DISABLED) // TODO: add dummy? - FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode); -#elif defined(__WINRT__) - FILE *fp = NULL; - fopen_s(&fp, file, mode); -#elif defined(__3DS__) - FILE *fp = N3DS_FileOpen(file, mode); -#else - FILE *fp = fopen(file, mode); -#endif - if (!fp) { - SDL_SetError("Couldn't open %s", file); - } else { - rwops = SDL_RWFromFP(fp, SDL_TRUE); - } - } -#else - SDL_SetError("SDL not compiled with stdio support"); -#endif /* !HAVE_STDIO_H */ - - return rwops; -} - -SDL_RWops *SDL_RWFromMem(void *mem, size_t size) -{ - SDL_RWops *rwops = NULL; - - if (!mem) { - SDL_InvalidParamError("mem"); - return NULL; - } - if (!size) { - SDL_InvalidParamError("size"); - return NULL; - } - - rwops = SDL_CreateRW(); - if (rwops) { - rwops->size = mem_size; - rwops->seek = mem_seek; - rwops->read = mem_read; - rwops->write = mem_write; - rwops->hidden.mem.base = (Uint8 *)mem; - rwops->hidden.mem.here = rwops->hidden.mem.base; - rwops->hidden.mem.stop = rwops->hidden.mem.base + size; - rwops->type = SDL_RWOPS_MEMORY; - } - return rwops; -} - -SDL_RWops *SDL_RWFromConstMem(const void *mem, size_t size) -{ - SDL_RWops *rwops = NULL; - - if (!mem) { - SDL_InvalidParamError("mem"); - return NULL; - } - if (!size) { - SDL_InvalidParamError("size"); - return NULL; - } - - rwops = SDL_CreateRW(); - if (rwops) { - rwops->size = mem_size; - rwops->seek = mem_seek; - rwops->read = mem_read; - rwops->hidden.mem.base = (Uint8 *)mem; - rwops->hidden.mem.here = rwops->hidden.mem.base; - rwops->hidden.mem.stop = rwops->hidden.mem.base + size; - rwops->type = SDL_RWOPS_MEMORY_RO; - } - return rwops; -} - -SDL_RWops *SDL_CreateRW(void) -{ - SDL_RWops *context; - - context = (SDL_RWops *)SDL_calloc(1, sizeof(*context)); - if (context) { - context->type = SDL_RWOPS_UNKNOWN; - } - return context; -} - -void SDL_DestroyRW(SDL_RWops *context) -{ - SDL_DestroyProperties(context->props); - SDL_free(context); -} - -/* Load all the data from an SDL data stream */ -void *SDL_LoadFile_RW(SDL_RWops *src, size_t *datasize, SDL_bool freesrc) -{ - const int FILE_CHUNK_SIZE = 1024; - Sint64 size, size_total; - size_t size_read; - char *data = NULL, *newdata; - SDL_bool loading_chunks = SDL_FALSE; - - if (!src) { - SDL_InvalidParamError("src"); - return NULL; - } - - size = SDL_RWsize(src); - if (size < 0) { - size = FILE_CHUNK_SIZE; - loading_chunks = SDL_TRUE; - } - if (size >= SDL_SIZE_MAX) { - goto done; - } - data = (char *)SDL_malloc((size_t)(size + 1)); - if (!data) { - goto done; - } - - size_total = 0; - for (;;) { - if (loading_chunks) { - if ((size_total + FILE_CHUNK_SIZE) > size) { - size = (size_total + FILE_CHUNK_SIZE); - if (size >= SDL_SIZE_MAX) { - newdata = NULL; - } else { - newdata = SDL_realloc(data, (size_t)(size + 1)); - } - if (!newdata) { - SDL_free(data); - data = NULL; - goto done; - } - data = newdata; - } - } - - size_read = SDL_RWread(src, data + size_total, (size_t)(size - size_total)); - if (size_read > 0) { - size_total += size_read; - continue; - } - - /* The stream status will remain set for the caller to check */ - break; - } - - if (datasize) { - *datasize = (size_t)size_total; - } - data[size_total] = '\0'; - -done: - if (freesrc && src) { - SDL_RWclose(src); - } - return data; -} - -void *SDL_LoadFile(const char *file, size_t *datasize) -{ - return SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, SDL_TRUE); -} - -SDL_PropertiesID SDL_GetRWProperties(SDL_RWops *context) -{ - if (!context) { - SDL_InvalidParamError("context"); - return 0; - } - - if (context->props == 0) { - context->props = SDL_CreateProperties(); - } - return context->props; -} - -Sint64 SDL_RWsize(SDL_RWops *context) -{ - if (!context) { - return SDL_InvalidParamError("context"); - } - if (!context->size) { - Sint64 pos, size; - - pos = SDL_RWseek(context, 0, SDL_RW_SEEK_CUR); - if (pos < 0) { - return -1; - } - size = SDL_RWseek(context, 0, SDL_RW_SEEK_END); - - SDL_RWseek(context, pos, SDL_RW_SEEK_SET); - return size; - } - return context->size(context); -} - -Sint64 SDL_RWseek(SDL_RWops *context, Sint64 offset, int whence) -{ - if (!context) { - return SDL_InvalidParamError("context"); - } - if (!context->seek) { - return SDL_Unsupported(); - } - return context->seek(context, offset, whence); -} - -Sint64 SDL_RWtell(SDL_RWops *context) -{ - return SDL_RWseek(context, 0, SDL_RW_SEEK_CUR); -} - -size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size) -{ - size_t bytes; - - if (!context) { - SDL_InvalidParamError("context"); - return 0; - } - if (!context->read) { - context->status = SDL_RWOPS_STATUS_WRITEONLY; - SDL_Unsupported(); - return 0; - } - - context->status = SDL_RWOPS_STATUS_READY; - SDL_ClearError(); - - if (size == 0) { - return 0; - } - - bytes = context->read(context, ptr, size); - if (bytes == 0 && context->status == SDL_RWOPS_STATUS_READY) { - if (*SDL_GetError()) { - context->status = SDL_RWOPS_STATUS_ERROR; - } else { - context->status = SDL_RWOPS_STATUS_EOF; - } - } - return bytes; -} - -size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size) -{ - size_t bytes; - - if (!context) { - SDL_InvalidParamError("context"); - return 0; - } - if (!context->write) { - context->status = SDL_RWOPS_STATUS_READONLY; - SDL_Unsupported(); - return 0; - } - - context->status = SDL_RWOPS_STATUS_READY; - SDL_ClearError(); - - if (size == 0) { - return 0; - } - - bytes = context->write(context, ptr, size); - if (bytes == 0 && context->status == SDL_RWOPS_STATUS_READY) { - context->status = SDL_RWOPS_STATUS_ERROR; - } - return bytes; -} - -size_t SDL_RWprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) -{ - va_list ap; - int size; - char *string; - size_t bytes; - - va_start(ap, fmt); - size = SDL_vasprintf(&string, fmt, ap); - va_end(ap); - if (size < 0) { - return 0; - } - - bytes = SDL_RWwrite(context, string, (size_t)size); - SDL_free(string); - return bytes; -} - -size_t SDL_RWvprintf(SDL_RWops *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) -{ - int size; - char *string; - size_t bytes; - - size = SDL_vasprintf(&string, fmt, ap); - if (size < 0) { - return 0; - } - - bytes = SDL_RWwrite(context, string, (size_t)size); - SDL_free(string); - return bytes; -} - -int SDL_RWclose(SDL_RWops *context) -{ - if (!context) { - return SDL_InvalidParamError("context"); - } - if (!context->close) { - SDL_DestroyRW(context); - return 0; - } - return context->close(context); -} - -/* Functions for dynamically reading and writing endian-specific values */ - -SDL_bool SDL_ReadU8(SDL_RWops *src, Uint8 *value) -{ - Uint8 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = data; - } - return result; -} - -SDL_bool SDL_ReadU16LE(SDL_RWops *src, Uint16 *value) -{ - Uint16 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = SDL_SwapLE16(data); - } - return result; -} - -SDL_bool SDL_ReadS16LE(SDL_RWops *src, Sint16 *value) -{ - return SDL_ReadU16LE(src, (Uint16 *)value); -} - -SDL_bool SDL_ReadU16BE(SDL_RWops *src, Uint16 *value) -{ - Uint16 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = SDL_SwapBE16(data); - } - return result; -} - -SDL_bool SDL_ReadS16BE(SDL_RWops *src, Sint16 *value) -{ - return SDL_ReadU16BE(src, (Uint16 *)value); -} - -SDL_bool SDL_ReadU32LE(SDL_RWops *src, Uint32 *value) -{ - Uint32 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = SDL_SwapLE32(data); - } - return result; -} - -SDL_bool SDL_ReadS32LE(SDL_RWops *src, Sint32 *value) -{ - return SDL_ReadU32LE(src, (Uint32 *)value); -} - -SDL_bool SDL_ReadU32BE(SDL_RWops *src, Uint32 *value) -{ - Uint32 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = SDL_SwapBE32(data); - } - return result; -} - -SDL_bool SDL_ReadS32BE(SDL_RWops *src, Sint32 *value) -{ - return SDL_ReadU32BE(src, (Uint32 *)value); -} - -SDL_bool SDL_ReadU64LE(SDL_RWops *src, Uint64 *value) -{ - Uint64 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = SDL_SwapLE64(data); - } - return result; -} - -SDL_bool SDL_ReadS64LE(SDL_RWops *src, Sint64 *value) -{ - return SDL_ReadU64LE(src, (Uint64 *)value); -} - -SDL_bool SDL_ReadU64BE(SDL_RWops *src, Uint64 *value) -{ - Uint64 data = 0; - SDL_bool result = SDL_FALSE; - - if (SDL_RWread(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; - } - if (value) { - *value = SDL_SwapBE64(data); - } - return result; -} - -SDL_bool SDL_ReadS64BE(SDL_RWops *src, Sint64 *value) -{ - return SDL_ReadU64BE(src, (Uint64 *)value); -} - -SDL_bool SDL_WriteU8(SDL_RWops *dst, Uint8 value) -{ - return (SDL_RWwrite(dst, &value, sizeof(value)) == sizeof(value)); -} - -SDL_bool SDL_WriteU16LE(SDL_RWops *dst, Uint16 value) -{ - const Uint16 swapped = SDL_SwapLE16(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); -} - -SDL_bool SDL_WriteS16LE(SDL_RWops *dst, Sint16 value) -{ - return SDL_WriteU16LE(dst, (Uint16)value); -} - -SDL_bool SDL_WriteU16BE(SDL_RWops *dst, Uint16 value) -{ - const Uint16 swapped = SDL_SwapBE16(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); -} - -SDL_bool SDL_WriteS16BE(SDL_RWops *dst, Sint16 value) -{ - return SDL_WriteU16BE(dst, (Uint16)value); -} - -SDL_bool SDL_WriteU32LE(SDL_RWops *dst, Uint32 value) -{ - const Uint32 swapped = SDL_SwapLE32(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); -} - -SDL_bool SDL_WriteS32LE(SDL_RWops *dst, Sint32 value) -{ - return SDL_WriteU32LE(dst, (Uint32)value); -} - -SDL_bool SDL_WriteU32BE(SDL_RWops *dst, Uint32 value) -{ - const Uint32 swapped = SDL_SwapBE32(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); -} - -SDL_bool SDL_WriteS32BE(SDL_RWops *dst, Sint32 value) -{ - return SDL_WriteU32BE(dst, (Uint32)value); -} - -SDL_bool SDL_WriteU64LE(SDL_RWops *dst, Uint64 value) -{ - const Uint64 swapped = SDL_SwapLE64(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); -} - -SDL_bool SDL_WriteS64LE(SDL_RWops *dst, Sint64 value) -{ - return SDL_WriteU64LE(dst, (Uint64)value); -} - -SDL_bool SDL_WriteU64BE(SDL_RWops *dst, Uint64 value) -{ - const Uint64 swapped = SDL_SwapBE64(value); - return (SDL_RWwrite(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); -} - -SDL_bool SDL_WriteS64BE(SDL_RWops *dst, Sint64 value) -{ - return SDL_WriteU64BE(dst, (Uint64)value); -} diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.h b/src/file/cocoa/SDL_iostreambundlesupport.h similarity index 91% rename from src/file/cocoa/SDL_rwopsbundlesupport.h rename to src/file/cocoa/SDL_iostreambundlesupport.h index c57ce452..e7b337a7 100644 --- a/src/file/cocoa/SDL_rwopsbundlesupport.h +++ b/src/file/cocoa/SDL_iostreambundlesupport.h @@ -19,12 +19,12 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifdef __APPLE__ +#ifdef SDL_PLATFORM_APPLE #include -#ifndef SDL_rwopsbundlesupport_h -#define SDL_rwopsbundlesupport_h +#ifndef SDL_iostreambundlesupport_h +#define SDL_iostreambundlesupport_h FILE *SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode); #endif #endif diff --git a/src/file/cocoa/SDL_rwopsbundlesupport.m b/src/file/cocoa/SDL_iostreambundlesupport.m similarity index 96% rename from src/file/cocoa/SDL_rwopsbundlesupport.m rename to src/file/cocoa/SDL_iostreambundlesupport.m index a6f763b4..93a7b434 100644 --- a/src/file/cocoa/SDL_rwopsbundlesupport.m +++ b/src/file/cocoa/SDL_iostreambundlesupport.m @@ -20,10 +20,10 @@ */ #include "SDL_internal.h" -#ifdef __APPLE__ +#ifdef SDL_PLATFORM_APPLE #import -#include "SDL_rwopsbundlesupport.h" +#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. @@ -62,4 +62,4 @@ FILE *SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode) } } -#endif /* __APPLE__ */ +#endif /* SDL_PLATFORM_APPLE */ diff --git a/src/file/n3ds/SDL_rwopsromfs.c b/src/file/n3ds/SDL_iostreamromfs.c similarity index 98% rename from src/file/n3ds/SDL_rwopsromfs.c rename to src/file/n3ds/SDL_iostreamromfs.c index afa9e53c..3af006b4 100644 --- a/src/file/n3ds/SDL_rwopsromfs.c +++ b/src/file/n3ds/SDL_iostreamromfs.c @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_rwopsromfs.h" +#include "SDL_iostreamromfs.h" /* Checks if the mode is a kind of reading */ static SDL_bool IsReadMode(const char *mode); diff --git a/src/file/n3ds/SDL_rwopsromfs.h b/src/file/n3ds/SDL_iostreamromfs.h similarity index 91% rename from src/file/n3ds/SDL_rwopsromfs.h rename to src/file/n3ds/SDL_iostreamromfs.h index 572a7144..4f8827fa 100644 --- a/src/file/n3ds/SDL_rwopsromfs.h +++ b/src/file/n3ds/SDL_iostreamromfs.h @@ -20,9 +20,9 @@ */ #include "SDL_internal.h" -#ifndef SDL_rwopsromfs_h_ -#define SDL_rwopsromfs_h_ +#ifndef SDL_iostreamromfs_h_ +#define SDL_iostreamromfs_h_ FILE *N3DS_FileOpen(const char *file, const char *mode); -#endif /* SDL_rwopsromfs_h_ */ +#endif /* SDL_iostreamromfs_h_ */ diff --git a/src/filesystem/SDL_filesystem.c b/src/filesystem/SDL_filesystem.c new file mode 100644 index 00000000..2a8667ff --- /dev/null +++ b/src/filesystem/SDL_filesystem.c @@ -0,0 +1,76 @@ +/* + 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_sysfilesystem.h" + +int SDL_RemovePath(const char *path) +{ + if (!path) { + return SDL_InvalidParamError("path"); + } + return SDL_SYS_RemovePath(path); +} + +int SDL_RenamePath(const char *oldpath, const char *newpath) +{ + if (!oldpath) { + return SDL_InvalidParamError("oldpath"); + } else if (!newpath) { + return SDL_InvalidParamError("newpath"); + } + return SDL_SYS_RenamePath(oldpath, newpath); +} + +int SDL_CreateDirectory(const char *path) +{ + /* TODO: Recursively create subdirectories */ + if (!path) { + return SDL_InvalidParamError("path"); + } + return SDL_SYS_CreateDirectory(path); +} + +int SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata) +{ + if (!path) { + return SDL_InvalidParamError("path"); + } else if (!callback) { + return SDL_InvalidParamError("callback"); + } + return SDL_SYS_EnumerateDirectory(path, path, callback, userdata); +} + +int SDL_GetPathInfo(const char *path, SDL_PathInfo *info) +{ + SDL_PathInfo dummy; + + if (!info) { + info = &dummy; + } + SDL_zerop(info); + + if (!path) { + return SDL_InvalidParamError("path"); + } + + return SDL_SYS_GetPathInfo(path, info); +} diff --git a/src/filesystem/SDL_sysfilesystem.h b/src/filesystem/SDL_sysfilesystem.h new file mode 100644 index 00000000..97f009fd --- /dev/null +++ b/src/filesystem/SDL_sysfilesystem.h @@ -0,0 +1,32 @@ +/* + 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_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); + +#endif + diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m index 71f674fa..aef0217d 100644 --- a/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -75,7 +75,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) org = ""; } -#if !TARGET_OS_TV +#ifndef SDL_PLATFORM_TVOS array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); #else /* tvOS does not have persistent local storage! @@ -95,7 +95,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) } array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); -#endif /* !TARGET_OS_TV */ +#endif /* !SDL_PLATFORM_TVOS */ if ([array count] > 0) { /* we only want the first item in the list. */ NSString *str = [array objectAtIndex:0]; @@ -129,7 +129,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) char *SDL_GetUserFolder(SDL_Folder folder) { @autoreleasepool { -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS SDL_SetError("tvOS does not have persistent storage"); return NULL; #else @@ -224,7 +224,7 @@ char *SDL_GetUserFolder(SDL_Folder folder) mkdir(retval, 0700); return retval; -#endif /* TARGET_OS_TV */ +#endif /* SDL_PLATFORM_TVOS */ } } diff --git a/src/filesystem/dummy/SDL_sysfsops.c b/src/filesystem/dummy/SDL_sysfsops.c new file mode 100644 index 00000000..63bd709a --- /dev/null +++ b/src/filesystem/dummy/SDL_sysfsops.c @@ -0,0 +1,54 @@ +/* + 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" + +#if defined(SDL_FSOPS_DUMMY) + +#include "../SDL_sysfilesystem.h" + +int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) +{ + return SDL_Unsupported(); +} + +int SDL_SYS_RemovePath(const char *path) +{ + return SDL_Unsupported(); +} + +int SDL_SYS_RenamePath(const char *oldpath, const char *newpath) +{ + return SDL_Unsupported(); +} + +int SDL_SYS_CreateDirectory(const char *path) +{ + return SDL_Unsupported(); +} + +int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) +{ + return SDL_Unsupported(); +} + +#endif // SDL_FSOPS_DUMMY + diff --git a/src/filesystem/posix/SDL_sysfsops.c b/src/filesystem/posix/SDL_sysfsops.c new file mode 100644 index 00000000..857782eb --- /dev/null +++ b/src/filesystem/posix/SDL_sysfsops.c @@ -0,0 +1,131 @@ +/* + 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" + +#if defined(SDL_FSOPS_POSIX) + +#include +#include +#include +#include +#include + +#include "../SDL_sysfilesystem.h" + +int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) +{ + int retval = 1; + + DIR *dir = opendir(path); + if (!dir) { + return SDL_SetError("Can't open directory: %s", strerror(errno)); + } + + struct dirent *ent; + while ((retval == 1) && ((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); + } + + closedir(dir); + + return retval; +} + +int 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 SDL_SetError("Can't remove path: %s", strerror(errno)); + } + return 0; +} + +int 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; +} + +int SDL_SYS_CreateDirectory(const char *path) +{ + const int rc = mkdir(path, 0770); + if (rc < 0) { + const int origerrno = errno; + 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 SDL_SetError("Can't create directory: %s", strerror(origerrno)); + } + return 0; +} + +int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) +{ + struct stat statbuf; + const int rc = stat(path, &statbuf); + if (rc < 0) { + return SDL_SetError("Can't stat: %s", strerror(errno)); + } else if (S_ISREG(statbuf.st_mode)) { + info->type = SDL_PATHTYPE_FILE; + info->size = (Uint64) statbuf.st_size; + } else if (S_ISDIR(statbuf.st_mode)) { + info->type = SDL_PATHTYPE_DIRECTORY; + info->size = 0; + } else { + info->type = SDL_PATHTYPE_OTHER; + info->size = (Uint64) statbuf.st_size; + } + +#if defined(HAVE_ST_MTIM) + /* 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; +#elif defined(SDL_PLATFORM_APPLE) + /* Apple platform stat structs use 'st_*timespec' naming. */ + info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctimespec.tv_sec) + statbuf.st_ctimespec.tv_nsec; + info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtimespec.tv_sec) + statbuf.st_mtimespec.tv_nsec; + info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atimespec.tv_sec) + statbuf.st_atimespec.tv_nsec; +#else + info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctime); + 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; +} + +#endif // SDL_FSOPS_POSIX + diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c index 91baf437..72e061a0 100644 --- a/src/filesystem/unix/SDL_sysfilesystem.c +++ b/src/filesystem/unix/SDL_sysfilesystem.c @@ -25,6 +25,7 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* System dependent filesystem routines */ +#include #include #include #include @@ -35,7 +36,7 @@ #include #include -#if defined(__FREEBSD__) || defined(__OPENBSD__) +#if defined(SDL_PLATFORM_FREEBSD) || defined(SDL_PLATFORM_OPENBSD) #include #endif @@ -68,7 +69,7 @@ static char *readSymLink(const char *path) return NULL; } -#ifdef __OPENBSD__ +#ifdef SDL_PLATFORM_OPENBSD static char *search_path_for_binary(const char *bin) { char *envr = SDL_getenv("PATH"); @@ -122,7 +123,7 @@ char *SDL_GetBasePath(void) { char *retval = NULL; -#ifdef __FREEBSD__ +#ifdef SDL_PLATFORM_FREEBSD char fullpath[PATH_MAX]; size_t buflen = sizeof(fullpath); const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; @@ -133,7 +134,7 @@ char *SDL_GetBasePath(void) } } #endif -#ifdef __OPENBSD__ +#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. */ char **cmdline; size_t len; @@ -196,11 +197,11 @@ char *SDL_GetBasePath(void) /* !!! 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 __FREEBSD__ +#ifdef SDL_PLATFORM_FREEBSD retval = readSymLink("/proc/curproc/file"); -#elif defined(__NETBSD__) +#elif defined(SDL_PLATFORM_NETBSD) retval = readSymLink("/proc/curproc/exe"); -#elif defined(__SOLARIS__) +#elif defined(SDL_PLATFORM_SOLARIS) retval = readSymLink("/proc/self/path/a.out"); #else retval = readSymLink("/proc/self/exe"); /* linux. */ @@ -217,7 +218,7 @@ char *SDL_GetBasePath(void) #endif } -#ifdef __SOLARIS__ /* try this as a fallback if /proc didn't pan out */ +#ifdef SDL_PLATFORM_SOLARIS /* try this as a fallback if /proc didn't pan out */ if (!retval) { const char *path = getexecname(); if ((path) && (path[0] == '/')) { /* must be absolute path... */ @@ -495,15 +496,14 @@ static char *xdg_user_dir_lookup (const char *type) return NULL; /* Special case desktop for historical compatibility */ - if (SDL_strcmp(type, "DESKTOP") == 0) - { - user_dir = (char*) SDL_malloc(SDL_strlen(home_dir) + - SDL_strlen("/Desktop") + 1); + if (SDL_strcmp(type, "DESKTOP") == 0) { + size_t length = SDL_strlen(home_dir) + SDL_strlen("/Desktop") + 1; + user_dir = (char*) SDL_malloc(length); if (!user_dir) return NULL; - strcpy(user_dir, home_dir); - strcat(user_dir, "/Desktop"); + SDL_strlcpy(user_dir, home_dir, length); + SDL_strlcat(user_dir, "/Desktop", length); return user_dir; } diff --git a/src/filesystem/windows/SDL_sysfsops.c b/src/filesystem/windows/SDL_sysfsops.c new file mode 100644 index 00000000..b688365d --- /dev/null +++ b/src/filesystem/windows/SDL_sysfsops.c @@ -0,0 +1,176 @@ +/* + 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" + +#if defined(SDL_FSOPS_WINDOWS) + +#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) +{ + int retval = 1; + 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++) { + if (drives & (1 << (i - 'A'))) { + name[0] = (char) i; + retval = cb(userdata, dirname, name); + } + } + } else { + const size_t patternlen = SDL_strlen(path) + 3; + char *pattern = (char *) SDL_malloc(patternlen); + if (!pattern) { + return -1; + } + + // you need a wildcard to enumerate through FindFirstFileEx(), but the wildcard is only checked in the + // filename element at the end of the path string, so always tack on a "\\*" to get everything, and + // also prevent any wildcards inserted by the app from being respected. + SDL_snprintf(pattern, patternlen, "%s\\*", path); + + WCHAR *wpattern = WIN_UTF8ToString(pattern); + SDL_free(pattern); + if (!wpattern) { + return -1; + } + + WIN32_FIND_DATAW entw; + HANDLE dir = FindFirstFileExW(wpattern, FindExInfoStandard, &entw, FindExSearchNameMatch, NULL, 0); + SDL_free(wpattern); + if (dir == INVALID_HANDLE_VALUE) { + return WIN_SetError("Failed to enumerate directory"); + } + + do { + const WCHAR *fn = entw.cFileName; + + if (fn[0] == '.') { // ignore "." and ".." + if ((fn[1] == '\0') || ((fn[1] == '.') && (fn[2] == '\0'))) { + continue; + } + } + + char *utf8fn = WIN_StringToUTF8(fn); + if (!utf8fn) { + retval = -1; + } else { + retval = cb(userdata, dirname, utf8fn); + SDL_free(utf8fn); + } + } while ((retval == 1) && (FindNextFileW(dir, &entw) != 0)); + + FindClose(dir); + } + + return retval; +} + +int SDL_SYS_RemovePath(const char *path) +{ + WCHAR *wpath = WIN_UTF8ToString(path); + if (!wpath) { + return -1; + } + + WIN32_FILE_ATTRIBUTE_DATA info; + if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &info)) { + 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 WIN_SetError("Couldn't get path's attributes"); + } + + 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; +} + +int SDL_SYS_RenamePath(const char *oldpath, const char *newpath) +{ + WCHAR *woldpath = WIN_UTF8ToString(oldpath); + if (!woldpath) { + return -1; + } + + WCHAR *wnewpath = WIN_UTF8ToString(newpath); + if (!wnewpath) { + SDL_free(woldpath); + return -1; + } + + const BOOL rc = MoveFileExW(woldpath, wnewpath, MOVEFILE_REPLACE_EXISTING); + SDL_free(wnewpath); + SDL_free(woldpath); + return !rc ? WIN_SetError("Couldn't rename path") : 0; +} + +int SDL_SYS_CreateDirectory(const char *path) +{ + WCHAR *wpath = WIN_UTF8ToString(path); + if (!wpath) { + return -1; + } + + const DWORD rc = CreateDirectoryW(wpath, NULL); + SDL_free(wpath); + return !rc ? WIN_SetError("Couldn't create directory") : 0; +} + +int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) +{ + WCHAR *wpath = WIN_UTF8ToString(path); + if (!wpath) { + return -1; + } + + WIN32_FILE_ATTRIBUTE_DATA winstat; + const BOOL rc = GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat); + SDL_free(wpath); + if (!rc) { + return WIN_SetError("Can't stat"); + } + + if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + info->type = SDL_PATHTYPE_DIRECTORY; + info->size = 0; + } else if (winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) { + info->type = SDL_PATHTYPE_OTHER; + info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); + } else { + info->type = SDL_PATHTYPE_FILE; + info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); + } + + info->create_time = SDL_TimeFromWindows(winstat.ftCreationTime.dwLowDateTime, winstat.ftCreationTime.dwHighDateTime); + info->modify_time = SDL_TimeFromWindows(winstat.ftLastWriteTime.dwLowDateTime, winstat.ftLastWriteTime.dwHighDateTime); + info->access_time = SDL_TimeFromWindows(winstat.ftLastAccessTime.dwLowDateTime, winstat.ftLastAccessTime.dwHighDateTime); + + return 1; +} + +#endif // SDL_FSOPS_WINDOWS + diff --git a/src/filesystem/winrt/SDL_sysfilesystem.cpp b/src/filesystem/winrt/SDL_sysfilesystem.cpp index d5b7c020..a2167999 100644 --- a/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ b/src/filesystem/winrt/SDL_sysfilesystem.cpp @@ -23,7 +23,7 @@ /* TODO, WinRT: remove the need to compile this with C++/CX (/ZW) extensions, and if possible, without C++ at all */ -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT extern "C" { #include "../../core/windows/SDL_windows.h" @@ -236,4 +236,4 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index 3fbac01e..d4502b11 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -24,16 +24,15 @@ #include "SDL_haptic_c.h" #include "../joystick/SDL_joystick_c.h" /* For SDL_IsJoystickValid */ -/* Global for SDL_windowshaptic.c */ -#if (defined(SDL_HAPTIC_DINPUT) && SDL_HAPTIC_DINPUT) || (defined(SDL_HAPTIC_XINPUT) && SDL_HAPTIC_XINPUT) -SDL_Haptic *SDL_haptics = NULL; -#else static SDL_Haptic *SDL_haptics = NULL; -#endif +static char SDL_haptic_magic; + +#define CHECK_HAPTIC_MAGIC(haptic, retval) \ + if (!haptic || haptic->magic != &SDL_haptic_magic) { \ + SDL_InvalidParamError("haptic"); \ + return retval; \ + } -/* - * Initializes the Haptic devices. - */ int SDL_InitHaptics(void) { int status; @@ -46,75 +45,82 @@ int SDL_InitHaptics(void) return status; } -/* - * Checks to see if the haptic device is valid - */ -static int ValidHaptic(SDL_Haptic *haptic) +static SDL_bool SDL_GetHapticIndex(SDL_HapticID instance_id, int *driver_index) { - int valid; - SDL_Haptic *hapticlist; + int num_haptics, device_index; - valid = 0; - if (haptic) { - hapticlist = SDL_haptics; - while (hapticlist) { - if (hapticlist == haptic) { - valid = 1; - break; + if (instance_id > 0) { + num_haptics = SDL_SYS_NumHaptics(); + for (device_index = 0; device_index < num_haptics; ++device_index) { + SDL_HapticID haptic_id = SDL_SYS_HapticInstanceID(device_index); + if (haptic_id == instance_id) { + *driver_index = device_index; + return SDL_TRUE; } - hapticlist = hapticlist->next; } } - /* Create the error here. */ - if (valid == 0) { - SDL_SetError("Haptic: Invalid haptic device identifier"); + SDL_SetError("Haptic device %" SDL_PRIu32 " not found", instance_id); + return SDL_FALSE; +} + +SDL_HapticID *SDL_GetHaptics(int *count) +{ + int device_index; + int haptic_index = 0, num_haptics = 0; + SDL_HapticID *haptics; + + num_haptics = SDL_SYS_NumHaptics(); + + haptics = (SDL_HapticID *)SDL_malloc((num_haptics + 1) * sizeof(*haptics)); + if (haptics) { + if (count) { + *count = num_haptics; + } + + for (device_index = 0; device_index < num_haptics; ++device_index) { + haptics[haptic_index] = SDL_SYS_HapticInstanceID(device_index); + SDL_assert(haptics[haptic_index] > 0); + ++haptic_index; + } + haptics[haptic_index] = 0; + } else { + if (count) { + *count = 0; + } } - return valid; + return haptics; } -/* - * Returns the number of available devices. - */ -int SDL_NumHaptics(void) +const char *SDL_GetHapticInstanceName(SDL_HapticID instance_id) { - return SDL_SYS_NumHaptics(); -} + int device_index; + const char *name = NULL; -/* - * Gets the name of a Haptic device by index. - */ -const char *SDL_HapticName(int device_index) -{ - if ((device_index < 0) || (device_index >= SDL_NumHaptics())) { - SDL_SetError("Haptic: There are %d haptic devices available", - SDL_NumHaptics()); - return NULL; + if (SDL_GetHapticIndex(instance_id, &device_index)) { + name = SDL_SYS_HapticName(device_index); } - return SDL_SYS_HapticName(device_index); + return name; } -/* - * Opens a Haptic device. - */ -SDL_Haptic *SDL_HapticOpen(int device_index) +SDL_Haptic *SDL_OpenHaptic(SDL_HapticID instance_id) { SDL_Haptic *haptic; SDL_Haptic *hapticlist; + const char *name; + int device_index = 0; - if ((device_index < 0) || (device_index >= SDL_NumHaptics())) { - SDL_SetError("Haptic: There are %d haptic devices available", - SDL_NumHaptics()); + if (!SDL_GetHapticIndex(instance_id, &device_index)) { return NULL; } hapticlist = SDL_haptics; - /* If the haptic is already open, return it - * TODO: Should we create haptic instance IDs like the Joystick API? + /* If the haptic device is already open, return it + * it is important that we have a single haptic device for each instance id */ while (hapticlist) { - if (device_index == hapticlist->index) { + if (instance_id == hapticlist->instance_id) { haptic = hapticlist; ++haptic->ref_count; return haptic; @@ -123,20 +129,27 @@ SDL_Haptic *SDL_HapticOpen(int device_index) } /* Create the haptic device */ - haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic)); + haptic = (SDL_Haptic *)SDL_calloc(1, sizeof(*haptic)); if (!haptic) { return NULL; } /* Initialize the haptic device */ - SDL_memset(haptic, 0, sizeof(*haptic)); + haptic->magic = &SDL_haptic_magic; + haptic->instance_id = instance_id; haptic->rumble_id = -1; - haptic->index = (Uint8)device_index; if (SDL_SYS_HapticOpen(haptic) < 0) { SDL_free(haptic); return NULL; } + if (!haptic->name) { + name = SDL_SYS_HapticName(device_index); + if (name) { + haptic->name = SDL_strdup(name); + } + } + /* Add haptic to list */ ++haptic->ref_count; /* Link the haptic in the list */ @@ -145,59 +158,42 @@ SDL_Haptic *SDL_HapticOpen(int device_index) /* Disable autocenter and set gain to max. */ if (haptic->supported & SDL_HAPTIC_GAIN) { - SDL_HapticSetGain(haptic, 100); + SDL_SetHapticGain(haptic, 100); } if (haptic->supported & SDL_HAPTIC_AUTOCENTER) { - SDL_HapticSetAutocenter(haptic, 0); + SDL_SetHapticAutocenter(haptic, 0); } return haptic; } -/* - * Returns 1 if the device has been opened. - */ -int SDL_HapticOpened(int device_index) +SDL_Haptic *SDL_GetHapticFromInstanceID(SDL_HapticID instance_id) { - int opened; - SDL_Haptic *hapticlist; + SDL_Haptic *haptic; - /* Make sure it's valid. */ - if ((device_index < 0) || (device_index >= SDL_NumHaptics())) { - SDL_SetError("Haptic: There are %d haptic devices available", - SDL_NumHaptics()); - return 0; - } - - opened = 0; - hapticlist = SDL_haptics; - /* TODO Should this use an instance ID? */ - while (hapticlist) { - if (hapticlist->index == (Uint8)device_index) { - opened = 1; + for (haptic = SDL_haptics; haptic; haptic = haptic->next) { + if (instance_id == haptic->instance_id) { break; } - hapticlist = hapticlist->next; } - return opened; + return haptic; } -/* - * Returns the index to a haptic device. - */ -int SDL_HapticIndex(SDL_Haptic *haptic) +SDL_HapticID SDL_GetHapticInstanceID(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, 0); - return haptic->index; + return haptic->instance_id; } -/* - * Returns SDL_TRUE if mouse is haptic, SDL_FALSE if it isn't. - */ -int SDL_MouseIsHaptic(void) +const char *SDL_GetHapticName(SDL_Haptic *haptic) +{ + CHECK_HAPTIC_MAGIC(haptic, 0); + + return haptic->name; +} + +SDL_bool SDL_IsMouseHaptic(void) { if (SDL_SYS_HapticMouse() < 0) { return SDL_FALSE; @@ -205,10 +201,7 @@ int SDL_MouseIsHaptic(void) return SDL_TRUE; } -/* - * Returns the haptic device if mouse is haptic or NULL elsewise. - */ -SDL_Haptic *SDL_HapticOpenFromMouse(void) +SDL_Haptic *SDL_OpenHapticFromMouse(void) { int device_index; @@ -219,52 +212,33 @@ SDL_Haptic *SDL_HapticOpenFromMouse(void) return NULL; } - return SDL_HapticOpen(device_index); + return SDL_OpenHaptic(device_index); } -/* - * Returns SDL_TRUE if joystick has haptic features. - */ -int SDL_JoystickIsHaptic(SDL_Joystick *joystick) +SDL_bool SDL_IsJoystickHaptic(SDL_Joystick *joystick) { - int ret; + SDL_bool result = SDL_FALSE; SDL_LockJoysticks(); { /* Must be a valid joystick */ - if (!SDL_IsJoystickValid(joystick)) { - SDL_UnlockJoysticks(); - return -1; + if (SDL_IsJoystickValid(joystick) && + !SDL_IsGamepad(SDL_GetJoystickInstanceID(joystick))) { + if (SDL_SYS_JoystickIsHaptic(joystick) > 0) { + result = SDL_TRUE; + } } - - ret = SDL_SYS_JoystickIsHaptic(joystick); } SDL_UnlockJoysticks(); - if (ret > 0) { - return SDL_TRUE; - } else if (ret == 0) { - return SDL_FALSE; - } - - return -1; + return result; } -/* - * Opens a haptic device from a joystick. - */ -SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) +SDL_Haptic *SDL_OpenHapticFromJoystick(SDL_Joystick *joystick) { SDL_Haptic *haptic; SDL_Haptic *hapticlist; - /* Make sure there is room. */ - if (SDL_NumHaptics() <= 0) { - SDL_SetError("Haptic: There are %d haptic devices available", - SDL_NumHaptics()); - return NULL; - } - SDL_LockJoysticks(); { /* Must be a valid joystick */ @@ -275,7 +249,8 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) } /* Joystick must be haptic */ - if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) { + if (SDL_IsGamepad(SDL_GetJoystickInstanceID(joystick)) || + SDL_SYS_JoystickIsHaptic(joystick) <= 0) { SDL_SetError("Haptic: Joystick isn't a haptic device."); SDL_UnlockJoysticks(); return NULL; @@ -294,14 +269,15 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) } /* Create the haptic device */ - haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic)); + haptic = (SDL_Haptic *)SDL_calloc(1, sizeof(*haptic)); if (!haptic) { SDL_UnlockJoysticks(); return NULL; } - /* Initialize the haptic device */ - SDL_memset(haptic, 0, sizeof(SDL_Haptic)); + /* Initialize the haptic device + * This function should fill in the instance ID and name. + */ haptic->rumble_id = -1; if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) { SDL_SetError("Haptic: SDL_SYS_HapticOpenFromJoystick failed."); @@ -309,6 +285,7 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) SDL_UnlockJoysticks(); return NULL; } + SDL_assert(haptic->instance_id != 0); } SDL_UnlockJoysticks(); @@ -321,19 +298,13 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick) return haptic; } -/* - * Closes a SDL_Haptic device. - */ -void SDL_HapticClose(SDL_Haptic *haptic) +void SDL_CloseHaptic(SDL_Haptic *haptic) { int i; SDL_Haptic *hapticlist; SDL_Haptic *hapticlistprev; - /* Must be valid */ - if (!ValidHaptic(haptic)) { - return; - } + CHECK_HAPTIC_MAGIC(haptic,); /* Check if it's still in use */ if (--haptic->ref_count > 0) { @@ -343,10 +314,11 @@ void SDL_HapticClose(SDL_Haptic *haptic) /* Close it, properly removing effects if needed */ for (i = 0; i < haptic->neffects; i++) { if (haptic->effects[i].hweffect != NULL) { - SDL_HapticDestroyEffect(haptic, i); + SDL_DestroyHapticEffect(haptic, i); } } SDL_SYS_HapticClose(haptic); + haptic->magic = NULL; /* Remove from the list */ hapticlist = SDL_haptics; @@ -366,77 +338,54 @@ void SDL_HapticClose(SDL_Haptic *haptic) hapticlist = hapticlist->next; } - /* Free */ + /* Free the data associated with this device */ + SDL_free(haptic->name); SDL_free(haptic); } -/* - * Cleans up after the subsystem. - */ void SDL_QuitHaptics(void) { while (SDL_haptics) { - SDL_HapticClose(SDL_haptics); + SDL_CloseHaptic(SDL_haptics); } SDL_SYS_HapticQuit(); } -/* - * Returns the number of effects a haptic device has. - */ -int SDL_HapticNumEffects(SDL_Haptic *haptic) +int SDL_GetMaxHapticEffects(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); return haptic->neffects; } -/* - * Returns the number of effects a haptic device can play. - */ -int SDL_HapticNumEffectsPlaying(SDL_Haptic *haptic) +int SDL_GetMaxHapticEffectsPlaying(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); return haptic->nplaying; } -/* - * Returns supported effects by the device. - */ -unsigned int SDL_HapticQuery(SDL_Haptic *haptic) +Uint32 SDL_GetHapticFeatures(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return 0; /* same as if no effects were supported */ - } + CHECK_HAPTIC_MAGIC(haptic, 0); return haptic->supported; } -/* - * Returns the number of axis on the device. - */ -int SDL_HapticNumAxes(SDL_Haptic *haptic) +int SDL_GetNumHapticAxes(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); return haptic->naxes; } -/* - * Checks to see if the device can support the effect. - */ -int SDL_HapticEffectSupported(SDL_Haptic *haptic, SDL_HapticEffect *effect) +SDL_bool SDL_HapticEffectSupported(SDL_Haptic *haptic, const SDL_HapticEffect *effect) { - if (!ValidHaptic(haptic)) { - return -1; + CHECK_HAPTIC_MAGIC(haptic, SDL_FALSE); + + if (!effect) { + return SDL_FALSE; } if ((haptic->supported & effect->type) != 0) { @@ -445,16 +394,14 @@ int SDL_HapticEffectSupported(SDL_Haptic *haptic, SDL_HapticEffect *effect) return SDL_FALSE; } -/* - * Creates a new haptic effect. - */ -int SDL_HapticNewEffect(SDL_Haptic *haptic, SDL_HapticEffect *effect) +int SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect) { int i; - /* Check for device validity. */ - if (!ValidHaptic(haptic)) { - return -1; + CHECK_HAPTIC_MAGIC(haptic, -1); + + if (!effect) { + return SDL_InvalidParamError("effect"); } /* Check to see if effect is supported */ @@ -480,9 +427,6 @@ int SDL_HapticNewEffect(SDL_Haptic *haptic, SDL_HapticEffect *effect) return SDL_SetError("Haptic: Device has no free space left."); } -/* - * Checks to see if an effect is valid. - */ static int ValidEffect(SDL_Haptic *haptic, int effect) { if ((effect < 0) || (effect >= haptic->neffects)) { @@ -492,16 +436,18 @@ static int ValidEffect(SDL_Haptic *haptic, int effect) return 1; } -/* - * Updates an effect. - */ -int SDL_HapticUpdateEffect(SDL_Haptic *haptic, int effect, - SDL_HapticEffect *data) +int SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, const SDL_HapticEffect *data) { - if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + CHECK_HAPTIC_MAGIC(haptic, -1); + + if (!ValidEffect(haptic, effect)) { return -1; } + if (!data) { + return SDL_InvalidParamError("data"); + } + /* Can't change type dynamically. */ if (data->type != haptic->effects[effect].effect.type) { return SDL_SetError("Haptic: Updating effect type is illegal."); @@ -518,12 +464,11 @@ int SDL_HapticUpdateEffect(SDL_Haptic *haptic, int effect, return 0; } -/* - * Runs the haptic effect on the device. - */ -int SDL_HapticRunEffect(SDL_Haptic *haptic, int effect, Uint32 iterations) +int SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations) { - if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + CHECK_HAPTIC_MAGIC(haptic, -1); + + if (!ValidEffect(haptic, effect)) { return -1; } @@ -535,12 +480,11 @@ int SDL_HapticRunEffect(SDL_Haptic *haptic, int effect, Uint32 iterations) return 0; } -/* - * Stops the haptic effect on the device. - */ -int SDL_HapticStopEffect(SDL_Haptic *haptic, int effect) +int SDL_StopHapticEffect(SDL_Haptic *haptic, int effect) { - if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + CHECK_HAPTIC_MAGIC(haptic, -1); + + if (!ValidEffect(haptic, effect)) { return -1; } @@ -552,12 +496,11 @@ int SDL_HapticStopEffect(SDL_Haptic *haptic, int effect) return 0; } -/* - * Gets rid of a haptic effect. - */ -void SDL_HapticDestroyEffect(SDL_Haptic *haptic, int effect) +void SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect) { - if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + CHECK_HAPTIC_MAGIC(haptic,); + + if (!ValidEffect(haptic, effect)) { return; } @@ -569,12 +512,11 @@ void SDL_HapticDestroyEffect(SDL_Haptic *haptic, int effect) SDL_SYS_HapticDestroyEffect(haptic, &haptic->effects[effect]); } -/* - * Gets the status of a haptic effect. - */ -int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect) +int SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect) { - if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) { + CHECK_HAPTIC_MAGIC(haptic, -1); + + if (!ValidEffect(haptic, effect)) { return -1; } @@ -585,17 +527,12 @@ int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect) return SDL_SYS_HapticGetEffectStatus(haptic, &haptic->effects[effect]); } -/* - * Sets the global gain of the device. - */ -int SDL_HapticSetGain(SDL_Haptic *haptic, int gain) +int SDL_SetHapticGain(SDL_Haptic *haptic, int gain) { const char *env; int real_gain, max_gain; - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); if (!(haptic->supported & SDL_HAPTIC_GAIN)) { return SDL_SetError("Haptic: Device does not support setting gain."); @@ -630,14 +567,9 @@ int SDL_HapticSetGain(SDL_Haptic *haptic, int gain) return 0; } -/* - * Makes the device autocenter, 0 disables. - */ -int SDL_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) +int SDL_SetHapticAutocenter(SDL_Haptic *haptic, int autocenter) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); if (!(haptic->supported & SDL_HAPTIC_AUTOCENTER)) { return SDL_SetError("Haptic: Device does not support setting autocenter."); @@ -654,14 +586,9 @@ int SDL_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) return 0; } -/* - * Pauses the haptic device. - */ -int SDL_HapticPause(SDL_Haptic *haptic) +int SDL_PauseHaptic(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); if (!(haptic->supported & SDL_HAPTIC_PAUSE)) { return SDL_SetError("Haptic: Device does not support setting pausing."); @@ -670,14 +597,9 @@ int SDL_HapticPause(SDL_Haptic *haptic) return SDL_SYS_HapticPause(haptic); } -/* - * Unpauses the haptic device. - */ -int SDL_HapticUnpause(SDL_Haptic *haptic) +int SDL_ResumeHaptic(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); if (!(haptic->supported & SDL_HAPTIC_PAUSE)) { return 0; /* Not going to be paused, so we pretend it's unpaused. */ @@ -686,41 +608,26 @@ int SDL_HapticUnpause(SDL_Haptic *haptic) return SDL_SYS_HapticUnpause(haptic); } -/* - * Stops all the currently playing effects. - */ -int SDL_HapticStopAll(SDL_Haptic *haptic) +int SDL_StopHapticEffects(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); return SDL_SYS_HapticStopAll(haptic); } -/* - * Checks to see if rumble is supported. - */ -int SDL_HapticRumbleSupported(SDL_Haptic *haptic) +SDL_bool SDL_HapticRumbleSupported(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, SDL_FALSE); /* Most things can use SINE, but XInput only has LEFTRIGHT. */ return (haptic->supported & (SDL_HAPTIC_SINE | SDL_HAPTIC_LEFTRIGHT)) != 0; } -/* - * Initializes the haptic device for simple rumble playback. - */ -int SDL_HapticRumbleInit(SDL_Haptic *haptic) +int SDL_InitHapticRumble(SDL_Haptic *haptic) { SDL_HapticEffect *efx = &haptic->rumble_effect; - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); /* Already allocated. */ if (haptic->rumble_id >= 0) { @@ -745,24 +652,19 @@ int SDL_HapticRumbleInit(SDL_Haptic *haptic) return SDL_SetError("Device doesn't support rumble"); } - haptic->rumble_id = SDL_HapticNewEffect(haptic, &haptic->rumble_effect); + haptic->rumble_id = SDL_CreateHapticEffect(haptic, &haptic->rumble_effect); if (haptic->rumble_id >= 0) { return 0; } return -1; } -/* - * Runs simple rumble on a haptic device - */ -int SDL_HapticRumblePlay(SDL_Haptic *haptic, float strength, Uint32 length) +int SDL_PlayHapticRumble(SDL_Haptic *haptic, float strength, Uint32 length) { SDL_HapticEffect *efx; Sint16 magnitude; - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); if (haptic->rumble_id < 0) { return SDL_SetError("Haptic: Rumble effect not initialized on haptic device"); @@ -784,28 +686,23 @@ int SDL_HapticRumblePlay(SDL_Haptic *haptic, float strength, Uint32 length) efx->leftright.small_magnitude = efx->leftright.large_magnitude = magnitude; efx->leftright.length = length; } else { - SDL_assert(0 && "This should have been caught elsewhere"); + SDL_assert(!"This should have been caught elsewhere"); } - if (SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) { + if (SDL_UpdateHapticEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) { return -1; } - return SDL_HapticRunEffect(haptic, haptic->rumble_id, 1); + return SDL_RunHapticEffect(haptic, haptic->rumble_id, 1); } -/* - * Stops the simple rumble on a haptic device. - */ -int SDL_HapticRumbleStop(SDL_Haptic *haptic) +int SDL_StopHapticRumble(SDL_Haptic *haptic) { - if (!ValidHaptic(haptic)) { - return -1; - } + CHECK_HAPTIC_MAGIC(haptic, -1); if (haptic->rumble_id < 0) { return SDL_SetError("Haptic: Rumble effect not initialized on haptic device"); } - return SDL_HapticStopEffect(haptic, haptic->rumble_id); + return SDL_StopHapticEffect(haptic, haptic->rumble_id); } diff --git a/src/haptic/SDL_syshaptic.h b/src/haptic/SDL_syshaptic.h index 71f7ed55..a0cba77c 100644 --- a/src/haptic/SDL_syshaptic.h +++ b/src/haptic/SDL_syshaptic.h @@ -40,20 +40,23 @@ struct haptic_effect */ struct SDL_Haptic { - Uint8 index; /* Stores index it is attached to */ + const void *magic; - struct haptic_effect *effects; /* Allocated effects */ - int neffects; /* Maximum amount of effects */ - int nplaying; /* Maximum amount of effects to play at the same time */ - unsigned int supported; /* Supported effects */ - int naxes; /* Number of axes on the device. */ + SDL_HapticID instance_id; /* Device instance, monotonically increasing from 0 */ + char *name; /* Device name - system dependent */ - struct haptic_hwdata *hwdata; /* Driver dependent */ - int ref_count; /* Count for multiple opens */ + struct haptic_effect *effects; /* Allocated effects */ + int neffects; /* Maximum amount of effects */ + int nplaying; /* Maximum amount of effects to play at the same time */ + Uint32 supported; /* Supported effects and features */ + int naxes; /* Number of axes on the device. */ + + struct haptic_hwdata *hwdata; /* Driver dependent */ + int ref_count; /* Count for multiple opens */ int rumble_id; /* ID of rumble effect for simple rumble API. */ SDL_HapticEffect rumble_effect; /* Rumble effect. */ - struct SDL_Haptic *next; /* pointer to next haptic we have allocated */ + struct SDL_Haptic *next; /* pointer to next haptic we have allocated */ }; /* @@ -66,6 +69,11 @@ extern int SDL_SYS_HapticInit(void); /* Function to return the number of haptic devices plugged in right now */ extern int SDL_SYS_NumHaptics(void); +/* + * Gets the instance ID of the haptic device + */ +extern SDL_HapticID SDL_SYS_HapticInstanceID(int index); + /* * Gets the device dependent name of the haptic device */ @@ -126,7 +134,7 @@ extern void SDL_SYS_HapticQuit(void); */ extern int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *base); + const SDL_HapticEffect *base); /* * Updates the haptic effect on the haptic device using data @@ -136,7 +144,7 @@ extern int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, */ extern int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *data); + const SDL_HapticEffect *data); /* * Runs the effect on the haptic device. diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c index bf8404c9..3f35004b 100644 --- a/src/haptic/android/SDL_syshaptic.c +++ b/src/haptic/android/SDL_syshaptic.c @@ -30,6 +30,7 @@ typedef struct SDL_hapticlist_item { + SDL_HapticID instance_id; int device_id; char *name; SDL_Haptic *haptic; @@ -66,6 +67,17 @@ static SDL_hapticlist_item *HapticByOrder(int index) return item; } +static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id) +{ + SDL_hapticlist_item *item; + for (item = SDL_hapticlist; item; item = item->next) { + if (instance_id == item->instance_id) { + return item; + } + } + return NULL; +} + static SDL_hapticlist_item *HapticByDevId(int device_id) { SDL_hapticlist_item *item; @@ -78,6 +90,15 @@ static SDL_hapticlist_item *HapticByDevId(int device_id) return NULL; } +SDL_HapticID SDL_SYS_HapticInstanceID(int index) +{ + SDL_hapticlist_item *item = HapticByOrder(index); + if (item) { + return item->instance_id; + } + return 0; +} + const char *SDL_SYS_HapticName(int index) { SDL_hapticlist_item *item = HapticByOrder(index); @@ -102,20 +123,23 @@ static SDL_hapticlist_item *OpenHaptic(SDL_Haptic *haptic, SDL_hapticlist_item * haptic->hwdata = (struct haptic_hwdata *)item; item->haptic = haptic; + haptic->instance_id = item->instance_id; + if (item->name) { + haptic->name = SDL_strdup(item->name); + } haptic->supported = SDL_HAPTIC_LEFTRIGHT; haptic->neffects = 1; haptic->nplaying = haptic->neffects; - haptic->effects = (struct haptic_effect *)SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); + haptic->effects = (struct haptic_effect *)SDL_calloc(haptic->neffects, sizeof(struct haptic_effect)); if (!haptic->effects) { return NULL; } - SDL_memset(haptic->effects, 0, sizeof(struct haptic_effect) * haptic->neffects); return item; } -static SDL_hapticlist_item *OpenHapticByOrder(SDL_Haptic *haptic, int index) +static SDL_hapticlist_item *OpenHapticByInstanceID(SDL_Haptic *haptic, SDL_HapticID instance_id) { - return OpenHaptic(haptic, HapticByOrder(index)); + return OpenHaptic(haptic, HapticByInstanceID(instance_id)); } static SDL_hapticlist_item *OpenHapticByDevId(SDL_Haptic *haptic, int device_id) @@ -125,7 +149,7 @@ static SDL_hapticlist_item *OpenHapticByDevId(SDL_Haptic *haptic, int device_id) int SDL_SYS_HapticOpen(SDL_Haptic *haptic) { - return OpenHapticByOrder(haptic, haptic->index) == NULL ? -1 : 0; + return OpenHapticByInstanceID(haptic, haptic->instance_id) == NULL ? -1 : 0; } int SDL_SYS_HapticMouse(void) @@ -177,14 +201,14 @@ void SDL_SYS_HapticQuit(void) } int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, - struct haptic_effect *effect, SDL_HapticEffect *base) + struct haptic_effect *effect, const SDL_HapticEffect *base) { return 0; } int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *data) + const SDL_HapticEffect *data) { return 0; } @@ -249,6 +273,7 @@ int Android_AddHaptic(int device_id, const char *name) return -1; } + item->instance_id = SDL_GetNextObjectID(); item->device_id = device_id; item->name = SDL_strdup(name); if (!item->name) { @@ -275,7 +300,7 @@ int Android_RemoveHaptic(int device_id) for (item = SDL_hapticlist; item; item = item->next) { /* found it, remove it. */ if (device_id == item->device_id) { - const int retval = item->haptic ? item->haptic->index : -1; + const int retval = item->haptic ? 0 : -1; if (prev) { prev->next = item->next; diff --git a/src/haptic/darwin/SDL_syshaptic.c b/src/haptic/darwin/SDL_syshaptic.c index a00cb9d6..b6c69c05 100644 --- a/src/haptic/darwin/SDL_syshaptic.c +++ b/src/haptic/darwin/SDL_syshaptic.c @@ -42,6 +42,7 @@ */ typedef struct SDL_hapticlist_item { + SDL_HapticID instance_id; char name[256]; /* Name of the device. */ io_service_t dev; /* Node we use to create the device. */ @@ -201,6 +202,17 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) return item; } +static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id) +{ + SDL_hapticlist_item *item; + for (item = SDL_hapticlist; item; item = item->next) { + if (instance_id == item->instance_id) { + return item; + } + } + return NULL; +} + int MacHaptic_MaybeAddDevice(io_object_t device) { IOReturn result; @@ -229,6 +241,7 @@ int MacHaptic_MaybeAddDevice(io_object_t device) if (!item) { return SDL_SetError("Could not allocate haptic storage"); } + item->instance_id = SDL_GetNextObjectID(); /* retain it as we are going to keep it around a while */ IOObjectRetain(device); @@ -287,7 +300,7 @@ int MacHaptic_MaybeRemoveDevice(io_object_t device) for (item = SDL_hapticlist; item; item = item->next) { /* found it, remove it. */ if (IOObjectIsEqualTo((io_object_t)item->dev, device)) { - const int retval = item->haptic ? item->haptic->index : -1; + const int retval = item->haptic ? 0 : -1; if (prev) { prev->next = item->next; @@ -313,6 +326,16 @@ int MacHaptic_MaybeRemoveDevice(io_object_t device) return -1; } +SDL_HapticID SDL_SYS_HapticInstanceID(int index) +{ + SDL_hapticlist_item *item; + item = HapticByDevIndex(index); + if (item) { + return item->instance_id; + } + return 0; +} + /* * Return the name of a haptic device, does not need to be opened. */ @@ -320,7 +343,10 @@ const char *SDL_SYS_HapticName(int index) { SDL_hapticlist_item *item; item = HapticByDevIndex(index); - return item->name; + if (item) { + return item->name; + } + return NULL; } /* @@ -419,8 +445,7 @@ static unsigned int GetSupportedFeatures(SDL_Haptic *haptic) /* Test for effects. */ FF_TEST(FFCAP_ET_CONSTANTFORCE, SDL_HAPTIC_CONSTANT); FF_TEST(FFCAP_ET_RAMPFORCE, SDL_HAPTIC_RAMP); - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE); */ + FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE); FF_TEST(FFCAP_ET_SINE, SDL_HAPTIC_SINE); FF_TEST(FFCAP_ET_TRIANGLE, SDL_HAPTIC_TRIANGLE); FF_TEST(FFCAP_ET_SAWTOOTHUP, SDL_HAPTIC_SAWTOOTHUP); @@ -535,7 +560,7 @@ creat_err: int SDL_SYS_HapticOpen(SDL_Haptic *haptic) { SDL_hapticlist_item *item; - item = HapticByDevIndex(haptic->index); + item = HapticByInstanceID(haptic->instance_id); return SDL_SYS_HapticOpenFromService(haptic, item->dev); } @@ -598,7 +623,6 @@ int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_IOKIT - int device_index = 0; SDL_hapticlist_item *item; if (joystick->driver != &SDL_DARWIN_JoystickDriver) { @@ -607,10 +631,13 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) for (item = SDL_hapticlist; item; item = item->next) { if (IOObjectIsEqualTo((io_object_t)item->dev, joystick->hwdata->ffservice)) { - haptic->index = device_index; + haptic->instance_id = item->instance_id; break; } - ++device_index; + } + + if (joystick->name) { + haptic->name = SDL_strdup(joystick->name); } return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice); @@ -682,7 +709,7 @@ static DWORD FFGetTriggerButton(Uint16 button) /* * Sets the direction. */ -static int SDL_SYS_SetDirection(FFEFFECT *effect, SDL_HapticDirection *dir, int naxes) +static int SDL_SYS_SetDirection(FFEFFECT *effect, const SDL_HapticDirection *dir, int naxes) { LONG *rglDir; @@ -743,7 +770,7 @@ static int SDL_SYS_SetDirection(FFEFFECT *effect, SDL_HapticDirection *dir, int /* * Creates the FFEFFECT from a SDL_HapticEffect. */ -static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffect *src) +static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, const SDL_HapticEffect *src) { int i; FFCONSTANTFORCE *constant = NULL; @@ -752,11 +779,11 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe FFRAMPFORCE *ramp = NULL; FFCUSTOMFORCE *custom = NULL; FFENVELOPE *envelope = NULL; - SDL_HapticConstant *hap_constant = NULL; - SDL_HapticPeriodic *hap_periodic = NULL; - SDL_HapticCondition *hap_condition = NULL; - SDL_HapticRamp *hap_ramp = NULL; - SDL_HapticCustom *hap_custom = NULL; + const SDL_HapticConstant *hap_constant = NULL; + const SDL_HapticPeriodic *hap_periodic = NULL; + const SDL_HapticCondition *hap_condition = NULL; + const SDL_HapticRamp *hap_ramp = NULL; + const SDL_HapticCustom *hap_custom = NULL; DWORD *axes = NULL; /* Set global stuff. */ @@ -834,8 +861,7 @@ static int SDL_SYS_ToFFEFFECT(SDL_Haptic *haptic, FFEFFECT *dest, SDL_HapticEffe break; case SDL_HAPTIC_SINE: - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* case SDL_HAPTIC_SQUARE: */ + case SDL_HAPTIC_SQUARE: case SDL_HAPTIC_TRIANGLE: case SDL_HAPTIC_SAWTOOTHUP: case SDL_HAPTIC_SAWTOOTHDOWN: @@ -1049,9 +1075,8 @@ SDL_SYS_HapticEffectType(Uint16 type) case SDL_HAPTIC_RAMP: return kFFEffectType_RampForce_ID; - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* case SDL_HAPTIC_SQUARE: - return kFFEffectType_Square_ID; */ + case SDL_HAPTIC_SQUARE: + return kFFEffectType_Square_ID; case SDL_HAPTIC_SINE: return kFFEffectType_Sine_ID; @@ -1090,7 +1115,7 @@ SDL_SYS_HapticEffectType(Uint16 type) * Creates a new haptic effect. */ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *base) + const SDL_HapticEffect *base) { HRESULT ret; CFUUIDRef type; @@ -1137,7 +1162,7 @@ err_hweffect: */ int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *data) + const SDL_HapticEffect *data) { HRESULT ret; FFEffectParameterFlag flags; diff --git a/src/haptic/dummy/SDL_syshaptic.c b/src/haptic/dummy/SDL_syshaptic.c index 419f7bad..feace4e1 100644 --- a/src/haptic/dummy/SDL_syshaptic.c +++ b/src/haptic/dummy/SDL_syshaptic.c @@ -39,6 +39,12 @@ int SDL_SYS_NumHaptics(void) return 0; } +SDL_HapticID SDL_SYS_HapticInstanceID(int index) +{ + SDL_SYS_LogicError(); + return 0; +} + const char *SDL_SYS_HapticName(int index) { SDL_SYS_LogicError(); @@ -81,14 +87,14 @@ void SDL_SYS_HapticQuit(void) } int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, - struct haptic_effect *effect, SDL_HapticEffect *base) + struct haptic_effect *effect, const SDL_HapticEffect *base) { return SDL_SYS_LogicError(); } int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *data) + const SDL_HapticEffect *data) { return SDL_SYS_LogicError(); } diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index c4e6c183..b80a641c 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -49,6 +49,7 @@ static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, */ typedef struct SDL_hapticlist_item { + SDL_HapticID instance_id; char *fname; /* Dev path name (like /dev/input/event1) */ SDL_Haptic *haptic; /* Associated haptic. */ dev_t dev_num; @@ -99,8 +100,7 @@ static int EV_IsHaptic(int fd) /* Convert supported features to SDL_HAPTIC platform-neutral features. */ EV_TEST(FF_CONSTANT, SDL_HAPTIC_CONSTANT); EV_TEST(FF_SINE, SDL_HAPTIC_SINE); - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE); */ + EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE); EV_TEST(FF_TRIANGLE, SDL_HAPTIC_TRIANGLE); EV_TEST(FF_SAW_UP, SDL_HAPTIC_SAWTOOTHUP); EV_TEST(FF_SAW_DOWN, SDL_HAPTIC_SAWTOOTHDOWN); @@ -196,6 +196,17 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) return item; } +static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id) +{ + SDL_hapticlist_item *item; + for (item = SDL_hapticlist; item; item = item->next) { + if (instance_id == item->instance_id) { + return item; + } + } + return NULL; +} + #ifdef SDL_USE_LIBUDEV static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) { @@ -229,24 +240,26 @@ static int MaybeAddDevice(const char *path) return -1; } - /* check to see if file exists */ - if (stat(path, &sb) != 0) { + /* try to open */ + fd = open(path, O_RDWR | O_CLOEXEC, 0); + if (fd < 0) { + return -1; + } + + /* get file status */ + if (fstat(fd, &sb) != 0) { + close(fd); return -1; } /* check for duplicates */ for (item = SDL_hapticlist; item; item = item->next) { if (item->dev_num == sb.st_rdev) { + close(fd); return -1; /* duplicate. */ } } - /* try to open */ - fd = open(path, O_RDWR | O_CLOEXEC, 0); - if (fd < 0) { - return -1; - } - #ifdef DEBUG_INPUT_EVENTS printf("Checking %s\n", path); #endif @@ -263,6 +276,7 @@ static int MaybeAddDevice(const char *path) return -1; } + item->instance_id = SDL_GetNextObjectID(); item->fname = SDL_strdup(path); if (!item->fname) { SDL_free(item); @@ -299,7 +313,7 @@ static int MaybeRemoveDevice(const char *path) for (item = SDL_hapticlist; item; item = item->next) { /* found it, remove it. */ if (SDL_strcmp(path, item->fname) == 0) { - const int retval = item->haptic ? item->haptic->index : -1; + const int retval = item->haptic ? 0 : -1; if (prev) { prev->next = item->next; @@ -326,6 +340,20 @@ static int MaybeRemoveDevice(const char *path) } #endif /* SDL_USE_LIBUDEV */ +/* + * Return the instance ID of a haptic device, does not need to be opened. + */ +SDL_HapticID SDL_SYS_HapticInstanceID(int index) +{ + SDL_hapticlist_item *item; + + item = HapticByDevIndex(index); + if (item) { + return item->instance_id; + } + return 0; +} + /* * Gets the name from a file descriptor. */ @@ -348,23 +376,23 @@ const char *SDL_SYS_HapticName(int index) { SDL_hapticlist_item *item; int fd; - const char *name; + const char *name = NULL; item = HapticByDevIndex(index); - /* Open the haptic device. */ - name = NULL; - fd = open(item->fname, O_RDONLY | O_CLOEXEC, 0); + if (item) { + /* Open the haptic device. */ + fd = open(item->fname, O_RDONLY | O_CLOEXEC, 0); - if (fd >= 0) { + if (fd >= 0) { - name = SDL_SYS_HapticNameFromFD(fd); - if (!name) { - /* No name found, return device character device */ - name = item->fname; + name = SDL_SYS_HapticNameFromFD(fd); + if (!name) { + /* No name found, return device character device */ + name = item->fname; + } + close(fd); } - close(fd); } - return name; } @@ -422,7 +450,7 @@ int SDL_SYS_HapticOpen(SDL_Haptic *haptic) int ret; SDL_hapticlist_item *item; - item = HapticByDevIndex(haptic->index); + item = HapticByInstanceID(haptic->instance_id); /* Open the character device */ fd = open(item->fname, O_RDWR | O_CLOEXEC, 0); if (fd < 0) { @@ -516,10 +544,10 @@ int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) { #ifdef SDL_JOYSTICK_LINUX - int device_index = 0; int fd; int ret; SDL_hapticlist_item *item; + const char *name; SDL_AssertJoysticksLocked(); @@ -529,14 +557,9 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) /* Find the joystick in the haptic list. */ for (item = SDL_hapticlist; item; item = item->next) { if (SDL_strcmp(item->fname, joystick->hwdata->fname) == 0) { + haptic->instance_id = item->instance_id; break; } - ++device_index; - } - haptic->index = device_index; - - if (device_index >= MAX_HAPTICS) { - return SDL_SetError("Haptic: Joystick doesn't have Haptic capabilities"); } fd = open(joystick->hwdata->fname, O_RDWR | O_CLOEXEC, 0); @@ -551,6 +574,10 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) haptic->hwdata->fname = SDL_strdup(joystick->hwdata->fname); + name = SDL_SYS_HapticNameFromFD(fd); + if (name) { + haptic->name = SDL_strdup(name); + } return 0; #else return -1; @@ -631,7 +658,7 @@ static Uint16 SDL_SYS_ToButton(Uint16 button) /* * Initializes the ff_effect usable direction from a SDL_HapticDirection. */ -static int SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection *src) +static int SDL_SYS_ToDirection(Uint16 *dest, const SDL_HapticDirection *src) { Uint32 tmp; @@ -692,13 +719,13 @@ static int SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection *src) * Initializes the Linux effect struct from a haptic_effect. * Values above 32767 (for unsigned) are unspecified so we must clamp. */ -static int SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect *src) +static int SDL_SYS_ToFFEffect(struct ff_effect *dest, const SDL_HapticEffect *src) { - SDL_HapticConstant *constant; - SDL_HapticPeriodic *periodic; - SDL_HapticCondition *condition; - SDL_HapticRamp *ramp; - SDL_HapticLeftRight *leftright; + const SDL_HapticConstant *constant; + const SDL_HapticPeriodic *periodic; + const SDL_HapticCondition *condition; + const SDL_HapticRamp *ramp; + const SDL_HapticLeftRight *leftright; /* Clear up */ SDL_memset(dest, 0, sizeof(struct ff_effect)); @@ -735,8 +762,7 @@ static int SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect *src) break; case SDL_HAPTIC_SINE: - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* case SDL_HAPTIC_SQUARE: */ + case SDL_HAPTIC_SQUARE: case SDL_HAPTIC_TRIANGLE: case SDL_HAPTIC_SAWTOOTHUP: case SDL_HAPTIC_SAWTOOTHDOWN: @@ -759,9 +785,8 @@ static int SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect *src) /* Periodic */ if (periodic->type == SDL_HAPTIC_SINE) { dest->u.periodic.waveform = FF_SINE; - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* else if (periodic->type == SDL_HAPTIC_SQUARE) - dest->u.periodic.waveform = FF_SQUARE; */ + } else if (periodic->type == SDL_HAPTIC_SQUARE) { + dest->u.periodic.waveform = FF_SQUARE; } else if (periodic->type == SDL_HAPTIC_TRIANGLE) { dest->u.periodic.waveform = FF_TRIANGLE; } else if (periodic->type == SDL_HAPTIC_SAWTOOTHUP) { @@ -894,7 +919,7 @@ static int SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect *src) * Creates a new haptic effect. */ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *base) + const SDL_HapticEffect *base) { struct ff_effect *linux_effect; @@ -935,7 +960,7 @@ new_effect_err: */ int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *data) + const SDL_HapticEffect *data) { struct ff_effect linux_effect; diff --git a/src/haptic/windows/SDL_dinputhaptic.c b/src/haptic/windows/SDL_dinputhaptic.c index 04f4a48c..8a36993a 100644 --- a/src/haptic/windows/SDL_dinputhaptic.c +++ b/src/haptic/windows/SDL_dinputhaptic.c @@ -71,7 +71,7 @@ int SDL_DINPUT_HapticInit(void) return SDL_SetError("Haptic: SubSystem already open."); } - if (!SDL_GetHintBoolean(SDL_HINT_DIRECTINPUT_ENABLED, SDL_TRUE)) { + if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, SDL_TRUE)) { /* In some environments, IDirectInput8_Initialize / _EnumDevices can take a minute even with no controllers. */ return 0; } @@ -139,7 +139,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance) /* Make sure we don't already have it */ for (item = SDL_hapticlist; item; item = item->next) { - if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) { + if (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) { return -1; /* Already added */ } } @@ -170,6 +170,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance) return -1; } + item->instance_id = SDL_GetNextObjectID(); item->name = WIN_StringToUTF8(pdidInstance->tszProductName); if (!item->name) { SDL_free(item); @@ -193,7 +194,7 @@ int SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance) } for (item = SDL_hapticlist; item; item = item->next) { - if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) { + if (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) { /* found it, remove it. */ return SDL_SYS_RemoveHapticDevice(prev, item); } @@ -259,8 +260,7 @@ static BOOL CALLBACK DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv) EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT); EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM); EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE); - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */ + EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE); EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP); EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN); @@ -298,7 +298,7 @@ static int SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic *haptic, LPDIRECTINPUTDEVI /* !!! FIXME: opening a haptic device here first will make an attempt to !!! FIXME: SDL_OpenJoystick() that same device fail later, since we !!! FIXME: have it open in exclusive mode. But this will allow - !!! FIXME: SDL_OpenJoystick() followed by SDL_HapticOpenFromJoystick() + !!! FIXME: SDL_OpenJoystick() followed by SDL_OpenHapticFromJoystick() !!! FIXME: to work, and that's probably the common case. Still, !!! FIXME: ideally, We need to unify the opening code. */ @@ -461,7 +461,6 @@ int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) { SDL_hapticlist_item *item; - Uint8 index = 0; HRESULT ret; DIDEVICEINSTANCE joy_instance; @@ -473,11 +472,11 @@ int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */ for (item = SDL_hapticlist; item; item = item->next) { - if (!item->bXInputHaptic && WIN_IsEqualGUID(&item->instance.guidInstance, &joy_instance.guidInstance)) { - haptic->index = index; + if (WIN_IsEqualGUID(&item->instance.guidInstance, &joy_instance.guidInstance)) { + haptic->instance_id = item->instance_id; + haptic->name = SDL_strdup(item->name); return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE); } - ++index; } return SDL_SetError("Couldn't find joystick in haptic device list"); @@ -525,7 +524,7 @@ static DWORD DIGetTriggerButton(Uint16 button) /* * Sets the direction. */ -static int SDL_SYS_SetDirection(DIEFFECT *effect, SDL_HapticDirection *dir, int naxes) +static int SDL_SYS_SetDirection(DIEFFECT *effect, const SDL_HapticDirection *dir, int naxes) { LONG *rglDir; @@ -537,7 +536,7 @@ static int SDL_SYS_SetDirection(DIEFFECT *effect, SDL_HapticDirection *dir, int } /* Has axes. */ - rglDir = SDL_malloc(sizeof(LONG) * naxes); + rglDir = (LONG *)SDL_malloc(sizeof(LONG) * naxes); if (!rglDir) { return -1; } @@ -587,7 +586,7 @@ static int SDL_SYS_SetDirection(DIEFFECT *effect, SDL_HapticDirection *dir, int * Creates the DIEFFECT from a SDL_HapticEffect. */ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, - SDL_HapticEffect *src) + const SDL_HapticEffect *src) { int i; DICONSTANTFORCE *constant; @@ -596,11 +595,11 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, DIRAMPFORCE *ramp; DICUSTOMFORCE *custom; DIENVELOPE *envelope; - SDL_HapticConstant *hap_constant; - SDL_HapticPeriodic *hap_periodic; - SDL_HapticCondition *hap_condition; - SDL_HapticRamp *hap_ramp; - SDL_HapticCustom *hap_custom; + const SDL_HapticConstant *hap_constant; + const SDL_HapticPeriodic *hap_periodic; + const SDL_HapticCondition *hap_condition; + const SDL_HapticRamp *hap_ramp; + const SDL_HapticCustom *hap_custom; DWORD *axes; /* Set global stuff. */ @@ -611,7 +610,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, dest->dwFlags = DIEFF_OBJECTOFFSETS; /* Seems obligatory. */ /* Envelope. */ - envelope = SDL_calloc(1, sizeof(DIENVELOPE)); + envelope = (DIENVELOPE *)SDL_calloc(1, sizeof(DIENVELOPE)); if (!envelope) { return -1; } @@ -625,7 +624,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, dest->cAxes = haptic->naxes; } if (dest->cAxes > 0) { - axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); + axes = (DWORD *)SDL_malloc(sizeof(DWORD) * dest->cAxes); if (!axes) { return -1; } @@ -643,7 +642,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, switch (src->type) { case SDL_HAPTIC_CONSTANT: hap_constant = &src->constant; - constant = SDL_calloc(1, sizeof(DICONSTANTFORCE)); + constant = (DICONSTANTFORCE *)SDL_calloc(1, sizeof(DICONSTANTFORCE)); if (!constant) { return -1; } @@ -678,13 +677,12 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, break; case SDL_HAPTIC_SINE: - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* case SDL_HAPTIC_SQUARE: */ + case SDL_HAPTIC_SQUARE: case SDL_HAPTIC_TRIANGLE: case SDL_HAPTIC_SAWTOOTHUP: case SDL_HAPTIC_SAWTOOTHDOWN: hap_periodic = &src->periodic; - periodic = SDL_calloc(1, sizeof(DIPERIODIC)); + periodic = (DIPERIODIC *)SDL_calloc(1, sizeof(DIPERIODIC)); if (!periodic) { return -1; } @@ -727,7 +725,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_INERTIA: case SDL_HAPTIC_FRICTION: hap_condition = &src->condition; - condition = SDL_calloc(dest->cAxes, sizeof(DICONDITION)); + condition = (DICONDITION *)SDL_calloc(dest->cAxes, sizeof(DICONDITION)); if (!condition) { return -1; } @@ -767,7 +765,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_RAMP: hap_ramp = &src->ramp; - ramp = SDL_calloc(1, sizeof(DIRAMPFORCE)); + ramp = (DIRAMPFORCE *)SDL_calloc(1, sizeof(DIRAMPFORCE)); if (!ramp) { return -1; } @@ -804,7 +802,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, case SDL_HAPTIC_CUSTOM: hap_custom = &src->custom; - custom = SDL_calloc(1, sizeof(DICUSTOMFORCE)); + custom = (DICUSTOMFORCE *)SDL_calloc(1, sizeof(DICUSTOMFORCE)); if (!custom) { return -1; } @@ -813,8 +811,7 @@ static int SDL_SYS_ToDIEFFECT(SDL_Haptic *haptic, DIEFFECT *dest, custom->cChannels = hap_custom->channels; custom->dwSamplePeriod = hap_custom->period * 1000UL; custom->cSamples = hap_custom->samples; - custom->rglForceData = - SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels); + custom->rglForceData = (LPLONG)SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels); for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) { /* Copy data. */ custom->rglForceData[i] = CCONVERT(hap_custom->data[i]); } @@ -880,7 +877,7 @@ static void SDL_SYS_HapticFreeDIEFFECT(DIEFFECT *effect, int type) * Gets the effect type from the generic SDL haptic effect wrapper. */ /* NOLINTNEXTLINE(readability-const-return-type): Can't fix Windows' headers */ -static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect *effect) +static REFGUID SDL_SYS_HapticEffectType(const SDL_HapticEffect *effect) { switch (effect->type) { case SDL_HAPTIC_CONSTANT: @@ -889,9 +886,8 @@ static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect *effect) case SDL_HAPTIC_RAMP: return &GUID_RampForce; - /* !!! FIXME: put this back when we have more bits in 2.1 */ - /* case SDL_HAPTIC_SQUARE: - return &GUID_Square; */ + case SDL_HAPTIC_SQUARE: + return &GUID_Square; case SDL_HAPTIC_SINE: return &GUID_Sine; @@ -924,7 +920,7 @@ static REFGUID SDL_SYS_HapticEffectType(SDL_HapticEffect *effect) return NULL; } } -int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base) +int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *base) { HRESULT ret; REFGUID type = SDL_SYS_HapticEffectType(base); @@ -954,7 +950,7 @@ err_effectdone: return -1; } -int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data) +int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data) { HRESULT ret; DWORD flags; @@ -1189,12 +1185,12 @@ void SDL_DINPUT_HapticQuit(void) { } -int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base) +int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *base) { return SDL_Unsupported(); } -int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data) +int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data) { return SDL_Unsupported(); } diff --git a/src/haptic/windows/SDL_dinputhaptic_c.h b/src/haptic/windows/SDL_dinputhaptic_c.h index 0f87afbc..1075a542 100644 --- a/src/haptic/windows/SDL_dinputhaptic_c.h +++ b/src/haptic/windows/SDL_dinputhaptic_c.h @@ -35,8 +35,8 @@ extern int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joyst extern int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick); extern void SDL_DINPUT_HapticClose(SDL_Haptic *haptic); extern void SDL_DINPUT_HapticQuit(void); -extern int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base); -extern int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data); +extern int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *base); +extern int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data); extern int SDL_DINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations); extern int SDL_DINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect); extern void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect); diff --git a/src/haptic/windows/SDL_windowshaptic.c b/src/haptic/windows/SDL_windowshaptic.c index b7dbae3f..cb334354 100644 --- a/src/haptic/windows/SDL_windowshaptic.c +++ b/src/haptic/windows/SDL_windowshaptic.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_HAPTIC_DINPUT) || defined(SDL_HAPTIC_XINPUT) +#ifdef SDL_HAPTIC_DINPUT #include "../SDL_syshaptic.h" #include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */ @@ -29,7 +29,6 @@ #include "SDL_windowshaptic_c.h" #include "SDL_dinputhaptic_c.h" -#include "SDL_xinputhaptic_c.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -53,9 +52,6 @@ int SDL_SYS_HapticInit(void) if (SDL_DINPUT_HapticInit() < 0) { return -1; } - if (SDL_XINPUT_HapticInit() < 0) { - return -1; - } /* The joystick subsystem will usually be initialized before haptics, * so the initial HapticMaybeAddDevice() calls from the joystick @@ -63,11 +59,7 @@ int SDL_SYS_HapticInit(void) * invoke those callbacks again here to pick up any joysticks that * were added prior to haptics initialization. */ for (device = SYS_Joystick; device; device = device->pNext) { - if (device->bXInputDevice) { - SDL_XINPUT_HapticMaybeAddDevice(device->XInputUserId); - } else { - SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice); - } + SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice); } return numhaptics; @@ -90,7 +82,7 @@ int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item) int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item) { - const int retval = item->haptic ? item->haptic->index : -1; + const int retval = item->haptic ? 0 : -1; if (prev) { prev->next = item->next; } else { @@ -127,6 +119,26 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index) return item; } +static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id) +{ + SDL_hapticlist_item *item; + for (item = SDL_hapticlist; item; item = item->next) { + if (instance_id == item->instance_id) { + return item; + } + } + return NULL; +} + +SDL_HapticID SDL_SYS_HapticInstanceID(int index) +{ + SDL_hapticlist_item *item = HapticByDevIndex(index); + if (item) { + return item->instance_id; + } + return 0; +} + /* * Return the name of a haptic device, does not need to be opened. */ @@ -141,12 +153,8 @@ const char *SDL_SYS_HapticName(int index) */ int SDL_SYS_HapticOpen(SDL_Haptic *haptic) { - SDL_hapticlist_item *item = HapticByDevIndex(haptic->index); - if (item->bXInputHaptic) { - return SDL_XINPUT_HapticOpen(haptic, item); - } else { - return SDL_DINPUT_HapticOpen(haptic, item); - } + SDL_hapticlist_item *item = HapticByInstanceID(haptic->instance_id); + return SDL_DINPUT_HapticOpen(haptic, item); } /* @@ -177,16 +185,9 @@ int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) if (joystick->driver != &SDL_WINDOWS_JoystickDriver) { return 0; } -#ifdef SDL_HAPTIC_XINPUT - if (joystick->hwdata->bXInputHaptic) { - return 1; - } -#endif -#ifdef SDL_HAPTIC_DINPUT if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) { return 1; } -#endif return 0; } @@ -198,13 +199,7 @@ int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) if (joystick->driver != &SDL_WINDOWS_JoystickDriver) { return 0; } - if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) { - return 0; /* one is XInput, one is not; not the same device. */ - } else if (joystick->hwdata->bXInputHaptic) { - return SDL_XINPUT_JoystickSameHaptic(haptic, joystick); - } else { - return SDL_DINPUT_JoystickSameHaptic(haptic, joystick); - } + return SDL_DINPUT_JoystickSameHaptic(haptic, joystick); } /* @@ -214,11 +209,7 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) { SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver); - if (joystick->hwdata->bXInputDevice) { - return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick); - } else { - return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick); - } + return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick); } /* @@ -234,11 +225,7 @@ void SDL_SYS_HapticClose(SDL_Haptic *haptic) haptic->neffects = 0; /* Clean up */ - if (haptic->hwdata->bXInputHaptic) { - SDL_XINPUT_HapticClose(haptic); - } else { - SDL_DINPUT_HapticClose(haptic); - } + SDL_DINPUT_HapticClose(haptic); /* Free */ SDL_free(haptic->hwdata); @@ -253,17 +240,6 @@ void SDL_SYS_HapticQuit(void) { SDL_hapticlist_item *item; SDL_hapticlist_item *next = NULL; - SDL_Haptic *hapticitem = NULL; - - extern SDL_Haptic *SDL_haptics; - for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) { - if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) { - /* we _have_ to stop the thread before we free the XInput DLL! */ - SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1); - SDL_WaitThread(hapticitem->hwdata->thread, NULL); - hapticitem->hwdata->thread = NULL; - } - } for (item = SDL_hapticlist; item; item = next) { /* Opened and not closed haptics are leaked, this is on purpose. @@ -274,7 +250,6 @@ void SDL_SYS_HapticQuit(void) SDL_free(item); } - SDL_XINPUT_HapticQuit(); SDL_DINPUT_HapticQuit(); numhaptics = 0; @@ -286,7 +261,7 @@ void SDL_SYS_HapticQuit(void) * Creates a new haptic effect. */ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - SDL_HapticEffect *base) + const SDL_HapticEffect *base) { int result; @@ -296,11 +271,7 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, return -1; } - if (haptic->hwdata->bXInputHaptic) { - result = SDL_XINPUT_HapticNewEffect(haptic, effect, base); - } else { - result = SDL_DINPUT_HapticNewEffect(haptic, effect, base); - } + result = SDL_DINPUT_HapticNewEffect(haptic, effect, base); if (result < 0) { SDL_free(effect->hweffect); effect->hweffect = NULL; @@ -311,28 +282,17 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, /* * Updates an effect. */ -int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, - struct haptic_effect *effect, - SDL_HapticEffect *data) +int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data); - } else { - return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data); - } + return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data); } /* * Runs an effect. */ -int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, - Uint32 iterations) +int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations); - } else { - return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations); - } + return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations); } /* @@ -340,11 +300,7 @@ int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, */ int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticStopEffect(haptic, effect); - } else { - return SDL_DINPUT_HapticStopEffect(haptic, effect); - } + return SDL_DINPUT_HapticStopEffect(haptic, effect); } /* @@ -352,11 +308,7 @@ int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect) */ void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect) { - if (haptic->hwdata->bXInputHaptic) { - SDL_XINPUT_HapticDestroyEffect(haptic, effect); - } else { - SDL_DINPUT_HapticDestroyEffect(haptic, effect); - } + SDL_DINPUT_HapticDestroyEffect(haptic, effect); SDL_free(effect->hweffect); effect->hweffect = NULL; } @@ -364,14 +316,9 @@ void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effec /* * Gets the status of a haptic effect. */ -int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, - struct haptic_effect *effect) +int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticGetEffectStatus(haptic, effect); - } else { - return SDL_DINPUT_HapticGetEffectStatus(haptic, effect); - } + return SDL_DINPUT_HapticGetEffectStatus(haptic, effect); } /* @@ -379,11 +326,7 @@ int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, */ int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticSetGain(haptic, gain); - } else { - return SDL_DINPUT_HapticSetGain(haptic, gain); - } + return SDL_DINPUT_HapticSetGain(haptic, gain); } /* @@ -391,11 +334,7 @@ int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain) */ int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter); - } else { - return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter); - } + return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter); } /* @@ -403,11 +342,7 @@ int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) */ int SDL_SYS_HapticPause(SDL_Haptic *haptic) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticPause(haptic); - } else { - return SDL_DINPUT_HapticPause(haptic); - } + return SDL_DINPUT_HapticPause(haptic); } /* @@ -415,11 +350,7 @@ int SDL_SYS_HapticPause(SDL_Haptic *haptic) */ int SDL_SYS_HapticUnpause(SDL_Haptic *haptic) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticUnpause(haptic); - } else { - return SDL_DINPUT_HapticUnpause(haptic); - } + return SDL_DINPUT_HapticUnpause(haptic); } /* @@ -427,11 +358,7 @@ int SDL_SYS_HapticUnpause(SDL_Haptic *haptic) */ int SDL_SYS_HapticStopAll(SDL_Haptic *haptic) { - if (haptic->hwdata->bXInputHaptic) { - return SDL_XINPUT_HapticStopAll(haptic); - } else { - return SDL_DINPUT_HapticStopAll(haptic); - } + return SDL_DINPUT_HapticStopAll(haptic); } /* Ends C function definitions when using C++ */ @@ -439,4 +366,4 @@ int SDL_SYS_HapticStopAll(SDL_Haptic *haptic) } #endif -#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */ +#endif /* SDL_HAPTIC_DINPUT */ diff --git a/src/haptic/windows/SDL_windowshaptic_c.h b/src/haptic/windows/SDL_windowshaptic_c.h index a84430c3..5c93edd7 100644 --- a/src/haptic/windows/SDL_windowshaptic_c.h +++ b/src/haptic/windows/SDL_windowshaptic_c.h @@ -42,8 +42,6 @@ struct haptic_hwdata #endif DWORD axes[3]; /* Axes to use. */ SDL_bool is_joystick; /* Device is loaded as joystick. */ - Uint8 bXInputHaptic; /* Supports force feedback via XInput. */ - Uint8 userid; /* XInput userid index for this joystick */ SDL_Thread *thread; SDL_Mutex *mutex; Uint64 stopTicks; @@ -53,16 +51,11 @@ struct haptic_hwdata /* * Haptic system effect data. */ -#if defined(SDL_HAPTIC_DINPUT) || defined(SDL_HAPTIC_XINPUT) +#ifdef SDL_HAPTIC_DINPUT struct haptic_hweffect { -#ifdef SDL_HAPTIC_DINPUT DIEFFECT effect; LPDIRECTINPUTEFFECT ref; -#endif -#ifdef SDL_HAPTIC_XINPUT - XINPUT_VIBRATION vibration; -#endif }; #endif @@ -71,14 +64,13 @@ struct haptic_hweffect */ typedef struct SDL_hapticlist_item { + SDL_HapticID instance_id; char *name; SDL_Haptic *haptic; #ifdef SDL_HAPTIC_DINPUT DIDEVICEINSTANCE instance; DIDEVCAPS capabilities; #endif - SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */ - Uint8 userid; /* XInput userid index for this joystick */ struct SDL_hapticlist_item *next; } SDL_hapticlist_item; diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c deleted file mode 100644 index 6e8de2a0..00000000 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ /dev/null @@ -1,443 +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_syshaptic.h" - -#ifdef SDL_HAPTIC_XINPUT - -#include "SDL_windowshaptic_c.h" -#include "SDL_xinputhaptic_c.h" -#include "../../core/windows/SDL_xinput.h" -#include "../../joystick/windows/SDL_windowsjoystick_c.h" -#include "../../thread/SDL_systhread.h" - -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Internal stuff. - */ -static SDL_bool loaded_xinput = SDL_FALSE; - -int SDL_XINPUT_HapticInit(void) -{ - if (SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE)) { - loaded_xinput = (WIN_LoadXInputDLL() == 0); - } - - /* If the joystick subsystem is active, it will manage adding XInput haptic devices */ - if (loaded_xinput && !SDL_WasInit(SDL_INIT_JOYSTICK)) { - DWORD i; - for (i = 0; i < XUSER_MAX_COUNT; i++) { - SDL_XINPUT_HapticMaybeAddDevice(i); - } - } - return 0; -} - -int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) -{ - const Uint8 userid = (Uint8)dwUserid; - SDL_hapticlist_item *item; - XINPUT_VIBRATION state; - - if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) { - return -1; - } - - /* Make sure we don't already have it */ - for (item = SDL_hapticlist; item; item = item->next) { - if (item->bXInputHaptic && item->userid == userid) { - return -1; /* Already added */ - } - } - - SDL_zero(state); - if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) { - return -1; /* no force feedback on this device. */ - } - - item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); - if (!item) { - return -1; - } - - /* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */ - { - char buf[64]; - (void)SDL_snprintf(buf, sizeof(buf), "XInput Controller #%d", 1 + userid); - item->name = SDL_strdup(buf); - } - - if (!item->name) { - SDL_free(item); - return -1; - } - - /* Copy the instance over, useful for creating devices. */ - item->bXInputHaptic = SDL_TRUE; - item->userid = userid; - - return SDL_SYS_AddHapticDevice(item); -} - -int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid) -{ - const Uint8 userid = (Uint8)dwUserid; - SDL_hapticlist_item *item; - SDL_hapticlist_item *prev = NULL; - - if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) { - return -1; - } - - for (item = SDL_hapticlist; item; item = item->next) { - if (item->bXInputHaptic && item->userid == userid) { - /* found it, remove it. */ - return SDL_SYS_RemoveHapticDevice(prev, item); - } - prev = item; - } - return -1; -} - -/* !!! FIXME: this is a hack, remove this later. */ -/* Since XInput doesn't offer a way to vibrate for X time, we hook into - * SDL_PumpEvents() to check if it's time to stop vibrating with some - * frequency. - * In practice, this works for 99% of use cases. But in an ideal world, - * we do this in a separate thread so that: - * - we aren't bound to when the app chooses to pump the event queue. - * - we aren't adding more polling to the event queue - * - we can emulate all the haptic effects correctly (start on a delay, - * mix multiple effects, etc). - * - * Mostly, this is here to get rumbling to work, and all the other features - * are absent in the XInput path for now. :( - */ -static int SDLCALL SDL_RunXInputHaptic(void *arg) -{ - struct haptic_hwdata *hwdata = (struct haptic_hwdata *)arg; - - while (!SDL_AtomicGet(&hwdata->stopThread)) { - SDL_Delay(50); - SDL_LockMutex(hwdata->mutex); - /* If we're currently running and need to stop... */ - if (hwdata->stopTicks) { - if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_GetTicks() >= hwdata->stopTicks) { - XINPUT_VIBRATION vibration = { 0, 0 }; - hwdata->stopTicks = 0; - XINPUTSETSTATE(hwdata->userid, &vibration); - } - } - SDL_UnlockMutex(hwdata->mutex); - } - - return 0; -} - -static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 userid) -{ - char threadName[32]; - XINPUT_VIBRATION vibration = { 0, 0 }; /* stop any current vibration */ - XINPUTSETSTATE(userid, &vibration); - - haptic->supported = SDL_HAPTIC_LEFTRIGHT; - - haptic->neffects = 1; - haptic->nplaying = 1; - - /* Prepare effects memory. */ - haptic->effects = (struct haptic_effect *) - SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); - if (!haptic->effects) { - return -1; - } - /* Clear the memory */ - SDL_memset(haptic->effects, 0, - sizeof(struct haptic_effect) * haptic->neffects); - - haptic->hwdata = (struct haptic_hwdata *)SDL_calloc(1, sizeof(*haptic->hwdata)); - if (!haptic->hwdata) { - SDL_free(haptic->effects); - haptic->effects = NULL; - return -1; - } - - haptic->hwdata->bXInputHaptic = 1; - haptic->hwdata->userid = userid; - - haptic->hwdata->mutex = SDL_CreateMutex(); - if (!haptic->hwdata->mutex) { - SDL_free(haptic->effects); - SDL_free(haptic->hwdata); - haptic->effects = NULL; - return SDL_SetError("Couldn't create XInput haptic mutex"); - } - - (void)SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%u", userid); - haptic->hwdata->thread = SDL_CreateThreadInternal(SDL_RunXInputHaptic, threadName, 64 * 1024, haptic->hwdata); - - if (!haptic->hwdata->thread) { - SDL_DestroyMutex(haptic->hwdata->mutex); - SDL_free(haptic->effects); - SDL_free(haptic->hwdata); - haptic->effects = NULL; - return SDL_SetError("Couldn't create XInput haptic thread"); - } - - return 0; -} - -int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item) -{ - return SDL_XINPUT_HapticOpenFromUserIndex(haptic, item->userid); -} - -int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) -{ - return haptic->hwdata->userid == joystick->hwdata->userid; -} - -int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) -{ - SDL_hapticlist_item *item; - Uint8 index = 0; - - /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */ - for (item = SDL_hapticlist; item; item = item->next) { - if (item->bXInputHaptic && item->userid == joystick->hwdata->userid) { - haptic->index = index; - return SDL_XINPUT_HapticOpenFromUserIndex(haptic, joystick->hwdata->userid); - } - ++index; - } - - return SDL_SetError("Couldn't find joystick in haptic device list"); -} - -void SDL_XINPUT_HapticClose(SDL_Haptic *haptic) -{ - SDL_AtomicSet(&haptic->hwdata->stopThread, 1); - SDL_WaitThread(haptic->hwdata->thread, NULL); - SDL_DestroyMutex(haptic->hwdata->mutex); -} - -void SDL_XINPUT_HapticQuit(void) -{ - if (loaded_xinput) { - WIN_UnloadXInputDLL(); - loaded_xinput = SDL_FALSE; - } -} - -int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base) -{ - SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */ - return SDL_XINPUT_HapticUpdateEffect(haptic, effect, base); -} - -int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data) -{ - XINPUT_VIBRATION *vib = &effect->hweffect->vibration; - SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT); - /* SDL_HapticEffect has max magnitude of 32767, XInput expects 65535 max, so multiply */ - vib->wLeftMotorSpeed = data->leftright.large_magnitude * 2; - vib->wRightMotorSpeed = data->leftright.small_magnitude * 2; - SDL_LockMutex(haptic->hwdata->mutex); - if (haptic->hwdata->stopTicks) { /* running right now? Update it. */ - XINPUTSETSTATE(haptic->hwdata->userid, vib); - } - SDL_UnlockMutex(haptic->hwdata->mutex); - return 0; -} - -int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations) -{ - XINPUT_VIBRATION *vib = &effect->hweffect->vibration; - SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */ - SDL_LockMutex(haptic->hwdata->mutex); - if (effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) { - haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY; - } else if ((!effect->effect.leftright.length) || (!iterations)) { - /* do nothing. Effect runs for zero milliseconds. */ - } else { - haptic->hwdata->stopTicks = SDL_GetTicks() + ((Uint64)effect->effect.leftright.length * iterations); - } - SDL_UnlockMutex(haptic->hwdata->mutex); - return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1; -} - -int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect) -{ - XINPUT_VIBRATION vibration = { 0, 0 }; - SDL_LockMutex(haptic->hwdata->mutex); - haptic->hwdata->stopTicks = 0; - SDL_UnlockMutex(haptic->hwdata->mutex); - return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1; -} - -void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect) -{ - SDL_XINPUT_HapticStopEffect(haptic, effect); -} - -int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticPause(SDL_Haptic *haptic) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic) -{ - XINPUT_VIBRATION vibration = { 0, 0 }; - SDL_LockMutex(haptic->hwdata->mutex); - haptic->hwdata->stopTicks = 0; - SDL_UnlockMutex(haptic->hwdata->mutex); - return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1; -} - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif - -#else /* !SDL_HAPTIC_XINPUT */ - -#include "../../core/windows/SDL_windows.h" - -typedef struct SDL_hapticlist_item SDL_hapticlist_item; - -int SDL_XINPUT_HapticInit(void) -{ - return 0; -} - -int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) -{ - return SDL_Unsupported(); -} - -void SDL_XINPUT_HapticClose(SDL_Haptic *haptic) -{ -} - -void SDL_XINPUT_HapticQuit(void) -{ -} - -int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect) -{ - return SDL_Unsupported(); -} - -void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect) -{ -} - -int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticPause(SDL_Haptic *haptic) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic) -{ - return SDL_Unsupported(); -} - -int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic) -{ - return SDL_Unsupported(); -} - -#endif /* SDL_HAPTIC_XINPUT */ diff --git a/src/haptic/windows/SDL_xinputhaptic_c.h b/src/haptic/windows/SDL_xinputhaptic_c.h deleted file mode 100644 index b61fd5c9..00000000 --- a/src/haptic/windows/SDL_xinputhaptic_c.h +++ /dev/null @@ -1,53 +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_windowshaptic_c.h" - -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -extern int SDL_XINPUT_HapticInit(void); -extern int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid); -extern int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid); -extern int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item); -extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick); -extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick); -extern void SDL_XINPUT_HapticClose(SDL_Haptic *haptic); -extern void SDL_XINPUT_HapticQuit(void); -extern int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base); -extern int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data); -extern int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations); -extern int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect); -extern void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect); -extern int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect); -extern int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain); -extern int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter); -extern int SDL_XINPUT_HapticPause(SDL_Haptic *haptic); -extern int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic); -extern int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic); - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif diff --git a/src/hidapi/BUILD.cmake.md b/src/hidapi/BUILD.cmake.md index 5555fd2e..573f910d 100644 --- a/src/hidapi/BUILD.cmake.md +++ b/src/hidapi/BUILD.cmake.md @@ -159,7 +159,7 @@ endif() HIDAPI can be easily used as a subdirectory of a larger CMake project: ```cmake # root CMakeLists.txt -cmake_minimum_required(VERSION 3.4.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.4.3...3.25 FATAL_ERROR) add_subdirectory(hidapi) add_subdirectory(my_application) diff --git a/src/hidapi/CMakeLists.txt b/src/hidapi/CMakeLists.txt index b4c99be5..d7086813 100644 --- a/src/hidapi/CMakeLists.txt +++ b/src/hidapi/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1.3...3.25 FATAL_ERROR) if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) add_subdirectory(src) diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c index 97a60c42..70ff8413 100644 --- a/src/hidapi/SDL_hidapi.c +++ b/src/hidapi/SDL_hidapi.c @@ -27,6 +27,7 @@ * This merges the two, at a small performance cost, until distributions * have granted access to /dev/hidraw* */ + #include "SDL_internal.h" #include "SDL_hidapi_c.h" @@ -39,11 +40,11 @@ #ifndef SDL_HIDAPI_DISABLED -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) #include "../core/windows/SDL_windows.h" #endif -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS #include #include #include @@ -100,15 +101,15 @@ static struct SDL_bool m_bCanGetNotifications; Uint64 m_unLastDetect; -#if defined(__WIN32__) || defined(__WINGDK__) - SDL_threadID m_nThreadID; +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) + SDL_ThreadID m_nThreadID; WNDCLASSEXA m_wndClass; HWND m_hwndMsg; HDEVNOTIFY m_hNotify; double m_flLastWin32MessageCheck; #endif -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS IONotificationPortRef m_notificationPort; mach_port_t m_notificationMach; #endif @@ -120,7 +121,7 @@ static struct #endif } SDL_HIDAPI_discovery; -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) struct _DEV_BROADCAST_HDR { DWORD dbch_size; @@ -166,9 +167,9 @@ static LRESULT CALLBACK ControllerWndProc(HWND hwnd, UINT message, WPARAM wParam return DefWindowProc(hwnd, message, wParam, lParam); } -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS static void CallbackIOServiceFunc(void *context, io_iterator_t portIterator) { /* Must drain the iterator, or we won't receive new notifications */ @@ -178,7 +179,7 @@ static void CallbackIOServiceFunc(void *context, io_iterator_t portIterator) ++SDL_HIDAPI_discovery.m_unDeviceChangeCounter; } } -#endif /* __MACOS__ */ +#endif /* SDL_PLATFORM_MACOS */ #ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY_INIT1 @@ -229,8 +230,8 @@ static void HIDAPI_InitializeDiscovery(void) SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_FALSE; SDL_HIDAPI_discovery.m_unLastDetect = 0; -#if defined(__WIN32__) || defined(__WINGDK__) - SDL_HIDAPI_discovery.m_nThreadID = SDL_ThreadID(); +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) + SDL_HIDAPI_discovery.m_nThreadID = SDL_GetCurrentThreadID(); SDL_zero(SDL_HIDAPI_discovery.m_wndClass); SDL_HIDAPI_discovery.m_wndClass.hInstance = GetModuleHandle(NULL); @@ -256,9 +257,9 @@ static void HIDAPI_InitializeDiscovery(void) SDL_HIDAPI_discovery.m_hNotify = RegisterDeviceNotification(SDL_HIDAPI_discovery.m_hwndMsg, &devBroadcast, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); SDL_HIDAPI_discovery.m_bCanGetNotifications = (SDL_HIDAPI_discovery.m_hNotify != 0); } -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS SDL_HIDAPI_discovery.m_notificationPort = IONotificationPortCreate(kIOMainPortDefault); if (SDL_HIDAPI_discovery.m_notificationPort) { { @@ -308,7 +309,7 @@ static void HIDAPI_InitializeDiscovery(void) SDL_HIDAPI_discovery.m_bCanGetNotifications = (SDL_HIDAPI_discovery.m_notificationMach != MACH_PORT_NULL); -#endif /* __MACOS__ */ +#endif /* SDL_PLATFORM_MACOS */ #ifdef SDL_USE_LIBUDEV if (linux_enumeration_method == ENUMERATION_LIBUDEV) { @@ -377,10 +378,10 @@ static void HIDAPI_UpdateDiscovery(void) return; } -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) #if 0 /* just let the usual SDL_PumpEvents loop dispatch these, fixing bug 4286. --ryan. */ /* We'll only get messages on the same thread that created the window */ - if (SDL_ThreadID() == SDL_HIDAPI_discovery.m_nThreadID) { + if (SDL_GetCurrentThreadID() == SDL_HIDAPI_discovery.m_nThreadID) { MSG msg; while (PeekMessage(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0, PM_NOREMOVE)) { if (GetMessageA(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0) != 0) { @@ -390,9 +391,9 @@ static void HIDAPI_UpdateDiscovery(void) } } #endif -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS if (SDL_HIDAPI_discovery.m_notificationPort) { struct { @@ -484,7 +485,7 @@ static void HIDAPI_ShutdownDiscovery(void) return; } -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) if (SDL_HIDAPI_discovery.m_hNotify) { UnregisterDeviceNotification(SDL_HIDAPI_discovery.m_hNotify); } @@ -496,7 +497,7 @@ static void HIDAPI_ShutdownDiscovery(void) UnregisterClassA(SDL_HIDAPI_discovery.m_wndClass.lpszClassName, SDL_HIDAPI_discovery.m_wndClass.hInstance); #endif -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS if (SDL_HIDAPI_discovery.m_notificationPort) { IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort); } @@ -571,17 +572,17 @@ typedef struct PLATFORM_hid_device_ PLATFORM_hid_device; #define read_thread PLATFORM_read_thread #define return_data PLATFORM_return_data -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX #include "SDL_hidapi_linux.h" -#elif defined(__NETBSD__) +#elif defined(SDL_PLATFORM_NETBSD) #include "SDL_hidapi_netbsd.h" -#elif defined(__MACOS__) +#elif defined(SDL_PLATFORM_MACOS) #include "SDL_hidapi_mac.h" -#elif defined(__WINDOWS__) || defined(__WINGDK__) +#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) #include "SDL_hidapi_windows.h" -#elif defined(__ANDROID__) +#elif defined(SDL_PLATFORM_ANDROID) #include "SDL_hidapi_android.h" -#elif defined(__IOS__) || defined(__TVOS__) +#elif defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) #include "SDL_hidapi_ios.h" #endif @@ -1099,7 +1100,7 @@ SDL_bool SDL_HIDAPI_ShouldIgnoreDevice(int bus, Uint16 vendor_id, Uint16 product if (vendor_id == USB_VENDOR_VALVE) { /* Ignore the mouse/keyboard interface on Steam Controllers */ if ( -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 /* Check the usage page and usage on both USB and Bluetooth */ #else /* Only check the usage page and usage on USB */ @@ -1232,7 +1233,7 @@ int SDL_hid_init(void) #ifdef HAVE_PLATFORM_BACKEND ++attempts; -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX udev_ctx = SDL_UDEV_GetUdevSyms(); #endif /* __LINUX __ */ if (udev_ctx && PLATFORM_hid_init() == 0) { @@ -1244,7 +1245,7 @@ int SDL_hid_init(void) return -1; } -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS hid_darwin_set_open_exclusive(0); #endif @@ -1273,7 +1274,7 @@ int SDL_hid_exit(void) if (udev_ctx) { result |= PLATFORM_hid_exit(); } -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX SDL_UDEV_ReleaseUdevSyms(); #endif /* __LINUX __ */ #endif /* HAVE_PLATFORM_BACKEND */ @@ -1688,7 +1689,7 @@ int SDL_hid_get_report_descriptor(SDL_hid_device *device, unsigned char *buf, si void SDL_hid_ble_scan(SDL_bool active) { -#if !defined(SDL_HIDAPI_DISABLED) && (defined(__IOS__) || defined(__TVOS__)) +#if !defined(SDL_HIDAPI_DISABLED) && (defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS)) extern void hid_ble_scan(int bStart); hid_ble_scan(active); #endif diff --git a/src/hidapi/SDL_hidapi_libusb.h b/src/hidapi/SDL_hidapi_libusb.h index 9f62be52..b98be80d 100644 --- a/src/hidapi/SDL_hidapi_libusb.h +++ b/src/hidapi/SDL_hidapi_libusb.h @@ -37,7 +37,9 @@ #pragma push_macro("strdup") #pragma push_macro("strncpy") #pragma push_macro("tolower") +#pragma push_macro("wcscmp") #pragma push_macro("wcsdup") +#pragma push_macro("wcsncpy") #undef calloc #undef malloc @@ -53,7 +55,9 @@ #undef strdup #undef strncpy #undef tolower +#undef wcscmp #undef wcsdup +#undef wcsncpy #define calloc SDL_calloc #define malloc SDL_malloc @@ -73,10 +77,12 @@ #define strdup SDL_strdup #define strncpy SDL_strlcpy #define tolower SDL_tolower +#define wcscmp SDL_wcscmp #define wcsdup SDL_wcsdup +#define wcsncpy SDL_wcslcpy -#ifndef __FreeBSD__ +#ifndef SDL_PLATFORM_FREEBSD /* this is awkwardly inlined, so we need to re-implement it here * so we can override the libusb_control_transfer call */ static int SDL_libusb_get_string_descriptor(libusb_device_handle *dev, @@ -87,7 +93,7 @@ static int SDL_libusb_get_string_descriptor(libusb_device_handle *dev, data, (uint16_t)length, 1000); /* Endpoint 0 IN */ } #define libusb_get_string_descriptor SDL_libusb_get_string_descriptor -#endif /* __FreeBSD__ */ +#endif /* SDL_PLATFORM_FREEBSD */ #define HIDAPI_THREAD_MODEL_INCLUDE "hidapi_thread_sdl.h" #ifndef LIBUSB_API_VERSION @@ -123,4 +129,6 @@ static int SDL_libusb_get_string_descriptor(libusb_device_handle *dev, #pragma pop_macro("strdup") #pragma pop_macro("strncpy") #pragma pop_macro("tolower") +#pragma pop_macro("wcscmp") #pragma pop_macro("wcsdup") +#pragma pop_macro("wcsncpy") diff --git a/src/hidapi/android/hid.cpp b/src/hidapi/android/hid.cpp index 098feb85..ea8d2797 100644 --- a/src/hidapi/android/hid.cpp +++ b/src/hidapi/android/hid.cpp @@ -1029,6 +1029,29 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReportResponse extern "C" { +// !!! FIXME: make this non-blocking! +static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted) +{ + SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1); +} + +static SDL_bool RequestBluetoothPermissions(const char *permission) +{ + // !!! FIXME: make this non-blocking! + SDL_AtomicInt permission_response; + SDL_AtomicSet(&permission_response, 0); + if (SDL_AndroidRequestPermission(permission, AndroidRequestPermissionBlockingCallback, &permission_response) == -1) { + return SDL_FALSE; + } + + while (SDL_AtomicGet(&permission_response) == 0) { + SDL_Delay(10); + } + + return SDL_AtomicGet(&permission_response) > 0; +} + + int hid_init(void) { if ( !g_initialized && g_HIDDeviceManagerCallbackHandler ) @@ -1046,7 +1069,7 @@ int hid_init(void) bool init_bluetooth = false; if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAM, SDL_FALSE)) { if (SDL_GetAndroidSDKVersion() < 31 || - Android_JNI_RequestPermission("android.permission.BLUETOOTH_CONNECT")) { + RequestBluetoothPermissions("android.permission.BLUETOOTH_CONNECT")) { init_bluetooth = true; } } diff --git a/src/hidapi/hidtest/CMakeLists.txt b/src/hidapi/hidtest/CMakeLists.txt index 701a4fb9..19c50e1f 100644 --- a/src/hidapi/hidtest/CMakeLists.txt +++ b/src/hidapi/hidtest/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1.3...3.25 FATAL_ERROR) project(hidtest C) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) diff --git a/src/hidapi/ios/hid.m b/src/hidapi/ios/hid.m index eef4297a..8f9e5fe8 100644 --- a/src/hidapi/ios/hid.m +++ b/src/hidapi/ios/hid.m @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(__IOS__) || defined(__TVOS__) +#if defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) #ifndef SDL_HIDAPI_DISABLED @@ -1034,4 +1034,4 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev) #endif /* !SDL_HIDAPI_DISABLED */ -#endif /* __IOS__ || __TVOS__ */ +#endif /* SDL_PLATFORM_IOS || SDL_PLATFORM_TVOS */ diff --git a/src/hidapi/libusb/CMakeLists.txt b/src/hidapi/libusb/CMakeLists.txt index 617cd551..4c458c56 100644 --- a/src/hidapi/libusb/CMakeLists.txt +++ b/src/hidapi/libusb/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR) list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_libusb.h") diff --git a/src/hidapi/linux/CMakeLists.txt b/src/hidapi/linux/CMakeLists.txt index 0970ac3f..9c627087 100644 --- a/src/hidapi/linux/CMakeLists.txt +++ b/src/hidapi/linux/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR) add_library(hidapi_hidraw ${HIDAPI_PUBLIC_HEADERS} diff --git a/src/hidapi/mac/CMakeLists.txt b/src/hidapi/mac/CMakeLists.txt index ccb0b91d..0a1c1d95 100644 --- a/src/hidapi/mac/CMakeLists.txt +++ b/src/hidapi/mac/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.4.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.4.3...3.25 FATAL_ERROR) list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_darwin.h") diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c index ee6666b6..db20b35c 100644 --- a/src/hidapi/mac/hid.c +++ b/src/hidapi/mac/hid.c @@ -594,6 +594,14 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, dev_vid = get_vendor_id(dev); dev_pid = get_product_id(dev); +#ifdef HIDAPI_IGNORE_DEVICE + /* See if there are any devices we should skip in enumeration */ + if (HIDAPI_IGNORE_DEVICE(get_bus_type(dev), dev_vid, dev_pid, usage_page, usage)) { + free(cur_dev); + return NULL; + } +#endif + cur_dev->usage_page = usage_page; cur_dev->usage = usage; @@ -691,9 +699,6 @@ static struct hid_device_info *create_device_info(IOHIDDeviceRef device) struct hid_device_info *root = create_device_info_with_usage(device, primary_usage_page, primary_usage); struct hid_device_info *cur = root; - if (!root) - return NULL; - CFArrayRef usage_pairs = get_usage_pairs(device); if (usage_pairs != NULL) { @@ -719,9 +724,13 @@ static struct hid_device_info *create_device_info(IOHIDDeviceRef device) continue; /* Already added. */ next = create_device_info_with_usage(device, usage_page, usage); - cur->next = next; - if (next != NULL) { - cur = next; + if (cur) { + if (next != NULL) { + cur->next = next; + cur = next; + } + } else { + root = cur = next; } } } @@ -788,18 +797,6 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, continue; } -#ifdef HIDAPI_IGNORE_DEVICE - /* See if there are any devices we should skip in enumeration */ - hid_bus_type bus_type = get_bus_type(dev); - unsigned short dev_vid = get_vendor_id(dev); - unsigned short dev_pid = get_product_id(dev); - unsigned short usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); - unsigned short usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); - if (HIDAPI_IGNORE_DEVICE(bus_type, dev_vid, dev_pid, usage_page, usage)) { - continue; - } -#endif - struct hid_device_info *tmp = create_device_info(dev); if (tmp == NULL) { continue; diff --git a/src/hidapi/netbsd/CMakeLists.txt b/src/hidapi/netbsd/CMakeLists.txt index 86067f89..3b3e4d04 100644 --- a/src/hidapi/netbsd/CMakeLists.txt +++ b/src/hidapi/netbsd/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR) add_library(hidapi_netbsd ${HIDAPI_PUBLIC_HEADERS} diff --git a/src/hidapi/subprojects/hidapi_build_cmake/CMakeLists.txt b/src/hidapi/subprojects/hidapi_build_cmake/CMakeLists.txt index 80aed67d..4586ce6a 100644 --- a/src/hidapi/subprojects/hidapi_build_cmake/CMakeLists.txt +++ b/src/hidapi/subprojects/hidapi_build_cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1.3...3.25 FATAL_ERROR) project(hidapi LANGUAGES C) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root") diff --git a/src/hidapi/windows/hid.c b/src/hidapi/windows/hid.c index 3a90a3db..660c20ce 100644 --- a/src/hidapi/windows/hid.c +++ b/src/hidapi/windows/hid.c @@ -72,6 +72,15 @@ typedef LONG NTSTATUS; /* BLUETOOTH_DEVICE_NAME_SIZE from bluetoothapis.h is 256 */ #define MAX_STRING_WCHARS 256 +/* For certain USB devices, using a buffer larger or equal to 127 wchars results + in successful completion of HID API functions, but a broken string is stored + in the output buffer. This behaviour persists even if HID API is bypassed and + HID IOCTLs are passed to the HID driver directly. Therefore, for USB devices, + the buffer MUST NOT exceed 126 WCHARs. +*/ + +#define MAX_STRING_WCHARS_USB 126 + static struct hid_api_version api_version = { .major = HID_API_VERSION_MAJOR, .minor = HID_API_VERSION_MINOR, @@ -719,11 +728,22 @@ end: } #endif /* HIDAPI_IGNORE_DEVICE */ -static void hid_internal_get_info(const wchar_t* interface_path, struct hid_device_info* dev) +/* Unfortunately, HID_API_BUS_xxx constants alone aren't enough to distinguish between BLUETOOTH and BLE */ + +#define HID_API_BUS_FLAG_BLE 0x01 + +typedef struct hid_internal_detect_bus_type_result_ { + DEVINST dev_node; + hid_bus_type bus_type; + unsigned int bus_flags; +} hid_internal_detect_bus_type_result; + +static hid_internal_detect_bus_type_result hid_internal_detect_bus_type(const wchar_t* interface_path) { wchar_t *device_id = NULL, *compatible_ids = NULL; CONFIGRET cr; DEVINST dev_node; + hid_internal_detect_bus_type_result result = { 0 }; /* Get the device id from interface path */ device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); @@ -754,54 +774,65 @@ static void hid_internal_get_info(const wchar_t* interface_path, struct hid_devi https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */ if (wcsstr(compatible_id, L"USB") != NULL) { - dev->bus_type = HID_API_BUS_USB; - hid_internal_get_usb_info(dev, dev_node); + result.bus_type = HID_API_BUS_USB; break; } /* Bluetooth devices https://docs.microsoft.com/windows-hardware/drivers/bluetooth/installing-a-bluetooth-device */ if (wcsstr(compatible_id, L"BTHENUM") != NULL) { - dev->bus_type = HID_API_BUS_BLUETOOTH; + result.bus_type = HID_API_BUS_BLUETOOTH; break; } /* Bluetooth LE devices */ if (wcsstr(compatible_id, L"BTHLEDEVICE") != NULL) { - dev->bus_type = HID_API_BUS_BLUETOOTH; - hid_internal_get_ble_info(dev, dev_node); + result.bus_type = HID_API_BUS_BLUETOOTH; + result.bus_flags |= HID_API_BUS_FLAG_BLE; break; } /* I2C devices https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support-and-power-management */ if (wcsstr(compatible_id, L"PNP0C50") != NULL) { - dev->bus_type = HID_API_BUS_I2C; + result.bus_type = HID_API_BUS_I2C; break; } /* SPI devices https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-for-spi */ if (wcsstr(compatible_id, L"PNP0C51") != NULL) { - dev->bus_type = HID_API_BUS_SPI; + result.bus_type = HID_API_BUS_SPI; break; } } + + result.dev_node = dev_node; + end: free(device_id); free(compatible_ids); + return result; } static char *hid_internal_UTF16toUTF8(const wchar_t *src) { char *dst = NULL; +#ifdef HIDAPI_USING_SDL_RUNTIME + int len = WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL); +#else int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL); +#endif if (len) { dst = (char*)calloc(len, sizeof(char)); if (dst == NULL) { return NULL; } +#ifdef HIDAPI_USING_SDL_RUNTIME + WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dst, len, NULL, NULL); +#else WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dst, len, NULL, NULL); +#endif } return dst; @@ -828,7 +859,10 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path, HIDD_ATTRIBUTES attrib; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; - wchar_t string[MAX_STRING_WCHARS]; + wchar_t string[MAX_STRING_WCHARS + 1]; + ULONG len; + ULONG size; + hid_internal_detect_bus_type_result detect_bus_type_result; /* Create the record. */ dev = (struct hid_device_info*)calloc(1, sizeof(struct hid_device_info)); @@ -862,25 +896,46 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path, HidD_FreePreparsedData(pp_data); } + /* detect bus type before reading string descriptors */ + detect_bus_type_result = hid_internal_detect_bus_type(path); + dev->bus_type = detect_bus_type_result.bus_type; + + len = dev->bus_type == HID_API_BUS_USB ? MAX_STRING_WCHARS_USB : MAX_STRING_WCHARS; + string[len] = L'\0'; + size = len * sizeof(wchar_t); + /* Serial Number */ string[0] = L'\0'; - HidD_GetSerialNumberString(handle, string, sizeof(string)); - string[MAX_STRING_WCHARS - 1] = L'\0'; + HidD_GetSerialNumberString(handle, string, size); dev->serial_number = _wcsdup(string); /* Manufacturer String */ string[0] = L'\0'; - HidD_GetManufacturerString(handle, string, sizeof(string)); - string[MAX_STRING_WCHARS - 1] = L'\0'; + HidD_GetManufacturerString(handle, string, size); dev->manufacturer_string = _wcsdup(string); /* Product String */ string[0] = L'\0'; - HidD_GetProductString(handle, string, sizeof(string)); - string[MAX_STRING_WCHARS - 1] = L'\0'; + HidD_GetProductString(handle, string, size); dev->product_string = _wcsdup(string); - hid_internal_get_info(path, dev); + /* now, the portion that depends on string descriptors */ + switch (dev->bus_type) { + case HID_API_BUS_USB: + hid_internal_get_usb_info(dev, detect_bus_type_result.dev_node); + break; + + case HID_API_BUS_BLUETOOTH: + if (detect_bus_type_result.bus_flags & HID_API_BUS_FLAG_BLE) + hid_internal_get_ble_info(dev, detect_bus_type_result.dev_node); + break; + + case HID_API_BUS_UNKNOWN: + case HID_API_BUS_SPI: + case HID_API_BUS_I2C: + /* shut down -Wswitch */ + break; + } return dev; } @@ -1564,7 +1619,12 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int { BOOL res; - res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * (DWORD) MIN(maxlen, MAX_STRING_WCHARS)); + if (dev->device_info && dev->device_info->bus_type == HID_API_BUS_USB && maxlen > MAX_STRING_WCHARS_USB) { + string[MAX_STRING_WCHARS_USB] = L'\0'; + maxlen = MAX_STRING_WCHARS_USB; + } + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)maxlen * sizeof(wchar_t)); if (!res) { register_winapi_error(dev, L"HidD_GetIndexedString"); return -1; diff --git a/src/hidapi/windows/hidapi_descriptor_reconstruct.c b/src/hidapi/windows/hidapi_descriptor_reconstruct.c index f6e693f6..6697d3c3 100644 --- a/src/hidapi/windows/hidapi_descriptor_reconstruct.c +++ b/src/hidapi/windows/hidapi_descriptor_reconstruct.c @@ -187,11 +187,10 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha return -1; } - struct rd_buffer rpt_desc = { - .buf = buf, - .buf_size = buf_size, - .byte_idx = 0 - }; + struct rd_buffer rpt_desc; + rpt_desc.buf = buf; + rpt_desc.buf_size = buf_size; + rpt_desc.byte_idx = 0; // Set pointer to the first node of link_collection_nodes phid_pp_link_collection_node link_collection_nodes = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray); diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 77852ee1..c5f56828 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -31,12 +31,10 @@ #include "controller_type.h" #include "usb_ids.h" #include "hidapi/SDL_hidapi_nintendo.h" - -#ifndef SDL_EVENTS_DISABLED #include "../events/SDL_events_c.h" -#endif -#ifdef __ANDROID__ + +#ifdef SDL_PLATFORM_ANDROID #endif /* Many gamepads turn the center button into an instantaneous button press */ @@ -162,11 +160,11 @@ static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gam static SDL_bool HasSameOutput(SDL_GamepadBinding *a, SDL_GamepadBinding *b) { - if (a->outputType != b->outputType) { + if (a->output_type != b->output_type) { return SDL_FALSE; } - if (a->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (a->output_type == SDL_GAMEPAD_BINDTYPE_AXIS) { return a->output.axis.axis == b->output.axis.axis; } else { return a->output.button == b->output.button; @@ -175,7 +173,7 @@ static SDL_bool HasSameOutput(SDL_GamepadBinding *a, SDL_GamepadBinding *b) static void ResetOutput(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadBinding *bind) { - if (bind->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (bind->output_type == SDL_GAMEPAD_BINDTYPE_AXIS) { SDL_SendGamepadAxis(timestamp, gamepad, bind->output.axis.axis, 0); } else { SDL_SendGamepadButton(timestamp, gamepad, bind->output.button, SDL_RELEASED); @@ -193,7 +191,7 @@ static void HandleJoystickAxis(Uint64 timestamp, SDL_Gamepad *gamepad, int axis, last_match = gamepad->last_match_axis[axis]; for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS && + if (binding->input_type == SDL_GAMEPAD_BINDTYPE_AXIS && axis == binding->input.axis.axis) { if (binding->input.axis.axis_min < binding->input.axis.axis_max) { if (value >= binding->input.axis.axis_min && @@ -217,7 +215,7 @@ static void HandleJoystickAxis(Uint64 timestamp, SDL_Gamepad *gamepad, int axis, } if (match) { - if (match->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (match->output_type == SDL_GAMEPAD_BINDTYPE_AXIS) { if (match->input.axis.axis_min != match->output.axis.axis_min || match->input.axis.axis_max != match->output.axis.axis_max) { float normalized_value = (float)(value - match->input.axis.axis_min) / (match->input.axis.axis_max - match->input.axis.axis_min); value = match->output.axis.axis_min + (int)(normalized_value * (match->output.axis.axis_max - match->output.axis.axis_min)); @@ -245,9 +243,9 @@ static void HandleJoystickButton(Uint64 timestamp, SDL_Gamepad *gamepad, int but for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->inputType == SDL_GAMEPAD_BINDTYPE_BUTTON && + if (binding->input_type == SDL_GAMEPAD_BINDTYPE_BUTTON && button == binding->input.button) { - if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (binding->output_type == SDL_GAMEPAD_BINDTYPE_AXIS) { int value = state ? binding->output.axis.axis_max : binding->output.axis.axis_min; SDL_SendGamepadAxis(timestamp, gamepad, binding->output.axis.axis, (Sint16)value); } else { @@ -269,10 +267,10 @@ static void HandleJoystickHat(Uint64 timestamp, SDL_Gamepad *gamepad, int hat, U changed_mask = (last_mask ^ value); for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->inputType == SDL_GAMEPAD_BINDTYPE_HAT && hat == binding->input.hat.hat) { + if (binding->input_type == SDL_GAMEPAD_BINDTYPE_HAT && hat == binding->input.hat.hat) { if ((changed_mask & binding->input.hat.hat_mask) != 0) { if (value & binding->input.hat.hat_mask) { - if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (binding->output_type == SDL_GAMEPAD_BINDTYPE_AXIS) { SDL_SendGamepadAxis(timestamp, gamepad, binding->output.axis.axis, (Sint16)binding->output.axis.axis_max); } else { SDL_SendGamepadButton(timestamp, gamepad, binding->output.button, SDL_PRESSED); @@ -294,17 +292,18 @@ static void HandleJoystickHat(Uint64 timestamp, SDL_Gamepad *gamepad, int hat, U duplicate events. */ static void RecenterGamepad(SDL_Gamepad *gamepad) { - SDL_GamepadButton button; - SDL_GamepadAxis axis; + int i; Uint64 timestamp = SDL_GetTicksNS(); - for (button = (SDL_GamepadButton)0; button < SDL_GAMEPAD_BUTTON_MAX; button++) { + for (i = 0; i < SDL_GAMEPAD_BUTTON_MAX; ++i) { + SDL_GamepadButton button = (SDL_GamepadButton)i; if (SDL_GetGamepadButton(gamepad, button)) { SDL_SendGamepadButton(timestamp, gamepad, button, SDL_RELEASED); } } - for (axis = (SDL_GamepadAxis)0; axis < SDL_GAMEPAD_AXIS_MAX; axis++) { + for (i = 0; i < SDL_GAMEPAD_AXIS_MAX; ++i) { + SDL_GamepadAxis axis = (SDL_GamepadAxis)i; if (SDL_GetGamepadAxis(gamepad, axis) != 0) { SDL_SendGamepadAxis(timestamp, gamepad, axis, 0); } @@ -584,7 +583,7 @@ static void PopMappingChangeTracking(void) SDL_free(tracker); } -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID /* * Helper function to guess at a mapping based on the elements reported for this gamepad */ @@ -685,7 +684,7 @@ static GamepadMapping_t *SDL_CreateMappingForAndroidGamepad(SDL_JoystickGUID gui return SDL_PrivateAddMappingForGUID(guid, mapping_string, &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT); } -#endif /* __ANDROID__ */ +#endif /* SDL_PLATFORM_ANDROID */ /* * Helper function to guess at a mapping for HIDAPI gamepads @@ -737,7 +736,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b11,", sizeof(mapping_string)); break; case k_eSwitchDeviceInfoControllerType_SEGA_Genesis: - SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,rightshoulder:b10,righttrigger:a5,start:b6,misc1:b11,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,misc1:b11,", sizeof(mapping_string)); break; case k_eWiiExtensionControllerType_None: SDL_strlcat(mapping_string, "a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,start:b6,x:b2,y:b3,", sizeof(mapping_string)); @@ -792,14 +791,14 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickGoogleStadiaController(vendor, product)) { /* The Google Stadia controller has a share button and a Google Assistant button */ - SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,misc2:b12", sizeof(mapping_string)); } else if (SDL_IsJoystickNVIDIASHIELDController(vendor, product)) { /* The NVIDIA SHIELD controller has a share button between back and start buttons */ SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); if (product == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V103) { - /* The original SHIELD controller has a touchpad as well */ - SDL_strlcat(mapping_string, "touchpad:b12,", sizeof(mapping_string)); + /* The original SHIELD controller has a touchpad and plus/minus buttons as well */ + SDL_strlcat(mapping_string, "touchpad:b12,misc2:b13,misc3:b14", sizeof(mapping_string)); } } else if (SDL_IsJoystickPS4(vendor, product)) { /* PS4 controllers have an additional touchpad button */ @@ -807,7 +806,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid } else if (SDL_IsJoystickPS5(vendor, product)) { /* PS5 controllers have a microphone button and an additional touchpad button */ SDL_strlcat(mapping_string, "touchpad:b11,misc1:b12,", sizeof(mapping_string)); - /* DualSense Edge controllers have paddles */ + /* DualSense Edge controllers have paddles and a microphone button */ if (SDL_IsJoystickDualSenseEdge(vendor, product)) { SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,paddle3:b14,paddle4:b13,", sizeof(mapping_string)); } @@ -859,16 +858,14 @@ static GamepadMapping_t *SDL_CreateMappingForWGIGamepad(SDL_JoystickGUID guid) /* * Helper function to scan the mappings database for a gamepad with the specified GUID */ -static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_JoystickGUID guid, SDL_bool match_crc, SDL_bool match_version) +static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_JoystickGUID guid, SDL_bool match_version) { - GamepadMapping_t *mapping; + GamepadMapping_t *mapping, *best_match = NULL; Uint16 crc = 0; SDL_AssertJoysticksLocked(); - if (match_crc) { - SDL_GetJoystickGUIDInfo(guid, NULL, NULL, NULL, &crc); - } + SDL_GetJoystickGUIDInfo(guid, NULL, NULL, NULL, &crc); /* Clear the CRC from the GUID for matching, the mappings never include it in the GUID */ SDL_SetJoystickGUIDCRC(&guid, 0); @@ -890,20 +887,24 @@ static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_JoystickGUID } if (SDL_memcmp(&guid, &mapping_guid, sizeof(guid)) == 0) { - Uint16 mapping_crc = 0; - - if (match_crc) { - const char *crc_string = SDL_strstr(mapping->mapping, SDL_GAMEPAD_CRC_FIELD); - if (crc_string) { - mapping_crc = (Uint16)SDL_strtol(crc_string + SDL_GAMEPAD_CRC_FIELD_SIZE, NULL, 16); + const char *crc_string = SDL_strstr(mapping->mapping, SDL_GAMEPAD_CRC_FIELD); + if (crc_string) { + Uint16 mapping_crc = (Uint16)SDL_strtol(crc_string + SDL_GAMEPAD_CRC_FIELD_SIZE, NULL, 16); + if (mapping_crc != crc) { + /* This mapping specified a CRC and they don't match */ + continue; } - } - if (crc == mapping_crc) { + + /* An exact match, including CRC */ return mapping; } + + if (!best_match) { + best_match = mapping; + } } } - return NULL; + return best_match; } /* @@ -912,19 +913,8 @@ static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_JoystickGUID static GamepadMapping_t *SDL_PrivateGetGamepadMappingForGUID(SDL_JoystickGUID guid, SDL_bool adding_mapping) { GamepadMapping_t *mapping; - Uint16 vendor, product, crc; - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, &crc); - if (crc) { - /* First check for exact CRC matching */ - mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_TRUE, SDL_TRUE); - if (mapping) { - return mapping; - } - } - - /* Now check for a mapping without CRC */ - mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_FALSE, SDL_TRUE); + mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_TRUE); if (mapping) { return mapping; } @@ -938,14 +928,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForGUID(SDL_JoystickGUID gu if (SDL_JoystickGUIDUsesVersion(guid)) { /* Try again, ignoring the version */ - if (crc) { - mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_TRUE, SDL_FALSE); - if (mapping) { - return mapping; - } - } - - mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_FALSE, SDL_FALSE); + mapping = SDL_PrivateMatchGamepadMappingForGUID(guid, SDL_FALSE); if (mapping) { return mapping; } @@ -965,7 +948,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForGUID(SDL_JoystickGUID gu mapping = SDL_CreateMappingForWGIGamepad(guid); } else if (SDL_IsJoystickVIRTUAL(guid)) { /* We'll pick up a robust mapping in VIRTUAL_JoystickGetGamepadMapping */ -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID } else { mapping = SDL_CreateMappingForAndroidGamepad(guid); #endif @@ -1087,7 +1070,12 @@ static const char *map_StringForGamepadButton[] = { "paddle2", "paddle3", "paddle4", - "touchpad" + "touchpad", + "misc2", + "misc3", + "misc4", + "misc5", + "misc6" }; SDL_COMPILE_TIME_ASSERT(map_StringForGamepadButton, SDL_arraysize(map_StringForGamepadButton) == SDL_GAMEPAD_BUTTON_MAX); @@ -1170,7 +1158,7 @@ static SDL_bool SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char axis = SDL_GetGamepadAxisFromString(szGameButton); button = SDL_PrivateGetGamepadButtonFromString(szGameButton, baxy_mapping); if (axis != SDL_GAMEPAD_AXIS_INVALID) { - bind.outputType = SDL_GAMEPAD_BINDTYPE_AXIS; + bind.output_type = SDL_GAMEPAD_BINDTYPE_AXIS; bind.output.axis.axis = axis; if (axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) { bind.output.axis.axis_min = 0; @@ -1188,7 +1176,7 @@ static SDL_bool SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char } } } else if (button != SDL_GAMEPAD_BUTTON_INVALID) { - bind.outputType = SDL_GAMEPAD_BINDTYPE_BUTTON; + bind.output_type = SDL_GAMEPAD_BINDTYPE_BUTTON; bind.output.button = button; } else { return SDL_FALSE; @@ -1202,7 +1190,7 @@ static SDL_bool SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char } if (szJoystickButton[0] == 'a' && SDL_isdigit((unsigned char)szJoystickButton[1])) { - bind.inputType = SDL_GAMEPAD_BINDTYPE_AXIS; + bind.input_type = SDL_GAMEPAD_BINDTYPE_AXIS; bind.input.axis.axis = SDL_atoi(&szJoystickButton[1]); if (half_axis_input == '+') { bind.input.axis.axis_min = 0; @@ -1220,13 +1208,13 @@ static SDL_bool SDL_PrivateParseGamepadElement(SDL_Gamepad *gamepad, const char bind.input.axis.axis_max = tmp; } } else if (szJoystickButton[0] == 'b' && SDL_isdigit((unsigned char)szJoystickButton[1])) { - bind.inputType = SDL_GAMEPAD_BINDTYPE_BUTTON; + bind.input_type = SDL_GAMEPAD_BINDTYPE_BUTTON; bind.input.button = SDL_atoi(&szJoystickButton[1]); } else if (szJoystickButton[0] == 'h' && SDL_isdigit((unsigned char)szJoystickButton[1]) && szJoystickButton[2] == '.' && SDL_isdigit((unsigned char)szJoystickButton[3])) { int hat = SDL_atoi(&szJoystickButton[1]); int mask = SDL_atoi(&szJoystickButton[3]); - bind.inputType = SDL_GAMEPAD_BINDTYPE_HAT; + bind.input_type = SDL_GAMEPAD_BINDTYPE_HAT; bind.input.hat.hat = hat; bind.input.hat.hat_mask = mask; } else { @@ -1416,8 +1404,8 @@ static void SDL_PrivateLoadButtonMapping(SDL_Gamepad *gamepad, GamepadMapping_t /* Set the zero point for triggers */ for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS && - binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS && + if (binding->input_type == SDL_GAMEPAD_BINDTYPE_AXIS && + binding->output_type == SDL_GAMEPAD_BINDTYPE_AXIS && (binding->output.axis.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || binding->output.axis.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) { if (binding->input.axis.axis < gamepad->joystick->naxes) { @@ -1435,7 +1423,7 @@ static char *SDL_PrivateGetGamepadGUIDFromMappingString(const char *pMapping) { const char *pFirstComma = SDL_strchr(pMapping, ','); if (pFirstComma) { - char *pchGUID = SDL_malloc(pFirstComma - pMapping + 1); + char *pchGUID = (char *)SDL_malloc(pFirstComma - pMapping + 1); if (!pchGUID) { return NULL; } @@ -1443,7 +1431,7 @@ static char *SDL_PrivateGetGamepadGUIDFromMappingString(const char *pMapping) pchGUID[pFirstComma - pMapping] = '\0'; /* Convert old style GUIDs to the new style in 2.0.5 */ -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) if (SDL_strlen(pchGUID) == 32 && SDL_memcmp(&pchGUID[20], "504944564944", 12) == 0) { SDL_memcpy(&pchGUID[20], "000000000000", 12); @@ -1451,7 +1439,7 @@ static char *SDL_PrivateGetGamepadGUIDFromMappingString(const char *pMapping) SDL_memcpy(&pchGUID[8], &pchGUID[0], 4); SDL_memcpy(&pchGUID[0], "03000000", 8); } -#elif defined(__MACOS__) +#elif defined(SDL_PLATFORM_MACOS) if (SDL_strlen(pchGUID) == 32 && SDL_memcmp(&pchGUID[4], "000000000000", 12) == 0 && SDL_memcmp(&pchGUID[20], "000000000000", 12) == 0) { @@ -1483,7 +1471,7 @@ static char *SDL_PrivateGetGamepadNameFromMappingString(const char *pMapping) return NULL; } - pchName = SDL_malloc(pSecondComma - pFirstComma); + pchName = (char *)SDL_malloc(pSecondComma - pFirstComma); if (!pchName) { return NULL; } @@ -1520,7 +1508,7 @@ static char *SDL_PrivateGetGamepadMappingFromMappingString(const char *pMapping) /* Trim whitespace */ length = SDL_strlen(result); - while (SDL_isspace(result[length - 1])) { + while (length > 0 && SDL_isspace(result[length - 1])) { --length; } result[length] = '\0'; @@ -1616,7 +1604,7 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co } AddMappingChangeTracking(pGamepadMapping); } else { - pGamepadMapping = SDL_malloc(sizeof(*pGamepadMapping)); + pGamepadMapping = (GamepadMapping_t *)SDL_malloc(sizeof(*pGamepadMapping)); if (!pGamepadMapping) { PopMappingChangeTracking(); SDL_free(pchName); @@ -1666,7 +1654,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForNameAndGUID(const char * SDL_AssertJoysticksLocked(); mapping = SDL_PrivateGetGamepadMappingForGUID(guid, SDL_FALSE); -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX if (!mapping && name) { if (SDL_strstr(name, "Xbox 360 Wireless Receiver")) { /* The Linux driver xpad.c maps the wireless dpad to buttons */ @@ -1676,7 +1664,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMappingForNameAndGUID(const char * &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT); } } -#endif /* __LINUX__ */ +#endif /* SDL_PLATFORM_LINUX */ if (!mapping) { mapping = s_pDefaultMapping; @@ -1753,6 +1741,11 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char * SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpleft", &raw_map->dpleft); SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpright", &raw_map->dpright); SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc1", &raw_map->misc1); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc2", &raw_map->misc2); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc3", &raw_map->misc3); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc4", &raw_map->misc4); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc5", &raw_map->misc5); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc6", &raw_map->misc6); /* Keep using paddle1-4 in the generated mapping so that it can be * reused with SDL2 */ SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "paddle1", &raw_map->right_paddle1); @@ -1796,7 +1789,7 @@ static GamepadMapping_t *SDL_PrivateGetGamepadMapping(SDL_JoystickID instance_id /* * Add or update an entry into the Mappings Database */ -int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) +int SDL_AddGamepadMappingsFromIO(SDL_IOStream *src, SDL_bool closeio) { const char *platform = SDL_GetPlatform(); int gamepads = 0; @@ -1804,7 +1797,7 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) size_t db_size; size_t platform_len; - buf = (char *)SDL_LoadFile_RW(src, &db_size, freesrc); + buf = (char *)SDL_LoadFile_IO(src, &db_size, closeio); if (!buf) { return SDL_SetError("Could not allocate space to read DB into memory"); } @@ -1852,7 +1845,7 @@ int SDL_AddGamepadMappingsFromRW(SDL_RWops *src, SDL_bool freesrc) int SDL_AddGamepadMappingsFromFile(const char *file) { - return SDL_AddGamepadMappingsFromRW(SDL_RWFromFile(file, "rb"), 1); + return SDL_AddGamepadMappingsFromIO(SDL_IOFromFile(file, "rb"), 1); } int SDL_ReloadGamepadMappings(void) @@ -1877,17 +1870,59 @@ int SDL_ReloadGamepadMappings(void) return 0; } +static char *SDL_ConvertMappingToPositional(const char *mapping) +{ + /* Add space for '!' and null terminator */ + size_t length = SDL_strlen(mapping) + 1 + 1; + char *remapped = (char *)SDL_malloc(length); + if (remapped) { + char *button_A; + char *button_B; + char *button_X; + char *button_Y; + char *hint; + + SDL_strlcpy(remapped, mapping, length); + button_A = SDL_strstr(remapped, "a:"); + button_B = SDL_strstr(remapped, "b:"); + button_X = SDL_strstr(remapped, "x:"); + button_Y = SDL_strstr(remapped, "y:"); + hint = SDL_strstr(remapped, "hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS"); + + if (button_A) { + *button_A = 'b'; + } + if (button_B) { + *button_B = 'a'; + } + if (button_X) { + *button_X = 'y'; + } + if (button_Y) { + *button_Y = 'x'; + } + if (hint) { + hint += 5; + SDL_memmove(hint + 1, hint, SDL_strlen(hint) + 1); + *hint = '!'; + } + } + return remapped; +} + /* * Add or update an entry into the Mappings Database with a priority */ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMappingPriority priority) { + char *remapped = NULL; char *pchGUID; SDL_JoystickGUID jGUID; SDL_bool is_default_mapping = SDL_FALSE; SDL_bool is_xinput_mapping = SDL_FALSE; SDL_bool existing = SDL_FALSE; GamepadMapping_t *pGamepadMapping; + int retval = -1; SDL_AssertJoysticksLocked(); @@ -1926,12 +1961,27 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa default_value = SDL_FALSE; } - value = SDL_GetHintBoolean(hint, default_value); - if (negate) { - value = !value; - } - if (!value) { - return 0; + if (SDL_strcmp(hint, "SDL_GAMECONTROLLER_USE_BUTTON_LABELS") == 0) { + /* This hint is used to signal whether the mapping uses positional buttons or not */ + if (negate) { + /* This mapping uses positional buttons, we can use it as-is */ + } else { + /* This mapping uses labeled buttons, we need to swap them to positional */ + remapped = SDL_ConvertMappingToPositional(mappingString); + if (!remapped) { + goto done; + } + mappingString = remapped; + } + } else { + value = SDL_GetHintBoolean(hint, default_value); + if (negate) { + value = !value; + } + if (!value) { + retval = 0; + goto done; + } } } } @@ -1944,14 +1994,16 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa if (tmp) { tmp += SDL_GAMEPAD_SDKGE_FIELD_SIZE; if (!(SDL_GetAndroidSDKVersion() >= SDL_atoi(tmp))) { - return SDL_SetError("SDK version %d < minimum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp)); + SDL_SetError("SDK version %d < minimum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp)); + goto done; } } tmp = SDL_strstr(mappingString, SDL_GAMEPAD_SDKLE_FIELD); if (tmp) { tmp += SDL_GAMEPAD_SDKLE_FIELD_SIZE; if (!(SDL_GetAndroidSDKVersion() <= SDL_atoi(tmp))) { - return SDL_SetError("SDK version %d > maximum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp)); + SDL_SetError("SDK version %d > maximum version %d", SDL_GetAndroidSDKVersion(), SDL_atoi(tmp)); + goto done; } } } @@ -1959,7 +2011,8 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa pchGUID = SDL_PrivateGetGamepadGUIDFromMappingString(mappingString); if (!pchGUID) { - return SDL_SetError("Couldn't parse GUID from %s", mappingString); + SDL_SetError("Couldn't parse GUID from %s", mappingString); + goto done; } if (!SDL_strcasecmp(pchGUID, "default")) { is_default_mapping = SDL_TRUE; @@ -1971,19 +2024,24 @@ static int SDL_PrivateAddGamepadMapping(const char *mappingString, SDL_GamepadMa pGamepadMapping = SDL_PrivateAddMappingForGUID(jGUID, mappingString, &existing, priority); if (!pGamepadMapping) { - return -1; + goto done; } if (existing) { - return 0; + retval = 0; } else { if (is_default_mapping) { s_pDefaultMapping = pGamepadMapping; } else if (is_xinput_mapping) { s_pXInputMapping = pGamepadMapping; } - return 1; + retval = 1; } +done: + if (remapped) { + SDL_free(remapped); + } + return retval; } /* @@ -2030,7 +2088,7 @@ static char *CreateMappingString(GamepadMapping_t *mapping, SDL_JoystickGUID gui needed += SDL_GAMEPAD_PLATFORM_FIELD_SIZE + SDL_strlen(platform) + 1; } - pMappingString = SDL_malloc(needed); + pMappingString = (char *)SDL_malloc(needed); if (!pMappingString) { return NULL; } @@ -2244,7 +2302,7 @@ static SDL_bool SDL_GetGamepadMappingFilePath(char *path, size_t size) return SDL_strlcpy(path, hint, size) < size; } -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID return SDL_snprintf(path, size, "%s/gamepad_map.txt", SDL_AndroidGetInternalStoragePath()) < size; #else return SDL_FALSE; @@ -2311,6 +2369,26 @@ int SDL_InitGamepads(void) return 0; } +SDL_bool SDL_HasGamepad(void) +{ + int num_joysticks = 0; + int num_gamepads = 0; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks); + if (joysticks) { + int i; + for (i = num_joysticks - 1; i >= 0 && num_gamepads == 0; --i) { + if (SDL_IsGamepad(joysticks[i])) { + ++num_gamepads; + } + } + SDL_free(joysticks); + } + if (num_gamepads > 0) { + return SDL_TRUE; + } + return SDL_FALSE; +} + SDL_JoystickID *SDL_GetGamepads(int *count) { int num_joysticks = 0; @@ -2498,7 +2576,7 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) Uint16 product; Uint16 version; -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX if (SDL_endswith(name, " Motion Sensors")) { /* Don't treat the PS3 and PS4 motion controls as a separate gamepad */ return SDL_TRUE; @@ -2532,11 +2610,11 @@ SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) /* We shouldn't ignore Steam's virtual gamepad since it's using the hints to filter out the real gamepads so it can remap input for the virtual gamepad */ /* https://partner.steamgames.com/doc/features/steam_gamepad/steam_input_gamepad_emulation_bestpractices */ SDL_bool bSteamVirtualGamepad = SDL_FALSE; -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX bSteamVirtualGamepad = (vendor == USB_VENDOR_VALVE && product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD); -#elif defined(__MACOS__) +#elif defined(SDL_PLATFORM_MACOS) bSteamVirtualGamepad = (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0); -#elif defined(__WIN32__) +#elif defined(SDL_PLATFORM_WIN32) /* We can't tell on Windows, but Steam will block others in input hooks */ bSteamVirtualGamepad = SDL_TRUE; #endif @@ -2663,7 +2741,7 @@ SDL_bool SDL_GamepadHasAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) { + if (binding->output_type == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) { retval = SDL_TRUE; break; } @@ -2689,12 +2767,12 @@ Sint16 SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->outputType == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) { + if (binding->output_type == SDL_GAMEPAD_BINDTYPE_AXIS && binding->output.axis.axis == axis) { int value = 0; SDL_bool valid_input_range; SDL_bool valid_output_range; - if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (binding->input_type == SDL_GAMEPAD_BINDTYPE_AXIS) { value = SDL_GetJoystickAxis(gamepad->joystick, binding->input.axis.axis); if (binding->input.axis.axis_min < binding->input.axis.axis_max) { valid_input_range = (value >= binding->input.axis.axis_min && value <= binding->input.axis.axis_max); @@ -2709,12 +2787,12 @@ Sint16 SDL_GetGamepadAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) } else { value = 0; } - } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_BUTTON) { + } else if (binding->input_type == SDL_GAMEPAD_BINDTYPE_BUTTON) { value = SDL_GetJoystickButton(gamepad->joystick, binding->input.button); if (value == SDL_PRESSED) { value = binding->output.axis.axis_max; } - } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_HAT) { + } else if (binding->input_type == SDL_GAMEPAD_BINDTYPE_HAT) { int hat_mask = SDL_GetJoystickHat(gamepad->joystick, binding->input.hat.hat); if (hat_mask & binding->input.hat.hat_mask) { value = binding->output.axis.axis_max; @@ -2754,7 +2832,7 @@ SDL_bool SDL_GamepadHasButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->outputType == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) { + if (binding->output_type == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) { retval = SDL_TRUE; break; } @@ -2780,8 +2858,8 @@ Uint8 SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) for (i = 0; i < gamepad->num_bindings; ++i) { SDL_GamepadBinding *binding = &gamepad->bindings[i]; - if (binding->outputType == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) { - if (binding->inputType == SDL_GAMEPAD_BINDTYPE_AXIS) { + if (binding->output_type == SDL_GAMEPAD_BINDTYPE_BUTTON && binding->output.button == button) { + if (binding->input_type == SDL_GAMEPAD_BINDTYPE_AXIS) { SDL_bool valid_input_range; int value = SDL_GetJoystickAxis(gamepad->joystick, binding->input.axis.axis); @@ -2799,10 +2877,10 @@ Uint8 SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) break; } } - } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_BUTTON) { + } else if (binding->input_type == SDL_GAMEPAD_BINDTYPE_BUTTON) { retval = SDL_GetJoystickButton(gamepad->joystick, binding->input.button); break; - } else if (binding->inputType == SDL_GAMEPAD_BINDTYPE_HAT) { + } else if (binding->input_type == SDL_GAMEPAD_BINDTYPE_HAT) { int hat_mask = SDL_GetJoystickHat(gamepad->joystick, binding->input.hat.hat); retval = (hat_mask & binding->input.hat.hat_mask) ? SDL_PRESSED : SDL_RELEASED; break; @@ -3487,36 +3565,6 @@ int SDL_RumbleGamepadTriggers(SDL_Gamepad *gamepad, Uint16 left_rumble, Uint16 r return SDL_RumbleJoystickTriggers(joystick, left_rumble, right_rumble, duration_ms); } -SDL_bool SDL_GamepadHasLED(SDL_Gamepad *gamepad) -{ - SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - - if (!joystick) { - return SDL_FALSE; - } - return SDL_JoystickHasLED(joystick); -} - -SDL_bool SDL_GamepadHasRumble(SDL_Gamepad *gamepad) -{ - SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - - if (!joystick) { - return SDL_FALSE; - } - return SDL_JoystickHasRumble(joystick); -} - -SDL_bool SDL_GamepadHasRumbleTriggers(SDL_Gamepad *gamepad) -{ - SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); - - if (!joystick) { - return SDL_FALSE; - } - return SDL_JoystickHasRumbleTriggers(joystick); -} - int SDL_SetGamepadLED(SDL_Gamepad *gamepad, Uint8 red, Uint8 green, Uint8 blue) { SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad); @@ -3635,7 +3683,6 @@ static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gamep /* translate the event, if desired */ posted = 0; -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(SDL_EVENT_GAMEPAD_AXIS_MOTION)) { SDL_Event event; event.type = SDL_EVENT_GAMEPAD_AXIS_MOTION; @@ -3645,7 +3692,6 @@ static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gamep event.gaxis.value = value; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ return posted; } @@ -3655,7 +3701,6 @@ static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gamep static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadButton button, Uint8 state) { int posted; -#ifndef SDL_EVENTS_DISABLED SDL_Event event; SDL_AssertJoysticksLocked(); @@ -3675,7 +3720,6 @@ static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gam /* Invalid state -- bail */ return 0; } -#endif /* !SDL_EVENTS_DISABLED */ if (button == SDL_GAMEPAD_BUTTON_GUIDE) { Uint64 now = SDL_GetTicks(); @@ -3697,7 +3741,6 @@ static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gam /* translate the event, if desired */ posted = 0; -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(event.type)) { event.common.timestamp = timestamp; event.gbutton.which = gamepad->joystick->instance_id; @@ -3705,11 +3748,9 @@ static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_Gam event.gbutton.state = state; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ return posted; } -#ifndef SDL_EVENTS_DISABLED static const Uint32 SDL_gamepad_event_list[] = { SDL_EVENT_GAMEPAD_AXIS_MOTION, SDL_EVENT_GAMEPAD_BUTTON_DOWN, @@ -3722,24 +3763,19 @@ static const Uint32 SDL_gamepad_event_list[] = { SDL_EVENT_GAMEPAD_TOUCHPAD_UP, SDL_EVENT_GAMEPAD_SENSOR_UPDATE, }; -#endif void SDL_SetGamepadEventsEnabled(SDL_bool enabled) { -#ifndef SDL_EVENTS_DISABLED unsigned int i; for (i = 0; i < SDL_arraysize(SDL_gamepad_event_list); ++i) { SDL_SetEventEnabled(SDL_gamepad_event_list[i], enabled); } -#endif /* !SDL_EVENTS_DISABLED */ } SDL_bool SDL_GamepadEventsEnabled(void) { SDL_bool enabled = SDL_FALSE; - -#ifndef SDL_EVENTS_DISABLED unsigned int i; for (i = 0; i < SDL_arraysize(SDL_gamepad_event_list); ++i) { @@ -3748,8 +3784,6 @@ SDL_bool SDL_GamepadEventsEnabled(void) break; } } -#endif /* SDL_EVENTS_DISABLED */ - return enabled; } @@ -3786,10 +3820,11 @@ const char *SDL_GetGamepadAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_ } SDL_UnlockJoysticks(); - return retval; -#else - return NULL; + if (retval && *retval) { + return retval; + } #endif + return NULL; } const char *SDL_GetGamepadAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) @@ -3806,8 +3841,9 @@ const char *SDL_GetGamepadAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_Ga } SDL_UnlockJoysticks(); - return retval; -#else - return NULL; + if (retval && *retval) { + return retval; + } #endif + return NULL; } diff --git a/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index 971cc0e9..ba6d1ebc 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -101,6 +101,7 @@ static const char *s_GamepadMappings[] = { "03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,", "03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,", "03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", + "03000000790000000600000000000000,Defender Joystick Cobra R4,crc:c77a,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2~,righty:a3~,start:b9,x:b3,y:b0,", "03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,", "030000006f0e00003001000000000000,EA SPORTS PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", @@ -110,7 +111,6 @@ static const char *s_GamepadMappings[] = { "03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,", "03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", - "03000000790000000600000000000000,G-Shark GS-GP702,crc:8e4f,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", "030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,", "03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", @@ -290,6 +290,7 @@ static const char *s_GamepadMappings[] = { "03000000a30600002106000000000000,Saitek PS1000,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,", "03000000a306000020f6000000000000,Saitek PS2700,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,", "03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,", + "03000000790000000600000000000000,Sanwa Supply JY-P76USV,crc:20f0,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b2,y:b3,", "0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,", "030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,", "030000008f0e00000800000000000000,SpeedLink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", @@ -334,7 +335,7 @@ static const char *s_GamepadMappings[] = { "030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", #endif -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS "03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000650000001000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a5,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", @@ -470,7 +471,7 @@ static const char *s_GamepadMappings[] = { "03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,", #endif -#if defined(SDL_JOYSTICK_LINUX) || defined(__OpenBSD__) +#if defined(SDL_JOYSTICK_LINUX) || defined(SDL_PLATFORM_OPENBSD) "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", @@ -768,19 +769,18 @@ static const char *s_GamepadMappings[] = { "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", - "030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,", "03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,", "030000009b2800008000000020020000,raphnet technologies 1-player WUSBMote v2.2,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,", "030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,", #endif -#ifdef __OpenBSD__ +#ifdef SDL_PLATFORM_OPENBSD "030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4~,start:b7,x:b2,y:b3,", #endif -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID "05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index e39fdc5e..b0da2088 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -28,9 +28,7 @@ #include "SDL_joystick_c.h" #include "SDL_steam_virtual_gamepad.h" -#ifndef SDL_EVENTS_DISABLED #include "../events/SDL_events_c.h" -#endif #include "../video/SDL_sysvideo.h" #include "../sensor/SDL_sensor_c.h" #include "hidapi/SDL_hidapijoystick_c.h" @@ -38,7 +36,7 @@ /* This is included in only one place because it has a large static list of controllers */ #include "controller_type.h" -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) /* Needed for checking for input remapping programs */ #include "../core/windows/SDL_windows.h" @@ -51,13 +49,16 @@ #endif static SDL_JoystickDriver *SDL_joystick_drivers[] = { -#ifdef SDL_JOYSTICK_HIDAPI /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */ +#ifdef SDL_JOYSTICK_HIDAPI /* Highest priority driver for supported devices */ &SDL_HIDAPI_JoystickDriver, #endif -#ifdef SDL_JOYSTICK_RAWINPUT /* Before WINDOWS_ driver, as WINDOWS wants to check if this driver is handling things */ +#ifdef SDL_JOYSTICK_GAMEINPUT /* Higher priority than other Windows drivers */ + &SDL_GAMEINPUT_JoystickDriver, +#endif +#ifdef SDL_JOYSTICK_RAWINPUT &SDL_RAWINPUT_JoystickDriver, #endif -#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT) /* Before WGI driver, as WGI wants to check if this driver is handling things */ +#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT) &SDL_WINDOWS_JoystickDriver, #endif #ifdef SDL_JOYSTICK_WGI @@ -72,7 +73,7 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = { #ifdef SDL_JOYSTICK_IOKIT &SDL_DARWIN_JoystickDriver, #endif -#if (defined(__MACOS__) || defined(__IOS__) || defined(__TVOS__)) && !defined(SDL_JOYSTICK_DISABLED) +#if (defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS)) && !defined(SDL_JOYSTICK_DISABLED) &SDL_IOS_JoystickDriver, #endif #ifdef SDL_JOYSTICK_ANDROID @@ -289,6 +290,7 @@ static Uint32 initial_flightstick_devices[] = { MAKE_VIDPID(0x046d, 0xc215), /* Logitech Extreme 3D */ MAKE_VIDPID(0x231d, 0x0126), /* Gunfighter Mk.III ‘Space Combat Edition’ (right) */ MAKE_VIDPID(0x231d, 0x0127), /* Gunfighter Mk.III ‘Space Combat Edition’ (left) */ + MAKE_VIDPID(0x362c, 0x0001), /* Yawman Arrow */ }; static SDL_vidpid_list flightstick_devices = { SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES, 0, 0, NULL, @@ -377,6 +379,7 @@ static Uint32 initial_wheel_devices[] = { MAKE_VIDPID(0x0eb7, 0x038e), /* Fanatec ClubSport Wheel Base V1 */ MAKE_VIDPID(0x0eb7, 0x0e03), /* Fanatec CSL Elite Wheel Base */ MAKE_VIDPID(0x11ff, 0x0511), /* DragonRise Inc. Wired Wheel (initial mode) (also known as PXN V900 (PS3), Superdrive SV-750, or a Genesis Seaborg 400) */ + MAKE_VIDPID(0x1209, 0xffb0), /* Generic FFBoard OpenFFBoard universal forcefeedback wheel */ MAKE_VIDPID(0x2433, 0xf300), /* Asetek SimSports Invicta Wheelbase */ MAKE_VIDPID(0x2433, 0xf301), /* Asetek SimSports Forte Wheelbase */ MAKE_VIDPID(0x2433, 0xf303), /* Asetek SimSports La Prima Wheelbase */ @@ -600,11 +603,9 @@ int SDL_InitJoysticks(void) SDL_joystick_lock = SDL_CreateMutex(); } -#ifndef SDL_EVENTS_DISABLED if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) { return -1; } -#endif /* !SDL_EVENTS_DISABLED */ SDL_LockJoysticks(); @@ -659,6 +660,48 @@ SDL_bool SDL_JoysticksOpened(void) return opened; } +SDL_bool SDL_JoystickHandledByAnotherDriver(struct SDL_JoystickDriver *driver, Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + int i; + SDL_bool result = SDL_FALSE; + + SDL_LockJoysticks(); + { + for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { + if (driver == SDL_joystick_drivers[i]) { + /* Higher priority drivers do not have this device */ + break; + } + if (SDL_joystick_drivers[i]->IsDevicePresent(vendor_id, product_id, version, name)) { + result = SDL_TRUE; + break; + } + } + } + SDL_UnlockJoysticks(); + + return result; +} + +SDL_bool SDL_HasJoystick(void) +{ + int i; + int total_joysticks = 0; + + SDL_LockJoysticks(); + { + for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { + total_joysticks += SDL_joystick_drivers[i]->GetCount(); + } + } + SDL_UnlockJoysticks(); + + if (total_joysticks > 0) { + return SDL_TRUE; + } + return SDL_FALSE; +} + SDL_JoystickID *SDL_GetJoysticks(int *count) { int i, num_joysticks, device_index; @@ -778,7 +821,7 @@ int SDL_GetJoystickInstancePlayerIndex(SDL_JoystickID instance_id) */ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) { -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT return SDL_TRUE; #else /*printf("JOYSTICK '%s' VID/PID 0x%.4x/0x%.4x AXES: %d\n", joystick->name, vendor, product, joystick->naxes);*/ @@ -789,7 +832,7 @@ static SDL_bool SDL_JoystickAxesCenteredAtZero(SDL_Joystick *joystick) } return SDL_VIDPIDInList(SDL_GetJoystickVendor(joystick), SDL_GetJoystickProduct(joystick), &zero_centered_devices); -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ } static SDL_bool IsROGAlly(SDL_Joystick *joystick) @@ -1058,29 +1101,31 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) joystickname = driver->GetDeviceName(device_index); if (joystickname) { joystick->name = SDL_strdup(joystickname); - } else { - joystick->name = NULL; } joystickpath = driver->GetDevicePath(device_index); if (joystickpath) { joystick->path = SDL_strdup(joystickpath); - } else { - joystick->path = NULL; } joystick->guid = driver->GetDeviceGUID(device_index); if (joystick->naxes > 0) { - joystick->axes = (SDL_JoystickAxisInfo *)SDL_calloc(joystick->naxes, sizeof(SDL_JoystickAxisInfo)); + joystick->axes = (SDL_JoystickAxisInfo *)SDL_calloc(joystick->naxes, sizeof(*joystick->axes)); + } + if (joystick->nballs > 0) { + joystick->balls = (SDL_JoystickBallData *)SDL_calloc(joystick->nballs, sizeof(*joystick->balls)); } if (joystick->nhats > 0) { - joystick->hats = (Uint8 *)SDL_calloc(joystick->nhats, sizeof(Uint8)); + joystick->hats = (Uint8 *)SDL_calloc(joystick->nhats, sizeof(*joystick->hats)); } if (joystick->nbuttons > 0) { - joystick->buttons = (Uint8 *)SDL_calloc(joystick->nbuttons, sizeof(Uint8)); + joystick->buttons = (Uint8 *)SDL_calloc(joystick->nbuttons, sizeof(*joystick->buttons)); } - if (((joystick->naxes > 0) && !joystick->axes) || ((joystick->nhats > 0) && !joystick->hats) || ((joystick->nbuttons > 0) && !joystick->buttons)) { + if (((joystick->naxes > 0) && !joystick->axes) || + ((joystick->nballs > 0) && !joystick->balls) || + ((joystick->nhats > 0) && !joystick->hats) || + ((joystick->nbuttons > 0) && !joystick->buttons)) { SDL_CloseJoystick(joystick); SDL_UnlockJoysticks(); return NULL; @@ -1305,6 +1350,16 @@ int SDL_GetNumJoystickHats(SDL_Joystick *joystick) return retval; } +/* + * Get the number of trackballs on a joystick + */ +int SDL_GetNumJoystickBalls(SDL_Joystick *joystick) +{ + CHECK_JOYSTICK_MAGIC(joystick, -1); + + return joystick->nballs; +} + /* * Get the number of buttons on a joystick */ @@ -1395,6 +1450,31 @@ Uint8 SDL_GetJoystickHat(SDL_Joystick *joystick, int hat) return state; } +/* + * Get the ball axis change since the last poll + */ +int SDL_GetJoystickBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) +{ + int retval; + + CHECK_JOYSTICK_MAGIC(joystick, -1); + + retval = 0; + if (ball < joystick->nballs) { + if (dx) { + *dx = joystick->balls[ball].dx; + } + if (dy) { + *dy = joystick->balls[ball].dy; + } + joystick->balls[ball].dx = 0; + joystick->balls[ball].dy = 0; + } else { + return SDL_SetError("Joystick only has %d balls", joystick->nballs); + } + return retval; +} + /* * Get the current state of a button on a joystick */ @@ -1528,8 +1608,6 @@ const char *SDL_GetJoystickName(SDL_Joystick *joystick) if (info) { retval = info->name; } else { - CHECK_JOYSTICK_MAGIC(joystick, NULL); - retval = joystick->name; } } @@ -1663,51 +1741,6 @@ int SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint1 return retval; } -SDL_bool SDL_JoystickHasLED(SDL_Joystick *joystick) -{ - SDL_bool retval; - - SDL_LockJoysticks(); - { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - - retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_LED) != 0; - } - SDL_UnlockJoysticks(); - - return retval; -} - -SDL_bool SDL_JoystickHasRumble(SDL_Joystick *joystick) -{ - SDL_bool retval; - - SDL_LockJoysticks(); - { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - - retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE) != 0; - } - SDL_UnlockJoysticks(); - - return retval; -} - -SDL_bool SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick) -{ - SDL_bool retval; - - SDL_LockJoysticks(); - { - CHECK_JOYSTICK_MAGIC(joystick, SDL_FALSE); - - retval = (joystick->driver->GetCapabilities(joystick) & SDL_JOYCAP_RUMBLE_TRIGGERS) != 0; - } - SDL_UnlockJoysticks(); - - return retval; -} - int SDL_SetJoystickLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { int retval; @@ -1809,6 +1842,7 @@ void SDL_CloseJoystick(SDL_Joystick *joystick) SDL_free(joystick->path); SDL_free(joystick->serial); SDL_free(joystick->axes); + SDL_free(joystick->balls); SDL_free(joystick->hats); SDL_free(joystick->buttons); for (i = 0; i < joystick->ntouchpads; i++) { @@ -1855,9 +1889,7 @@ void SDL_QuitJoysticks(void) SDL_joystick_player_count = 0; } -#ifndef SDL_EVENTS_DISABLED SDL_QuitSubSystem(SDL_INIT_EVENTS); -#endif SDL_QuitSteamVirtualGamepadInfo(); @@ -1971,7 +2003,6 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id) SDL_SetJoystickIDForPlayerIndex(player_index, instance_id); } -#ifndef SDL_EVENTS_DISABLED { SDL_Event event; @@ -1983,7 +2014,6 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id) SDL_PushEvent(&event); } } -#endif /* !SDL_EVENTS_DISABLED */ SDL_joystick_being_added = SDL_FALSE; @@ -2032,9 +2062,7 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id) { SDL_Joystick *joystick = NULL; int player_index; -#ifndef SDL_EVENTS_DISABLED SDL_Event event; -#endif SDL_AssertJoysticksLocked(); @@ -2054,7 +2082,6 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id) SDL_PrivateGamepadRemoved(instance_id); } -#ifndef SDL_EVENTS_DISABLED event.type = SDL_EVENT_JOYSTICK_REMOVED; event.common.timestamp = 0; @@ -2062,7 +2089,6 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id) event.jdevice.which = instance_id; SDL_PushEvent(&event); } -#endif /* !SDL_EVENTS_DISABLED */ player_index = SDL_GetPlayerIndexForJoystickID(instance_id); if (player_index >= 0) { @@ -2125,7 +2151,6 @@ int SDL_SendJoystickAxis(Uint64 timestamp, SDL_Joystick *joystick, Uint8 axis, S /* Post the event, if desired */ posted = 0; -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(SDL_EVENT_JOYSTICK_AXIS_MOTION)) { SDL_Event event; event.type = SDL_EVENT_JOYSTICK_AXIS_MOTION; @@ -2135,7 +2160,41 @@ int SDL_SendJoystickAxis(Uint64 timestamp, SDL_Joystick *joystick, Uint8 axis, S event.jaxis.value = value; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ + return posted; +} + +int SDL_SendJoystickBall(Uint64 timestamp, SDL_Joystick *joystick, Uint8 ball, Sint16 xrel, Sint16 yrel) +{ + int posted; + + SDL_AssertJoysticksLocked(); + + /* Make sure we're not getting garbage events */ + if (ball >= joystick->nballs) { + return 0; + } + + /* We ignore events if we don't have keyboard focus. */ + if (SDL_PrivateJoystickShouldIgnoreEvent()) { + return 0; + } + + /* Update internal mouse state */ + joystick->balls[ball].dx += xrel; + joystick->balls[ball].dy += yrel; + + /* Post the event, if desired */ + posted = 0; + if (SDL_EventEnabled(SDL_EVENT_JOYSTICK_BALL_MOTION)) { + SDL_Event event; + event.type = SDL_EVENT_JOYSTICK_BALL_MOTION; + event.common.timestamp = timestamp; + event.jball.which = joystick->instance_id; + event.jball.ball = ball; + event.jball.xrel = xrel; + event.jball.yrel = yrel; + posted = SDL_PushEvent(&event) == 1; + } return posted; } @@ -2169,7 +2228,6 @@ int SDL_SendJoystickHat(Uint64 timestamp, SDL_Joystick *joystick, Uint8 hat, Uin /* Post the event, if desired */ posted = 0; -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(SDL_EVENT_JOYSTICK_HAT_MOTION)) { SDL_Event event; event.type = SDL_EVENT_JOYSTICK_HAT_MOTION; @@ -2179,14 +2237,12 @@ int SDL_SendJoystickHat(Uint64 timestamp, SDL_Joystick *joystick, Uint8 hat, Uin event.jhat.value = value; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ return posted; } int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 button, Uint8 state) { int posted; -#ifndef SDL_EVENTS_DISABLED SDL_Event event; SDL_AssertJoysticksLocked(); @@ -2202,7 +2258,6 @@ int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butto /* Invalid state -- bail */ return 0; } -#endif /* !SDL_EVENTS_DISABLED */ SDL_AssertJoysticksLocked(); @@ -2229,7 +2284,6 @@ int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butto /* Post the event, if desired */ posted = 0; -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(event.type)) { event.common.timestamp = timestamp; event.jbutton.which = joystick->instance_id; @@ -2237,7 +2291,6 @@ int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butto event.jbutton.state = state; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ return posted; } @@ -2352,9 +2405,9 @@ void SDL_UpdateJoysticks(void) SDL_UnlockJoysticks(); } -#ifndef SDL_EVENTS_DISABLED static const Uint32 SDL_joystick_event_list[] = { SDL_EVENT_JOYSTICK_AXIS_MOTION, + SDL_EVENT_JOYSTICK_BALL_MOTION, SDL_EVENT_JOYSTICK_HAT_MOTION, SDL_EVENT_JOYSTICK_BUTTON_DOWN, SDL_EVENT_JOYSTICK_BUTTON_UP, @@ -2362,24 +2415,19 @@ static const Uint32 SDL_joystick_event_list[] = { SDL_EVENT_JOYSTICK_REMOVED, SDL_EVENT_JOYSTICK_BATTERY_UPDATED }; -#endif void SDL_SetJoystickEventsEnabled(SDL_bool enabled) { -#ifndef SDL_EVENTS_DISABLED unsigned int i; for (i = 0; i < SDL_arraysize(SDL_joystick_event_list); ++i) { SDL_SetEventEnabled(SDL_joystick_event_list[i], enabled); } -#endif /* SDL_EVENTS_DISABLED */ } SDL_bool SDL_JoystickEventsEnabled(void) { SDL_bool enabled = SDL_FALSE; - -#ifndef SDL_EVENTS_DISABLED unsigned int i; for (i = 0; i < SDL_arraysize(SDL_joystick_event_list); ++i) { @@ -2388,8 +2436,6 @@ SDL_bool SDL_JoystickEventsEnabled(void) break; } } -#endif /* !SDL_EVENTS_DISABLED */ - return enabled; } @@ -2631,7 +2677,7 @@ SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 produc *guid16++ = SDL_SwapLE16(bus); *guid16++ = SDL_SwapLE16(crc); - if (vendor && product) { + if (vendor) { *guid16++ = SDL_SwapLE16(vendor); *guid16++ = 0; *guid16++ = SDL_SwapLE16(product); @@ -2647,7 +2693,9 @@ SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 produc guid.data[14] = driver_signature; guid.data[15] = driver_data; } - SDL_strlcpy((char *)guid16, product_name, available_space); + if (product_name) { + SDL_strlcpy((char *)guid16, product_name, available_space); + } } return guid; } @@ -3369,7 +3417,6 @@ void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel SDL_assert(joystick->ref_count); /* make sure we are calling this only for update, not for initialization */ if (ePowerLevel != joystick->epowerlevel) { -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(SDL_EVENT_JOYSTICK_BATTERY_UPDATED)) { SDL_Event event; event.type = SDL_EVENT_JOYSTICK_BATTERY_UPDATED; @@ -3378,7 +3425,6 @@ void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel event.jbattery.level = ePowerLevel; SDL_PushEvent(&event); } -#endif /* !SDL_EVENTS_DISABLED */ joystick->epowerlevel = ePowerLevel; } } @@ -3475,7 +3521,6 @@ int SDL_SendJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, int touch /* Post the event, if desired */ posted = 0; -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(event_type)) { SDL_Event event; event.type = event_type; @@ -3488,7 +3533,6 @@ int SDL_SendJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, int touch event.gtouchpad.pressure = pressure; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ return posted; } @@ -3516,7 +3560,6 @@ int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorT joystick->update_complete = timestamp; /* Post the event, if desired */ -#ifndef SDL_EVENTS_DISABLED if (SDL_EventEnabled(SDL_EVENT_GAMEPAD_SENSOR_UPDATE)) { SDL_Event event; event.type = SDL_EVENT_GAMEPAD_SENSOR_UPDATE; @@ -3532,7 +3575,6 @@ int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorT event.gsensor.sensor_timestamp = sensor_timestamp; posted = SDL_PushEvent(&event) == 1; } -#endif /* !SDL_EVENTS_DISABLED */ } break; } diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 95ab4f71..fd50467c 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -54,6 +54,9 @@ extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_l /* Function to return whether there are any joysticks opened by the application */ extern SDL_bool SDL_JoysticksOpened(void); +/* Function to determine whether a device is currently detected by this driver */ +extern SDL_bool SDL_JoystickHandledByAnotherDriver(struct SDL_JoystickDriver *driver, Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name); + /* Function to standardize the name for a controller This should be freed with SDL_free() when no longer needed */ @@ -158,18 +161,13 @@ extern void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id); extern SDL_bool SDL_IsJoystickBeingAdded(void); extern void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id); extern void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick); -extern int SDL_SendJoystickAxis(Uint64 timestamp, SDL_Joystick *joystick, - Uint8 axis, Sint16 value); -extern int SDL_SendJoystickHat(Uint64 timestamp, SDL_Joystick *joystick, - Uint8 hat, Uint8 value); -extern int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, - Uint8 button, Uint8 state); -extern int SDL_SendJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, - int touchpad, int finger, Uint8 state, float x, float y, float pressure); -extern int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, - SDL_SensorType type, Uint64 sensor_timestamp, const float *data, int num_values); -extern void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick, - SDL_JoystickPowerLevel ePowerLevel); +extern int SDL_SendJoystickAxis(Uint64 timestamp, SDL_Joystick *joystick, Uint8 axis, Sint16 value); +extern int SDL_SendJoystickBall(Uint64 timestamp, SDL_Joystick *joystick, Uint8 ball, Sint16 xrel, Sint16 yrel); +extern int SDL_SendJoystickHat(Uint64 timestamp, SDL_Joystick *joystick, Uint8 hat, Uint8 value); +extern int SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 button, Uint8 state); +extern int SDL_SendJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure); +extern int SDL_SendJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorType type, Uint64 sensor_timestamp, const float *data, int num_values); +extern void SDL_SendJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel); /* Function to get the Steam virtual gamepad info for a joystick */ extern const struct SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id); @@ -212,6 +210,11 @@ typedef struct SDL_GamepadMapping SDL_InputMapping dpleft; SDL_InputMapping dpright; SDL_InputMapping misc1; + SDL_InputMapping misc2; + SDL_InputMapping misc3; + SDL_InputMapping misc4; + SDL_InputMapping misc5; + SDL_InputMapping misc6; SDL_InputMapping right_paddle1; SDL_InputMapping left_paddle1; SDL_InputMapping right_paddle2; diff --git a/src/joystick/SDL_steam_virtual_gamepad.c b/src/joystick/SDL_steam_virtual_gamepad.c index b8b2038a..602c3d80 100644 --- a/src/joystick/SDL_steam_virtual_gamepad.c +++ b/src/joystick/SDL_steam_virtual_gamepad.c @@ -23,7 +23,7 @@ #include "SDL_joystick_c.h" #include "SDL_steam_virtual_gamepad.h" -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 #include "../core/windows/SDL_windows.h" #else #include @@ -43,7 +43,7 @@ static Uint64 GetFileModificationTime(const char *file) { Uint64 modification_time = 0; -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 WCHAR *wFile = WIN_UTF8ToStringW(file); if (wFile) { HANDLE hFile = CreateFileW(wFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); @@ -219,6 +219,7 @@ SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void) if (slot >= 0) { AddVirtualGamepadInfo(slot, &info); } + SDL_free(info.name); SDL_free(data); SDL_steam_virtual_gamepad_info_file_mtime = mtime; diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index ae50d8f6..68eb038e 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -32,6 +32,7 @@ extern "C" { #endif /* The SDL joystick structure */ + typedef struct SDL_JoystickAxisInfo { Sint16 initial_value; /* Initial axis state */ @@ -43,6 +44,12 @@ typedef struct SDL_JoystickAxisInfo SDL_bool sending_initial_value; /* Whether we are sending the initial axis value */ } SDL_JoystickAxisInfo; +typedef struct SDL_JoystickBallData +{ + int dx; + int dy; +} SDL_JoystickBallData; + typedef struct SDL_JoystickTouchpadFingerInfo { Uint8 state; @@ -82,6 +89,9 @@ struct SDL_Joystick int naxes _guarded; /* Number of axis controls on the joystick */ SDL_JoystickAxisInfo *axes _guarded; + int nballs _guarded; /* Number of trackballs on the joystick */ + SDL_JoystickBallData *balls _guarded; /* Current ball motion deltas */ + int nhats _guarded; /* Number of hats on the joystick */ Uint8 *hats _guarded; /* Current hat states */ @@ -141,11 +151,6 @@ struct SDL_Joystick #define SDL_HARDWARE_BUS_BLUETOOTH 0x05 #define SDL_HARDWARE_BUS_VIRTUAL 0xFF -/* Joystick capability flags for GetCapabilities() */ -#define SDL_JOYCAP_LED 0x01 -#define SDL_JOYCAP_RUMBLE 0x02 -#define SDL_JOYCAP_RUMBLE_TRIGGERS 0x04 - /* Macro to combine a USB vendor ID and product ID into a single Uint32 value */ #define MAKE_VIDPID(VID, PID) (((Uint32)(VID)) << 16 | (PID)) @@ -163,6 +168,9 @@ typedef struct SDL_JoystickDriver /* Function to cause any queued joystick insertions to be processed */ void (*Detect)(void); + /* Function to determine whether a device is currently detected by this driver */ + SDL_bool (*IsDevicePresent)(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name); + /* Function to get the device-dependent name of a joystick */ const char *(*GetDeviceName)(int device_index); @@ -195,9 +203,6 @@ typedef struct SDL_JoystickDriver int (*Rumble)(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); int (*RumbleTriggers)(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble); - /* Capability detection */ - Uint32 (*GetCapabilities)(SDL_Joystick *joystick); - /* LED functionality */ int (*SetLED)(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); @@ -253,6 +258,7 @@ extern SDL_JoystickDriver SDL_PS2_JoystickDriver; extern SDL_JoystickDriver SDL_PSP_JoystickDriver; extern SDL_JoystickDriver SDL_VITA_JoystickDriver; extern SDL_JoystickDriver SDL_N3DS_JoystickDriver; +extern SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver; /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index cacb47b9..11707742 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -52,8 +52,6 @@ #define AKEYCODE_BUTTON_16 203 #endif -#define ANDROID_ACCELEROMETER_NAME "Android Accelerometer" -#define ANDROID_ACCELEROMETER_DEVICE_ID INT_MIN #define ANDROID_MAX_NBUTTONS 36 static SDL_joylist_item *JoystickByDeviceId(int device_id); @@ -207,7 +205,7 @@ int Android_OnPadDown(int device_id, int keycode) if (item && item->joystick) { SDL_SendJoystickButton(timestamp, item->joystick, button, SDL_PRESSED); } else { - SDL_SendKeyboardKey(timestamp, SDL_PRESSED, button_to_scancode(button)); + SDL_SendKeyboardKey(timestamp, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, button_to_scancode(button)); } SDL_UnlockJoysticks(); return 0; @@ -227,7 +225,7 @@ int Android_OnPadUp(int device_id, int keycode) if (item && item->joystick) { SDL_SendJoystickButton(timestamp, item->joystick, button, SDL_RELEASED); } else { - SDL_SendKeyboardKey(timestamp, SDL_RELEASED, button_to_scancode(button)); + SDL_SendKeyboardKey(timestamp, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, button_to_scancode(button)); } SDL_UnlockJoysticks(); return 0; @@ -303,7 +301,7 @@ int Android_OnHat(int device_id, int hat_id, int x, int y) return -1; } -int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, SDL_bool is_accelerometer, int button_mask, int naxes, int axis_mask, int nhats) +int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats) { SDL_joylist_item *item; SDL_JoystickGUID guid; @@ -323,12 +321,9 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v goto done; } -#ifdef SDL_JOYSTICK_HIDAPI - if (HIDAPI_IsDevicePresent(vendor_id, product_id, 0, name)) { - /* The HIDAPI driver is taking care of this device */ + if (SDL_JoystickHandledByAnotherDriver(&SDL_ANDROID_JoystickDriver, vendor_id, product_id, 0, name)) { goto done; } -#endif #ifdef DEBUG_JOYSTICK SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats\n", name, desc, vendor_id, product_id, naxes, nhats); @@ -366,7 +361,6 @@ int Android_AddJoystick(int device_id, const char *name, const char *desc, int v goto done; } - item->is_accelerometer = is_accelerometer; if (button_mask == 0xFFFFFFFF) { item->nbuttons = ANDROID_MAX_NBUTTONS; } else { @@ -463,11 +457,6 @@ static void ANDROID_JoystickDetect(void); static int ANDROID_JoystickInit(void) { ANDROID_JoystickDetect(); - - if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) { - /* Default behavior, accelerometer as joystick */ - Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, ANDROID_ACCELEROMETER_NAME, 0, 0, SDL_TRUE, 0, 3, 0x0003, 0); - } return 0; } @@ -490,6 +479,12 @@ static void ANDROID_JoystickDetect(void) } } +static SDL_bool ANDROID_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + static SDL_joylist_item *GetJoystickByDevIndex(int device_index) { SDL_joylist_item *item = SDL_joylist; @@ -577,7 +572,6 @@ static int ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index) return SDL_SetError("Joystick already opened"); } - joystick->instance_id = item->device_instance; joystick->hwdata = (struct joystick_hwdata *)item; item->joystick = joystick; joystick->nhats = item->nhats; @@ -597,11 +591,6 @@ static int ANDROID_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru return SDL_Unsupported(); } -static Uint32 ANDROID_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - static int ANDROID_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -619,31 +608,6 @@ static int ANDROID_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool en static void ANDROID_JoystickUpdate(SDL_Joystick *joystick) { - SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata; - - if (!item) { - return; - } - - if (item->is_accelerometer) { - int i; - Sint16 value; - float values[3]; - Uint64 timestamp = SDL_GetTicksNS(); - - if (Android_JNI_GetAccelerometerValues(values)) { - for (i = 0; i < 3; i++) { - if (values[i] > 1.0f) { - values[i] = 1.0f; - } else if (values[i] < -1.0f) { - values[i] = -1.0f; - } - - value = (Sint16)(values[i] * 32767.0f); - SDL_SendJoystickAxis(timestamp, item->joystick, i, value); - } - } - } } static void ANDROID_JoystickClose(SDL_Joystick *joystick) @@ -684,6 +648,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = { ANDROID_JoystickInit, ANDROID_JoystickGetCount, ANDROID_JoystickDetect, + ANDROID_JoystickIsDevicePresent, ANDROID_JoystickGetDeviceName, ANDROID_JoystickGetDevicePath, ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -694,7 +659,6 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = { ANDROID_JoystickOpen, ANDROID_JoystickRumble, ANDROID_JoystickRumbleTriggers, - ANDROID_JoystickGetCapabilities, ANDROID_JoystickSetLED, ANDROID_JoystickSendEffect, ANDROID_JoystickSetSensorsEnabled, diff --git a/src/joystick/android/SDL_sysjoystick_c.h b/src/joystick/android/SDL_sysjoystick_c.h index 28dd6b3b..06424887 100644 --- a/src/joystick/android/SDL_sysjoystick_c.h +++ b/src/joystick/android/SDL_sysjoystick_c.h @@ -32,7 +32,7 @@ extern int Android_OnPadDown(int device_id, int keycode); extern int Android_OnPadUp(int device_id, int keycode); extern int Android_OnJoy(int device_id, int axisnum, float value); extern int Android_OnHat(int device_id, int hat_id, int x, int y); -extern int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, SDL_bool is_accelerometer, int button_mask, int naxes, int axis_mask, int nhats); +extern int Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats); extern int Android_RemoveJoystick(int device_id); /* A linked list of available joysticks */ @@ -42,7 +42,6 @@ typedef struct SDL_joylist_item int device_id; /* Android's device id */ char *name; /* "SideWinder 3D Pro" or whatever */ SDL_JoystickGUID guid; - SDL_bool is_accelerometer; SDL_Joystick *joystick; int nbuttons, naxes, nhats; int dpad_state; diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m index 3aa0c82a..81626a77 100644 --- a/src/joystick/apple/SDL_mfijoystick.m +++ b/src/joystick/apple/SDL_mfijoystick.m @@ -25,25 +25,22 @@ #include "../SDL_joystick_c.h" #include "../hidapi/SDL_hidapijoystick_c.h" #include "../usb_ids.h" +#include "../../events/SDL_events_c.h" #include "SDL_mfijoystick_c.h" -#ifndef SDL_EVENTS_DISABLED -#include "../../events/SDL_events_c.h" -#endif -#if TARGET_OS_IOS -#define SDL_JOYSTICK_iOS_ACCELEROMETER +#if defined(SDL_PLATFORM_IOS) && !defined(SDL_PLATFORM_TVOS) #import #endif -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS #include #include #ifndef NSAppKitVersionNumber10_15 #define NSAppKitVersionNumber10_15 1894 #endif -#endif /* __MACOS__ */ +#endif /* SDL_PLATFORM_MACOS */ #ifdef SDL_JOYSTICK_MFI #import @@ -70,7 +67,7 @@ static id disconnectObserver = nil; * they are only ever used indirectly through objc_msgSend */ @interface GCController (SDL) -#if defined(__MACOS__) && (__MAC_OS_X_VERSION_MAX_ALLOWED <= 101600) +#if defined(SDL_PLATFORM_MACOS) && (__MAC_OS_X_VERSION_MAX_ALLOWED <= 101600) + (BOOL)supportsHIDDevice:(IOHIDDeviceRef)device; #endif #if !((__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 130000) || (__MAC_OS_VERSION_MAX_ALLOWED >= 1500000)) @@ -114,11 +111,6 @@ static id disconnectObserver = nil; #endif /* SDL_JOYSTICK_MFI */ -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER -static const char *accelerometerName = "iOS Accelerometer"; -static CMMotionManager *motionManager = nil; -#endif /* SDL_JOYSTICK_iOS_ACCELEROMETER */ - static SDL_JoystickDeviceItem *deviceList = NULL; static int numjoysticks = 0; @@ -242,6 +234,7 @@ static void CheckControllerSiriRemote(GCController *controller, int *is_siri_rem *is_siri_remote = 0; } +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE static BOOL ElementAlreadyHandled(SDL_JoystickDeviceItem *device, NSString *element, NSDictionary *elements) { if ([element isEqualToString:@"Left Thumbstick Left"] || @@ -327,7 +320,7 @@ static BOOL ElementAlreadyHandled(SDL_JoystickDeviceItem *device, NSString *elem /* The Nintendo Switch JoyCon home button doesn't ever show as being held down */ return TRUE; } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS /* The OS uses the home button, it's not available to apps */ return TRUE; #endif @@ -340,6 +333,7 @@ static BOOL ElementAlreadyHandled(SDL_JoystickDeviceItem *device, NSString *elem } return FALSE; } +#endif /* ENABLE_PHYSICAL_INPUT_PROFILE */ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller) { @@ -372,6 +366,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle NSLog(@"Product name: %@\n", controller.vendorName); NSLog(@"Product category: %@\n", controller.productCategory); NSLog(@"Elements available:\n"); +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { NSDictionary *elements = controller.physicalInputProfile.elements; for (id key in controller.physicalInputProfile.buttons) { @@ -384,6 +379,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle NSLog(@"\tHat: %@\n", key); } } +#endif #endif device->is_xbox = IsControllerXbox(controller); @@ -486,7 +482,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle vendor = USB_VENDOR_APPLE; product = 2; subtype = 2; -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS } else if (controller.microGamepad) { vendor = USB_VENDOR_APPLE; product = 3; @@ -502,7 +498,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle NSDictionary *elements = controller.physicalInputProfile.elements; /* Provide both axes and analog buttons as SDL axes */ - device->axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] + NSArray *axes = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { if (ElementAlreadyHandled(device, (NSString *)object, elements)) { return NO; @@ -517,8 +513,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } return NO; }]]; - device->naxes = (int)device->axes.count; - device->buttons = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] + NSArray *buttons = [[[elements allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { if (ElementAlreadyHandled(device, (NSString *)object, elements)) { return NO; @@ -530,7 +525,12 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } return NO; }]]; - device->nbuttons = (int)device->buttons.count; + /* Explicitly retain the arrays because SDL_JoystickDeviceItem is a + * struct, and ARC doesn't work with structs. */ + device->naxes = (int)axes.count; + device->axes = (__bridge NSArray *)CFBridgingRetain(axes); + device->nbuttons = (int)buttons.count; + device->buttons = (__bridge NSArray *)CFBridgingRetain(buttons); subtype = 4; #ifdef DEBUG_CONTROLLER_PROFILE @@ -543,10 +543,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } #endif /* DEBUG_CONTROLLER_PROFILE */ -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS /* tvOS turns the menu button into a system gesture, so we grab it here instead */ if (elements[GCInputButtonMenu] && !elements[@"Button Home"]) { - device->pause_button_index = [device->buttons indexOfObject:GCInputButtonMenu]; + device->pause_button_index = (int)[device->buttons indexOfObject:GCInputButtonMenu]; } #endif } else @@ -590,7 +590,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle has_direct_menu = TRUE; } } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS /* The single menu button isn't very reliable, at least as of tvOS 16.1 */ if ((device->button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) == 0) { has_direct_menu = FALSE; @@ -622,7 +622,7 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle device->nhats = 1; /* d-pad */ device->nbuttons = nbuttons; } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS else if (controller.microGamepad) { int nbuttons = 0; @@ -672,8 +672,8 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle } #endif /* SDL_JOYSTICK_MFI */ -#if defined(SDL_JOYSTICK_iOS_ACCELEROMETER) || defined(SDL_JOYSTICK_MFI) -static void IOS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer) +#if defined(SDL_JOYSTICK_MFI) +static void IOS_AddJoystickDevice(GCController *controller) { SDL_JoystickDeviceItem *device = deviceList; @@ -689,24 +689,10 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet return; } - device->accelerometer = accelerometer; device->instance_id = SDL_GetNextObjectID(); device->pause_button_index = -1; - if (accelerometer) { -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER - device->name = SDL_strdup(accelerometerName); - device->naxes = 3; /* Device acceleration in the x, y, and z axes. */ - device->nhats = 0; - device->nbuttons = 0; - - /* Use the accelerometer name as a GUID. */ - SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name))); -#else - SDL_free(device); - return; -#endif /* SDL_JOYSTICK_iOS_ACCELEROMETER */ - } else if (controller) { + if (controller) { #ifdef SDL_JOYSTICK_MFI if (!IOS_AddMFIJoystickDevice(device, controller)) { SDL_free(device->name); @@ -733,7 +719,7 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet SDL_PrivateJoystickAdded(device->instance_id); } -#endif /* SDL_JOYSTICK_iOS_ACCELEROMETER || SDL_JOYSTICK_MFI */ +#endif /* SDL_JOYSTICK_MFI */ static SDL_JoystickDeviceItem *IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device) { @@ -768,13 +754,20 @@ static SDL_JoystickDeviceItem *IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem * #ifdef SDL_JOYSTICK_MFI @autoreleasepool { + /* These were explicitly retained in the struct, so they should be explicitly released before freeing the struct. */ if (device->controller) { - /* The controller was explicitly retained in the struct, so it - * should be explicitly released before freeing the struct. */ GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller)); controller.controllerPausedHandler = nil; device->controller = nil; } + if (device->axes) { + CFRelease((__bridge CFTypeRef)device->axes); + device->axes = nil; + } + if (device->buttons) { + CFRelease((__bridge CFTypeRef)device->buttons); + device->buttons = nil; + } } #endif /* SDL_JOYSTICK_MFI */ @@ -788,7 +781,7 @@ static SDL_JoystickDeviceItem *IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem * return next; } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS static void SDLCALL SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *oldValue, const char *newValue) { BOOL allowRotation = newValue != NULL && *newValue != '0'; @@ -801,7 +794,7 @@ static void SDLCALL SDL_AppleTVRemoteRotationHintChanged(void *udata, const char } } } -#endif /* TARGET_OS_TV */ +#endif /* SDL_PLATFORM_TVOS */ static int IOS_JoystickInit(void) { @@ -809,7 +802,7 @@ static int IOS_JoystickInit(void) return 0; } -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS #if SDL_HAS_BUILTIN(__builtin_available) if (@available(macOS 10.16, *)) { /* Continue with initialization on macOS 11+ */ @@ -826,12 +819,6 @@ static int IOS_JoystickInit(void) #ifdef SDL_JOYSTICK_MFI NSNotificationCenter *center; #endif -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER - if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) { - /* Default behavior, accelerometer as joystick */ - IOS_AddJoystickDevice(nil, SDL_TRUE); - } -#endif #ifdef SDL_JOYSTICK_MFI /* GameController.framework was added in iOS 7. */ @@ -842,13 +829,13 @@ static int IOS_JoystickInit(void) /* For whatever reason, this always returns an empty array on macOS 11.0.1 */ for (GCController *controller in [GCController controllers]) { - IOS_AddJoystickDevice(controller, SDL_FALSE); + IOS_AddJoystickDevice(controller); } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS SDL_AddHintCallback(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_AppleTVRemoteRotationHintChanged, NULL); -#endif /* TARGET_OS_TV */ +#endif /* SDL_PLATFORM_TVOS */ center = [NSNotificationCenter defaultCenter]; @@ -858,7 +845,7 @@ static int IOS_JoystickInit(void) usingBlock:^(NSNotification *note) { GCController *controller = note.object; SDL_LockJoysticks(); - IOS_AddJoystickDevice(controller, SDL_FALSE); + IOS_AddJoystickDevice(controller); SDL_UnlockJoysticks(); }]; @@ -892,6 +879,12 @@ static void IOS_JoystickDetect(void) { } +static SDL_bool IOS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers through this method */ + return SDL_FALSE; +} + static const char *IOS_JoystickGetDeviceName(int device_index) { SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index); @@ -955,7 +948,6 @@ static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index) } joystick->hwdata = device; - joystick->instance_id = device->instance_id; joystick->naxes = device->naxes; joystick->nhats = device->nhats; @@ -968,54 +960,62 @@ static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index) device->joystick = joystick; @autoreleasepool { - if (device->accelerometer) { -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER - if (motionManager == nil) { - motionManager = [[CMMotionManager alloc] init]; - } - - /* Shorter times between updates can significantly increase CPU usage. */ - motionManager.accelerometerUpdateInterval = 0.1; - [motionManager startAccelerometerUpdates]; -#endif - } else { #ifdef SDL_JOYSTICK_MFI - if (device->pause_button_index >= 0) { - GCController *controller = device->controller; - controller.controllerPausedHandler = ^(GCController *c) { - if (joystick->hwdata) { - joystick->hwdata->pause_button_pressed = SDL_GetTicks(); - } - }; - } + if (device->pause_button_index >= 0) { + GCController *controller = device->controller; + controller.controllerPausedHandler = ^(GCController *c) { + if (joystick->hwdata) { + joystick->hwdata->pause_button_pressed = SDL_GetTicks(); + } + }; + } #ifdef ENABLE_MFI_SENSORS - if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { - GCController *controller = joystick->hwdata->controller; - GCMotion *motion = controller.motion; - if (motion && motion.hasRotationRate) { - SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 0.0f); - } - if (motion && motion.hasGravityAndUserAcceleration) { - SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 0.0f); - } + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { + GCController *controller = joystick->hwdata->controller; + GCMotion *motion = controller.motion; + if (motion && motion.hasRotationRate) { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 0.0f); } + if (motion && motion.hasGravityAndUserAcceleration) { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 0.0f); + } + } #endif /* ENABLE_MFI_SENSORS */ #ifdef ENABLE_MFI_SYSTEM_GESTURE_STATE - if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { - GCController *controller = joystick->hwdata->controller; - for (id key in controller.physicalInputProfile.buttons) { - GCControllerButtonInput *button = controller.physicalInputProfile.buttons[key]; - if ([button isBoundToSystemGesture]) { - button.preferredSystemGestureState = GCSystemGestureStateDisabled; + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { + GCController *controller = joystick->hwdata->controller; + for (id key in controller.physicalInputProfile.buttons) { + GCControllerButtonInput *button = controller.physicalInputProfile.buttons[key]; + if ([button isBoundToSystemGesture]) { + button.preferredSystemGestureState = GCSystemGestureStateDisabled; + } + } + } +#endif /* ENABLE_MFI_SYSTEM_GESTURE_STATE */ + + if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { + GCController *controller = device->controller; +#ifdef ENABLE_MFI_LIGHT + if (controller.light) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, SDL_TRUE); + } +#endif + +#ifdef ENABLE_MFI_RUMBLE + if (controller.haptics) { + for (GCHapticsLocality locality in controller.haptics.supportedLocalities) { + if ([locality isEqualToString:GCHapticsLocalityHandles]) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } else if ([locality isEqualToString:GCHapticsLocalityTriggers]) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE); } } } -#endif /* ENABLE_MFI_SYSTEM_GESTURE_STATE */ - -#endif /* SDL_JOYSTICK_MFI */ +#endif } +#endif /* SDL_JOYSTICK_MFI */ } if (device->is_siri_remote) { ++SDL_AppleTVRemoteOpenedAsJoystick; @@ -1024,50 +1024,6 @@ static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index) return 0; } -static void IOS_AccelerometerUpdate(SDL_Joystick *joystick) -{ -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER - const float maxgforce = SDL_IPHONE_MAX_GFORCE; - const SInt16 maxsint16 = 0x7FFF; - CMAcceleration accel; - Uint64 timestamp = SDL_GetTicksNS(); - - @autoreleasepool { - if (!motionManager.isAccelerometerActive) { - return; - } - - accel = motionManager.accelerometerData.acceleration; - } - - /* - Convert accelerometer data from floating point to Sint16, which is what - the joystick system expects. - - To do the conversion, the data is first clamped onto the interval - [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied - by MAX_SINT16 so that it is mapped to the full range of an Sint16. - - You can customize the clamped range of this function by modifying the - SDL_IPHONE_MAX_GFORCE macro in SDL_config_ios.h. - - Once converted to Sint16, the accelerometer data no longer has coherent - units. You can convert the data back to units of g-force by multiplying - it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF. - */ - - /* clamp the data */ - accel.x = SDL_clamp(accel.x, -maxgforce, maxgforce); - accel.y = SDL_clamp(accel.y, -maxgforce, maxgforce); - accel.z = SDL_clamp(accel.z, -maxgforce, maxgforce); - - /* pass in data mapped to range of SInt16 */ - SDL_SendJoystickAxis(timestamp, joystick, 0, (accel.x / maxgforce) * maxsint16); - SDL_SendJoystickAxis(timestamp, joystick, 1, -(accel.y / maxgforce) * maxsint16); - SDL_SendJoystickAxis(timestamp, joystick, 2, (accel.z / maxgforce) * maxsint16); -#endif /* SDL_JOYSTICK_iOS_ACCELEROMETER */ -} - #ifdef SDL_JOYSTICK_MFI static Uint8 IOS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad) { @@ -1103,7 +1059,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) int i; Uint64 timestamp = SDL_GetTicksNS(); -#ifdef DEBUG_CONTROLLER_STATE +#if defined(DEBUG_CONTROLLER_STATE) && defined(ENABLE_PHYSICAL_INPUT_PROFILE) if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { if (controller.physicalInputProfile) { for (id key in controller.physicalInputProfile.buttons) { @@ -1130,6 +1086,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } #endif /* DEBUG_CONTROLLER_STATE */ +#ifdef ENABLE_PHYSICAL_INPUT_PROFILE if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { NSDictionary *elements = controller.physicalInputProfile.elements; NSDictionary *buttons = controller.physicalInputProfile.buttons; @@ -1156,7 +1113,9 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) } SDL_SendJoystickButton(timestamp, joystick, button++, value); } - } else if (controller.extendedGamepad) { + } else +#endif + if (controller.extendedGamepad) { SDL_bool isstack; GCExtendedGamepad *gamepad = controller.extendedGamepad; @@ -1250,7 +1209,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) SDL_small_free(buttons, isstack); } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS else if (controller.microGamepad) { GCMicroGamepad *gamepad = controller.microGamepad; @@ -1273,7 +1232,7 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick) SDL_SendJoystickButton(timestamp, joystick, i, buttons[i]); } } -#endif /* TARGET_OS_TV */ +#endif /* SDL_PLATFORM_TVOS */ if (joystick->nhats > 0) { SDL_SendJoystickHat(timestamp, joystick, 0, hatstate); @@ -1627,44 +1586,6 @@ static int IOS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble #endif } -static Uint32 IOS_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - Uint32 result = 0; - -#if defined(ENABLE_MFI_LIGHT) || defined(ENABLE_MFI_RUMBLE) - @autoreleasepool { - SDL_JoystickDeviceItem *device = joystick->hwdata; - - if (device == NULL) { - return 0; - } - - if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { - GCController *controller = device->controller; -#ifdef ENABLE_MFI_LIGHT - if (controller.light) { - result |= SDL_JOYCAP_LED; - } -#endif - -#ifdef ENABLE_MFI_RUMBLE - if (controller.haptics) { - for (GCHapticsLocality locality in controller.haptics.supportedLocalities) { - if ([locality isEqualToString:GCHapticsLocalityHandles]) { - result |= SDL_JOYCAP_RUMBLE; - } else if ([locality isEqualToString:GCHapticsLocalityTriggers]) { - result |= SDL_JOYCAP_RUMBLE_TRIGGERS; - } - } - } -#endif - } - } -#endif /* ENABLE_MFI_LIGHT || ENABLE_MFI_RUMBLE */ - - return result; -} - static int IOS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { #ifdef ENABLE_MFI_LIGHT @@ -1728,9 +1649,7 @@ static void IOS_JoystickUpdate(SDL_Joystick *joystick) return; } - if (device->accelerometer) { - IOS_AccelerometerUpdate(joystick); - } else if (device->controller) { + if (device->controller) { IOS_MFIJoystickUpdate(joystick); } } @@ -1756,11 +1675,7 @@ static void IOS_JoystickClose(SDL_Joystick *joystick) } #endif /* ENABLE_MFI_RUMBLE */ - if (device->accelerometer) { -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER - [motionManager stopAccelerometerUpdates]; -#endif - } else if (device->controller) { + if (device->controller) { #ifdef SDL_JOYSTICK_MFI GCController *controller = device->controller; controller.controllerPausedHandler = nil; @@ -1801,19 +1716,15 @@ static void IOS_JoystickQuit(void) disconnectObserver = nil; } -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS SDL_DelHintCallback(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_AppleTVRemoteRotationHintChanged, NULL); -#endif /* TARGET_OS_TV */ +#endif /* SDL_PLATFORM_TVOS */ #endif /* SDL_JOYSTICK_MFI */ while (deviceList != NULL) { IOS_RemoveJoystickDevice(deviceList); } - -#ifdef SDL_JOYSTICK_iOS_ACCELEROMETER - motionManager = nil; -#endif } numjoysticks = 0; @@ -1826,9 +1737,6 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi if (device == NULL) { return SDL_FALSE; } - if (device->accelerometer) { - return SDL_FALSE; - } if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { int axis = 0; @@ -1962,7 +1870,7 @@ static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi return SDL_FALSE; } -#if defined(SDL_JOYSTICK_MFI) && defined(__MACOS__) +#if defined(SDL_JOYSTICK_MFI) && defined(SDL_PLATFORM_MACOS) SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device) { if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_MFI, SDL_TRUE)) { @@ -2176,6 +2084,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = { IOS_JoystickInit, IOS_JoystickGetCount, IOS_JoystickDetect, + IOS_JoystickIsDevicePresent, IOS_JoystickGetDeviceName, IOS_JoystickGetDevicePath, IOS_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -2186,7 +2095,6 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = { IOS_JoystickOpen, IOS_JoystickRumble, IOS_JoystickRumbleTriggers, - IOS_JoystickGetCapabilities, IOS_JoystickSetLED, IOS_JoystickSendEffect, IOS_JoystickSetSensorsEnabled, diff --git a/src/joystick/apple/SDL_mfijoystick_c.h b/src/joystick/apple/SDL_mfijoystick_c.h index 0dae2ac6..4a974913 100644 --- a/src/joystick/apple/SDL_mfijoystick_c.h +++ b/src/joystick/apple/SDL_mfijoystick_c.h @@ -25,14 +25,13 @@ #include "../SDL_sysjoystick.h" -#include +#import +#import @class GCController; typedef struct joystick_hwdata { - SDL_bool accelerometer; - GCController __unsafe_unretained *controller; void *rumble; int pause_button_index; @@ -58,8 +57,8 @@ typedef struct joystick_hwdata SDL_bool is_backbone_one; int is_siri_remote; - NSArray *axes; - NSArray *buttons; + NSArray __unsafe_unretained *axes; + NSArray __unsafe_unretained *buttons; SDL_bool has_dualshock_touchpad; SDL_bool has_xbox_paddles; diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c index dcc2980c..eda5e308 100644 --- a/src/joystick/bsd/SDL_bsdjoystick.c +++ b/src/joystick/bsd/SDL_bsdjoystick.c @@ -59,7 +59,7 @@ #include #endif -#if defined(__FREEBSD__) || defined(__FreeBSD_kernel__) +#if defined(SDL_PLATFORM_FREEBSD) #include #if __FreeBSD_kernel_version > 800063 #include @@ -77,7 +77,7 @@ #include "../SDL_joystick_c.h" #include "../hidapi/SDL_hidapijoystick_c.h" -#if defined(__FREEBSD__) || SDL_HAVE_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) || defined(__DragonFly_) +#if defined(SDL_PLATFORM_FREEBSD) || SDL_HAVE_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) || defined(__DragonFly_) #define SUPPORT_JOY_GAMEPORT #endif @@ -85,7 +85,7 @@ #define MAX_JOY_JOYS 2 #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS) -#ifdef __OpenBSD__ +#ifdef SDL_PLATFORM_OPENBSD #define HUG_DPAD_UP 0x90 #define HUG_DPAD_DOWN 0x91 @@ -101,10 +101,10 @@ struct report { -#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) || \ +#if defined(SDL_PLATFORM_FREEBSD) && (__FreeBSD_kernel_version > 900000) || \ defined(__DragonFly__) void *buf; /* Buffer */ -#elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) +#elif defined(SDL_PLATFORM_FREEBSD) && (__FreeBSD_kernel_version > 800063) struct usb_gen_descriptor *buf; /* Buffer */ #else struct usb_ctl_report *buf; /* Buffer */ @@ -187,10 +187,10 @@ static void report_free(struct report *); #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063) #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) -#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)) || \ +#elif (defined(SDL_PLATFORM_FREEBSD) && (__FreeBSD_kernel_version > 900000)) || \ defined(__DragonFly__) #define REP_BUF_DATA(rep) ((rep)->buf) -#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) +#elif (defined(SDL_PLATFORM_FREEBSD) && (__FreeBSD_kernel_version > 800063)) #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) #else #define REP_BUF_DATA(rep) ((rep)->buf->data) @@ -296,7 +296,7 @@ CreateHwData(const char *path) goto usberr; } rep = &hw->inreport; -#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#if defined(SDL_PLATFORM_FREEBSD) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) rep->rid = hid_get_report_id(fd); if (rep->rid < 0) { #else @@ -312,7 +312,7 @@ CreateHwData(const char *path) path); goto usberr; } -#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#if defined(USBHID_NEW) || (defined(SDL_PLATFORM_FREEBSD) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid); #else hdata = hid_start_parse(hw->repdesc, 1 << hid_input); @@ -336,7 +336,7 @@ CreateHwData(const char *path) if (joyaxe >= 0) { hw->axis_map[joyaxe] = 1; } else if (usage == HUG_HAT_SWITCH -#ifdef __OpenBSD__ +#ifdef SDL_PLATFORM_OPENBSD || usage == HUG_DPAD_UP #endif ) { @@ -374,7 +374,7 @@ CreateHwData(const char *path) /* The poll blocks the event thread. */ fcntl(fd, F_SETFL, O_NONBLOCK); -#ifdef __NetBSD__ +#ifdef SDL_PLATFORM_NETBSD /* Flush pending events */ if (rep) { while (read(fd, REP_BUF_DATA(rep), rep->size) == rep->size) @@ -427,15 +427,8 @@ static int MaybeAddDevice(const char *path) name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product); guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0); -#ifdef SDL_JOYSTICK_HIDAPI - if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) { - /* The HIDAPI driver is taking care of this device */ - SDL_free(name); - FreeHwData(hw); - return -1; - } -#endif - if (SDL_ShouldIgnoreJoystick(name, guid)) { + if (SDL_ShouldIgnoreJoystick(name, guid) || + SDL_JoystickHandledByAnotherDriver(&SDL_BSD_JoystickDriver, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) { SDL_free(name); FreeHwData(hw); return -1; @@ -487,7 +480,7 @@ static int BSD_JoystickInit(void) int i; for (i = 0; i < MAX_UHID_JOYS; i++) { -#if defined(__OpenBSD__) && (OpenBSD >= 202105) +#if defined(SDL_PLATFORM_OPENBSD) && (OpenBSD >= 202105) SDL_snprintf(s, SDL_arraysize(s), "/dev/ujoy/%d", i); #else SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i); @@ -516,6 +509,12 @@ static void BSD_JoystickDetect(void) { } +static SDL_bool BSD_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + static SDL_joylist_item *GetJoystickByDevIndex(int device_index) { SDL_joylist_item *item = SDL_joylist; @@ -596,7 +595,6 @@ static int BSD_JoystickOpen(SDL_Joystick *joy, int device_index) return -1; } - joy->instance_id = item->device_instance; joy->hwdata = hw; joy->naxes = hw->naxes; joy->nbuttons = hw->nbuttons; @@ -612,7 +610,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy) struct report *rep; int nbutton, naxe = -1; Sint32 v; -#ifdef __OpenBSD__ +#ifdef SDL_PLATFORM_OPENBSD Sint32 dpad[4] = { 0, 0, 0, 0 }; #endif Uint64 timestamp = SDL_GetTicksNS(); @@ -663,7 +661,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy) rep = &joy->hwdata->inreport; while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) { -#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#if defined(USBHID_NEW) || (defined(SDL_PLATFORM_FREEBSD) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); #else hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); @@ -693,7 +691,7 @@ static void BSD_JoystickUpdate(SDL_Joystick *joy) hatval_to_sdl(v) - hitem.logical_minimum); } -#ifdef __OpenBSD__ +#ifdef SDL_PLATFORM_OPENBSD /* here D-pad directions are reported like separate buttons. * calculate the SDL hat value from the 4 separate values. */ @@ -767,7 +765,7 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind) #ifdef __DragonFly__ len = hid_report_size(rd, repinfo[repind].kind, r->rid); -#elif defined __FREEBSD__ +#elif defined(SDL_PLATFORM_FREEBSD) #if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) #if (__FreeBSD_kernel_version <= 500111) len = hid_report_size(rd, r->rid, repinfo[repind].kind); @@ -791,7 +789,7 @@ static int report_alloc(struct report *r, struct report_desc *rd, int repind) r->size = len; if (r->size > 0) { -#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) || defined(__DragonFly__) +#if defined(SDL_PLATFORM_FREEBSD) && (__FreeBSD_kernel_version > 900000) || defined(__DragonFly__) r->buf = SDL_malloc(r->size); #else r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) + @@ -829,11 +827,6 @@ static SDL_bool BSD_JoystickGetGamepadMapping(int device_index, SDL_GamepadMappi return SDL_FALSE; } -static Uint32 BSD_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - static int BSD_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -853,6 +846,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = { BSD_JoystickInit, BSD_JoystickGetCount, BSD_JoystickDetect, + BSD_JoystickIsDevicePresent, BSD_JoystickGetDeviceName, BSD_JoystickGetDevicePath, BSD_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -863,7 +857,6 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = { BSD_JoystickOpen, BSD_JoystickRumble, BSD_JoystickRumbleTriggers, - BSD_JoystickGetCapabilities, BSD_JoystickSetLED, BSD_JoystickSendEffect, BSD_JoystickSetSensorsEnabled, diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 036fdd41..6ff8fef5 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -490,12 +490,9 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) SDL_free(name); } -#ifdef SDL_JOYSTICK_HIDAPI - if (HIDAPI_IsDevicePresent(vendor, product, version, pDevice->product)) { - /* The HIDAPI driver is taking care of this device */ + if (SDL_JoystickHandledByAnotherDriver(&SDL_DARWIN_JoystickDriver, vendor, product, version, pDevice->product)) { return SDL_FALSE; } -#endif pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0); pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string); @@ -564,7 +561,7 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender /* Allocate an instance ID for this device */ device->instance_id = SDL_GetNextObjectID(); - /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ + /* We have to do some storage of the io_service_t for SDL_OpenHapticFromJoystick */ ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) { device->ffservice = ioservice; @@ -714,13 +711,19 @@ static void DARWIN_JoystickDetect(void) } } -const char *DARWIN_JoystickGetDeviceName(int device_index) +static SDL_bool DARWIN_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + +static const char *DARWIN_JoystickGetDeviceName(int device_index) { recDevice *device = GetDeviceForIndex(device_index); return device ? device->product : "UNKNOWN"; } -const char *DARWIN_JoystickGetDevicePath(int device_index) +static const char *DARWIN_JoystickGetDevicePath(int device_index) { return NULL; } @@ -762,7 +765,6 @@ static int DARWIN_JoystickOpen(SDL_Joystick *joystick, int device_index) { recDevice *device = GetDeviceForIndex(device_index); - joystick->instance_id = device->instance_id; joystick->hwdata = device; device->joystick = joystick; joystick->name = device->product; @@ -770,6 +772,11 @@ static int DARWIN_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->naxes = device->axes; joystick->nhats = device->hats; joystick->nbuttons = device->buttons; + + if (device->ffservice) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } + return 0; } @@ -908,22 +915,6 @@ static int DARWIN_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rum return SDL_Unsupported(); } -static Uint32 DARWIN_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - recDevice *device = joystick->hwdata; - Uint32 result = 0; - - if (!device) { - return 0; - } - - if (device->ffservice) { - result |= SDL_JOYCAP_RUMBLE; - } - - return result; -} - static int DARWIN_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -1074,6 +1065,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = { DARWIN_JoystickInit, DARWIN_JoystickGetCount, DARWIN_JoystickDetect, + DARWIN_JoystickIsDevicePresent, DARWIN_JoystickGetDeviceName, DARWIN_JoystickGetDevicePath, DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -1084,7 +1076,6 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = { DARWIN_JoystickOpen, DARWIN_JoystickRumble, DARWIN_JoystickRumbleTriggers, - DARWIN_JoystickGetCapabilities, DARWIN_JoystickSetLED, DARWIN_JoystickSendEffect, DARWIN_JoystickSetSensorsEnabled, diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index 125e3c03..93387575 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -41,6 +41,11 @@ static void DUMMY_JoystickDetect(void) { } +static SDL_bool DUMMY_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + return SDL_FALSE; +} + static const char *DUMMY_JoystickGetDeviceName(int device_index) { return NULL; @@ -92,11 +97,6 @@ static int DUMMY_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumb return SDL_Unsupported(); } -static Uint32 DUMMY_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - static int DUMMY_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -133,6 +133,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = { DUMMY_JoystickInit, DUMMY_JoystickGetCount, DUMMY_JoystickDetect, + DUMMY_JoystickIsDevicePresent, DUMMY_JoystickGetDeviceName, DUMMY_JoystickGetDevicePath, DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -143,7 +144,6 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = { DUMMY_JoystickOpen, DUMMY_JoystickRumble, DUMMY_JoystickRumbleTriggers, - DUMMY_JoystickGetCapabilities, DUMMY_JoystickSetLED, DUMMY_JoystickSendEffect, DUMMY_JoystickSetSensorsEnabled, diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 3a6cd9d0..ffbefa4b 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -259,6 +259,12 @@ static void EMSCRIPTEN_JoystickDetect(void) { } +static SDL_bool EMSCRIPTEN_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + static const char *EMSCRIPTEN_JoystickGetDeviceName(int device_index) { return JoystickByDeviceIndex(device_index)->name; @@ -305,7 +311,6 @@ static int EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index) return SDL_SetError("Joystick already opened"); } - joystick->instance_id = item->device_instance; joystick->hwdata = (struct joystick_hwdata *)item; item->joystick = joystick; @@ -395,11 +400,6 @@ static SDL_bool EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_Gamep return SDL_FALSE; } -static Uint32 EMSCRIPTEN_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - static int EMSCRIPTEN_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -419,6 +419,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = { EMSCRIPTEN_JoystickInit, EMSCRIPTEN_JoystickGetCount, EMSCRIPTEN_JoystickDetect, + EMSCRIPTEN_JoystickIsDevicePresent, EMSCRIPTEN_JoystickGetDeviceName, EMSCRIPTEN_JoystickGetDevicePath, EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -429,7 +430,6 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = { EMSCRIPTEN_JoystickOpen, EMSCRIPTEN_JoystickRumble, EMSCRIPTEN_JoystickRumbleTriggers, - EMSCRIPTEN_JoystickGetCapabilities, EMSCRIPTEN_JoystickSetLED, EMSCRIPTEN_JoystickSendEffect, EMSCRIPTEN_JoystickSetSensorsEnabled, diff --git a/src/joystick/gdk/SDL_gameinputjoystick.c b/src/joystick/gdk/SDL_gameinputjoystick.c new file mode 100644 index 00000000..c3ee5a2e --- /dev/null +++ b/src/joystick/gdk/SDL_gameinputjoystick.c @@ -0,0 +1,723 @@ +/* + 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_JOYSTICK_GAMEINPUT + +#include "../SDL_sysjoystick.h" +#include "../usb_ids.h" + +#include +#define COBJMACROS +#include + + +typedef struct GAMEINPUT_InternalDevice +{ + IGameInputDevice *device; + char path[(APP_LOCAL_DEVICE_ID_SIZE * 2) + 1]; + char *name; + SDL_JoystickGUID guid; /* generated by SDL */ + SDL_JoystickID device_instance; /* generated by SDL */ + const GameInputDeviceInfo *info; + SDL_bool isAdded; + SDL_bool isDeleteRequested; +} GAMEINPUT_InternalDevice; + +typedef struct GAMEINPUT_InternalList +{ + GAMEINPUT_InternalDevice **devices; + int count; +} GAMEINPUT_InternalList; + +typedef struct joystick_hwdata +{ + GAMEINPUT_InternalDevice *devref; + SDL_bool report_sensors; + GameInputRumbleParams rumbleParams; + GameInputCallbackToken guide_button_callback_token; +} GAMEINPUT_InternalJoystickHwdata; + + +static GAMEINPUT_InternalList g_GameInputList = { NULL }; +static void *g_hGameInputDLL = NULL; +static IGameInput *g_pGameInput = NULL; +static GameInputCallbackToken g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE; + + +static SDL_bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info) +{ + if (info->supportedInput & GameInputKindGamepad) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) +{ + GAMEINPUT_InternalDevice **devicelist = NULL; + GAMEINPUT_InternalDevice *elem = NULL; + const GameInputDeviceInfo *info = NULL; + Uint16 bus = SDL_HARDWARE_BUS_USB; + Uint16 vendor = 0; + Uint16 product = 0; + Uint16 version = 0; + const char *manufacturer_string = NULL; + const char *product_string = NULL; + char tmp[4]; + int idx = 0; + + info = IGameInputDevice_GetDeviceInfo(pDevice); + if (info->capabilities & GameInputDeviceCapabilityWireless) { + bus = SDL_HARDWARE_BUS_BLUETOOTH; + } else { + bus = SDL_HARDWARE_BUS_USB; + } + vendor = info->vendorId; + product = info->productId; + version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor; + + if (SDL_JoystickHandledByAnotherDriver(&SDL_GAMEINPUT_JoystickDriver, vendor, product, version, "")) { + return 0; + } + + for (idx = 0; idx < g_GameInputList.count; ++idx) { + elem = g_GameInputList.devices[idx]; + if (elem && elem->device == pDevice) { + /* we're already added */ + return 0; + } + } + + elem = (GAMEINPUT_InternalDevice *)SDL_calloc(1, sizeof(*elem)); + if (!elem) { + return SDL_OutOfMemory(); + } + + devicelist = (GAMEINPUT_InternalDevice **)SDL_realloc(g_GameInputList.devices, sizeof(elem) * (g_GameInputList.count + 1LL)); + if (!devicelist) { + SDL_free(elem); + return SDL_OutOfMemory(); + } + + /* Generate a device path */ + for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) { + SDL_snprintf(tmp, SDL_arraysize(tmp), "%02hhX", info->deviceId.value[idx]); + SDL_strlcat(elem->path, tmp, SDL_arraysize(tmp)); + } + + if (info->deviceStrings) { + /* In theory we could get the manufacturer and product strings here, but they're NULL for all the controllers I've tested */ + } + + if (info->displayName) { + /* This could give us a product string, but it's NULL for all the controllers I've tested */ + } + + IGameInputDevice_AddRef(pDevice); + elem->device = pDevice; + elem->name = SDL_CreateJoystickName(vendor, product, manufacturer_string, product_string); + elem->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, manufacturer_string, product_string, 'g', 0); + elem->device_instance = SDL_GetNextObjectID(); + elem->info = info; + + g_GameInputList.devices = devicelist; + g_GameInputList.devices[g_GameInputList.count++] = elem; + + return 0; +} + +static int GAMEINPUT_InternalRemoveByIndex(int idx) +{ + GAMEINPUT_InternalDevice **devicelist = NULL; + GAMEINPUT_InternalDevice *elem; + int bytes = 0; + + if (idx < 0 || idx >= g_GameInputList.count) { + return SDL_SetError("GAMEINPUT_InternalRemoveByIndex argument idx %d is out of range", idx); + } + + elem = g_GameInputList.devices[idx]; + if (elem) { + IGameInputDevice_Release(elem->device); + SDL_free(elem->name); + SDL_free(elem); + } + g_GameInputList.devices[idx] = NULL; + + if (g_GameInputList.count == 1) { + /* last element in the list, free the entire list then */ + SDL_free(g_GameInputList.devices); + g_GameInputList.devices = NULL; + } else { + if (idx != g_GameInputList.count - 1) { + bytes = sizeof(*devicelist) * (g_GameInputList.count - idx); + SDL_memmove(&g_GameInputList.devices[idx], &g_GameInputList.devices[idx + 1], bytes); + } + } + + /* decrement the count and return */ + return g_GameInputList.count--; +} + +static GAMEINPUT_InternalDevice *GAMEINPUT_InternalFindByIndex(int idx) +{ + /* We're guaranteed that the index is in range when this is called */ + return g_GameInputList.devices[idx]; +} + +static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback( + _In_ GameInputCallbackToken callbackToken, + _In_ void* context, + _In_ IGameInputDevice* device, + _In_ uint64_t timestamp, + _In_ GameInputDeviceStatus currentStatus, + _In_ GameInputDeviceStatus previousStatus) +{ + int idx = 0; + GAMEINPUT_InternalDevice *elem = NULL; + + if (!device) { + /* This should never happen, but ignore it if it does */ + return; + } + + if (currentStatus & GameInputDeviceConnected) { + GAMEINPUT_InternalAddOrFind(device); + } else { + for (idx = 0; idx < g_GameInputList.count; ++idx) { + elem = g_GameInputList.devices[idx]; + if (elem && elem->device == device) { + /* will be deleted on the next Detect call */ + elem->isDeleteRequested = SDL_TRUE; + break; + } + } + } +} + +static void GAMEINPUT_JoystickDetect(void); + +static int GAMEINPUT_JoystickInit(void) +{ + HRESULT hR; + + if (!g_hGameInputDLL) { + g_hGameInputDLL = SDL_LoadObject("gameinput.dll"); + if (!g_hGameInputDLL) { + return -1; + } + } + + if (!g_pGameInput) { + typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput); + GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate"); + if (!GameInputCreateFunc) { + return -1; + } + + hR = GameInputCreateFunc(&g_pGameInput); + if (FAILED(hR)) { + return SDL_SetError("GameInputCreate failure with HRESULT of %08X", hR); + } + } + + hR = IGameInput_RegisterDeviceCallback(g_pGameInput, + NULL, + GameInputKindController, + GameInputDeviceConnected, + GameInputBlockingEnumeration, + NULL, + GAMEINPUT_InternalJoystickDeviceCallback, + &g_GameInputCallbackToken); + if (FAILED(hR)) { + return SDL_SetError("IGameInput::RegisterDeviceCallback failure with HRESULT of %08X", hR); + } + + GAMEINPUT_JoystickDetect(); + + return 0; +} + +static int GAMEINPUT_JoystickGetCount(void) +{ + return g_GameInputList.count; +} + +static void GAMEINPUT_JoystickDetect(void) +{ + int idx = 0; + GAMEINPUT_InternalDevice *elem = NULL; + + for (idx = 0; idx < g_GameInputList.count; ++idx) { + elem = g_GameInputList.devices[idx]; + if (!elem) { + continue; + } + + if (!elem->isAdded) { + SDL_PrivateJoystickAdded(elem->device_instance); + elem->isAdded = SDL_TRUE; + } + + if (elem->isDeleteRequested || !(IGameInputDevice_GetDeviceStatus(elem->device) & GameInputDeviceConnected)) { + SDL_PrivateJoystickRemoved(elem->device_instance); + GAMEINPUT_InternalRemoveByIndex(idx--); + } + } +} + +static SDL_bool GAMEINPUT_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + int idx = 0; + GAMEINPUT_InternalDevice *elem = NULL; + + if (vendor_id == USB_VENDOR_MICROSOFT && + product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) { + /* The Xbox One controller shows up as a hardcoded raw input VID/PID, which we definitely handle */ + return SDL_TRUE; + } + + for (idx = 0; idx < g_GameInputList.count; ++idx) { + elem = g_GameInputList.devices[idx]; + if (elem && vendor_id == elem->info->vendorId && product_id == elem->info->productId) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static const char *GAMEINPUT_JoystickGetDeviceName(int device_index) +{ + return GAMEINPUT_InternalFindByIndex(device_index)->name; +} + +static const char *GAMEINPUT_JoystickGetDevicePath(int device_index) +{ + /* APP_LOCAL_DEVICE_ID as a hex string, since it's required for some association callbacks */ + return GAMEINPUT_InternalFindByIndex(device_index)->path; +} + +static int GAMEINPUT_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) +{ + /* Steamworks API is not available in GDK */ + return -1; +} + +static int GAMEINPUT_JoystickGetDevicePlayerIndex(int device_index) +{ + return -1; +} + +static void GAMEINPUT_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + +static SDL_JoystickGUID GAMEINPUT_JoystickGetDeviceGUID(int device_index) +{ + return GAMEINPUT_InternalFindByIndex(device_index)->guid; +} + +static SDL_JoystickID GAMEINPUT_JoystickGetDeviceInstanceID(int device_index) +{ + return GAMEINPUT_InternalFindByIndex(device_index)->device_instance; +} + +static SDL_JoystickPowerLevel GAMEINPUT_InternalGetPowerLevel(IGameInputDevice *device) +{ + GameInputBatteryState battery_state; + + SDL_zero(battery_state); + IGameInputDevice_GetBatteryState(device, &battery_state); + + if (battery_state.status == GameInputBatteryDischarging) { + /* FIXME: What are the units for remainingCapacity? */ + } + return SDL_JOYSTICK_POWER_UNKNOWN; +} + +#if 0 +static void CALLBACK GAMEINPUT_InternalGuideButtonCallback(GameInputCallbackToken callbackToken, void *context, IGameInputDevice *device, uint64_t timestamp, bool isPressed) +{ + SDL_Joystick *joystick = (SDL_Joystick *)context; + + SDL_LockJoysticks(); + SDL_SendJoystickButton(0, joystick, SDL_GAMEPAD_BUTTON_GUIDE, isPressed ? SDL_PRESSED : SDL_RELEASED); + SDL_UnlockJoysticks(); +} +#endif + +static int GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) +{ + GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index); + const GameInputDeviceInfo *info = elem->info; + GAMEINPUT_InternalJoystickHwdata *hwdata = NULL; + + if (!elem) { + return -1; + } + + hwdata = (GAMEINPUT_InternalJoystickHwdata *)SDL_calloc(1, sizeof(*hwdata)); + if (!hwdata) { + return SDL_OutOfMemory(); + } + + hwdata->devref = elem; + + joystick->hwdata = hwdata; + if (GAMEINPUT_InternalIsGamepad(info)) { + joystick->naxes = 6; + joystick->nbuttons = 11; + joystick->nhats = 1; + } else { + joystick->naxes = info->controllerAxisCount; + joystick->nbuttons = info->controllerButtonCount; + joystick->nhats = info->controllerSwitchCount; + } + + if (GAMEINPUT_InternalIsGamepad(info)) { +#if 0 /* The actual signature for this function is GameInputClient::RegisterSystemButtonCallback(struct IGameInputDevice *,enum GameInputSystemButtons,void *,void (*)(unsigned __int64,void *,struct IGameInputDevice *,unsigned __int64,enum GameInputSystemButtons,enum GameInputSystemButtons),unsigned __int64 *) */ + IGameInput_RegisterGuideButtonCallback(g_pGameInput, elem->device, joystick, GAMEINPUT_InternalGuideButtonCallback, &hwdata->guide_button_callback_token); +#endif + } + + if (info->supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } + if (info->supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE); + } + + if (info->supportedInput & GameInputKindTouch) { + SDL_PrivateJoystickAddTouchpad(joystick, info->touchPointCount); + } + + if (info->supportedInput & GameInputKindMotion) { + /* FIXME: What's the sensor update rate? */ + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 250.0f); + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 250.0f); + } + + if (info->capabilities & GameInputDeviceCapabilityWireless) { + joystick->epowerlevel = GAMEINPUT_InternalGetPowerLevel(elem->device); + } else { + joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; + } + return 0; +} + +static int GAMEINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) +{ + /* don't check for caps here, since SetRumbleState doesn't return any result - we don't need to check it */ + GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; + GameInputRumbleParams *params = &hwdata->rumbleParams; + params->lowFrequency = (float)low_frequency_rumble / (float)SDL_MAX_UINT16; + params->highFrequency = (float)high_frequency_rumble / (float)SDL_MAX_UINT16; + IGameInputDevice_SetRumbleState(hwdata->devref->device, params); + return 0; +} + +static int GAMEINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) +{ + /* don't check for caps here, since SetRumbleState doesn't return any result - we don't need to check it */ + GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; + GameInputRumbleParams *params = &hwdata->rumbleParams; + params->leftTrigger = (float)left_rumble / (float)SDL_MAX_UINT16; + params->rightTrigger = (float)right_rumble / (float)SDL_MAX_UINT16; + IGameInputDevice_SetRumbleState(hwdata->devref->device, params); + return 0; +} + +static int GAMEINPUT_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) +{ + return SDL_Unsupported(); +} + +static int GAMEINPUT_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) +{ + return SDL_Unsupported(); +} + +static int GAMEINPUT_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) +{ + joystick->hwdata->report_sensors = enabled; + return 0; +} + +static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) +{ + GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; + IGameInputDevice *device = hwdata->devref->device; + const GameInputDeviceInfo *info = hwdata->devref->info; + IGameInputReading *reading = NULL; + Uint64 timestamp = SDL_GetTicksNS(); + GameInputGamepadState state; + HRESULT hR; + + hR = IGameInput_GetCurrentReading(g_pGameInput, info->supportedInput, device, &reading); + if (FAILED(hR)) { + /* don't SetError here since there can be a legitimate case when there's no reading avail */ + return; + } + + /* FIXME: See if we can get the delta between the reading timestamp and current time and apply the offset to timestamp */ + + if (GAMEINPUT_InternalIsGamepad(info)) { + static WORD s_XInputButtons[] = { + GameInputGamepadA, /* SDL_GAMEPAD_BUTTON_SOUTH */ + GameInputGamepadB, /* SDL_GAMEPAD_BUTTON_EAST */ + GameInputGamepadX, /* SDL_GAMEPAD_BUTTON_WEST */ + GameInputGamepadY, /* SDL_GAMEPAD_BUTTON_NORTH */ + GameInputGamepadView, /* SDL_GAMEPAD_BUTTON_BACK */ + 0, /* The guide button is not available */ + GameInputGamepadMenu, /* SDL_GAMEPAD_BUTTON_START */ + GameInputGamepadLeftThumbstick, /* SDL_GAMEPAD_BUTTON_LEFT_STICK */ + GameInputGamepadRightThumbstick, /* SDL_GAMEPAD_BUTTON_RIGHT_STICK */ + GameInputGamepadLeftShoulder, /* SDL_GAMEPAD_BUTTON_LEFT_SHOULDER */ + GameInputGamepadRightShoulder, /* SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER */ + }; + Uint8 btnidx = 0, btnstate = 0, hat = 0; + + if (IGameInputReading_GetGamepadState(reading, &state)) { + for (btnidx = 0; btnidx < SDL_arraysize(s_XInputButtons); ++btnidx) { + WORD button_mask = s_XInputButtons[btnidx]; + if (!button_mask) { + continue; + } + btnstate = (state.buttons & button_mask) ? SDL_PRESSED : SDL_RELEASED; + SDL_SendJoystickButton(timestamp, joystick, btnidx, btnstate); + } + + if (state.buttons & GameInputGamepadDPadUp) { + hat |= SDL_HAT_UP; + } + if (state.buttons & GameInputGamepadDPadDown) { + hat |= SDL_HAT_DOWN; + } + if (state.buttons & GameInputGamepadDPadLeft) { + hat |= SDL_HAT_LEFT; + } + if (state.buttons & GameInputGamepadDPadRight) { + hat |= SDL_HAT_RIGHT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + +#define CONVERT_AXIS(v) (Sint16)(((v) < 0.0f) ? ((v)*32768.0f) : ((v)*32767.0f)) + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, CONVERT_AXIS(state.leftThumbstickX)); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, CONVERT_AXIS(-state.leftThumbstickY)); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, CONVERT_AXIS(state.rightThumbstickX)); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, CONVERT_AXIS(-state.rightThumbstickY)); +#undef CONVERT_AXIS +#define CONVERT_TRIGGER(v) (Sint16)((v)*65535.0f - 32768.0f) + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, CONVERT_TRIGGER(state.leftTrigger)); + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, CONVERT_TRIGGER(state.rightTrigger)); +#undef CONVERT_TRIGGER + } + } else { + bool *button_state = SDL_stack_alloc(bool, info->controllerButtonCount); + float *axis_state = SDL_stack_alloc(float, info->controllerAxisCount); + + if (button_state) { + uint32_t i; + uint32_t button_count = IGameInputReading_GetControllerButtonState(reading, info->controllerButtonCount, button_state); + for (i = 0; i < button_count; ++i) { + SDL_SendJoystickButton(timestamp, joystick, i, button_state[i]); + } + SDL_stack_free(button_state); + } + +#define CONVERT_AXIS(v) (Sint16)((v)*65535.0f - 32768.0f) + if (axis_state) { + uint32_t i; + uint32_t axis_count = IGameInputReading_GetControllerAxisState(reading, info->controllerAxisCount, axis_state); + for (i = 0; i < axis_count; ++i) { + SDL_SendJoystickAxis(timestamp, joystick, i, CONVERT_AXIS(axis_state[i])); + } + SDL_stack_free(axis_state); + } +#undef CONVERT_AXIS + } + + if (info->supportedInput & GameInputKindTouch) { + GameInputTouchState *touch_state = SDL_stack_alloc(GameInputTouchState, info->touchPointCount); + if (touch_state) { + uint32_t i; + uint32_t touch_count = IGameInputReading_GetTouchState(reading, info->touchPointCount, touch_state); + for (i = 0; i < touch_count; ++i) { + GameInputTouchState *touch = &touch_state[i]; + /* FIXME: We should use touch->touchId to track fingers instead of using i below */ + SDL_SendJoystickTouchpad(timestamp, joystick, 0, i, SDL_PRESSED, touch->positionX * info->touchSensorInfo[i].resolutionX, touch->positionY * info->touchSensorInfo[0].resolutionY, touch->pressure); + } + SDL_stack_free(touch_state); + } + } + + if (hwdata->report_sensors) { + GameInputMotionState motion_state; + + if (IGameInputReading_GetMotionState(reading, &motion_state)) { + /* FIXME: How do we interpret the motion data? */ + } + } + + IGameInputReading_Release(reading); + + if (joystick->epowerlevel != SDL_JOYSTICK_POWER_WIRED) { + /* FIXME: We can poll this at a much lower rate */ + SDL_SendJoystickBatteryLevel(joystick, GAMEINPUT_InternalGetPowerLevel(device)); + } +} + +static void GAMEINPUT_JoystickClose(SDL_Joystick* joystick) +{ + GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; + + if (hwdata->guide_button_callback_token) { + IGameInput_UnregisterCallback(g_pGameInput, hwdata->guide_button_callback_token, 5000); + } + SDL_free(hwdata); + + joystick->hwdata = NULL; +} + +static void GAMEINPUT_JoystickQuit(void) +{ + if (g_pGameInput) { + /* free the callback */ + IGameInput_UnregisterCallback(g_pGameInput, g_GameInputCallbackToken, /*timeoutInUs:*/ 10000); + g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE; + + /* free the list */ + while (g_GameInputList.count > 0) { + GAMEINPUT_InternalRemoveByIndex(0); + } + + IGameInput_Release(g_pGameInput); + g_pGameInput = NULL; + } + + if (g_hGameInputDLL) { + SDL_UnloadObject(g_hGameInputDLL); + g_hGameInputDLL = NULL; + } +} + +static SDL_bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) +{ + GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index); + + if (!GAMEINPUT_InternalIsGamepad(elem->info)) { + return SDL_FALSE; + } + + out->a.kind = EMappingKind_Button; + out->a.target = SDL_GAMEPAD_BUTTON_SOUTH; + + out->b.kind = EMappingKind_Button; + out->b.target = SDL_GAMEPAD_BUTTON_EAST; + + out->x.kind = EMappingKind_Button; + out->x.target = SDL_GAMEPAD_BUTTON_WEST; + + out->y.kind = EMappingKind_Button; + out->y.target = SDL_GAMEPAD_BUTTON_NORTH; + + out->back.kind = EMappingKind_Button; + out->back.target = SDL_GAMEPAD_BUTTON_BACK; + + /* The guide button isn't available, so don't map it */ + + out->start.kind = EMappingKind_Button; + out->start.target = SDL_GAMEPAD_BUTTON_START; + + out->leftstick.kind = EMappingKind_Button; + out->leftstick.target = SDL_GAMEPAD_BUTTON_LEFT_STICK; + + out->rightstick.kind = EMappingKind_Button; + out->rightstick.target = SDL_GAMEPAD_BUTTON_RIGHT_STICK; + + out->leftshoulder.kind = EMappingKind_Button; + out->leftshoulder.target = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER; + + out->rightshoulder.kind = EMappingKind_Button; + out->rightshoulder.target = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER; + + out->dpup.kind = EMappingKind_Hat; + out->dpup.target = SDL_HAT_UP; + + out->dpdown.kind = EMappingKind_Hat; + out->dpdown.target = SDL_HAT_DOWN; + + out->dpleft.kind = EMappingKind_Hat; + out->dpleft.target = SDL_HAT_LEFT; + + out->dpright.kind = EMappingKind_Hat; + out->dpright.target = SDL_HAT_RIGHT; + + out->leftx.kind = EMappingKind_Axis; + out->leftx.target = SDL_GAMEPAD_AXIS_LEFTX; + + out->lefty.kind = EMappingKind_Axis; + out->lefty.target = SDL_GAMEPAD_AXIS_LEFTY; + + out->rightx.kind = EMappingKind_Axis; + out->rightx.target = SDL_GAMEPAD_AXIS_RIGHTX; + + out->righty.kind = EMappingKind_Axis; + out->righty.target = SDL_GAMEPAD_AXIS_RIGHTY; + + out->lefttrigger.kind = EMappingKind_Axis; + out->lefttrigger.target = SDL_GAMEPAD_AXIS_LEFT_TRIGGER; + + out->righttrigger.kind = EMappingKind_Axis; + out->righttrigger.target = SDL_GAMEPAD_AXIS_RIGHT_TRIGGER; + + return SDL_TRUE; +} + + +SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver = +{ + GAMEINPUT_JoystickInit, + GAMEINPUT_JoystickGetCount, + GAMEINPUT_JoystickDetect, + GAMEINPUT_JoystickIsDevicePresent, + GAMEINPUT_JoystickGetDeviceName, + GAMEINPUT_JoystickGetDevicePath, + GAMEINPUT_JoystickGetDeviceSteamVirtualGamepadSlot, + GAMEINPUT_JoystickGetDevicePlayerIndex, + GAMEINPUT_JoystickSetDevicePlayerIndex, + GAMEINPUT_JoystickGetDeviceGUID, + GAMEINPUT_JoystickGetDeviceInstanceID, + GAMEINPUT_JoystickOpen, + GAMEINPUT_JoystickRumble, + GAMEINPUT_JoystickRumbleTriggers, + GAMEINPUT_JoystickSetLED, + GAMEINPUT_JoystickSendEffect, + GAMEINPUT_JoystickSetSensorsEnabled, + GAMEINPUT_JoystickUpdate, + GAMEINPUT_JoystickClose, + GAMEINPUT_JoystickQuit, + GAMEINPUT_JoystickGetGamepadMapping +}; + + +#endif /* SDL_JOYSTICK_GAMEINPUT */ diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 9110b0ad..4191acff 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -70,12 +70,14 @@ extern "C" for (i = 0; (numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i) { if (joystick.GetDeviceName(i, name) == B_OK) { if (joystick.Open(name) != B_ERROR) { - BString stick_name; - joystick.GetControllerName(&stick_name); - SDL_joyport[numjoysticks] = SDL_strdup(name); - SDL_joyname[numjoysticks] = SDL_CreateJoystickName(0, 0, NULL, stick_name.String()); - numjoysticks++; - joystick.Close(); + BString stick_name; + joystick.GetControllerName(&stick_name); + SDL_joyport[numjoysticks] = SDL_strdup(name); + SDL_joyname[numjoysticks] = SDL_CreateJoystickName(0, 0, NULL, stick_name.String()); + numjoysticks++; + joystick.Close(); + + SDL_PrivateJoystickAdded(numjoysticks); } } } @@ -91,6 +93,12 @@ extern "C" { } + static SDL_bool HAIKU_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) + { + /* We don't override any other drivers */ + return SDL_FALSE; + } + static const char *HAIKU_JoystickGetDeviceName(int device_index) { return SDL_joyname[device_index]; @@ -133,7 +141,6 @@ extern "C" BJoystick *stick; /* Create the joystick data structure */ - joystick->instance_id = device_index; joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata)); if (joystick->hwdata == NULL) { return -1; @@ -272,11 +279,6 @@ extern "C" return SDL_FALSE; } - static Uint32 HAIKU_JoystickGetCapabilities(SDL_Joystick *joystick) - { - return 0; - } - static int HAIKU_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -298,6 +300,7 @@ extern "C" HAIKU_JoystickInit, HAIKU_JoystickGetCount, HAIKU_JoystickDetect, + HAIKU_JoystickIsDevicePresent, HAIKU_JoystickGetDeviceName, HAIKU_JoystickGetDevicePath, HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -308,7 +311,6 @@ extern "C" HAIKU_JoystickOpen, HAIKU_JoystickRumble, HAIKU_JoystickRumbleTriggers, - HAIKU_JoystickGetCapabilities, HAIKU_JoystickSetLED, HAIKU_JoystickSendEffect, HAIKU_JoystickSetSensorsEnabled, diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index ee90fdf5..cffe6d65 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -179,7 +179,7 @@ static SDL_bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) } } - SDL_AddHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE, SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx); HIDAPI_SetDeviceName(device, "Nintendo GameCube Controller"); @@ -459,7 +459,7 @@ static Uint32 HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *d for (i = 0; i < MAX_CONTROLLERS; i += 1) { if (joystick->instance_id == ctx->joysticks[i]) { if (!ctx->wireless[i] && ctx->rumbleAllowed[i]) { - result |= SDL_JOYCAP_RUMBLE; + result |= SDL_JOYSTICK_CAP_RUMBLE; break; } } @@ -499,7 +499,7 @@ static void HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device) { SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context; - SDL_DelHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE, SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx); } diff --git a/src/joystick/hidapi/SDL_hidapi_luna.c b/src/joystick/hidapi/SDL_hidapi_luna.c index ed408a2f..dfc821da 100644 --- a/src/joystick/hidapi/SDL_hidapi_luna.c +++ b/src/joystick/hidapi/SDL_hidapi_luna.c @@ -32,7 +32,7 @@ /*#define DEBUG_LUNA_PROTOCOL*/ /* Sending rumble on macOS blocks for a long time and eventually fails */ -#ifndef __MACOS__ +#ifndef SDL_PLATFORM_MACOS #define ENABLE_LUNA_BLUETOOTH_RUMBLE #endif @@ -142,7 +142,7 @@ static Uint32 HIDAPI_DriverLuna_GetJoystickCapabilities(SDL_HIDAPI_Device *devic #ifdef ENABLE_LUNA_BLUETOOTH_RUMBLE if (device->product_id == BLUETOOTH_PRODUCT_LUNA_CONTROLLER) { - result |= SDL_JOYCAP_RUMBLE; + result |= SDL_JOYSTICK_CAP_RUMBLE; } #endif diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index 8992f0d8..217b81f3 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -40,6 +40,41 @@ typedef enum k_EPS3ReportIdEffects = 1, } EPS3ReportId; +typedef enum +{ + k_EPS3SonySixaxisReportIdState = 0, + k_EPS3SonySixaxisReportIdEffects = 0, +} EPS3SonySixaxisReportId; + +/* Commands for Sony's sixaxis.sys Windows driver */ +/* All commands must be sent using 49-byte buffer containing output report */ +/* Byte 0 indicates reportId and must always be 0 */ +/* Byte 1 indicates a command, supported values are specified below: */ +typedef enum +{ + /* This command allows to set user LEDs. */ + /* Bytes 5,6.7.8 contain mode for corresponding LED: 0 - LED is off, 1 - LED in on, 2 - LED is flashing. */ + /* Bytes 9-16 specify 64-bit LED flash period in 100 ns units if some LED is flashing, otherwise not used. */ + k_EPS3SixaxisCommandSetLEDs = 1, + + /* This command allows to set left and right motors. */ + /* Byte 5 is right motor duration (0-255) and byte 6, if not zero, activates right motor. Zero value disables right motor. */ + /* Byte 7 is left motor duration (0-255) and byte 8 is left motor amplitude (0-255). */ + k_EPS3SixaxisCommandSetMotors = 2, + + /* This command allows to block/unblock setting device LEDs by applications. */ + /* Byte 5 is used as parameter - any non-zero value blocks LEDs, zero value will unblock LEDs. */ + k_EPS3SixaxisCommandBlockLEDs = 3, + + /* This command refreshes driver settings. No parameters used. */ + /* When sixaxis driver loads it reads 'CurrentDriverSetting' binary value from 'HKLM\System\CurrentControlSet\Services\sixaxis\Parameters' registry key. */ + /* If the key is not present then default values are used. Sending this command forces sixaxis driver to re-read the registry and update driver settings. */ + k_EPS3SixaxisCommandRefreshDriverSetting = 9, + + /* This command clears current bluetooth pairing. No parameters used. */ + k_EPS3SixaxisCommandClearPairing = 10 +} EPS3SixaxisDriverCommands; + typedef struct { SDL_HIDAPI_Device *device; @@ -69,15 +104,16 @@ static SDL_bool HIDAPI_DriverPS3_IsEnabled(void) { SDL_bool default_value; -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS /* This works well on macOS */ default_value = SDL_TRUE; -#elif defined(__WINDOWS__) - /* You can't initialize the controller with the stock Windows drivers +#elif defined(SDL_PLATFORM_WIN32) + /* For official Sony driver (sixaxis.sys) use SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER. + * * See https://github.com/ViGEm/DsHidMini as an alternative driver */ default_value = SDL_FALSE; -#elif defined(__LINUX__) +#elif defined(SDL_PLATFORM_LINUX) /* Linux drivers do a better job of managing the transition between * USB and Bluetooth. There are also some quirks in communicating * with PS3 controllers that have been implemented in SDL's hidapi @@ -267,7 +303,7 @@ static int HIDAPI_DriverPS3_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SD static Uint32 HIDAPI_DriverPS3_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return SDL_JOYCAP_RUMBLE; + return SDL_JOYSTICK_CAP_RUMBLE; } static int HIDAPI_DriverPS3_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) @@ -984,6 +1020,395 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3ThirdParty = { HIDAPI_DriverPS3ThirdParty_FreeDevice, }; +static int HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(SDL_HIDAPI_Device *device); +static int HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(SDL_HIDAPI_Device *device); + +static void HIDAPI_DriverPS3SonySixaxis_RegisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, callback, userdata); +} + +static void HIDAPI_DriverPS3SonySixaxis_UnregisterHints(SDL_HintCallback callback, void *userdata) +{ + SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, callback, userdata); +} + +static SDL_bool HIDAPI_DriverPS3SonySixaxis_IsEnabled(void) +{ +#ifdef SDL_PLATFORM_WIN32 + return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, SDL_FALSE); +#else + return SDL_FALSE; +#endif +} + +static SDL_bool HIDAPI_DriverPS3SonySixaxis_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) +{ + if (vendor_id == USB_VENDOR_SONY && product_id == USB_PRODUCT_SONY_DS3) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +static SDL_bool HIDAPI_DriverPS3SonySixaxis_InitDevice(SDL_HIDAPI_Device *device) +{ + SDL_DriverPS3_Context *ctx; + + ctx = (SDL_DriverPS3_Context *)SDL_calloc(1, sizeof(*ctx)); + if (!ctx) { + return SDL_FALSE; + } + ctx->device = device; + + device->context = ctx; + + Uint8 data[USB_PACKET_LENGTH]; + + int size = ReadFeatureReport(device->dev, 0xf2, data, sizeof(data)); + if (size < 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverPS3SonySixaxis_InitDevice(): Couldn't read feature report 0xf2. Trying again with 0x0."); + SDL_zeroa(data); + size = ReadFeatureReport(device->dev, 0x00, data, sizeof(data)); + if (size < 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverPS3SonySixaxis_InitDevice(): Couldn't read feature report 0x00."); + return SDL_FALSE; + } +#ifdef DEBUG_PS3_PROTOCOL + HIDAPI_DumpPacket("PS3 0x0 packet: size = %d", data, size); +#endif + } +#ifdef DEBUG_PS3_PROTOCOL + HIDAPI_DumpPacket("PS3 0xF2 packet: size = %d", data, size); +#endif + + device->type = SDL_GAMEPAD_TYPE_PS3; + HIDAPI_SetDeviceName(device, "PS3 Controller"); + + return HIDAPI_JoystickConnected(device, NULL); +} + +static int HIDAPI_DriverPS3SonySixaxis_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void HIDAPI_DriverPS3SonySixaxis_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + if (!ctx) { + return; + } + + ctx->player_index = player_index; + + /* This will set the new LED state based on the new player index */ + HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(device); +} + +static SDL_bool HIDAPI_DriverPS3SonySixaxis_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + SDL_AssertJoysticksLocked(); + + ctx->joystick = joystick; + ctx->effects_updated = SDL_FALSE; + ctx->rumble_left = 0; + ctx->rumble_right = 0; + SDL_zeroa(ctx->last_state); + + /* Initialize player index (needed for setting LEDs) */ + ctx->player_index = SDL_GetJoystickPlayerIndex(joystick); + + /* Initialize the joystick capabilities */ + joystick->nbuttons = 11; + joystick->naxes = 16; + joystick->nhats = 1; + joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED; + + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); + + return SDL_TRUE; +} + +static int HIDAPI_DriverPS3SonySixaxis_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + ctx->rumble_left = (low_frequency_rumble >> 8); + ctx->rumble_right = (high_frequency_rumble >> 8); + + return HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(device); +} + +static int HIDAPI_DriverPS3SonySixaxis_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble) +{ + return SDL_Unsupported(); +} + +static Uint32 HIDAPI_DriverPS3SonySixaxis_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + return 0; +} + +static int HIDAPI_DriverPS3SonySixaxis_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) +{ + return SDL_Unsupported(); +} + +static int HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *effect, int size) +{ + Uint8 data[49]; + int report_size; + + SDL_zeroa(data); + + data[0] = k_EPS3SonySixaxisReportIdEffects; + report_size = sizeof(data); + + /* No offset with Sony sixaxis.sys driver*/ + SDL_memcpy(&data, effect, SDL_min(sizeof(data), (size_t)size)); + + if (SDL_HIDAPI_SendRumble(device, data, report_size) != report_size) { + return SDL_SetError("Couldn't send rumble packet"); + } + return 0; +} + +static int HIDAPI_DriverPS3SonySixaxis_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + ctx->report_sensors = enabled; + + return 0; +} + +static void HIDAPI_DriverPS3SonySixaxis_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context *ctx, Uint8 *data, int size) +{ + Sint16 axis; + Uint64 timestamp = SDL_GetTicksNS(); + + if (ctx->last_state[2] != data[2]) { + Uint8 hat = 0; + + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + + if (data[2] & 0x10) { + hat |= SDL_HAT_UP; + } + if (data[2] & 0x20) { + hat |= SDL_HAT_RIGHT; + } + if (data[2] & 0x40) { + hat |= SDL_HAT_DOWN; + } + if (data[2] & 0x80) { + hat |= SDL_HAT_LEFT; + } + SDL_SendJoystickHat(timestamp, joystick, 0, hat); + } + + if (ctx->last_state[3] != data[3]) { + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (data[3] & 0x04) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, (data[3] & 0x08) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, (data[3] & 0x10) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, (data[3] & 0x20) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, (data[3] & 0x40) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, (data[3] & 0x80) ? SDL_PRESSED : SDL_RELEASED); + } + + if (ctx->last_state[4] != data[4]) { + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + } + + axis = ((int)data[18] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis); + axis = ((int)data[19] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis); + axis = ((int)data[6] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis); + axis = ((int)data[7] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis); + axis = ((int)data[8] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis); + axis = ((int)data[9] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis); + + /* Buttons are mapped as axes in the order they appear in the button enumeration */ + { + static int button_axis_offsets[] = { + 24, /* SDL_GAMEPAD_BUTTON_SOUTH */ + 23, /* SDL_GAMEPAD_BUTTON_EAST */ + 25, /* SDL_GAMEPAD_BUTTON_WEST */ + 22, /* SDL_GAMEPAD_BUTTON_NORTH */ + 0, /* SDL_GAMEPAD_BUTTON_BACK */ + 0, /* SDL_GAMEPAD_BUTTON_GUIDE */ + 0, /* SDL_GAMEPAD_BUTTON_START */ + 0, /* SDL_GAMEPAD_BUTTON_LEFT_STICK */ + 0, /* SDL_GAMEPAD_BUTTON_RIGHT_STICK */ + 20, /* SDL_GAMEPAD_BUTTON_LEFT_SHOULDER */ + 21, /* SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER */ + 14, /* SDL_GAMEPAD_BUTTON_DPAD_UP */ + 16, /* SDL_GAMEPAD_BUTTON_DPAD_DOWN */ + 17, /* SDL_GAMEPAD_BUTTON_DPAD_LEFT */ + 15, /* SDL_GAMEPAD_BUTTON_DPAD_RIGHT */ + }; + Uint8 i, axis_index = 6; + + for (i = 0; i < SDL_arraysize(button_axis_offsets); ++i) { + int offset = button_axis_offsets[i]; + if (!offset) { + /* This button doesn't report as an axis */ + continue; + } + + axis = ((int)data[offset] * 257) - 32768; + SDL_SendJoystickAxis(timestamp, joystick, axis_index, axis); + ++axis_index; + } + } + + if (ctx->report_sensors) { + float sensor_data[3]; + + sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42])); + sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46])); + sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44])); + SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data)); + } + + SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); +} + +static SDL_bool HIDAPI_DriverPS3SonySixaxis_UpdateDevice(SDL_HIDAPI_Device *device) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + SDL_Joystick *joystick = NULL; + Uint8 data[USB_PACKET_LENGTH]; + int size; + + if (device->num_joysticks > 0) { + joystick = SDL_GetJoystickFromInstanceID(device->joysticks[0]); + } else { + return SDL_FALSE; + } + + if (!joystick) { + return SDL_FALSE; + } + + /* With sixaxis.sys driver we need to use hid_get_feature_report instead of hid_read */ + size = ReadFeatureReport(device->dev, 0x0, data, sizeof(data)); + if (size < 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "HIDAPI_DriverPS3SonySixaxis_UpdateDevice(): Couldn't read feature report 0x00"); + return SDL_FALSE; + } + + switch (data[0]) { + case k_EPS3SonySixaxisReportIdState: + HIDAPI_DriverPS3SonySixaxis_HandleStatePacket(joystick, ctx, &data[1], size - 1); /* report data starts in data[1] */ + + /* Wait for the first report to set the LED state after the controller stops blinking */ + if (!ctx->effects_updated) { + HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(device); + ctx->effects_updated = SDL_TRUE; + } + + break; + default: +#ifdef DEBUG_JOYSTICK + SDL_Log("Unknown PS3 packet: 0x%.2x\n", data[0]); +#endif + break; + } + + if (size < 0) { + /* Read error, device is disconnected */ + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); + } + return size >= 0; +} + +static void HIDAPI_DriverPS3SonySixaxis_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + ctx->joystick = NULL; +} + +static void HIDAPI_DriverPS3SonySixaxis_FreeDevice(SDL_HIDAPI_Device *device) +{ +} + +static int HIDAPI_DriverPS3_UpdateRumbleSonySixaxis(SDL_HIDAPI_Device *device) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + Uint8 effects[] = { + 0x0, /* Report Id */ + k_EPS3SixaxisCommandSetMotors, /* 2 = Set Motors */ + 0x00, 0x00, 0x00, /* padding */ + 0xff, /* Small Motor duration - 0xff is forever */ + 0x00, /* Small Motor off/on (0 or 1) */ + 0xff, /* Large Motor duration - 0xff is forever */ + 0x00 /* Large Motor force (0 to 255) */ + }; + + effects[6] = ctx->rumble_right ? 1 : 0; /* Small motor */ + effects[8] = ctx->rumble_left; /* Large motor */ + + return HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects)); +} + +static int HIDAPI_DriverPS3_UpdateLEDsSonySixaxis(SDL_HIDAPI_Device *device) +{ + SDL_DriverPS3_Context *ctx = (SDL_DriverPS3_Context *)device->context; + + Uint8 effects[] = { + 0x0, /* Report Id */ + k_EPS3SixaxisCommandSetLEDs, /* 1 = Set LEDs */ + 0x00, 0x00, 0x00, /* padding */ + 0x00, 0x00, 0x00, 0x00 /* LED #4, LED #3, LED #2, LED #1 (0 = Off, 1 = On, 2 = Flashing) */ + }; + + /* Turn on LED light on DS3 Controller for relevant player (player_index 0 lights up LED #1, player_index 1 lights up LED #2, etc) */ + if (ctx->player_index < 4) { + effects[8 - ctx->player_index] = 1; + } + + return HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect(device, ctx->joystick, effects, sizeof(effects)); +} + +SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3SonySixaxis = { + SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, + SDL_TRUE, + HIDAPI_DriverPS3SonySixaxis_RegisterHints, + HIDAPI_DriverPS3SonySixaxis_UnregisterHints, + HIDAPI_DriverPS3SonySixaxis_IsEnabled, + HIDAPI_DriverPS3SonySixaxis_IsSupportedDevice, + HIDAPI_DriverPS3SonySixaxis_InitDevice, + HIDAPI_DriverPS3SonySixaxis_GetDevicePlayerIndex, + HIDAPI_DriverPS3SonySixaxis_SetDevicePlayerIndex, + HIDAPI_DriverPS3SonySixaxis_UpdateDevice, + HIDAPI_DriverPS3SonySixaxis_OpenJoystick, + HIDAPI_DriverPS3SonySixaxis_RumbleJoystick, + HIDAPI_DriverPS3SonySixaxis_RumbleJoystickTriggers, + HIDAPI_DriverPS3SonySixaxis_GetJoystickCapabilities, + HIDAPI_DriverPS3SonySixaxis_SetJoystickLED, + HIDAPI_DriverPS3SonySixaxis_SendJoystickEffect, + HIDAPI_DriverPS3SonySixaxis_SetJoystickSensorsEnabled, + HIDAPI_DriverPS3SonySixaxis_CloseJoystick, + HIDAPI_DriverPS3SonySixaxis_FreeDevice, +}; + #endif /* SDL_JOYSTICK_HIDAPI_PS3 */ #endif /* SDL_JOYSTICK_HIDAPI */ diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 91ce0f5c..ebb1936b 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -723,6 +723,8 @@ static void HIDAPI_DriverPS4_SetEnhancedModeAvailable(SDL_DriverPS4_Context *ctx if (ctx->device->is_bluetooth && ctx->official_controller) { ctx->report_battery = SDL_TRUE; } + + HIDAPI_UpdateDeviceProperties(ctx->device); } static void HIDAPI_DriverPS4_SetEnhancedMode(SDL_DriverPS4_Context *ctx) @@ -869,10 +871,10 @@ static Uint32 HIDAPI_DriverPS4_GetJoystickCapabilities(SDL_HIDAPI_Device *device if (ctx->enhanced_mode_available) { if (ctx->lightbar_supported) { - result |= SDL_JOYCAP_LED; + result |= SDL_JOYSTICK_CAP_RGB_LED; } if (ctx->vibration_supported) { - result |= SDL_JOYCAP_RUMBLE; + result |= SDL_JOYSTICK_CAP_RUMBLE; } } diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 7ce112c9..0e52bf82 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -818,6 +818,8 @@ static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx if (ctx->device->is_bluetooth) { ctx->report_battery = SDL_TRUE; } + + HIDAPI_UpdateDeviceProperties(ctx->device); } static void HIDAPI_DriverPS5_SetEnhancedMode(SDL_DriverPS5_Context *ctx) @@ -1000,10 +1002,13 @@ static Uint32 HIDAPI_DriverPS5_GetJoystickCapabilities(SDL_HIDAPI_Device *device if (ctx->enhanced_mode_available) { if (ctx->lightbar_supported) { - result |= SDL_JOYCAP_LED; + result |= SDL_JOYSTICK_CAP_RGB_LED; + } + if (ctx->playerled_supported) { + result |= SDL_JOYSTICK_CAP_PLAYER_LED; } if (ctx->vibration_supported) { - result |= SDL_JOYCAP_RUMBLE; + result |= SDL_JOYSTICK_CAP_RUMBLE; } } diff --git a/src/joystick/hidapi/SDL_hidapi_rumble.c b/src/joystick/hidapi/SDL_hidapi_rumble.c index 5d270fc1..8dd7316c 100644 --- a/src/joystick/hidapi/SDL_hidapi_rumble.c +++ b/src/joystick/hidapi/SDL_hidapi_rumble.c @@ -168,7 +168,7 @@ int SDL_HIDAPI_LockRumble(void) { SDL_HIDAPI_RumbleContext *ctx = &rumble_context; - if (SDL_AtomicCAS(&ctx->initialized, SDL_FALSE, SDL_TRUE)) { + if (SDL_AtomicCompareAndSwap(&ctx->initialized, SDL_FALSE, SDL_TRUE)) { if (SDL_HIDAPI_StartRumbleThread(ctx) < 0) { return -1; } diff --git a/src/joystick/hidapi/SDL_hidapi_shield.c b/src/joystick/hidapi/SDL_hidapi_shield.c index 0128f698..8ae208e3 100644 --- a/src/joystick/hidapi/SDL_hidapi_shield.c +++ b/src/joystick/hidapi/SDL_hidapi_shield.c @@ -204,7 +204,7 @@ static SDL_bool HIDAPI_DriverShield_OpenJoystick(SDL_HIDAPI_Device *device, SDL_ static int HIDAPI_DriverShield_SendNextRumble(SDL_HIDAPI_Device *device) { - SDL_DriverShield_Context *ctx = device->context; + SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context; Uint8 rumble_data[3]; if (!ctx->rumble_update_pending) { @@ -235,7 +235,7 @@ static int HIDAPI_DriverShield_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joy return 0; } else { - SDL_DriverShield_Context *ctx = device->context; + SDL_DriverShield_Context *ctx = (SDL_DriverShield_Context *)device->context; /* The rumble motors are quite intense, so tone down the intensity like the official driver does */ ctx->left_motor_amplitude = low_frequency_rumble >> 11; @@ -258,7 +258,7 @@ static int HIDAPI_DriverShield_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, static Uint32 HIDAPI_DriverShield_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return SDL_JOYCAP_RUMBLE; + return SDL_JOYSTICK_CAP_RUMBLE; } static int HIDAPI_DriverShield_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) @@ -268,7 +268,7 @@ static int HIDAPI_DriverShield_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joy static int HIDAPI_DriverShield_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size) { - const Uint8 *data_bytes = data; + const Uint8 *data_bytes = (const Uint8 *)data; if (size > 1) { /* Single command byte followed by a variable length payload */ diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index f55664bc..5f284b20 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -33,7 +33,7 @@ enum { - SDL_GAMEPAD_BUTTON_STADIA_SHARE = 11, + SDL_GAMEPAD_BUTTON_STADIA_CAPTURE = 11, SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, SDL_GAMEPAD_NUM_STADIA_BUTTONS, }; @@ -147,7 +147,7 @@ static Uint32 HIDAPI_DriverStadia_GetJoystickCapabilities(SDL_HIDAPI_Device *dev Uint32 caps = 0; if (ctx->rumble_supported) { - caps |= SDL_JOYCAP_RUMBLE; + caps |= SDL_JOYSTICK_CAP_RUMBLE; } return caps; } @@ -218,7 +218,7 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_SHARE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_CAPTURE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); } diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 2e09abee..1c932232 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -112,14 +112,14 @@ typedef struct SteamControllerStateInternal_t #define STEAM_LEFT_TRIGGER_MASK 0x00000002 #define STEAM_RIGHT_BUMPER_MASK 0x00000004 #define STEAM_LEFT_BUMPER_MASK 0x00000008 -#define STEAM_BUTTON_0_MASK 0x00000010 /* Y */ -#define STEAM_BUTTON_1_MASK 0x00000020 /* B */ -#define STEAM_BUTTON_2_MASK 0x00000040 /* X */ -#define STEAM_BUTTON_3_MASK 0x00000080 /* A */ -#define STEAM_TOUCH_0_MASK 0x00000100 /* DPAD UP */ -#define STEAM_TOUCH_1_MASK 0x00000200 /* DPAD RIGHT */ -#define STEAM_TOUCH_2_MASK 0x00000400 /* DPAD LEFT */ -#define STEAM_TOUCH_3_MASK 0x00000800 /* DPAD DOWN */ +#define STEAM_BUTTON_NORTH_MASK 0x00000010 /* Y */ +#define STEAM_BUTTON_EAST_MASK 0x00000020 /* B */ +#define STEAM_BUTTON_WEST_MASK 0x00000040 /* X */ +#define STEAM_BUTTON_SOUTH_MASK 0x00000080 /* A */ +#define STEAM_DPAD_UP_MASK 0x00000100 /* DPAD UP */ +#define STEAM_DPAD_RIGHT_MASK 0x00000200 /* DPAD RIGHT */ +#define STEAM_DPAD_LEFT_MASK 0x00000400 /* DPAD LEFT */ +#define STEAM_DPAD_DOWN_MASK 0x00000800 /* DPAD DOWN */ #define STEAM_BUTTON_MENU_MASK 0x00001000 /* SELECT */ #define STEAM_BUTTON_STEAM_MASK 0x00002000 /* GUIDE */ #define STEAM_BUTTON_ESCAPE_MASK 0x00004000 /* START */ @@ -347,7 +347,7 @@ static int GetFeatureReport(SDL_hid_device *dev, unsigned char uBuffer[65]) // On Windows and macOS, BLE devices get 2 copies of the feature report ID, one that is removed by ReadFeatureReport, // and one that's included in the buffer we receive. We pad the bytes to read and skip over the report ID // if necessary. -#if defined(__WIN32__) || defined(__MACOS__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_MACOS) ++ucBytesToRead; ++ucDataStartOffset; #endif @@ -980,13 +980,13 @@ static SDL_bool HIDAPI_DriverSteam_InitDevice(SDL_HIDAPI_Device *device) } device->context = ctx; -#ifdef __WIN32__ +#ifdef SDL_PLATFORM_WIN32 if (device->serial) { /* We get a garbage serial number on Windows */ SDL_free(device->serial); device->serial = NULL; } -#endif /* __WIN32__ */ +#endif /* SDL_PLATFORM_WIN32 */ HIDAPI_SetDeviceName(device, "Steam Controller"); @@ -1125,16 +1125,16 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) Uint8 hat = 0; SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, - (ctx->m_state.ulButtons & STEAM_BUTTON_3_MASK) ? SDL_PRESSED : SDL_RELEASED); + (ctx->m_state.ulButtons & STEAM_BUTTON_SOUTH_MASK) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, - (ctx->m_state.ulButtons & STEAM_BUTTON_1_MASK) ? SDL_PRESSED : SDL_RELEASED); + (ctx->m_state.ulButtons & STEAM_BUTTON_EAST_MASK) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, - (ctx->m_state.ulButtons & STEAM_BUTTON_2_MASK) ? SDL_PRESSED : SDL_RELEASED); + (ctx->m_state.ulButtons & STEAM_BUTTON_WEST_MASK) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, - (ctx->m_state.ulButtons & STEAM_BUTTON_0_MASK) ? SDL_PRESSED : SDL_RELEASED); + (ctx->m_state.ulButtons & STEAM_BUTTON_NORTH_MASK) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, (ctx->m_state.ulButtons & STEAM_LEFT_BUMPER_MASK) ? SDL_PRESSED : SDL_RELEASED); @@ -1158,16 +1158,16 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_RIGHT_PADDLE, (ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) ? SDL_PRESSED : SDL_RELEASED); - if (ctx->m_state.ulButtons & STEAM_TOUCH_0_MASK) { + if (ctx->m_state.ulButtons & STEAM_DPAD_UP_MASK) { hat |= SDL_HAT_UP; } - if (ctx->m_state.ulButtons & STEAM_TOUCH_3_MASK) { + if (ctx->m_state.ulButtons & STEAM_DPAD_DOWN_MASK) { hat |= SDL_HAT_DOWN; } - if (ctx->m_state.ulButtons & STEAM_TOUCH_2_MASK) { + if (ctx->m_state.ulButtons & STEAM_DPAD_LEFT_MASK) { hat |= SDL_HAT_LEFT; } - if (ctx->m_state.ulButtons & STEAM_TOUCH_1_MASK) { + if (ctx->m_state.ulButtons & STEAM_DPAD_RIGHT_MASK) { hat |= SDL_HAT_RIGHT; } SDL_SendJoystickHat(timestamp, joystick, 0, hat); diff --git a/src/joystick/hidapi/SDL_hidapi_steamdeck.c b/src/joystick/hidapi/SDL_hidapi_steamdeck.c index b387add9..c7593556 100644 --- a/src/joystick/hidapi/SDL_hidapi_steamdeck.c +++ b/src/joystick/hidapi/SDL_hidapi_steamdeck.c @@ -388,7 +388,7 @@ static int HIDAPI_DriverSteamDeck_RumbleJoystickTriggers(SDL_HIDAPI_Device *devi static Uint32 HIDAPI_DriverSteamDeck_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return SDL_JOYCAP_RUMBLE; + return SDL_JOYSTICK_CAP_RUMBLE; } static int HIDAPI_DriverSteamDeck_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index c0f8a64b..15290d1c 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -727,6 +727,7 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c ctx->m_bPlayerLights = bPlayerLights; UpdateSlotLED(ctx); + HIDAPI_UpdateDeviceProperties(ctx->device); } } @@ -1577,12 +1578,16 @@ static Uint32 HIDAPI_DriverSwitch_GetJoystickCapabilities(SDL_HIDAPI_Device *dev SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context; Uint32 result = 0; + if (ctx->m_bPlayerLights && !ctx->m_bInputOnly) { + result |= SDL_JOYSTICK_CAP_PLAYER_LED; + } + if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_ProController && !ctx->m_bInputOnly) { - /* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */ - result |= SDL_JOYCAP_RUMBLE; + /* Doesn't have an RGB LED, so don't return SDL_JOYSTICK_CAP_RGB_LED here */ + result |= SDL_JOYSTICK_CAP_RUMBLE; } else if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft || ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) { - result |= SDL_JOYCAP_RUMBLE; + result |= SDL_JOYSTICK_CAP_RUMBLE; } return result; } diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index 065c3b97..4ab5c974 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -128,6 +128,14 @@ typedef struct Uint8 ucNExtensionBytes; } WiiButtonData; +typedef struct +{ + Uint16 min; + Uint16 max; + Uint16 center; + Uint16 deadzone; +} StickCalibrationData; + typedef struct { SDL_HIDAPI_Device *device; @@ -147,13 +155,7 @@ typedef struct Uint64 m_ulNextMotionPlusCheck; SDL_bool m_bDisconnected; - struct StickCalibrationData - { - Uint16 min; - Uint16 max; - Uint16 center; - Uint16 deadzone; - } m_StickCalibrationData[6]; + StickCalibrationData m_StickCalibrationData[6]; } SDL_DriverWii_Context; static void HIDAPI_DriverWii_RegisterHints(SDL_HintCallback callback, void *userdata) @@ -454,7 +456,7 @@ static void CheckMotionPlusConnection(SDL_DriverWii_Context *ctx) static void ActivateMotionPlusWithMode(SDL_DriverWii_Context *ctx, Uint8 mode) { -#ifdef __LINUX__ +#ifdef SDL_PLATFORM_LINUX /* Linux drivers maintain a lot of state around the Motion Plus * extension, so don't mess with it here. */ @@ -824,7 +826,7 @@ static int HIDAPI_DriverWii_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SD static Uint32 HIDAPI_DriverWii_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return SDL_JOYCAP_RUMBLE; + return SDL_JOYSTICK_CAP_RUMBLE; } static int HIDAPI_DriverWii_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) @@ -857,7 +859,7 @@ static int HIDAPI_DriverWii_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, return 0; } -static void PostStickCalibrated(Uint64 timestamp, SDL_Joystick *joystick, struct StickCalibrationData *calibration, Uint8 axis, Uint16 data) +static void PostStickCalibrated(Uint64 timestamp, SDL_Joystick *joystick, StickCalibrationData *calibration, Uint8 axis, Uint16 data) { Sint16 value = 0; if (!calibration->center) { @@ -1366,7 +1368,7 @@ static void HandleStatus(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick) static void HandleResponse(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick) { - EWiiInputReportIDs type = ctx->m_rgucReadBuffer[0]; + EWiiInputReportIDs type = (EWiiInputReportIDs)ctx->m_rgucReadBuffer[0]; WiiButtonData data; SDL_assert(type == k_eWiiInputReportIDs_Acknowledge || type == k_eWiiInputReportIDs_ReadMemory); SDL_zero(data); @@ -1473,7 +1475,7 @@ static void HandleButtonPacket(SDL_DriverWii_Context *ctx, SDL_Joystick *joystic static void HandleInput(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick) { - EWiiInputReportIDs type = ctx->m_rgucReadBuffer[0]; + EWiiInputReportIDs type = (EWiiInputReportIDs)ctx->m_rgucReadBuffer[0]; /* Set up for handling input */ ctx->timestamp = SDL_GetTicksNS(); diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index d0097fb7..819487b0 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -80,7 +80,7 @@ static SDL_bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device /* This is the chatpad or other input interface, not the Xbox 360 interface */ return SDL_FALSE; } -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS if (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0) { /* This is the Steam Virtual Gamepad, which isn't supported by this driver */ return SDL_FALSE; @@ -115,7 +115,7 @@ static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot, SDL_bool on) static void UpdateSlotLED(SDL_DriverXbox360_Context *ctx) { - if (ctx->player_lights) { + if (ctx->player_lights && ctx->player_index >= 0) { SetSlotLED(ctx->device->dev, (ctx->player_index % 4), SDL_TRUE); } else { SetSlotLED(ctx->device->dev, 0, SDL_FALSE); @@ -131,6 +131,7 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c ctx->player_lights = player_lights; UpdateSlotLED(ctx); + HIDAPI_UpdateDeviceProperties(ctx->device); } } @@ -197,7 +198,7 @@ static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL static int HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) { -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS if (SDL_IsJoystickBluetoothXboxOne(device->vendor_id, device->product_id)) { Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 }; @@ -240,8 +241,13 @@ static int HIDAPI_DriverXbox360_RumbleJoystickTriggers(SDL_HIDAPI_Device *device static Uint32 HIDAPI_DriverXbox360_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - /* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */ - return SDL_JOYCAP_RUMBLE; + SDL_DriverXbox360_Context *ctx = (SDL_DriverXbox360_Context *)device->context; + Uint32 result = SDL_JOYSTICK_CAP_RUMBLE; + + if (ctx->player_lights) { + result |= SDL_JOYSTICK_CAP_PLAYER_LED; + } + return result; } static int HIDAPI_DriverXbox360_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) @@ -262,7 +268,7 @@ static int HIDAPI_DriverXbox360_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *dev static void HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size) { Sint16 axis; -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS const SDL_bool invert_y_axes = SDL_FALSE; #else const SDL_bool invert_y_axes = SDL_TRUE; diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index db16c376..acae253a 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -87,7 +87,7 @@ static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot, SDL_bool on) static void UpdateSlotLED(SDL_DriverXbox360W_Context *ctx) { - if (ctx->player_lights) { + if (ctx->player_lights && ctx->player_index >= 0) { SetSlotLED(ctx->device->dev, (ctx->player_index % 4), SDL_TRUE); } else { SetSlotLED(ctx->device->dev, 0, SDL_FALSE); @@ -103,6 +103,7 @@ static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, c ctx->player_lights = player_lights; UpdateSlotLED(ctx); + HIDAPI_UpdateDeviceProperties(ctx->device); } } @@ -210,8 +211,13 @@ static int HIDAPI_DriverXbox360W_RumbleJoystickTriggers(SDL_HIDAPI_Device *devic static Uint32 HIDAPI_DriverXbox360W_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - /* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */ - return SDL_JOYCAP_RUMBLE; + SDL_DriverXbox360W_Context *ctx = (SDL_DriverXbox360W_Context *)device->context; + Uint32 result = SDL_JOYSTICK_CAP_RUMBLE; + + if (ctx->player_lights) { + result |= SDL_JOYSTICK_CAP_PLAYER_LED; + } + return result; } static int HIDAPI_DriverXbox360W_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 4631f1fa..c9b48ab7 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -35,7 +35,7 @@ /* Define this if you want to log all packets from the controller */ /*#define DEBUG_XBOX_PROTOCOL*/ -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) #define XBOX_ONE_DRIVER_ACTIVE 1 #else #define XBOX_ONE_DRIVER_ACTIVE 0 @@ -350,7 +350,7 @@ static SDL_bool HIDAPI_DriverXboxOne_IsEnabled(void) static SDL_bool HIDAPI_DriverXboxOne_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol) { -#ifdef __MACOS__ +#ifdef SDL_PLATFORM_MACOS /* Wired Xbox One controllers are handled by the 360Controller driver */ if (!SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) { return SDL_FALSE; @@ -540,13 +540,13 @@ static Uint32 HIDAPI_DriverXboxOne_GetJoystickCapabilities(SDL_HIDAPI_Device *de SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context; Uint32 result = 0; - result |= SDL_JOYCAP_RUMBLE; + result |= SDL_JOYSTICK_CAP_RUMBLE; if (ctx->has_trigger_rumble) { - result |= SDL_JOYCAP_RUMBLE_TRIGGERS; + result |= SDL_JOYSTICK_CAP_TRIGGER_RUMBLE; } if (ctx->has_color_led) { - result |= SDL_JOYCAP_LED; + result |= SDL_JOYSTICK_CAP_RGB_LED; } return result; @@ -673,16 +673,16 @@ static void HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_D if (ctx->last_state[1] != data[1]) { Uint8 hat = 0; - if (data[2] & 0x01) { + if (data[1] & 0x01) { hat |= SDL_HAT_UP; } - if (data[2] & 0x02) { + if (data[1] & 0x02) { hat |= SDL_HAT_DOWN; } - if (data[2] & 0x04) { + if (data[1] & 0x04) { hat |= SDL_HAT_LEFT; } - if (data[2] & 0x08) { + if (data[1] & 0x08) { hat |= SDL_HAT_RIGHT; } SDL_SendJoystickHat(timestamp, joystick, 0, hat); @@ -1225,17 +1225,19 @@ static int EncodeVariableInt(Uint8 *buf, Uint32 val) return i + 1; } -static int DecodeVariableInt(const Uint8 *data, int len, Uint32 *val) +static int DecodeVariableInt(const Uint8 *data, int len, void *out) { int i; + Uint32 val = 0; - for (i = 0; i < sizeof(*val) && i < len; i++) { - *val |= (data[i] & 0x7F) << (i * 7); + for (i = 0; i < sizeof(val) && i < len; i++) { + val |= (data[i] & 0x7F) << (i * 7); if (!(data[i] & 0x80)) { break; } } + SDL_memcpy(out, &val, sizeof(val)); return i + 1; } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index bb1f9376..cb1f1081 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -27,7 +27,7 @@ #include "SDL_hidapi_rumble.h" #include "../../SDL_hints_c.h" -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) #include "../windows/SDL_rawinputjoystick_c.h" #endif @@ -53,6 +53,7 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = { #ifdef SDL_JOYSTICK_HIDAPI_PS3 &SDL_HIDAPI_DriverPS3, &SDL_HIDAPI_DriverPS3ThirdParty, + &SDL_HIDAPI_DriverPS3SonySixaxis, #endif #ifdef SDL_JOYSTICK_HIDAPI_PS4 &SDL_HIDAPI_DriverPS4, @@ -163,6 +164,12 @@ SDL_bool HIDAPI_SupportsPlaystationDetection(Uint16 vendor, Uint16 product) } return SDL_TRUE; case USB_VENDOR_MADCATZ: + if (product == USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK) { + /* This is not a Playstation compatible device */ + return SDL_FALSE; + } + return SDL_TRUE; + case USB_VENDOR_MAYFLASH: return SDL_TRUE; case USB_VENDOR_NACON: case USB_VENDOR_NACON_ALT: @@ -451,7 +458,7 @@ static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, SDL_bool *remove /* Wait a little bit for the device to initialize */ SDL_Delay(10); -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID /* On Android we need to leave joysticks unlocked because it calls * out to the main thread for permissions and the main thread can * be in the process of handling controller input. @@ -857,6 +864,54 @@ void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joyst SDL_UnlockJoysticks(); } +static void HIDAPI_UpdateJoystickProperties(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) +{ + SDL_PropertiesID props = SDL_GetJoystickProperties(joystick); + Uint32 caps = device->driver->GetJoystickCapabilities(device, joystick); + + if (caps & SDL_JOYSTICK_CAP_MONO_LED) { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN, SDL_TRUE); + } else { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN, SDL_FALSE); + } + if (caps & SDL_JOYSTICK_CAP_RGB_LED) { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, SDL_TRUE); + } else { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, SDL_FALSE); + } + if (caps & SDL_JOYSTICK_CAP_PLAYER_LED) { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_PLAYER_LED_BOOLEAN, SDL_TRUE); + } else { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_PLAYER_LED_BOOLEAN, SDL_FALSE); + } + if (caps & SDL_JOYSTICK_CAP_RUMBLE) { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } else { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_FALSE); + } + if (caps & SDL_JOYSTICK_CAP_TRIGGER_RUMBLE) { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE); + } else { + SDL_SetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_FALSE); + } +} + +void HIDAPI_UpdateDeviceProperties(SDL_HIDAPI_Device *device) +{ + int i; + + SDL_LockJoysticks(); + + for (i = 0; i < device->num_joysticks; ++i) { + SDL_Joystick *joystick = SDL_GetJoystickFromInstanceID(device->joysticks[i]); + if (joystick) { + HIDAPI_UpdateJoystickProperties(device, joystick); + } + } + + SDL_UnlockJoysticks(); +} + static int HIDAPI_JoystickGetCount(void) { return SDL_HIDAPI_numjoysticks; @@ -1206,9 +1261,9 @@ SDL_bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type) return SDL_FALSE; } - if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) { + if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) { HIDAPI_UpdateDeviceList(); - SDL_AtomicUnlock(&SDL_HIDAPI_spinlock); + SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock); } SDL_LockJoysticks(); @@ -1251,9 +1306,9 @@ SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 vers } #endif /* SDL_JOYSTICK_HIDAPI_XBOX360 || SDL_JOYSTICK_HIDAPI_XBOXONE */ if (supported) { - if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) { + if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) { HIDAPI_UpdateDeviceList(); - SDL_AtomicUnlock(&SDL_HIDAPI_spinlock); + SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock); } } @@ -1313,13 +1368,13 @@ SDL_GamepadType HIDAPI_GetGamepadTypeFromGUID(SDL_JoystickGUID guid) static void HIDAPI_JoystickDetect(void) { - if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) { + if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) { Uint32 count = SDL_hid_device_change_count(); if (SDL_HIDAPI_change_count != count) { SDL_HIDAPI_change_count = count; HIDAPI_UpdateDeviceList(); } - SDL_AtomicUnlock(&SDL_HIDAPI_spinlock); + SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock); } } @@ -1332,7 +1387,7 @@ void HIDAPI_UpdateDevices(void) /* Update the devices, which may change connected joysticks and send events */ /* Prepare the existing device list */ - if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) { + if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) { for (device = SDL_HIDAPI_devices; device; device = device->next) { if (device->parent) { continue; @@ -1346,7 +1401,7 @@ void HIDAPI_UpdateDevices(void) } } } - SDL_AtomicUnlock(&SDL_HIDAPI_spinlock); + SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock); } } @@ -1469,6 +1524,8 @@ static int HIDAPI_JoystickOpen(SDL_Joystick *joystick, int device_index) return -1; } + HIDAPI_UpdateJoystickProperties(device, joystick); + if (device->serial) { joystick->serial = SDL_strdup(device->serial); } @@ -1518,18 +1575,6 @@ static int HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rum return result; } -static Uint32 HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - Uint32 result = 0; - SDL_HIDAPI_Device *device = NULL; - - if (HIDAPI_GetJoystickDevice(joystick, &device)) { - result = device->driver->GetJoystickCapabilities(device, joystick); - } - - return result; -} - static int HIDAPI_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { int result; @@ -1659,6 +1704,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = { HIDAPI_JoystickInit, HIDAPI_JoystickGetCount, HIDAPI_JoystickDetect, + HIDAPI_IsDevicePresent, HIDAPI_JoystickGetDeviceName, HIDAPI_JoystickGetDevicePath, HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -1669,7 +1715,6 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = { HIDAPI_JoystickOpen, HIDAPI_JoystickRumble, HIDAPI_JoystickRumbleTriggers, - HIDAPI_JoystickGetCapabilities, HIDAPI_JoystickSetLED, HIDAPI_JoystickSendEffect, HIDAPI_JoystickSetSensorsEnabled, diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index 9cb17021..45fa9ec5 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -40,8 +40,23 @@ #define SDL_JOYSTICK_HIDAPI_XBOXONE #define SDL_JOYSTICK_HIDAPI_SHIELD +/* Joystick capability definitions */ +#define SDL_JOYSTICK_CAP_MONO_LED 0x00000001 +#define SDL_JOYSTICK_CAP_RGB_LED 0x00000002 +#define SDL_JOYSTICK_CAP_PLAYER_LED 0x00000004 +#define SDL_JOYSTICK_CAP_RUMBLE 0x00000010 +#define SDL_JOYSTICK_CAP_TRIGGER_RUMBLE 0x00000020 + /* Whether HIDAPI is enabled by default */ +#if defined(SDL_PLATFORM_ANDROID) || \ + defined(SDL_PLATFORM_IOS) || \ + defined(SDL_PLATFORM_TVOS) || \ + defined(SDL_PLATFORM_VISIONOS) +/* On Android, HIDAPI prompts for permissions and acquires exclusive access to the device, and on Apple mobile platforms it doesn't do anything except for handling Bluetooth Steam Controllers, so we'll leave it off by default. */ +#define SDL_HIDAPI_DEFAULT SDL_FALSE +#else #define SDL_HIDAPI_DEFAULT SDL_TRUE +#endif /* The maximum size of a USB packet for HID devices */ #define USB_PACKET_LENGTH 64 @@ -124,6 +139,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverNintendoClassic; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3ThirdParty; +extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS3SonySixaxis; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5; extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverShield; @@ -156,6 +172,7 @@ extern SDL_bool HIDAPI_HasConnectedUSBDevice(const char *serial); extern void HIDAPI_DisconnectBluetoothDevice(const char *serial); extern SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID); extern void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID); +extern void HIDAPI_UpdateDeviceProperties(SDL_HIDAPI_Device *device); extern void HIDAPI_DumpPacket(const char *prefix, const Uint8 *data, int size); diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 742bbf42..a43d7e97 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -310,14 +310,11 @@ static int IsJoystick(const char *path, int fd, char **name_return, Uint16 *vend return 0; } -#ifdef SDL_JOYSTICK_HIDAPI if (!IsVirtualJoystick(inpid.vendor, inpid.product, inpid.version, name) && - HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version, name)) { - /* The HIDAPI driver is taking care of this device */ + SDL_JoystickHandledByAnotherDriver(&SDL_LINUX_JoystickDriver, inpid.vendor, inpid.product, inpid.version, name)) { SDL_free(name); return 0; } -#endif FixupDeviceInfoForMapping(fd, &inpid); @@ -363,7 +360,7 @@ static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_clas switch (udev_type) { case SDL_UDEV_DEVICEADDED: - if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { + if (!(udev_class & (SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_ACCELEROMETER))) { return; } if (SDL_classic_joysticks) { @@ -420,7 +417,13 @@ static void MaybeAddDevice(const char *path) return; } - if (stat(path, &sb) == -1) { + fd = open(path, O_RDONLY | O_CLOEXEC, 0); + if (fd < 0) { + return; + } + + if (fstat(fd, &sb) == -1) { + close(fd); return; } @@ -438,11 +441,6 @@ static void MaybeAddDevice(const char *path) } } - fd = open(path, O_RDONLY | O_CLOEXEC, 0); - if (fd < 0) { - goto done; - } - #ifdef DEBUG_INPUT_EVENTS SDL_Log("Checking %s\n", path); #endif @@ -510,9 +508,7 @@ static void MaybeAddDevice(const char *path) } done: - if (fd >= 0) { - close(fd); - } + close(fd); SDL_UnlockJoysticks(); } @@ -974,7 +970,7 @@ static void LINUX_JoystickDetect(void) } else #endif #ifdef HAVE_INOTIFY - if (inotify_fd >= 0 && last_joy_detect_time != 0) { + if (inotify_fd >= 0 && last_joy_detect_time != 0) { LINUX_InotifyJoystickDetect(); } else #endif @@ -987,11 +983,17 @@ static void LINUX_JoystickDetect(void) SDL_UpdateSteamControllers(); } +static SDL_bool LINUX_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + static int LINUX_JoystickInit(void) { const char *devices = SDL_GetHint(SDL_HINT_JOYSTICK_DEVICE); - SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE); + SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_LINUX_CLASSIC, SDL_FALSE); enumeration_method = ENUMERATION_UNSET; @@ -1040,21 +1042,24 @@ static int LINUX_JoystickInit(void) } if (enumeration_method == ENUMERATION_LIBUDEV) { - if (SDL_UDEV_Init() < 0) { - return SDL_SetError("Could not initialize UDEV"); - } + if (SDL_UDEV_Init() == 0) { + /* Set up the udev callback */ + if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) { + SDL_UDEV_Quit(); + return SDL_SetError("Could not set up joystick <-> udev callback"); + } - /* Set up the udev callback */ - if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) { - SDL_UDEV_Quit(); - return SDL_SetError("Could not set up joystick <-> udev callback"); + /* Force a scan to build the initial device list */ + SDL_UDEV_Scan(); + } else { + SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, + "udev init failed, disabling udev integration"); + enumeration_method = ENUMERATION_FALLBACK; } - - /* Force a scan to build the initial device list */ - SDL_UDEV_Scan(); - } else + } #endif - { + + if (enumeration_method != ENUMERATION_LIBUDEV) { #ifdef HAVE_INOTIFY inotify_fd = SDL_inotify_init1(); @@ -1145,6 +1150,16 @@ static SDL_JoystickID LINUX_JoystickGetDeviceInstanceID(int device_index) return GetJoystickByDevIndex(device_index)->device_instance; } +static int allocate_balldata(SDL_Joystick *joystick) +{ + joystick->hwdata->balls = + (struct hwdata_ball *)SDL_calloc(joystick->nballs, sizeof(struct hwdata_ball)); + if (joystick->hwdata->balls == NULL) { + return -1; + } + return 0; +} + static int allocate_hatdata(SDL_Joystick *joystick) { int i; @@ -1178,7 +1193,7 @@ static SDL_bool GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct } /* If the hint says so, treat all hats as digital. */ - if (SDL_GetHintBoolean(SDL_HINT_LINUX_DIGITAL_HATS, SDL_FALSE)) { + if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS, SDL_FALSE)) { return SDL_TRUE; } @@ -1204,8 +1219,8 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor) unsigned long relbit[NBITS(REL_MAX)] = { 0 }; unsigned long ffbit[NBITS(FF_MAX)] = { 0 }; Uint8 key_pam_size, abs_pam_size; - SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_FALSE); - SDL_bool use_hat_deadzones = SDL_GetHintBoolean(SDL_HINT_LINUX_HAT_DEADZONES, SDL_TRUE); + SDL_bool use_deadzones = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_LINUX_DEADZONES, SDL_FALSE); + SDL_bool use_hat_deadzones = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES, SDL_TRUE); SDL_AssertJoysticksLocked(); @@ -1317,6 +1332,9 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor) ++joystick->naxes; } } + if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) { + ++joystick->nballs; + } } else if ((ioctl(fd, JSIOCGBUTTONS, &key_pam_size, sizeof(key_pam_size)) >= 0) && (ioctl(fd, JSIOCGAXES, &abs_pam_size, sizeof(abs_pam_size)) >= 0)) { @@ -1424,6 +1442,11 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor) } /* Allocate data to keep track of these thingamajigs */ + if (joystick->nballs > 0) { + if (allocate_balldata(joystick) < 0) { + joystick->nballs = 0; + } + } if (joystick->nhats > 0) { if (allocate_hatdata(joystick) < 0) { joystick->nhats = 0; @@ -1573,7 +1596,6 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) return SDL_SetError("No such device"); } - joystick->instance_id = item->device_instance; joystick->hwdata = (struct joystick_hwdata *) SDL_calloc(1, sizeof(*joystick->hwdata)); if (!joystick->hwdata) { @@ -1609,6 +1631,9 @@ static int LINUX_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->hwdata->fd_sensor = -1; } + if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } return 0; } @@ -1660,19 +1685,6 @@ static int LINUX_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumb return SDL_Unsupported(); } -static Uint32 LINUX_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - Uint32 result = 0; - - SDL_AssertJoysticksLocked(); - - if (joystick->hwdata->ff_rumble || joystick->hwdata->ff_sine) { - result |= SDL_JOYCAP_RUMBLE; - } - - return result; -} - static int LINUX_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -1762,6 +1774,11 @@ static void HandleHat(Uint64 timestamp, SDL_Joystick *stick, int hatidx, int axi } } +static void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) +{ + stick->hwdata->balls[ball].axis[axis] += value; +} + static int AxisCorrect(SDL_Joystick *joystick, int which, int value) { struct axis_correct *correct; @@ -1852,6 +1869,8 @@ static void PollAllValues(Uint64 timestamp, SDL_Joystick *joystick) } } } + + /* Joyballs are relative input, so there's no poll state. Events only! */ } static void PollAllSensors(Uint64 timestamp, SDL_Joystick *joystick) @@ -1960,6 +1979,17 @@ static void HandleInputEvents(SDL_Joystick *joystick) break; } break; + case EV_REL: + switch (code) { + case REL_X: + case REL_Y: + code -= REL_X; + HandleBall(joystick, code / 2, code % 2, event->value); + break; + default: + break; + } + break; case EV_SYN: switch (code) { case SYN_DROPPED: @@ -1977,6 +2007,7 @@ static void HandleInputEvents(SDL_Joystick *joystick) default: break; } + break; default: break; } @@ -2067,6 +2098,7 @@ static void HandleInputEvents(SDL_Joystick *joystick) default: break; } + break; default: break; } @@ -2129,6 +2161,8 @@ static void HandleClassicEvents(SDL_Joystick *joystick) static void LINUX_JoystickUpdate(SDL_Joystick *joystick) { + int i; + SDL_AssertJoysticksLocked(); if (joystick->hwdata->m_bSteamController) { @@ -2141,6 +2175,19 @@ static void LINUX_JoystickUpdate(SDL_Joystick *joystick) } else { HandleInputEvents(joystick); } + + /* Deliver ball motion updates */ + for (i = 0; i < joystick->nballs; ++i) { + int xrel, yrel; + + xrel = joystick->hwdata->balls[i].axis[0]; + yrel = joystick->hwdata->balls[i].axis[1]; + if (xrel || yrel) { + joystick->hwdata->balls[i].axis[0] = 0; + joystick->hwdata->balls[i].axis[1] = 0; + SDL_SendJoystickBall(0, joystick, (Uint8)i, xrel, yrel); + } + } } /* Function to close a joystick after use */ @@ -2168,6 +2215,7 @@ static void LINUX_JoystickClose(SDL_Joystick *joystick) SDL_free(joystick->hwdata->key_pam); SDL_free(joystick->hwdata->abs_pam); SDL_free(joystick->hwdata->hats); + SDL_free(joystick->hwdata->balls); SDL_free(joystick->hwdata->fname); SDL_free(joystick->hwdata); } @@ -2696,6 +2744,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = { LINUX_JoystickInit, LINUX_JoystickGetCount, LINUX_JoystickDetect, + LINUX_JoystickIsDevicePresent, LINUX_JoystickGetDeviceName, LINUX_JoystickGetDevicePath, LINUX_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -2706,7 +2755,6 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = { LINUX_JoystickOpen, LINUX_JoystickRumble, LINUX_JoystickRumbleTriggers, - LINUX_JoystickGetCapabilities, LINUX_JoystickSetLED, LINUX_JoystickSendEffect, LINUX_JoystickSetSensorsEnabled, diff --git a/src/joystick/linux/SDL_sysjoystick_c.h b/src/joystick/linux/SDL_sysjoystick_c.h index 98bee204..8e441c0a 100644 --- a/src/joystick/linux/SDL_sysjoystick_c.h +++ b/src/joystick/linux/SDL_sysjoystick_c.h @@ -43,6 +43,12 @@ struct joystick_hwdata struct ff_effect effect; Uint32 effect_expiration; + /* The current Linux joystick driver maps balls to two axes */ + struct hwdata_ball + { + int axis[2]; + } *balls; + /* The current Linux joystick driver maps hats to two axes */ struct hwdata_hat { diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index 79a666f6..5837d916 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -62,6 +62,7 @@ static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick); static int N3DS_JoystickInit(void) { hidInit(); + SDL_PrivateJoystickAdded(1); return 0; } @@ -91,7 +92,6 @@ static int N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nbuttons = NB_BUTTONS; joystick->naxes = 4; joystick->nhats = 0; - joystick->instance_id = device_index; return 0; } @@ -226,6 +226,12 @@ static void N3DS_JoystickDetect(void) { } +static SDL_bool N3DS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + static const char *N3DS_JoystickGetDevicePath(int device_index) { return NULL; @@ -245,11 +251,6 @@ static void N3DS_JoystickSetDevicePlayerIndex(int device_index, int player_index { } -static Uint32 N3DS_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - static int N3DS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) { return SDL_Unsupported(); @@ -271,27 +272,27 @@ static int N3DS_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int } SDL_JoystickDriver SDL_N3DS_JoystickDriver = { - .Init = N3DS_JoystickInit, - .GetCount = N3DS_JoystickGetCount, - .Detect = N3DS_JoystickDetect, - .GetDeviceName = N3DS_JoystickGetDeviceName, - .GetDevicePath = N3DS_JoystickGetDevicePath, - .GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot, - .GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex, - .SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex, - .GetDeviceGUID = N3DS_JoystickGetDeviceGUID, - .GetDeviceInstanceID = N3DS_JoystickGetDeviceInstanceID, - .Open = N3DS_JoystickOpen, - .Rumble = N3DS_JoystickRumble, - .RumbleTriggers = N3DS_JoystickRumbleTriggers, - .GetCapabilities = N3DS_JoystickGetCapabilities, - .SetLED = N3DS_JoystickSetLED, - .SendEffect = N3DS_JoystickSendEffect, - .SetSensorsEnabled = N3DS_JoystickSetSensorsEnabled, - .Update = N3DS_JoystickUpdate, - .Close = N3DS_JoystickClose, - .Quit = N3DS_JoystickQuit, - .GetGamepadMapping = N3DS_JoystickGetGamepadMapping + N3DS_JoystickInit, + N3DS_JoystickGetCount, + N3DS_JoystickDetect, + N3DS_JoystickIsDevicePresent, + N3DS_JoystickGetDeviceName, + N3DS_JoystickGetDevicePath, + N3DS_JoystickGetDeviceSteamVirtualGamepadSlot, + N3DS_JoystickGetDevicePlayerIndex, + N3DS_JoystickSetDevicePlayerIndex, + N3DS_JoystickGetDeviceGUID, + N3DS_JoystickGetDeviceInstanceID, + N3DS_JoystickOpen, + N3DS_JoystickRumble, + N3DS_JoystickRumbleTriggers, + N3DS_JoystickSetLED, + N3DS_JoystickSendEffect, + N3DS_JoystickSetSensorsEnabled, + N3DS_JoystickUpdate, + N3DS_JoystickClose, + N3DS_JoystickQuit, + N3DS_JoystickGetGamepadMapping }; #endif /* SDL_JOYSTICK_N3DS */ diff --git a/src/joystick/ps2/SDL_sysjoystick.c b/src/joystick/ps2/SDL_sysjoystick.c index 5fc5df32..5042dcda 100644 --- a/src/joystick/ps2/SDL_sysjoystick.c +++ b/src/joystick/ps2/SDL_sysjoystick.c @@ -122,6 +122,7 @@ static int PS2_JoystickInit(void) info->slot = (uint8_t)slot; info->opened = 1; enabled_pads++; + SDL_PrivateJoystickAdded(enabled_pads); } } } @@ -140,6 +141,12 @@ static void PS2_JoystickDetect() { } +static SDL_bool PS2_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + /* Function to get the device-dependent name of a joystick */ static const char *PS2_JoystickGetDeviceName(int index) { @@ -208,7 +215,8 @@ static int PS2_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nbuttons = PS2_BUTTONS; joystick->naxes = PS2_TOTAL_AXIS; joystick->nhats = 0; - joystick->instance_id = device_index; + + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); return 0; } @@ -240,31 +248,25 @@ static int PS2_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl /* Rumble functionality */ static int PS2_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right) { - return -1; -} - -/* Capability detection */ -static Uint32 PS2_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return SDL_JOYCAP_RUMBLE; + return SDL_Unsupported(); } /* LED functionality */ static int PS2_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { - return -1; + return SDL_Unsupported(); } /* General effects */ static int PS2_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) { - return -1; + return SDL_Unsupported(); } /* Sensor functionality */ static int PS2_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) { - return -1; + return SDL_Unsupported(); } /* Function to update the state of a joystick - called as a device poll. @@ -345,6 +347,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = { PS2_JoystickInit, PS2_JoystickGetCount, PS2_JoystickDetect, + PS2_JoystickIsDevicePresent, PS2_JoystickGetDeviceName, PS2_JoystickGetDevicePath, PS2_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -355,7 +358,6 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = { PS2_JoystickOpen, PS2_JoystickRumble, PS2_JoystickRumbleTriggers, - PS2_JoystickGetCapabilities, PS2_JoystickSetLED, PS2_JoystickSendEffect, PS2_JoystickSetSensorsEnabled, diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index f66abfaa..544cc758 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -93,6 +93,8 @@ static int PSP_JoystickInit(void) analog_map[127 - i] = -1 * analog_map[i + 128]; } + SDL_PrivateJoystickAdded(1); + return 1; } @@ -105,6 +107,12 @@ static void PSP_JoystickDetect(void) { } +static SDL_bool PSP_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + /* Function to get the device-dependent name of a joystick */ static const char *PSP_JoystickGetDeviceName(int device_index) { @@ -158,7 +166,6 @@ static int PSP_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nbuttons = SDL_arraysize(button_map); joystick->naxes = 2; joystick->nhats = 0; - joystick->instance_id = device_index; return 0; } @@ -173,11 +180,6 @@ static int PSP_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble return SDL_Unsupported(); } -static Uint32 PSP_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - static int PSP_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -208,7 +210,9 @@ static void PSP_JoystickUpdate(SDL_Joystick *joystick) static unsigned char old_x = 0, old_y = 0; Uint64 timestamp = SDL_GetTicksNS(); - sceCtrlReadBufferPositive(&pad, 1); + if (sceCtrlPeekBufferPositive(&pad, 1) <= 0) { + return; + } buttons = pad.Buttons; x = pad.Lx; y = pad.Ly; @@ -256,6 +260,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = { PSP_JoystickInit, PSP_JoystickGetCount, PSP_JoystickDetect, + PSP_JoystickIsDevicePresent, PSP_JoystickGetDeviceName, PSP_JoystickGetDevicePath, PSP_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -266,7 +271,6 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = { PSP_JoystickOpen, PSP_JoystickRumble, PSP_JoystickRumbleTriggers, - PSP_JoystickGetCapabilities, PSP_JoystickSetLED, PSP_JoystickSendEffect, PSP_JoystickSetSensorsEnabled, diff --git a/src/joystick/sort_controllers.py b/src/joystick/sort_controllers.py index 1442656c..efbb5163 100755 --- a/src/joystick/sort_controllers.py +++ b/src/joystick/sort_controllers.py @@ -35,6 +35,15 @@ def find_element(prefix, bindings): return -1 +def get_crc_from_entry(entry): + crc = "" + line = "".join(entry) + bindings = line.split(",") + pos = find_element("crc:", bindings) + if pos >= 0: + crc = bindings[pos][4:] + return crc + def save_controller(line): global controllers match = split_pattern.match(line) @@ -93,7 +102,7 @@ def save_controller(line): entry.append(match.group(5)) controllers.append(entry) - entry_id = entry[1] + entry[3] + entry_id = entry[1] + get_crc_from_entry(entry) if ',sdk' in line or ',hint:' in line: conditionals.append(entry_id) @@ -102,7 +111,7 @@ def write_controllers(): global controller_guids # Check for duplicates for entry in controllers: - entry_id = entry[1] + entry[3] + entry_id = entry[1] + get_crc_from_entry(entry) if (entry_id in controller_guids and entry_id not in conditionals): current_name = entry[2] existing_name = controller_guids[entry_id][2] diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 0db98ac9..e673bb8a 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -37,6 +37,7 @@ #define USB_VENDOR_HYPERKIN 0x2e24 #define USB_VENDOR_LOGITECH 0x046d #define USB_VENDOR_MADCATZ 0x0738 +#define USB_VENDOR_MAYFLASH 0x33df #define USB_VENDOR_MICROSOFT 0x045e #define USB_VENDOR_NACON 0x146b #define USB_VENDOR_NACON_ALT 0x3285 @@ -73,6 +74,7 @@ #define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184 #define USB_PRODUCT_LOGITECH_F310 0xc216 #define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1 +#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRELESS 0x0d16 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18 diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index d7859bf3..f55da7f6 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -122,7 +122,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des return SDL_SetError("Unsupported virtual joystick description version %u", desc->version); } - hwdata = SDL_calloc(1, sizeof(joystick_hwdata)); + hwdata = (joystick_hwdata *)SDL_calloc(1, sizeof(joystick_hwdata)); if (!hwdata) { VIRTUAL_FreeHWData(hwdata); return 0; @@ -207,7 +207,7 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des /* Allocate fields for different control-types */ if (hwdata->desc.naxes > 0) { - hwdata->axes = SDL_calloc(hwdata->desc.naxes, sizeof(Sint16)); + hwdata->axes = (Sint16 *)SDL_calloc(hwdata->desc.naxes, sizeof(Sint16)); if (!hwdata->axes) { VIRTUAL_FreeHWData(hwdata); return 0; @@ -222,14 +222,14 @@ SDL_JoystickID SDL_JoystickAttachVirtualInner(const SDL_VirtualJoystickDesc *des } } if (hwdata->desc.nbuttons > 0) { - hwdata->buttons = SDL_calloc(hwdata->desc.nbuttons, sizeof(Uint8)); + hwdata->buttons = (Uint8 *)SDL_calloc(hwdata->desc.nbuttons, sizeof(Uint8)); if (!hwdata->buttons) { VIRTUAL_FreeHWData(hwdata); return 0; } } if (hwdata->desc.nhats > 0) { - hwdata->hats = SDL_calloc(hwdata->desc.nhats, sizeof(Uint8)); + hwdata->hats = (Uint8 *)SDL_calloc(hwdata->desc.nhats, sizeof(Uint8)); if (!hwdata->hats) { VIRTUAL_FreeHWData(hwdata); return 0; @@ -353,6 +353,12 @@ static void VIRTUAL_JoystickDetect(void) { } +static SDL_bool VIRTUAL_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers... or do we? */ + return SDL_FALSE; +} + static const char *VIRTUAL_JoystickGetDeviceName(int device_index) { joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); @@ -416,12 +422,21 @@ static int VIRTUAL_JoystickOpen(SDL_Joystick *joystick, int device_index) if (!hwdata) { return SDL_SetError("No such device"); } - joystick->instance_id = hwdata->instance_id; joystick->hwdata = hwdata; joystick->naxes = hwdata->desc.naxes; joystick->nbuttons = hwdata->desc.nbuttons; joystick->nhats = hwdata->desc.nhats; hwdata->joystick = joystick; + + if (hwdata->desc.SetLED) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, SDL_TRUE); + } + if (hwdata->desc.Rumble) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } + if (hwdata->desc.RumbleTriggers) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE); + } return 0; } @@ -465,28 +480,6 @@ static int VIRTUAL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru return result; } -static Uint32 VIRTUAL_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - joystick_hwdata *hwdata; - Uint32 caps = 0; - - SDL_AssertJoysticksLocked(); - - hwdata = joystick->hwdata; - if (hwdata) { - if (hwdata->desc.Rumble) { - caps |= SDL_JOYCAP_RUMBLE; - } - if (hwdata->desc.RumbleTriggers) { - caps |= SDL_JOYCAP_RUMBLE_TRIGGERS; - } - if (hwdata->desc.SetLED) { - caps |= SDL_JOYCAP_LED; - } - } - return caps; -} - static int VIRTUAL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { int result; @@ -694,6 +687,36 @@ static SDL_bool VIRTUAL_JoystickGetGamepadMapping(int device_index, SDL_GamepadM out->left_paddle2.target = current_button++; } + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_TOUCHPAD))) { + out->touchpad.kind = EMappingKind_Button; + out->touchpad.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC2))) { + out->misc2.kind = EMappingKind_Button; + out->misc2.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC3))) { + out->misc3.kind = EMappingKind_Button; + out->misc3.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC4))) { + out->misc4.kind = EMappingKind_Button; + out->misc4.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC5))) { + out->misc5.kind = EMappingKind_Button; + out->misc5.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC6))) { + out->misc6.kind = EMappingKind_Button; + out->misc6.target = current_button++; + } + if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTX))) { out->leftx.kind = EMappingKind_Axis; out->leftx.target = current_axis++; @@ -731,6 +754,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = { VIRTUAL_JoystickInit, VIRTUAL_JoystickGetCount, VIRTUAL_JoystickDetect, + VIRTUAL_JoystickIsDevicePresent, VIRTUAL_JoystickGetDeviceName, VIRTUAL_JoystickGetDevicePath, VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -741,7 +765,6 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = { VIRTUAL_JoystickOpen, VIRTUAL_JoystickRumble, VIRTUAL_JoystickRumbleTriggers, - VIRTUAL_JoystickGetCapabilities, VIRTUAL_JoystickSetLED, VIRTUAL_JoystickSendEffect, VIRTUAL_JoystickSetSensorsEnabled, diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c index 4eb9edfd..09b7ab82 100644 --- a/src/joystick/vita/SDL_sysjoystick.c +++ b/src/joystick/vita/SDL_sysjoystick.c @@ -101,7 +101,7 @@ static int calc_bezier_y(float t) * Joystick 0 should be the system default joystick. * It should return number of joysticks, or -1 on an unrecoverable fatal error. */ -int VITA_JoystickInit(void) +static int VITA_JoystickInit(void) { int i; SceCtrlPortInfo myPortInfo; @@ -124,7 +124,8 @@ int VITA_JoystickInit(void) // after the app has already started. SDL_numjoysticks = 1; - SDL_PrivateJoystickAdded(0); + SDL_PrivateJoystickAdded(SDL_numjoysticks); + // How many additional paired controllers are there? sceCtrlGetControllerPortInfo(&myPortInfo); @@ -132,29 +133,35 @@ int VITA_JoystickInit(void) // and that is the first one, so start at port 2 for (i = 2; i <= 4; i++) { if (myPortInfo.port[i] != SCE_CTRL_TYPE_UNPAIRED) { + ++SDL_numjoysticks; SDL_PrivateJoystickAdded(SDL_numjoysticks); - SDL_numjoysticks++; } } return SDL_numjoysticks; } -int VITA_JoystickGetCount() +static int VITA_JoystickGetCount() { return SDL_numjoysticks; } -void VITA_JoystickDetect() +static void VITA_JoystickDetect() { } +static SDL_bool VITA_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + /* Function to perform the mapping from device index to the instance id for this index */ -SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index) +static SDL_JoystickID VITA_JoystickGetDeviceInstanceID(int device_index) { return device_index + 1; } -const char *VITA_JoystickGetDeviceName(int index) +static const char *VITA_JoystickGetDeviceName(int index) { if (index == 0) { return "PSVita Controller"; @@ -176,7 +183,7 @@ const char *VITA_JoystickGetDeviceName(int index) return NULL; } -const char *VITA_JoystickGetDevicePath(int index) +static const char *VITA_JoystickGetDevicePath(int index) { return NULL; } @@ -200,12 +207,14 @@ static void VITA_JoystickSetDevicePlayerIndex(int device_index, int player_index This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ -int VITA_JoystickOpen(SDL_Joystick *joystick, int device_index) +static int VITA_JoystickOpen(SDL_Joystick *joystick, int device_index) { joystick->nbuttons = SDL_arraysize(ext_button_map); joystick->naxes = 6; joystick->nhats = 0; - joystick->instance_id = device_index; + + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, SDL_TRUE); + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); return 0; } @@ -306,16 +315,16 @@ static void VITA_JoystickUpdate(SDL_Joystick *joystick) } /* Function to close a joystick after use */ -void VITA_JoystickClose(SDL_Joystick *joystick) +static void VITA_JoystickClose(SDL_Joystick *joystick) { } /* Function to perform any system-specific joystick related cleanup */ -void VITA_JoystickQuit(void) +static void VITA_JoystickQuit(void) { } -SDL_JoystickGUID VITA_JoystickGetDeviceGUID(int device_index) +static SDL_JoystickGUID VITA_JoystickGetDeviceGUID(int device_index) { /* the GUID is just the name for now */ const char *name = VITA_JoystickGetDeviceName(device_index); @@ -344,12 +353,6 @@ static int VITA_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint return SDL_Unsupported(); } -static Uint32 VITA_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - // always return LED and rumble supported for now - return SDL_JOYCAP_LED | SDL_JOYCAP_RUMBLE; -} - static int VITA_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { int index = (int)SDL_GetJoystickInstanceID(joystick) - 1; @@ -381,6 +384,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = { VITA_JoystickInit, VITA_JoystickGetCount, VITA_JoystickDetect, + VITA_JoystickIsDevicePresent, VITA_JoystickGetDeviceName, VITA_JoystickGetDevicePath, VITA_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -388,17 +392,12 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = { VITA_JoystickSetDevicePlayerIndex, VITA_JoystickGetDeviceGUID, VITA_JoystickGetDeviceInstanceID, - VITA_JoystickOpen, - VITA_JoystickRumble, VITA_JoystickRumbleTriggers, - - VITA_JoystickGetCapabilities, VITA_JoystickSetLED, VITA_JoystickSendEffect, VITA_JoystickSetSensorsEnabled, - VITA_JoystickUpdate, VITA_JoystickClose, VITA_JoystickQuit, diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c index 63c31a3c..f96a6515 100644 --- a/src/joystick/windows/SDL_dinputjoystick.c +++ b/src/joystick/windows/SDL_dinputjoystick.c @@ -398,7 +398,7 @@ int SDL_DINPUT_JoystickInit(void) HRESULT result; HINSTANCE instance; - if (!SDL_GetHintBoolean(SDL_HINT_DIRECTINPUT_ENABLED, SDL_TRUE)) { + if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, SDL_TRUE)) { /* In some environments, IDirectInput8_Initialize / _EnumDevices can take a minute even with no controllers. */ dinput = NULL; return 0; @@ -516,13 +516,7 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)); -#ifdef SDL_JOYSTICK_HIDAPI - CHECK(!HIDAPI_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)); -#endif - -#ifdef SDL_JOYSTICK_RAWINPUT - CHECK(!RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)); -#endif + CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname)); WINDOWS_AddJoystickDevice(pNewJoystick); pNewJoystick = NULL; @@ -826,6 +820,8 @@ int SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystic return SetDIerror("IDirectInputDevice8::SetProperty", result); } */ + + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); } /* What buttons and axes does it have? */ @@ -853,6 +849,7 @@ int SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystic } else if (FAILED(result)) { return SetDIerror("IDirectInputDevice8::SetProperty", result); } + joystick->hwdata->first_update = SDL_TRUE; /* Poll and wait for initial device state to be populated */ result = IDirectInputDevice8_Poll(joystick->hwdata->InputDevice); @@ -945,17 +942,6 @@ int SDL_DINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl return 0; } -Uint32 SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - Uint32 result = 0; - - if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) { - result |= SDL_JOYCAP_RUMBLE; - } - - return result; -} - static Uint8 TranslatePOV(DWORD value) { const Uint8 HAT_VALS[] = { @@ -1130,7 +1116,14 @@ void SDL_DINPUT_JoystickUpdate(SDL_Joystick *joystick) IDirectInputDevice8_Poll(joystick->hwdata->InputDevice); } - if (joystick->hwdata->buffered) { + if (joystick->hwdata->first_update) { + /* Poll to get the initial state of the joystick */ + UpdateDINPUTJoystickState_Polled(joystick); + joystick->hwdata->first_update = SDL_FALSE; + return; + } + + if (joystick->hwdata->buffered ) { UpdateDINPUTJoystickState_Buffered(joystick); } else { UpdateDINPUTJoystickState_Polled(joystick); @@ -1193,11 +1186,6 @@ int SDL_DINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl return SDL_Unsupported(); } -Uint32 SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - void SDL_DINPUT_JoystickUpdate(SDL_Joystick *joystick) { } diff --git a/src/joystick/windows/SDL_dinputjoystick_c.h b/src/joystick/windows/SDL_dinputjoystick_c.h index d864f737..780f6a36 100644 --- a/src/joystick/windows/SDL_dinputjoystick_c.h +++ b/src/joystick/windows/SDL_dinputjoystick_c.h @@ -30,7 +30,6 @@ extern void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext); extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version); extern int SDL_DINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice); extern int SDL_DINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); -extern Uint32 SDL_DINPUT_JoystickGetCapabilities(SDL_Joystick *joystick); extern void SDL_DINPUT_JoystickUpdate(SDL_Joystick *joystick); extern void SDL_DINPUT_JoystickClose(SDL_Joystick *joystick); extern void SDL_DINPUT_JoystickQuit(void); diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c index 77add539..e59df1d9 100644 --- a/src/joystick/windows/SDL_rawinputjoystick.c +++ b/src/joystick/windows/SDL_rawinputjoystick.c @@ -686,7 +686,7 @@ static void RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx) typedef HRESULT(WINAPI * WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER * hstringHeader, HSTRING * string); typedef HRESULT(WINAPI * RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory); -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = WindowsCreateStringReference; RoGetActivationFactory_t RoGetActivationFactoryFunc = RoGetActivationFactory; #else @@ -886,10 +886,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice) CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1); /* Only take XInput-capable devices */ CHECK(SDL_strstr(dev_name, "IG_") != NULL); -#ifdef SDL_JOYSTICK_HIDAPI - /* Don't take devices handled by HIDAPI */ - CHECK(!HIDAPI_IsDevicePresent((Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, "")); -#endif + CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_RAWINPUT_JoystickDriver, (Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, "")); device = (SDL_RAWINPUT_Device *)SDL_calloc(1, sizeof(SDL_RAWINPUT_Device)); CHECK(device); device->hDevice = hDevice; @@ -1062,42 +1059,6 @@ SDL_bool RAWINPUT_IsEnabled() return SDL_RAWINPUT_inited && !SDL_RAWINPUT_remote_desktop; } -SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) -{ - SDL_RAWINPUT_Device *device; - - /* If we're being asked about a device, that means another API just detected one, so rescan */ -#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT - xinput_device_change = SDL_TRUE; -#endif - - device = SDL_RAWINPUT_devices; - while (device) { - if (vendor_id == device->vendor_id && product_id == device->product_id) { - return SDL_TRUE; - } - - /* The Xbox 360 wireless controller shows up as product 0 in WGI. - Try to match it to a Raw Input device via name or known product ID. */ - if (vendor_id == device->vendor_id && product_id == 0 && - ((name && SDL_strstr(device->name, name) != NULL) || - (device->vendor_id == USB_VENDOR_MICROSOFT && - device->product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER))) { - return SDL_TRUE; - } - - /* The Xbox One controller shows up as a hardcoded raw input VID/PID */ - if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 && - device->vendor_id == USB_VENDOR_MICROSOFT && - device->product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) { - return SDL_TRUE; - } - - device = device->next; - } - return SDL_FALSE; -} - static void RAWINPUT_PostUpdate(void) { #ifdef SDL_JOYSTICK_RAWINPUT_MATCHING @@ -1181,6 +1142,42 @@ static void RAWINPUT_JoystickDetect(void) RAWINPUT_PostUpdate(); } +static SDL_bool RAWINPUT_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + SDL_RAWINPUT_Device *device; + + /* If we're being asked about a device, that means another API just detected one, so rescan */ +#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT + xinput_device_change = SDL_TRUE; +#endif + + device = SDL_RAWINPUT_devices; + while (device) { + if (vendor_id == device->vendor_id && product_id == device->product_id) { + return SDL_TRUE; + } + + /* The Xbox 360 wireless controller shows up as product 0 in WGI. + Try to match it to a Raw Input device via name or known product ID. */ + if (vendor_id == device->vendor_id && product_id == 0 && + ((name && SDL_strstr(device->name, name) != NULL) || + (device->vendor_id == USB_VENDOR_MICROSOFT && + device->product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER))) { + return SDL_TRUE; + } + + /* The Xbox One controller shows up as a hardcoded raw input VID/PID */ + if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 && + device->vendor_id == USB_VENDOR_MICROSOFT && + device->product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) { + return SDL_TRUE; + } + + device = device->next; + } + return SDL_FALSE; +} + static SDL_RAWINPUT_Device *RAWINPUT_GetDeviceByIndex(int device_index) { SDL_RAWINPUT_Device *device = SDL_RAWINPUT_devices; @@ -1431,6 +1428,21 @@ static int RAWINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; +#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT + if (ctx->is_xinput) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + } +#endif +#ifdef SDL_JOYSTICK_RAWINPUT_WGI + if (ctx->is_xinput) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + + if (ctx->is_xboxone) { + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE); + } + } +#endif + return 0; } @@ -1506,31 +1518,6 @@ static int RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_r #endif } -static Uint32 RAWINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - Uint32 result = 0; -#if defined(SDL_JOYSTICK_RAWINPUT_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT_WGI) - RAWINPUT_DeviceContext *ctx = joystick->hwdata; - -#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT - if (ctx->is_xinput) { - result |= SDL_JOYCAP_RUMBLE; - } -#endif -#ifdef SDL_JOYSTICK_RAWINPUT_WGI - if (ctx->is_xinput) { - result |= SDL_JOYCAP_RUMBLE; - - if (ctx->is_xboxone) { - result |= SDL_JOYCAP_RUMBLE_TRIGGERS; - } - } -#endif -#endif /**/ - - return result; -} - static int RAWINPUT_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -2216,6 +2203,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = { RAWINPUT_JoystickInit, RAWINPUT_JoystickGetCount, RAWINPUT_JoystickDetect, + RAWINPUT_JoystickIsDevicePresent, RAWINPUT_JoystickGetDeviceName, RAWINPUT_JoystickGetDevicePath, RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -2226,7 +2214,6 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = { RAWINPUT_JoystickOpen, RAWINPUT_JoystickRumble, RAWINPUT_JoystickRumbleTriggers, - RAWINPUT_JoystickGetCapabilities, RAWINPUT_JoystickSetLED, RAWINPUT_JoystickSendEffect, RAWINPUT_JoystickSetSensorsEnabled, diff --git a/src/joystick/windows/SDL_rawinputjoystick_c.h b/src/joystick/windows/SDL_rawinputjoystick_c.h index d4f9e79f..510bc8ae 100644 --- a/src/joystick/windows/SDL_rawinputjoystick_c.h +++ b/src/joystick/windows/SDL_rawinputjoystick_c.h @@ -24,9 +24,6 @@ /* Return true if the RawInput driver is enabled */ extern SDL_bool RAWINPUT_IsEnabled(); -/* Return true if a RawInput device is present and supported as a joystick */ -extern SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name); - /* Registers for input events */ extern int RAWINPUT_RegisterNotifications(HWND hWnd); extern int RAWINPUT_UnregisterNotifications(); diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c index c79cf8e7..2ac64a03 100644 --- a/src/joystick/windows/SDL_windows_gaming_input.c +++ b/src/joystick/windows/SDL_windows_gaming_input.c @@ -61,7 +61,7 @@ typedef struct WindowsGamingInputControllerState int steam_virtual_gamepad_slot; } WindowsGamingInputControllerState; -typedef HRESULT(WINAPI *CoIncrementMTAUsage_t)(PVOID *pCookie); +typedef HRESULT(WINAPI *CoIncrementMTAUsage_t)(CO_MTA_USAGE_COOKIE *pCookie); typedef HRESULT(WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void **factory); typedef HRESULT(WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string); typedef HRESULT(WINAPI *WindowsDeleteString_t)(HSTRING string); @@ -106,7 +106,6 @@ DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController2, 0x43c0c035 DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, 0xeb8d0792, 0xe95a, 0x4b19, 0xaf, 0xc7, 0x0a, 0x59, 0xf8, 0xbf, 0x75, 0x9e); extern SDL_bool SDL_XINPUT_Enabled(void); -extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version); static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product) @@ -448,23 +447,12 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde name = SDL_strdup(""); } -#ifdef SDL_JOYSTICK_HIDAPI - if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) { - ignore_joystick = SDL_TRUE; - } -#endif - -#ifdef SDL_JOYSTICK_RAWINPUT - if (!ignore_joystick && RAWINPUT_IsDevicePresent(vendor, product, version, name)) { - ignore_joystick = SDL_TRUE; - } -#endif - - if (!ignore_joystick && SDL_DINPUT_JoystickPresent(vendor, product, version)) { + if (!ignore_joystick && SDL_JoystickHandledByAnotherDriver(&SDL_WGI_JoystickDriver, vendor, product, version, name)) { ignore_joystick = SDL_TRUE; } if (!ignore_joystick && SDL_IsXInputDevice(vendor, product)) { + /* This hasn't been detected by the RAWINPUT driver yet, but it will be picked up later. */ ignore_joystick = SDL_TRUE; } @@ -563,6 +551,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeRemo #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4028) /* formal parameter 3 different from declaration, when using older buggy WGI headers */ +#pragma warning(disable : 4113) /* formal parameter 3 different from declaration (a more specific warning added in VS 2022), when using older buggy WGI headers */ #endif static __FIEventHandler_1_Windows__CGaming__CInput__CRawGameControllerVtbl controller_added_vtbl = { @@ -603,7 +592,7 @@ static int WGI_JoystickInit(void) return SDL_SetError("RoInitialize() failed"); } -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT wgi.CoIncrementMTAUsage = CoIncrementMTAUsage; wgi.RoGetActivationFactory = RoGetActivationFactory; wgi.WindowsCreateStringReference = WindowsCreateStringReference; @@ -617,16 +606,16 @@ static int WGI_JoystickInit(void) RESOLVE(WindowsDeleteString); RESOLVE(WindowsGetStringRawBuffer); #undef RESOLVE -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT { /* There seems to be a bug in Windows where a dependency of WGI can be unloaded from memory prior to WGI itself. * This results in Windows_Gaming_Input!GameController::~GameController() invoking an unloaded DLL and crashing. * As a workaround, we will keep a reference to the MTA to prevent COM from unloading DLLs later. * See https://github.com/libsdl-org/SDL/issues/5552 for more details. */ - static PVOID cookie = NULL; + static CO_MTA_USAGE_COOKIE cookie = NULL; if (!cookie) { hr = wgi.CoIncrementMTAUsage(&cookie); if (FAILED(hr)) { @@ -684,6 +673,12 @@ static void WGI_JoystickDetect(void) { } +static SDL_bool WGI_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + /* We don't override any other drivers */ + return SDL_FALSE; +} + static const char *WGI_JoystickGetDeviceName(int device_index) { return wgi.controllers[device_index].name; @@ -749,6 +744,11 @@ static int WGI_JoystickOpen(SDL_Joystick *joystick, int device_index) __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(hwdata->controller, &joystick->naxes); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_SwitchCount(hwdata->controller, &joystick->nhats); + if (hwdata->gamepad) { + /* FIXME: Can WGI even tell us if trigger rumble is supported? */ + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE); + } return 0; } @@ -794,18 +794,6 @@ static int WGI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble } } -static Uint32 WGI_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - struct joystick_hwdata *hwdata = joystick->hwdata; - - if (hwdata->gamepad) { - /* FIXME: Can WGI even tell us if trigger rumble is supported? */ - return SDL_JOYCAP_RUMBLE | SDL_JOYCAP_RUMBLE_TRIGGERS; - } else { - return 0; - } -} - static int WGI_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -1016,6 +1004,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = { WGI_JoystickInit, WGI_JoystickGetCount, WGI_JoystickDetect, + WGI_JoystickIsDevicePresent, WGI_JoystickGetDeviceName, WGI_JoystickGetDevicePath, WGI_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -1026,7 +1015,6 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = { WGI_JoystickOpen, WGI_JoystickRumble, WGI_JoystickRumbleTriggers, - WGI_JoystickGetCapabilities, WGI_JoystickSetLED, WGI_JoystickSendEffect, WGI_JoystickSetSensorsEnabled, diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 11aa16a9..6bd204ae 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -35,7 +35,8 @@ #include "../SDL_sysjoystick.h" #include "../../thread/SDL_systhread.h" #include "../../core/windows/SDL_windows.h" -#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#include "../../core/windows/SDL_hid.h" +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) #include #endif @@ -46,168 +47,39 @@ #include "SDL_rawinputjoystick_c.h" #include "../../haptic/windows/SDL_dinputhaptic_c.h" /* For haptic hot plugging */ -#include "../../haptic/windows/SDL_xinputhaptic_c.h" /* For haptic hot plugging */ #ifndef DEVICE_NOTIFY_WINDOW_HANDLE #define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000 #endif -/* CM_Register_Notification definitions */ - -#define CR_SUCCESS (0x00000000) - -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -DECLARE_HANDLE(HCMNOTIFICATION); -typedef HCMNOTIFICATION *PHCMNOTIFICATION; - -typedef enum _CM_NOTIFY_FILTER_TYPE -{ - CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE = 0, - CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE, - CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE, - CM_NOTIFY_FILTER_TYPE_MAX -} CM_NOTIFY_FILTER_TYPE, - *PCM_NOTIFY_FILTER_TYPE; - -typedef struct _CM_NOTIFY_FILTER -{ - DWORD cbSize; - DWORD Flags; - CM_NOTIFY_FILTER_TYPE FilterType; - DWORD Reserved; - union - { - struct - { - GUID ClassGuid; - } DeviceInterface; - struct - { - HANDLE hTarget; - } DeviceHandle; - struct - { - WCHAR InstanceId[200]; - } DeviceInstance; - } u; -} CM_NOTIFY_FILTER, *PCM_NOTIFY_FILTER; - -typedef enum _CM_NOTIFY_ACTION -{ - CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL = 0, - CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL, - CM_NOTIFY_ACTION_DEVICEQUERYREMOVE, - CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED, - CM_NOTIFY_ACTION_DEVICEREMOVEPENDING, - CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE, - CM_NOTIFY_ACTION_DEVICECUSTOMEVENT, - CM_NOTIFY_ACTION_DEVICEINSTANCEENUMERATED, - CM_NOTIFY_ACTION_DEVICEINSTANCESTARTED, - CM_NOTIFY_ACTION_DEVICEINSTANCEREMOVED, - CM_NOTIFY_ACTION_MAX -} CM_NOTIFY_ACTION, - *PCM_NOTIFY_ACTION; - -typedef struct _CM_NOTIFY_EVENT_DATA -{ - CM_NOTIFY_FILTER_TYPE FilterType; - DWORD Reserved; - union - { - struct - { - GUID ClassGuid; - WCHAR SymbolicLink[ANYSIZE_ARRAY]; - } DeviceInterface; - struct - { - GUID EventGuid; - LONG NameOffset; - DWORD DataSize; - BYTE Data[ANYSIZE_ARRAY]; - } DeviceHandle; - struct - { - WCHAR InstanceId[ANYSIZE_ARRAY]; - } DeviceInstance; - } u; -} CM_NOTIFY_EVENT_DATA, *PCM_NOTIFY_EVENT_DATA; - -typedef DWORD(CALLBACK *PCM_NOTIFY_CALLBACK)(HCMNOTIFICATION hNotify, PVOID Context, CM_NOTIFY_ACTION Action, PCM_NOTIFY_EVENT_DATA EventData, DWORD EventDataSize); - -typedef DWORD(WINAPI *CM_Register_NotificationFunc)(PCM_NOTIFY_FILTER pFilter, PVOID pContext, PCM_NOTIFY_CALLBACK pCallback, PHCMNOTIFICATION pNotifyContext); -typedef DWORD(WINAPI *CM_Unregister_NotificationFunc)(HCMNOTIFICATION NotifyContext); - /* local variables */ static SDL_bool s_bJoystickThread = SDL_FALSE; -static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE; static SDL_Condition *s_condJoystickThread = NULL; static SDL_Mutex *s_mutexJoyStickEnum = NULL; static SDL_Thread *s_joystickThread = NULL; static SDL_bool s_bJoystickThreadQuit = SDL_FALSE; +static Uint64 s_lastDeviceChange = 0; static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */ -#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) -static HMODULE cfgmgr32_lib_handle; -static CM_Register_NotificationFunc CM_Register_Notification; -static CM_Unregister_NotificationFunc CM_Unregister_Notification; -static HCMNOTIFICATION s_DeviceNotificationFuncHandle; + +static SDL_bool WindowsDeviceChanged(void) +{ + return (s_lastDeviceChange != WIN_GetLastDeviceNotification()); +} + +static void SetWindowsDeviceChanged(void) +{ + s_lastDeviceChange = 0; +} void WINDOWS_RAWINPUTEnabledChanged(void) { - s_bWindowsDeviceChanged = SDL_TRUE; + SetWindowsDeviceChanged(); } -static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size) -{ - if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL || - action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) { - s_bWindowsDeviceChanged = SDL_TRUE; - } - return ERROR_SUCCESS; -} - -static void SDL_CleanupDeviceNotificationFunc(void) -{ - if (cfgmgr32_lib_handle) { - if (s_DeviceNotificationFuncHandle != NULL && CM_Unregister_Notification) { - CM_Unregister_Notification(s_DeviceNotificationFuncHandle); - s_DeviceNotificationFuncHandle = NULL; - } - - FreeLibrary(cfgmgr32_lib_handle); - cfgmgr32_lib_handle = NULL; - } -} - -static SDL_bool SDL_CreateDeviceNotificationFunc(void) -{ - cfgmgr32_lib_handle = LoadLibraryA("cfgmgr32.dll"); - if (cfgmgr32_lib_handle) { - CM_Register_Notification = (CM_Register_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Register_Notification"); - CM_Unregister_Notification = (CM_Unregister_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Unregister_Notification"); - if (CM_Register_Notification && CM_Unregister_Notification) { - CM_NOTIFY_FILTER notify_filter; - - SDL_zero(notify_filter); - notify_filter.cbSize = sizeof(notify_filter); - notify_filter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; - notify_filter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_HID; - if (CM_Register_Notification(¬ify_filter, NULL, SDL_DeviceNotificationFunc, &s_DeviceNotificationFuncHandle) == CR_SUCCESS) { - return SDL_TRUE; - } - } - } - - SDL_CleanupDeviceNotificationFunc(); - return SDL_FALSE; -} +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) typedef struct { @@ -240,7 +112,7 @@ static LRESULT CALLBACK SDL_PrivateJoystickDetectProc(HWND hwnd, UINT msg, WPARA if (wParam == IDT_SDL_DEVICE_CHANGE_TIMER_1 || wParam == IDT_SDL_DEVICE_CHANGE_TIMER_2) { KillTimer(hwnd, wParam); - s_bWindowsDeviceChanged = SDL_TRUE; + SetWindowsDeviceChanged(); return 0; } break; @@ -328,7 +200,7 @@ static SDL_bool SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, } SDL_UnlockMutex(mutex); - while (lastret > 0 && s_bWindowsDeviceChanged == SDL_FALSE) { + while (lastret > 0 && !WindowsDeviceChanged()) { lastret = GetMessage(&msg, NULL, 0, 0); /* WM_QUIT causes return value of 0 */ if (lastret > 0) { TranslateMessage(&msg); @@ -339,11 +211,11 @@ static SDL_bool SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, return (lastret != -1); } -#endif /* !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) */ +#endif /* !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) */ -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) static SDL_DeviceNotificationData s_notification_data; #endif @@ -355,7 +227,7 @@ static int SDLCALL SDL_JoystickThread(void *_data) SDL_zeroa(bOpenedXInputDevices); #endif -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) if (SDL_CreateDeviceNotification(&s_notification_data) < 0) { return -1; } @@ -363,7 +235,7 @@ static int SDLCALL SDL_JoystickThread(void *_data) SDL_LockMutex(s_mutexJoyStickEnum); while (s_bJoystickThreadQuit == SDL_FALSE) { -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) if (SDL_WaitForDeviceNotification(&s_notification_data, s_mutexJoyStickEnum) == SDL_FALSE) { #else { @@ -379,7 +251,7 @@ static int SDLCALL SDL_JoystickThread(void *_data) const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities); const SDL_bool available = (result == ERROR_SUCCESS); if (bOpenedXInputDevices[userId] != available) { - s_bWindowsDeviceChanged = SDL_TRUE; + SetWindowsDeviceChanged(); bOpenedXInputDevices[userId] = available; } } @@ -393,7 +265,7 @@ static int SDLCALL SDL_JoystickThread(void *_data) SDL_UnlockMutex(s_mutexJoyStickEnum); -#if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) SDL_CleanupDeviceNotification(&s_notification_data); #endif @@ -431,7 +303,7 @@ static void SDL_StopJoystickThread(void) s_bJoystickThreadQuit = SDL_TRUE; SDL_BroadcastCondition(s_condJoystickThread); /* signal the joystick thread to quit */ SDL_UnlockMutex(s_mutexJoyStickEnum); - PostThreadMessage(SDL_GetThreadID(s_joystickThread), WM_QUIT, 0, 0); + PostThreadMessage((DWORD)SDL_GetThreadID(s_joystickThread), WM_QUIT, 0, 0); /* Unlock joysticks while the joystick thread finishes processing messages */ SDL_AssertJoysticksLocked(); @@ -448,7 +320,7 @@ static void SDL_StopJoystickThread(void) s_joystickThread = NULL; } -#endif /* !defined(__WINRT__) */ +#endif /* !defined(SDL_PLATFORM_WINRT) */ void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device) { @@ -477,13 +349,9 @@ static int WINDOWS_JoystickInit(void) return -1; } - s_bWindowsDeviceChanged = SDL_TRUE; /* force a scan of the system for joysticks this first time */ - - WINDOWS_JoystickDetect(); - -#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) - SDL_CreateDeviceNotificationFunc(); + WIN_InitDeviceNotification(); +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) s_bJoystickThread = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_THREAD, SDL_FALSE); if (s_bJoystickThread) { if (SDL_StartJoystickThread() < 0) { @@ -496,13 +364,18 @@ static int WINDOWS_JoystickInit(void) } #endif -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) /* On Xbox, force create the joystick thread for device detection (since other methods don't work */ s_bJoystickThread = SDL_TRUE; if (SDL_StartJoystickThread() < 0) { return -1; } #endif + + SetWindowsDeviceChanged(); /* force a scan of the system for joysticks this first time */ + + WINDOWS_JoystickDetect(); + return 0; } @@ -525,7 +398,7 @@ void WINDOWS_JoystickDetect(void) JoyStick_DeviceData *pCurList = NULL; /* only enum the devices if the joystick thread told us something changed */ - if (!s_bWindowsDeviceChanged) { + if (!WindowsDeviceChanged()) { return; /* thread hasn't signaled, nothing to do right now. */ } @@ -533,7 +406,7 @@ void WINDOWS_JoystickDetect(void) SDL_LockMutex(s_mutexJoyStickEnum); } - s_bWindowsDeviceChanged = SDL_FALSE; + s_lastDeviceChange = WIN_GetLastDeviceNotification(); pCurList = SYS_Joystick; SYS_Joystick = NULL; @@ -551,11 +424,7 @@ void WINDOWS_JoystickDetect(void) while (pCurList) { JoyStick_DeviceData *pListNext = NULL; - if (pCurList->bXInputDevice) { -#ifdef SDL_HAPTIC_XINPUT - SDL_XINPUT_HapticMaybeRemoveDevice(pCurList->XInputUserId); -#endif - } else { + if (!pCurList->bXInputDevice) { #ifdef SDL_HAPTIC_DINPUT SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice); #endif @@ -571,11 +440,7 @@ void WINDOWS_JoystickDetect(void) for (pCurList = SYS_Joystick; pCurList; pCurList = pCurList->pNext) { if (pCurList->send_add_event) { - if (pCurList->bXInputDevice) { -#ifdef SDL_HAPTIC_XINPUT - SDL_XINPUT_HapticMaybeAddDevice(pCurList->XInputUserId); -#endif - } else { + if (!pCurList->bXInputDevice) { #ifdef SDL_HAPTIC_DINPUT SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice); #endif @@ -588,6 +453,17 @@ void WINDOWS_JoystickDetect(void) } } +static SDL_bool WINDOWS_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) +{ + if (SDL_DINPUT_JoystickPresent(vendor_id, product_id, version)) { + return SDL_TRUE; + } + if (SDL_XINPUT_JoystickPresent(vendor_id, product_id, version)) { + return SDL_TRUE; + } + return SDL_FALSE; +} + static const char *WINDOWS_JoystickGetDeviceName(int device_index) { JoyStick_DeviceData *device = SYS_Joystick; @@ -713,15 +589,6 @@ static int WINDOWS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_ru return SDL_Unsupported(); } -static Uint32 WINDOWS_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - if (joystick->hwdata->bXInputDevice) { - return SDL_XINPUT_JoystickGetCapabilities(joystick); - } else { - return SDL_DINPUT_JoystickGetCapabilities(joystick); - } -} - static int WINDOWS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) { return SDL_Unsupported(); @@ -775,17 +642,15 @@ void WINDOWS_JoystickQuit(void) } SYS_Joystick = NULL; -#if !defined(__WINRT__) && !defined(__XBOXONE__) && !defined(__XBOXSERIES__) +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) if (s_bJoystickThread) { SDL_StopJoystickThread(); } else { SDL_CleanupDeviceNotification(&s_notification_data); } - - SDL_CleanupDeviceNotificationFunc(); #endif -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) if (s_bJoystickThread) { SDL_StopJoystickThread(); } @@ -794,7 +659,7 @@ void WINDOWS_JoystickQuit(void) SDL_DINPUT_JoystickQuit(); SDL_XINPUT_JoystickQuit(); - s_bWindowsDeviceChanged = SDL_FALSE; + WIN_QuitDeviceNotification(); } static SDL_bool WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) @@ -806,6 +671,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = { WINDOWS_JoystickInit, WINDOWS_JoystickGetCount, WINDOWS_JoystickDetect, + WINDOWS_JoystickIsDevicePresent, WINDOWS_JoystickGetDeviceName, WINDOWS_JoystickGetDevicePath, WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot, @@ -816,7 +682,6 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = { WINDOWS_JoystickOpen, WINDOWS_JoystickRumble, WINDOWS_JoystickRumbleTriggers, - WINDOWS_JoystickGetCapabilities, WINDOWS_JoystickSetLED, WINDOWS_JoystickSendEffect, WINDOWS_JoystickSetSensorsEnabled, @@ -826,11 +691,6 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = { WINDOWS_JoystickGetGamepadMapping }; -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif - #else #ifdef SDL_JOYSTICK_RAWINPUT diff --git a/src/joystick/windows/SDL_windowsjoystick_c.h b/src/joystick/windows/SDL_windowsjoystick_c.h index cea67f91..1493589e 100644 --- a/src/joystick/windows/SDL_windowsjoystick_c.h +++ b/src/joystick/windows/SDL_windowsjoystick_c.h @@ -76,6 +76,7 @@ struct joystick_hwdata LPDIRECTINPUTDEVICE8 InputDevice; DIDEVCAPS Capabilities; SDL_bool buffered; + SDL_bool first_update; input_t Inputs[MAX_INPUTS]; int NumInputs; int NumSliders; diff --git a/src/joystick/windows/SDL_xinputjoystick.c b/src/joystick/windows/SDL_xinputjoystick.c index 42a5f41e..09739eb7 100644 --- a/src/joystick/windows/SDL_xinputjoystick.c +++ b/src/joystick/windows/SDL_xinputjoystick.c @@ -39,23 +39,6 @@ extern "C" { */ static SDL_bool s_bXInputEnabled = SDL_TRUE; -static SDL_bool SDL_XInputUseOldJoystickMapping() -{ -#ifdef __WINRT__ - /* TODO: remove this __WINRT__ block, but only after integrating with UWP/WinRT's HID API */ - /* FIXME: Why are Win8/10 different here? -flibit */ - return NTDDI_VERSION < NTDDI_WIN10; -#elif defined(__XBOXONE__) || defined(__XBOXSERIES__) - return SDL_FALSE; -#else - static int s_XInputUseOldJoystickMapping = -1; - if (s_XInputUseOldJoystickMapping < 0) { - s_XInputUseOldJoystickMapping = SDL_GetHintBoolean(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING, SDL_FALSE); - } - return s_XInputUseOldJoystickMapping > 0; -#endif -} - SDL_bool SDL_XINPUT_Enabled(void) { return s_bXInputEnabled; @@ -75,49 +58,52 @@ static const char *GetXInputName(const Uint8 userid, BYTE SubType) { static char name[32]; - if (SDL_XInputUseOldJoystickMapping()) { - (void)SDL_snprintf(name, sizeof(name), "X360 Controller #%d", 1 + userid); - } else { - switch (SubType) { - case XINPUT_DEVSUBTYPE_GAMEPAD: - (void)SDL_snprintf(name, sizeof(name), "XInput Controller #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_WHEEL: - (void)SDL_snprintf(name, sizeof(name), "XInput Wheel #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_ARCADE_STICK: - (void)SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_FLIGHT_STICK: - (void)SDL_snprintf(name, sizeof(name), "XInput FlightStick #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_DANCE_PAD: - (void)SDL_snprintf(name, sizeof(name), "XInput DancePad #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_GUITAR: - case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE: - case XINPUT_DEVSUBTYPE_GUITAR_BASS: - (void)SDL_snprintf(name, sizeof(name), "XInput Guitar #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_DRUM_KIT: - (void)SDL_snprintf(name, sizeof(name), "XInput DrumKit #%d", 1 + userid); - break; - case XINPUT_DEVSUBTYPE_ARCADE_PAD: - (void)SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%d", 1 + userid); - break; - default: - (void)SDL_snprintf(name, sizeof(name), "XInput Device #%d", 1 + userid); - break; - } + switch (SubType) { + case XINPUT_DEVSUBTYPE_GAMEPAD: + (void)SDL_snprintf(name, sizeof(name), "XInput Controller #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_WHEEL: + (void)SDL_snprintf(name, sizeof(name), "XInput Wheel #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_ARCADE_STICK: + (void)SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_FLIGHT_STICK: + (void)SDL_snprintf(name, sizeof(name), "XInput FlightStick #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_DANCE_PAD: + (void)SDL_snprintf(name, sizeof(name), "XInput DancePad #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_GUITAR: + case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE: + case XINPUT_DEVSUBTYPE_GUITAR_BASS: + (void)SDL_snprintf(name, sizeof(name), "XInput Guitar #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_DRUM_KIT: + (void)SDL_snprintf(name, sizeof(name), "XInput DrumKit #%d", 1 + userid); + break; + case XINPUT_DEVSUBTYPE_ARCADE_PAD: + (void)SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%d", 1 + userid); + break; + default: + (void)SDL_snprintf(name, sizeof(name), "XInput Device #%d", 1 + userid); + break; } return name; } static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion) { - XINPUT_CAPABILITIES_EX capabilities; + SDL_XINPUT_CAPABILITIES_EX capabilities; if (!XINPUTGETCAPABILITIESEX || XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) != ERROR_SUCCESS) { + /* Use a generic VID/PID representing an XInput controller */ + if (pVID) { + *pVID = USB_VENDOR_MICROSOFT; + } + if (pPID) { + *pPID = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; + } return SDL_FALSE; } @@ -141,7 +127,7 @@ static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Ui int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid) { - XINPUT_CAPABILITIES_EX capabilities; + SDL_XINPUT_CAPABILITIES_EX capabilities; if (XINPUTGETCAPABILITIESEX && XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) == ERROR_SUCCESS && @@ -175,10 +161,6 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC } #endif - if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD) { - return; - } - if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN) { return; } @@ -215,9 +197,7 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC return; /* better luck next time? */ } (void)SDL_snprintf(pNewJoystick->path, sizeof(pNewJoystick->path), "XInput#%u", userid); - if (!SDL_XInputUseOldJoystickMapping()) { - pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 'x', SubType); - } + pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, vendor, product, version, NULL, name, 'x', SubType); pNewJoystick->SubType = SubType; pNewJoystick->XInputUserId = userid; @@ -226,22 +206,10 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC return; } -#ifdef SDL_JOYSTICK_HIDAPI - /* Since we're guessing about the VID/PID, use a hard-coded VID/PID to represent XInput */ - if (HIDAPI_IsDevicePresent(USB_VENDOR_MICROSOFT, USB_PRODUCT_XBOX360_XUSB_CONTROLLER, version, pNewJoystick->joystickname)) { - /* The HIDAPI driver is taking care of this device */ + if (SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname)) { SDL_free(pNewJoystick); return; } -#endif - -#ifdef SDL_JOYSTICK_RAWINPUT - if (RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)) { - /* The RAWINPUT driver is taking care of this device */ - SDL_free(pNewJoystick); - return; - } -#endif WINDOWS_AddJoystickDevice(pNewJoystick); } @@ -264,6 +232,29 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext) } } +SDL_bool SDL_XINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version) +{ + int iuserid; + + if (!s_bXInputEnabled) { + return SDL_FALSE; + } + + /* iterate in reverse, so these are in the final list in ascending numeric order. */ + for (iuserid = 0; iuserid < XUSER_MAX_COUNT; ++iuserid) { + const Uint8 userid = (Uint8)iuserid; + Uint16 slot_vendor; + Uint16 slot_product; + Uint16 slot_version; + if (GetXInputDeviceInfo(userid, &slot_vendor, &slot_product, &slot_version)) { + if (vendor == slot_vendor && product == slot_product && version == slot_version) { + return SDL_TRUE; + } + } + } + return SDL_FALSE; +} + int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice) { const Uint8 userId = joystickdevice->XInputUserId; @@ -287,14 +278,12 @@ int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystic joystick->hwdata->userid = userId; /* The XInput API has a hard coded button/axis mapping, so we just match it */ - if (SDL_XInputUseOldJoystickMapping()) { - joystick->naxes = 6; - joystick->nbuttons = 15; - } else { - joystick->naxes = 6; - joystick->nbuttons = 11; - joystick->nhats = 1; - } + joystick->naxes = 6; + joystick->nbuttons = 11; + joystick->nhats = 1; + + SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE); + return 0; } @@ -326,33 +315,6 @@ static void UpdateXInputJoystickBatteryInformation(SDL_Joystick *joystick, XINPU } } -static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation) -{ - static WORD s_XInputButtons[] = { - XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT, - XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB, - XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, - XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y, - XINPUT_GAMEPAD_GUIDE - }; - WORD wButtons = pXInputState->Gamepad.wButtons; - Uint8 button; - Uint64 timestamp = SDL_GetTicksNS(); - - SDL_SendJoystickAxis(timestamp, joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX); - SDL_SendJoystickAxis(timestamp, joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY))); - SDL_SendJoystickAxis(timestamp, joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX); - SDL_SendJoystickAxis(timestamp, joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY))); - SDL_SendJoystickAxis(timestamp, joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768)); - SDL_SendJoystickAxis(timestamp, joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768)); - - for (button = 0; button < (Uint8)SDL_arraysize(s_XInputButtons); ++button) { - SDL_SendJoystickButton(timestamp, joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED); - } - - UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation); -} - static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation) { static WORD s_XInputButtons[] = { @@ -410,11 +372,6 @@ int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl return 0; } -Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return SDL_JOYCAP_RUMBLE; -} - void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick) { DWORD result; @@ -435,17 +392,13 @@ void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick) result = XINPUTGETBATTERYINFORMATION(joystick->hwdata->userid, BATTERY_DEVTYPE_GAMEPAD, &XBatteryInformation); } -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) /* XInputOnGameInput doesn't ever change dwPacketNumber, so have to just update every frame */ UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation); #else /* only fire events if the data changed from last time */ if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) { - if (SDL_XInputUseOldJoystickMapping()) { - UpdateXInputJoystickState_OLD(joystick, &XInputState, &XBatteryInformation); - } else { - UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation); - } + UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation); joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber; } #endif @@ -485,6 +438,11 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext) { } +SDL_bool SDL_XINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version) +{ + return SDL_FALSE; +} + int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice) { return SDL_Unsupported(); @@ -495,11 +453,6 @@ int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumbl return SDL_Unsupported(); } -Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick) -{ - return 0; -} - void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick) { } diff --git a/src/joystick/windows/SDL_xinputjoystick_c.h b/src/joystick/windows/SDL_xinputjoystick_c.h index 18008638..b244ced3 100644 --- a/src/joystick/windows/SDL_xinputjoystick_c.h +++ b/src/joystick/windows/SDL_xinputjoystick_c.h @@ -30,9 +30,9 @@ extern "C" { extern SDL_bool SDL_XINPUT_Enabled(void); extern int SDL_XINPUT_JoystickInit(void); extern void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext); +extern SDL_bool SDL_XINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version); extern int SDL_XINPUT_JoystickOpen(SDL_Joystick *joystick, JoyStick_DeviceData *joystickdevice); extern int SDL_XINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); -extern Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickQuit(void); diff --git a/src/libm/k_rem_pio2.c b/src/libm/k_rem_pio2.c index 4b807591..3dd5b2bf 100644 --- a/src/libm/k_rem_pio2.c +++ b/src/libm/k_rem_pio2.c @@ -271,13 +271,11 @@ recompute: } /* compute PIo2[0,...,jp]*q[jz,...,0] */ + SDL_zero(fq); for(i=jz;i>=0;i--) { for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; fq[jz-i] = fw; } - if ((jz+1) < SDL_arraysize(f)) { - SDL_memset(&fq[jz+1], 0, sizeof (fq) - ((jz+1) * sizeof (fq[0]))); - } /* compress fq[] into y[] */ switch(prec) { diff --git a/src/libm/math_private.h b/src/libm/math_private.h index ba5d8346..9beb4102 100644 --- a/src/libm/math_private.h +++ b/src/libm/math_private.h @@ -26,7 +26,7 @@ #define libm_hidden_def(x) #define strong_alias(x, y) -#if !defined(__HAIKU__) && !defined(__PSP__) && !defined(__3DS__) && !defined(__PS2__) /* already defined in a system header. */ +#if !defined(SDL_PLATFORM_HAIKU) && !defined(SDL_PLATFORM_PSP) && !defined(SDL_PLATFORM_3DS) && !defined(SDL_PLATFORM_PS2) /* already defined in a system header. */ typedef unsigned int u_int32_t; #endif diff --git a/src/loadso/dummy/SDL_sysloadso.c b/src/loadso/dummy/SDL_sysloadso.c index 9a2f524b..476d8447 100644 --- a/src/loadso/dummy/SDL_sysloadso.c +++ b/src/loadso/dummy/SDL_sysloadso.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_LOADSO_DUMMY) || defined(SDL_LOADSO_DISABLED) +#if defined(SDL_LOADSO_DUMMY) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* System dependent library loading routines */ @@ -44,4 +44,4 @@ void SDL_UnloadObject(void *handle) /* no-op. */ } -#endif /* SDL_LOADSO_DUMMY || SDL_LOADSO_DISABLED */ +#endif /* SDL_LOADSO_DUMMY */ diff --git a/src/loadso/windows/SDL_sysloadso.c b/src/loadso/windows/SDL_sysloadso.c index 92a61beb..6ddfb19b 100644 --- a/src/loadso/windows/SDL_sysloadso.c +++ b/src/loadso/windows/SDL_sysloadso.c @@ -37,7 +37,7 @@ void *SDL_LoadObject(const char *sofile) return NULL; } tstr = WIN_UTF8ToString(sofile); -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT /* WinRT only publicly supports LoadPackagedLibrary() for loading .dll files. LoadLibrary() is a private API, and not available for apps (that can be published to MS' Windows Store.) @@ -60,7 +60,7 @@ void *SDL_LoadObject(const char *sofile) SDL_FunctionPointer SDL_LoadFunction(void *handle, const char *name) { - void *symbol = (void *)GetProcAddress((HMODULE)handle, name); + SDL_FunctionPointer symbol = (SDL_FunctionPointer)GetProcAddress((HMODULE)handle, name); if (!symbol) { char errbuf[512]; SDL_strlcpy(errbuf, "Failed loading ", SDL_arraysize(errbuf)); diff --git a/src/locale/n3ds/SDL_syslocale.c b/src/locale/n3ds/SDL_syslocale.c index 02ba03a4..7bbde70d 100644 --- a/src/locale/n3ds/SDL_syslocale.c +++ b/src/locale/n3ds/SDL_syslocale.c @@ -33,7 +33,7 @@ int SDL_SYS_GetPreferredLocales(char *buf, size_t buflen) { /* The 3DS only supports these 12 languages, only one can be active at a time */ static const char AVAILABLE_LOCALES[][6] = { "ja_JP", "en_US", "fr_FR", "de_DE", - "it_IT", "es_ES", "zn_CN", "ko_KR", + "it_IT", "es_ES", "zh_CN", "ko_KR", "nl_NL", "pt_PT", "ru_RU", "zh_TW" }; u8 current_locale = GetLocaleIndex(); if (current_locale != BAD_LOCALE) { @@ -45,12 +45,11 @@ int SDL_SYS_GetPreferredLocales(char *buf, size_t buflen) static u8 GetLocaleIndex(void) { u8 current_locale; + Result result; if (R_FAILED(cfguInit())) { return BAD_LOCALE; } - if (R_FAILED(CFGU_GetSystemLanguage(¤t_locale))) { - return BAD_LOCALE; - } + result = CFGU_GetSystemLanguage(¤t_locale); cfguExit(); - return current_locale; + return R_SUCCEEDED(result) ? current_locale : BAD_LOCALE; } diff --git a/src/main/SDL_main_callbacks.c b/src/main/SDL_main_callbacks.c index a89ffb91..a87a56b2 100644 --- a/src/main/SDL_main_callbacks.c +++ b/src/main/SDL_main_callbacks.c @@ -26,6 +26,7 @@ static SDL_AppEvent_func SDL_main_event_callback; static SDL_AppIterate_func SDL_main_iteration_callback; static SDL_AppQuit_func SDL_main_quit_callback; static SDL_AtomicInt apprc; // use an atomic, since events might land from any thread and we don't want to wrap this all in a mutex. A CAS makes sure we only move from zero once. +static void *SDL_main_appstate = NULL; // Return true if this event needs to be processed before returning from the event watcher static SDL_bool ShouldDispatchImmediately(SDL_Event *event) @@ -46,7 +47,7 @@ static SDL_bool ShouldDispatchImmediately(SDL_Event *event) static void SDL_DispatchMainCallbackEvent(SDL_Event *event) { if (SDL_AtomicGet(&apprc) == 0) { // if already quitting, don't send the event to the app. - SDL_AtomicCAS(&apprc, 0, SDL_main_event_callback(event)); + SDL_AtomicCompareAndSwap(&apprc, 0, SDL_main_event_callback(SDL_main_appstate, event)); } } @@ -95,8 +96,8 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_ SDL_main_quit_callback = appquit; SDL_AtomicSet(&apprc, 0); - const int rc = appinit(argc, argv); - if (SDL_AtomicCAS(&apprc, 0, rc) && (rc == 0)) { // bounce if SDL_AppInit already said abort, otherwise... + const int rc = appinit(&SDL_main_appstate, argc, argv); + if (SDL_AtomicCompareAndSwap(&apprc, 0, rc) && (rc == 0)) { // bounce if SDL_AppInit already said abort, otherwise... // make sure we definitely have events initialized, even if the app didn't do it. if (SDL_InitSubSystem(SDL_INIT_EVENTS) == -1) { SDL_AtomicSet(&apprc, -1); @@ -121,8 +122,8 @@ int SDL_IterateMainCallbacks(SDL_bool pump_events) int rc = SDL_AtomicGet(&apprc); if (rc == 0) { - rc = SDL_main_iteration_callback(); - if (!SDL_AtomicCAS(&apprc, 0, rc)) { + rc = SDL_main_iteration_callback(SDL_main_appstate); + if (!SDL_AtomicCompareAndSwap(&apprc, 0, rc)) { rc = SDL_AtomicGet(&apprc); // something else already set a quit result, keep that. } } @@ -132,7 +133,8 @@ int SDL_IterateMainCallbacks(SDL_bool pump_events) void SDL_QuitMainCallbacks(void) { SDL_DelEventWatch(SDL_MainCallbackEventWatcher, NULL); - SDL_main_quit_callback(); + SDL_main_quit_callback(SDL_main_appstate); + SDL_main_appstate = NULL; // just in case. // for symmetry, you should explicitly Quit what you Init, but we might come through here uninitialized and SDL_Quit() will clear everything anyhow. //SDL_QuitSubSystem(SDL_INIT_EVENTS); diff --git a/src/main/SDL_main_callbacks.h b/src/main/SDL_main_callbacks.h index 5a906cfc..54cda2fc 100644 --- a/src/main/SDL_main_callbacks.h +++ b/src/main/SDL_main_callbacks.h @@ -22,7 +22,7 @@ #ifndef SDL_main_callbacks_h_ #define SDL_main_callbacks_h_ -SDL_bool SDL_HasMainCallbacks(); +SDL_bool SDL_HasMainCallbacks(void); int SDL_InitMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func _appiter, SDL_AppEvent_func _appevent, SDL_AppQuit_func _appquit); int SDL_IterateMainCallbacks(SDL_bool pump_events); void SDL_QuitMainCallbacks(void); diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index 8adbf6c4..59bfbad9 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -23,7 +23,7 @@ #include "../SDL_main_callbacks.h" #include "../../video/SDL_sysvideo.h" -#ifndef __IOS__ +#ifndef SDL_PLATFORM_IOS static int callback_rate_increment = 0; @@ -80,4 +80,4 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, return (rc < 0) ? 1 : 0; } -#endif // !__IOS__ +#endif // !SDL_PLATFORM_IOS diff --git a/src/main/ios/SDL_sysmain_callbacks.m b/src/main/ios/SDL_sysmain_callbacks.m index 09bc9932..ab00d333 100644 --- a/src/main/ios/SDL_sysmain_callbacks.m +++ b/src/main/ios/SDL_sysmain_callbacks.m @@ -22,7 +22,7 @@ #include "SDL_internal.h" #include "../SDL_main_callbacks.h" -#ifdef __IOS__ +#ifdef SDL_PLATFORM_IOS #import diff --git a/src/misc/ios/SDL_sysurl.m b/src/misc/ios/SDL_sysurl.m index 719e0b2c..8038bc73 100644 --- a/src/misc/ios/SDL_sysurl.m +++ b/src/misc/ios/SDL_sysurl.m @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(__IOS__) || defined(__TVOS__) +#if defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) #include "../SDL_sysurl.h" @@ -30,7 +30,7 @@ int SDL_SYS_OpenURL(const char *url) { @autoreleasepool { -#if TARGET_OS_XR +#ifdef SDL_PLATFORM_VISIONOS return SDL_Unsupported(); // openURL is not suported on visionOS #else NSString *nsstr = [NSString stringWithUTF8String:url]; @@ -40,4 +40,4 @@ int SDL_SYS_OpenURL(const char *url) } } -#endif /* __IOS__ || __TVOS__ */ +#endif /* SDL_PLATFORM_IOS || SDL_PLATFORM_TVOS */ diff --git a/src/misc/macos/SDL_sysurl.m b/src/misc/macos/SDL_sysurl.m index 2eff382a..9a098f64 100644 --- a/src/misc/macos/SDL_sysurl.m +++ b/src/misc/macos/SDL_sysurl.m @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(__MACOS__) +#if defined(SDL_PLATFORM_MACOS) #include "../SDL_sysurl.h" @@ -36,4 +36,4 @@ int SDL_SYS_OpenURL(const char *url) } } -#endif /* __MACOS__ */ +#endif /* SDL_PLATFORM_MACOS */ diff --git a/src/misc/windows/SDL_sysurl.c b/src/misc/windows/SDL_sysurl.c index 11d720cf..fe4c877b 100644 --- a/src/misc/windows/SDL_sysurl.c +++ b/src/misc/windows/SDL_sysurl.c @@ -25,7 +25,7 @@ #include -#if defined(__XBOXONE__) || defined(__XBOXSERIES__) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) int SDL_SYS_OpenURL(const char *url) { /* Not supported */ diff --git a/src/power/uikit/SDL_syspower.m b/src/power/uikit/SDL_syspower.m index 3049c1e0..bca259f3 100644 --- a/src/power/uikit/SDL_syspower.m +++ b/src/power/uikit/SDL_syspower.m @@ -27,7 +27,7 @@ #include "SDL_syspower.h" -#if !TARGET_OS_TV +#ifndef SDL_PLATFORM_TVOS /* turn off the battery monitor if it's been more than X ms since last check. */ static const int BATTERY_MONITORING_TIMEOUT = 3000; static Uint64 SDL_UIKitLastPowerInfoQuery = 0; @@ -48,15 +48,15 @@ void SDL_UIKit_UpdateBatteryMonitoring(void) { /* Do nothing. */ } -#endif /* !TARGET_OS_TV */ +#endif /* !SDL_PLATFORM_TVOS */ SDL_bool SDL_GetPowerInfo_UIKit(SDL_PowerState *state, int *seconds, int *percent) { -#if TARGET_OS_TV +#ifdef SDL_PLATFORM_TVOS *state = SDL_POWERSTATE_NO_BATTERY; *seconds = -1; *percent = -1; -#else /* TARGET_OS_TV */ +#else /* SDL_PLATFORM_TVOS */ @autoreleasepool { UIDevice *uidev = [UIDevice currentDevice]; @@ -96,7 +96,7 @@ SDL_bool SDL_GetPowerInfo_UIKit(SDL_PowerState *state, int *seconds, int *percen const float level = uidev.batteryLevel; *percent = ((level < 0.0f) ? -1 : ((int)((level * 100) + 0.5f))); } -#endif /* TARGET_OS_TV */ +#endif /* SDL_PLATFORM_TVOS */ return SDL_TRUE; /* always the definitive answer on iOS. */ } diff --git a/src/render/SDL_d3dmath.c b/src/render/SDL_d3dmath.c index 7b50487c..ade1adeb 100644 --- a/src/render/SDL_d3dmath.c +++ b/src/render/SDL_d3dmath.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if (defined(SDL_VIDEO_RENDER_D3D) || defined(SDL_VIDEO_RENDER_D3D11) || defined(SDL_VIDEO_RENDER_D3D12)) && !defined(SDL_RENDER_DISABLED) +#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12 || SDL_VIDEO_RENDER_VULKAN) #include "SDL_d3dmath.h" @@ -129,4 +129,4 @@ Float4X4 MatrixRotationZ(float r) return m; } -#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) */ +#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) */ diff --git a/src/render/SDL_d3dmath.h b/src/render/SDL_d3dmath.h index 95b52601..ab8d2895 100644 --- a/src/render/SDL_d3dmath.h +++ b/src/render/SDL_d3dmath.h @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if (defined(SDL_VIDEO_RENDER_D3D) || defined(SDL_VIDEO_RENDER_D3D11) || defined(SDL_VIDEO_RENDER_D3D12)) && !defined(SDL_RENDER_DISABLED) +#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12 || SDL_VIDEO_RENDER_VULKAN) /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -78,4 +78,4 @@ Float4X4 MatrixRotationZ(float r); } #endif -#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) */ +#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12 || SDL_VIDEO_RENDER_VULKAN)*/ diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index a0396323..923d361d 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -27,7 +27,7 @@ #include "../video/SDL_pixels_c.h" #include "../video/SDL_video_c.h" -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID #include "../core/android/SDL_android.h" #endif @@ -37,13 +37,14 @@ SDL_AddEventWatch to catch SDL_EVENT_WILL_ENTER_BACKGROUND events and stopped drawing themselves. Other platforms still draw, as the compositor can use it, and more importantly: drawing to render targets isn't lost. But I still think this should probably be removed at some point in the future. --ryan. */ -#if defined(__IOS__) || defined(__TVOS__) || defined(__ANDROID__) +#if defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) || defined(SDL_PLATFORM_ANDROID) #define DONT_DRAW_WHILE_HIDDEN 1 #else #define DONT_DRAW_WHILE_HIDDEN 0 #endif -#define SDL_PROPERTY_WINDOW_RENDERER "SDL.internal.window.renderer" +#define SDL_PROP_WINDOW_RENDERER_POINTER "SDL.internal.window.renderer" +#define SDL_PROP_TEXTURE_PARENT_POINTER "SDL.internal.texture.parent" #define CHECK_RENDERER_MAGIC(renderer, retval) \ if (!(renderer) || (renderer)->magic != &SDL_renderer_magic) { \ @@ -89,33 +90,36 @@ this should probably be removed at some point in the future. --ryan. */ #ifndef SDL_RENDER_DISABLED static const SDL_RenderDriver *render_drivers[] = { -#ifdef SDL_VIDEO_RENDER_D3D12 - &D3D12_RenderDriver, -#endif -#ifdef SDL_VIDEO_RENDER_D3D11 +#if SDL_VIDEO_RENDER_D3D11 &D3D11_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_D3D +#if SDL_VIDEO_RENDER_D3D12 + &D3D12_RenderDriver, +#endif +#if SDL_VIDEO_RENDER_D3D &D3D_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_METAL +#if SDL_VIDEO_RENDER_METAL &METAL_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_OGL +#if SDL_VIDEO_RENDER_OGL &GL_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_OGL_ES2 +#if SDL_VIDEO_RENDER_OGL_ES2 &GLES2_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_PS2 +#if SDL_VIDEO_RENDER_PS2 &PS2_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_PSP +#if SDL_VIDEO_RENDER_PSP &PSP_RenderDriver, #endif -#ifdef SDL_VIDEO_RENDER_VITA_GXM +#if SDL_VIDEO_RENDER_VITA_GXM &VITA_GXM_RenderDriver, #endif +#if SDL_VIDEO_RENDER_VULKAN + &VULKAN_RenderDriver, +#endif #if SDL_VIDEO_RENDER_SW &SW_RenderDriver #endif @@ -125,6 +129,51 @@ static const SDL_RenderDriver *render_drivers[] = { char SDL_renderer_magic; char SDL_texture_magic; + +void SDL_SetupRendererColorspace(SDL_Renderer *renderer, SDL_PropertiesID props) +{ + renderer->output_colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB); +} + +static float sRGBtoLinear(float v) +{ + return v <= 0.04045f ? (v / 12.92f) : SDL_powf(((v + 0.055f) / 1.055f), 2.4f); +} + +static float sRGBfromLinear(float v) +{ + return v <= 0.0031308f ? (v * 12.92f) : (SDL_powf(v, 1.0f / 2.4f) * 1.055f - 0.055f); +} + +SDL_bool SDL_RenderingLinearSpace(SDL_Renderer *renderer) +{ + SDL_Colorspace colorspace; + + if (renderer->target) { + colorspace = renderer->target->colorspace; + } else { + colorspace = renderer->output_colorspace; + } + if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +void SDL_ConvertToLinear(SDL_FColor *color) +{ + color->r = sRGBtoLinear(color->r); + color->g = sRGBtoLinear(color->g); + color->b = sRGBtoLinear(color->b); +} + +void SDL_ConvertFromLinear(SDL_FColor *color) +{ + color->r = sRGBfromLinear(color->r); + color->g = sRGBfromLinear(color->g); + color->b = sRGBfromLinear(color->b); +} + static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd) { #if 0 @@ -151,72 +200,72 @@ static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd) break; case SDL_RENDERCMD_SETDRAWCOLOR: - SDL_Log(" %u. set draw color (first=%u, r=%d, g=%d, b=%d, a=%d)", i++, + SDL_Log(" %u. set draw color (first=%u, r=%d, g=%d, b=%d, a=%d, color_scale=%g)", i++, (unsigned int) cmd->data.color.first, (int) cmd->data.color.r, (int) cmd->data.color.g, - (int) cmd->data.color.b, (int) cmd->data.color.a); + (int) cmd->data.color.b, (int) cmd->data.color.a, cmd->data.color.color_scale); break; case SDL_RENDERCMD_CLEAR: - SDL_Log(" %u. clear (first=%u, r=%d, g=%d, b=%d, a=%d)", i++, + SDL_Log(" %u. clear (first=%u, r=%d, g=%d, b=%d, a=%d, color_scale=%g)", i++, (unsigned int) cmd->data.color.first, (int) cmd->data.color.r, (int) cmd->data.color.g, - (int) cmd->data.color.b, (int) cmd->data.color.a); + (int) cmd->data.color.b, (int) cmd->data.color.a, cmd->data.color.color_scale); break; case SDL_RENDERCMD_DRAW_POINTS: - SDL_Log(" %u. draw points (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++, + SDL_Log(" %u. draw points (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++, (unsigned int) cmd->data.draw.first, (unsigned int) cmd->data.draw.count, (int) cmd->data.draw.r, (int) cmd->data.draw.g, (int) cmd->data.draw.b, (int) cmd->data.draw.a, - (int) cmd->data.draw.blend); + (int) cmd->data.draw.blend, cmd->data.draw.color_scale); break; case SDL_RENDERCMD_DRAW_LINES: - SDL_Log(" %u. draw lines (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++, + SDL_Log(" %u. draw lines (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++, (unsigned int) cmd->data.draw.first, (unsigned int) cmd->data.draw.count, (int) cmd->data.draw.r, (int) cmd->data.draw.g, (int) cmd->data.draw.b, (int) cmd->data.draw.a, - (int) cmd->data.draw.blend); + (int) cmd->data.draw.blend, cmd->data.draw.color_scale); break; case SDL_RENDERCMD_FILL_RECTS: - SDL_Log(" %u. fill rects (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d)", i++, + SDL_Log(" %u. fill rects (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g)", i++, (unsigned int) cmd->data.draw.first, (unsigned int) cmd->data.draw.count, (int) cmd->data.draw.r, (int) cmd->data.draw.g, (int) cmd->data.draw.b, (int) cmd->data.draw.a, - (int) cmd->data.draw.blend); + (int) cmd->data.draw.blend, cmd->data.draw.color_scale); break; case SDL_RENDERCMD_COPY: - SDL_Log(" %u. copy (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++, + SDL_Log(" %u. copy (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++, (unsigned int) cmd->data.draw.first, (unsigned int) cmd->data.draw.count, (int) cmd->data.draw.r, (int) cmd->data.draw.g, (int) cmd->data.draw.b, (int) cmd->data.draw.a, - (int) cmd->data.draw.blend, cmd->data.draw.texture); + (int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture); break; case SDL_RENDERCMD_COPY_EX: - SDL_Log(" %u. copyex (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++, + SDL_Log(" %u. copyex (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++, (unsigned int) cmd->data.draw.first, (unsigned int) cmd->data.draw.count, (int) cmd->data.draw.r, (int) cmd->data.draw.g, (int) cmd->data.draw.b, (int) cmd->data.draw.a, - (int) cmd->data.draw.blend, cmd->data.draw.texture); + (int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture); break; case SDL_RENDERCMD_GEOMETRY: - SDL_Log(" %u. geometry (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, tex=%p)", i++, + SDL_Log(" %u. geometry (first=%u, count=%u, r=%d, g=%d, b=%d, a=%d, blend=%d, color_scale=%g, tex=%p)", i++, (unsigned int) cmd->data.draw.first, (unsigned int) cmd->data.draw.count, (int) cmd->data.draw.r, (int) cmd->data.draw.g, (int) cmd->data.draw.b, (int) cmd->data.draw.a, - (int) cmd->data.draw.blend, cmd->data.draw.texture); + (int) cmd->data.draw.blend, cmd->data.draw.color_scale, cmd->data.draw.texture); break; } @@ -250,6 +299,7 @@ static int FlushRenderCommands(SDL_Renderer *renderer) renderer->vertex_data_used = 0; renderer->render_command_generation++; renderer->color_queued = SDL_FALSE; + renderer->color_scale_queued = SDL_FALSE; renderer->viewport_queued = SDL_FALSE; renderer->cliprect_queued = SDL_FALSE; return retval; @@ -318,7 +368,7 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer) renderer->render_commands_pool = retval->next; retval->next = NULL; } else { - retval = SDL_calloc(1, sizeof(*retval)); + retval = (SDL_RenderCommand *)SDL_calloc(1, sizeof(*retval)); if (!retval) { return NULL; } @@ -407,27 +457,28 @@ static int QueueCmdSetClipRect(SDL_Renderer *renderer) return retval; } -static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_Color *col) +static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_FColor *color) { - const Uint32 color = (((Uint32)col->a << 24) | (col->r << 16) | (col->g << 8) | col->b); int retval = 0; - if (!renderer->color_queued || (color != renderer->last_queued_color)) { + if (!renderer->color_queued || + color->r != renderer->last_queued_color.r || + color->g != renderer->last_queued_color.g || + color->b != renderer->last_queued_color.b || + color->a != renderer->last_queued_color.a) { SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); retval = -1; if (cmd) { cmd->command = SDL_RENDERCMD_SETDRAWCOLOR; cmd->data.color.first = 0; /* render backend will fill this in. */ - cmd->data.color.r = col->r; - cmd->data.color.g = col->g; - cmd->data.color.b = col->b; - cmd->data.color.a = col->a; + cmd->data.color.color_scale = renderer->color_scale; + cmd->data.color.color = *color; retval = renderer->QueueSetDrawColor(renderer, cmd); if (retval < 0) { cmd->command = SDL_RENDERCMD_NO_OP; } else { - renderer->last_queued_color = color; + renderer->last_queued_color = *color; renderer->color_queued = SDL_TRUE; } } @@ -444,10 +495,8 @@ static int QueueCmdClear(SDL_Renderer *renderer) cmd->command = SDL_RENDERCMD_CLEAR; cmd->data.color.first = 0; - cmd->data.color.r = renderer->color.r; - cmd->data.color.g = renderer->color.g; - cmd->data.color.b = renderer->color.b; - cmd->data.color.a = renderer->color.a; + cmd->data.color.color_scale = renderer->color_scale; + cmd->data.color.color = renderer->color; return 0; } @@ -455,7 +504,7 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren { SDL_RenderCommand *cmd = NULL; int retval = 0; - SDL_Color *color; + SDL_FColor *color; SDL_BlendMode blendMode; if (texture) { @@ -485,10 +534,8 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren cmd->command = cmdtype; cmd->data.draw.first = 0; /* render backend will fill this in. */ cmd->data.draw.count = 0; /* render backend will fill this in. */ - cmd->data.draw.r = color->r; - cmd->data.draw.g = color->g; - cmd->data.draw.b = color->b; - cmd->data.draw.a = color->a; + cmd->data.draw.color_scale = renderer->color_scale; + cmd->data.draw.color = *color; cmd->data.draw.blend = blendMode; cmd->data.draw.texture = texture; } @@ -611,7 +658,7 @@ static int QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_ static int QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcquad, const SDL_FRect *dstrect, - const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y) + const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y) { SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_COPY_EX, texture); int retval = -1; @@ -626,7 +673,7 @@ static int QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, static int QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, const float *xy, int xy_stride, - const SDL_Color *color, int color_stride, + const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices, @@ -665,6 +712,47 @@ static void UpdateMainViewDimensions(SDL_Renderer *renderer) } } +static void UpdateHDRProperties(SDL_Renderer *renderer) +{ + SDL_DisplayID displayID = SDL_GetDisplayForWindow(renderer->window); + SDL_PropertiesID display_props; + SDL_PropertiesID renderer_props; + + if (!displayID) { + return; + } + + display_props = SDL_GetDisplayProperties(displayID); + if (!display_props) { + return; + } + + renderer_props = SDL_GetRendererProperties(renderer); + if (!renderer_props) { + return; + } + + renderer->color_scale /= renderer->SDR_white_point; + + if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + renderer->SDR_white_point = SDL_GetFloatProperty(display_props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f); + renderer->HDR_headroom = SDL_GetFloatProperty(display_props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f); + } else { + renderer->SDR_white_point = 1.0f; + renderer->HDR_headroom = 1.0f; + } + + if (renderer->HDR_headroom > 1.0f) { + SDL_SetBooleanProperty(renderer_props, SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN, SDL_TRUE); + } else { + SDL_SetBooleanProperty(renderer_props, SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN, SDL_FALSE); + } + SDL_SetFloatProperty(renderer_props, SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT, renderer->SDR_white_point); + SDL_SetFloatProperty(renderer_props, SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT, renderer->HDR_headroom); + + renderer->color_scale *= renderer->SDR_white_point; +} + static int UpdateLogicalPresentation(SDL_Renderer *renderer); @@ -720,14 +808,18 @@ static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event) if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) { renderer->hidden = SDL_FALSE; } + } else if (event->type == SDL_EVENT_WINDOW_DISPLAY_CHANGED) { + UpdateHDRProperties(renderer); } } + } else if (event->type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) { + UpdateHDRProperties(renderer); } return 0; } -int SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags, SDL_Window **window, SDL_Renderer **renderer) +int SDL_CreateWindowAndRenderer(int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer) { *window = SDL_CreateWindow(NULL, width, height, window_flags); if (!*window) { @@ -805,73 +897,86 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) { #ifndef SDL_RENDER_DISABLED - SDL_Window *window = SDL_GetProperty(props, SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER, NULL); - SDL_Surface *surface = SDL_GetProperty(props, SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER, NULL); - const char *name = SDL_GetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, NULL); + SDL_Window *window = (SDL_Window *)SDL_GetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, NULL); + SDL_Surface *surface = (SDL_Surface *)SDL_GetProperty(props, SDL_PROP_RENDERER_CREATE_SURFACE_POINTER, NULL); + const char *name = SDL_GetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, NULL); SDL_Renderer *renderer = NULL; const int n = SDL_GetNumRenderDrivers(); const char *hint; - int i; + int i, attempted = 0; + SDL_PropertiesID new_props; - if (!window && surface) { - return SDL_CreateSoftwareRenderer(surface); - } - -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID Android_ActivityMutex_Lock_Running(); #endif - if (!window) { + if ((!window && !surface) || (window && surface)) { SDL_InvalidParamError("window"); goto error; } - if (SDL_HasWindowSurface(window)) { + if (window && SDL_WindowHasSurface(window)) { SDL_SetError("Surface already associated with window"); goto error; } - if (SDL_GetRenderer(window)) { + if (window && SDL_GetRenderer(window)) { SDL_SetError("Renderer already associated with window"); goto error; } hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC); if (hint && *hint) { - SDL_SetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)); + SDL_SetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)); } - if (!name) { - name = SDL_GetHint(SDL_HINT_RENDER_DRIVER); - } - - if (name) { - for (i = 0; i < n; i++) { - const SDL_RenderDriver *driver = render_drivers[i]; - if (SDL_strcasecmp(name, driver->info.name) == 0) { - /* Create a new renderer instance */ - renderer = driver->CreateRenderer(window, props); - break; - } + if (surface) { +#if SDL_VIDEO_RENDER_SW + renderer = SW_CreateRendererForSurface(surface, props); +#else + renderer = NULL; + SDL_SetError("SDL not built with software renderer"); +#endif + if (!renderer) { + goto error; } } else { - for (i = 0; i < n; i++) { - const SDL_RenderDriver *driver = render_drivers[i]; - /* Create a new renderer instance */ - renderer = driver->CreateRenderer(window, props); - if (renderer) { - /* Yay, we got one! */ - break; + if (!name) { + name = SDL_GetHint(SDL_HINT_RENDER_DRIVER); + } + + if (name) { + for (i = 0; i < n; i++) { + const SDL_RenderDriver *driver = render_drivers[i]; + if (SDL_strcasecmp(name, driver->info.name) == 0) { + /* Create a new renderer instance */ + ++attempted; + renderer = driver->CreateRenderer(window, props); + break; + } } + } else { + for (i = 0; i < n; i++) { + const SDL_RenderDriver *driver = render_drivers[i]; + /* Create a new renderer instance */ + ++attempted; + renderer = driver->CreateRenderer(window, props); + if (renderer) { + /* Yay, we got one! */ + break; + } + } + } + + if (!renderer) { + if (!name || !attempted) { + SDL_SetError("Couldn't find matching render driver"); + } + goto error; } } - if (!renderer) { - SDL_SetError("Couldn't find matching render driver"); - goto error; - } - - if (SDL_GetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { + if (SDL_GetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { renderer->wanted_vsync = SDL_TRUE; if (!(renderer->info.flags & SDL_RENDERER_PRESENTVSYNC)) { @@ -886,6 +991,10 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) renderer->magic = &SDL_renderer_magic; renderer->window = window; renderer->target_mutex = SDL_CreateMutex(); + if (surface) { + renderer->main_view.pixel_w = surface->w; + renderer->main_view.pixel_h = surface->h; + } renderer->main_view.viewport.w = -1; renderer->main_view.viewport.h = -1; renderer->main_view.scale.x = 1.0f; @@ -908,31 +1017,59 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props) /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */ renderer->render_command_generation = 1; - renderer->line_method = SDL_GetRenderLineMethod(); - - if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) { - renderer->hidden = SDL_TRUE; + if (renderer->info.flags & SDL_RENDERER_SOFTWARE) { + /* Software renderer always uses line method, for speed */ + renderer->line_method = SDL_RENDERLINEMETHOD_LINES; } else { - renderer->hidden = SDL_FALSE; + renderer->line_method = SDL_GetRenderLineMethod(); } - SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_RENDERER, renderer); + renderer->SDR_white_point = 1.0f; + renderer->HDR_headroom = 1.0f; + renderer->color_scale = 1.0f; + + if (window) { + if (SDL_GetWindowFlags(window) & SDL_WINDOW_TRANSPARENT) { + renderer->transparent_window = SDL_TRUE; + } + + if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) { + renderer->hidden = SDL_TRUE; + } + } + + new_props = SDL_GetRendererProperties(renderer); + SDL_SetStringProperty(new_props, SDL_PROP_RENDERER_NAME_STRING, renderer->info.name); + if (window) { + SDL_SetProperty(new_props, SDL_PROP_RENDERER_WINDOW_POINTER, window); + } + if (surface) { + SDL_SetProperty(new_props, SDL_PROP_RENDERER_SURFACE_POINTER, surface); + } + SDL_SetNumberProperty(new_props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, renderer->output_colorspace); + UpdateHDRProperties(renderer); + + if (window) { + SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_RENDERER_POINTER, renderer); + } SDL_SetRenderViewport(renderer, NULL); - SDL_AddEventWatch(SDL_RendererEventWatch, renderer); + if (window) { + SDL_AddEventWatch(SDL_RendererEventWatch, renderer); + } SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "Created renderer: %s", renderer->info.name); -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID Android_ActivityMutex_Unlock(); #endif return renderer; error: -#ifdef __ANDROID__ +#ifdef SDL_PLATFORM_ANDROID Android_ActivityMutex_Unlock(); #endif return NULL; @@ -947,14 +1084,14 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl { SDL_Renderer *renderer; SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetProperty(props, SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER, window); + SDL_SetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, window); if (flags & SDL_RENDERER_SOFTWARE) { - SDL_SetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, "software"); + SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, "software"); } else { - SDL_SetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, name); + SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, name); } if (flags & SDL_RENDERER_PRESENTVSYNC) { - SDL_SetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_TRUE); + SDL_SetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_TRUE); } renderer = SDL_CreateRendererWithProperties(props); SDL_DestroyProperties(props); @@ -963,33 +1100,12 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) { -#if !defined(SDL_RENDER_DISABLED) && SDL_VIDEO_RENDER_SW +#if SDL_VIDEO_RENDER_SW SDL_Renderer *renderer; - - renderer = SW_CreateRendererForSurface(surface); - - if (renderer) { - VerifyDrawQueueFunctions(renderer); - renderer->magic = &SDL_renderer_magic; - renderer->target_mutex = SDL_CreateMutex(); - renderer->main_view.pixel_w = surface->w; - renderer->main_view.pixel_h = surface->h; - renderer->main_view.viewport.w = -1; - renderer->main_view.viewport.h = -1; - renderer->main_view.scale.x = 1.0f; - renderer->main_view.scale.y = 1.0f; - renderer->view = &renderer->main_view; - renderer->dpi_scale.x = 1.0f; - renderer->dpi_scale.y = 1.0f; - - /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */ - renderer->render_command_generation = 1; - - /* Software renderer always uses line method, for speed */ - renderer->line_method = SDL_RENDERLINEMETHOD_LINES; - - SDL_SetRenderViewport(renderer, NULL); - } + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetProperty(props, SDL_PROP_RENDERER_CREATE_SURFACE_POINTER, surface); + renderer = SDL_CreateRendererWithProperties(props); + SDL_DestroyProperties(props); return renderer; #else SDL_SetError("SDL not built with rendering support"); @@ -999,7 +1115,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) SDL_Renderer *SDL_GetRenderer(SDL_Window *window) { - return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_RENDERER, NULL); + return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_RENDERER_POINTER, NULL); } SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer) @@ -1035,7 +1151,7 @@ int SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) } else if (renderer->window) { return SDL_GetWindowSizeInPixels(renderer->window, w, h); } else { - SDL_assert(0 && "This should never happen"); + SDL_assert(!"This should never happen"); return SDL_SetError("Renderer doesn't support querying output size"); } } @@ -1069,9 +1185,9 @@ static SDL_bool IsSupportedBlendMode(SDL_Renderer *renderer, SDL_BlendMode blend } } -static SDL_bool IsSupportedFormat(SDL_Renderer *renderer, Uint32 format) +static SDL_bool IsSupportedFormat(SDL_Renderer *renderer, SDL_PixelFormatEnum format) { - Uint32 i; + int i; for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (renderer->info.texture_formats[i] == format) { @@ -1081,9 +1197,9 @@ static SDL_bool IsSupportedFormat(SDL_Renderer *renderer, Uint32 format) return SDL_FALSE; } -static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, Uint32 format) +static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, SDL_PixelFormatEnum format) { - Uint32 i; + int i; if (SDL_ISPIXELFORMAT_FOURCC(format)) { /* Look for an exact match */ @@ -1092,6 +1208,19 @@ static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, Uint32 format) return renderer->info.texture_formats[i]; } } + } else if (SDL_ISPIXELFORMAT_10BIT(format) || SDL_ISPIXELFORMAT_FLOAT(format)) { + if (SDL_ISPIXELFORMAT_10BIT(format)) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { + if (SDL_ISPIXELFORMAT_10BIT(renderer->info.texture_formats[i])) { + return renderer->info.texture_formats[i]; + } + } + } + for (i = 0; i < renderer->info.num_texture_formats; ++i) { + if (SDL_ISPIXELFORMAT_FLOAT(renderer->info.texture_formats[i])) { + return renderer->info.texture_formats[i]; + } + } } else { SDL_bool hasAlpha = SDL_ISPIXELFORMAT_ALPHA(format); @@ -1106,28 +1235,14 @@ static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, Uint32 format) return renderer->info.texture_formats[0]; } -static SDL_ScaleMode SDL_GetScaleMode(void) -{ - const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); - - if (!hint || SDL_strcasecmp(hint, "nearest") == 0) { - return SDL_SCALEMODE_NEAREST; - } else if (SDL_strcasecmp(hint, "linear") == 0) { - return SDL_SCALEMODE_LINEAR; - } else if (SDL_strcasecmp(hint, "best") == 0) { - return SDL_SCALEMODE_BEST; - } else { - return (SDL_ScaleMode)SDL_atoi(hint); - } -} - SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props) { SDL_Texture *texture; - Uint32 format = (Uint32)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_UNKNOWN); - int access = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); - int w = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER, 0); - int h = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER, 0); + SDL_PixelFormatEnum format = (SDL_PixelFormatEnum)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_UNKNOWN); + int access = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); + int w = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, 0); + int h = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, 0); + SDL_Colorspace default_colorspace; SDL_bool texture_is_fourcc_and_target; CHECK_RENDERER_MAGIC(renderer, NULL); @@ -1154,20 +1269,24 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert SDL_SetError("Texture dimensions are limited to %dx%d", renderer->info.max_texture_width, renderer->info.max_texture_height); return NULL; } + + default_colorspace = SDL_GetDefaultColorspaceForFormat(format); + texture = (SDL_Texture *)SDL_calloc(1, sizeof(*texture)); if (!texture) { return NULL; } texture->magic = &SDL_texture_magic; + texture->colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, default_colorspace); texture->format = format; texture->access = access; texture->w = w; texture->h = h; - texture->color.r = 255; - texture->color.g = 255; - texture->color.b = 255; - texture->color.a = 255; - texture->scaleMode = SDL_GetScaleMode(); + texture->color.r = 1.0f; + texture->color.g = 1.0f; + texture->color.b = 1.0f; + texture->color.a = 1.0f; + texture->scaleMode = SDL_SCALEMODE_LINEAR; texture->view.pixel_w = w; texture->view.pixel_h = h; texture->view.viewport.w = -1; @@ -1181,29 +1300,42 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert } renderer->textures = texture; - /* FOURCC format cannot be used directly by renderer back-ends for target texture */ - texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(texture->format)); + texture->SDR_white_point = SDL_GetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT, SDL_GetDefaultSDRWhitePoint(texture->colorspace)); + texture->HDR_headroom = SDL_GetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT, SDL_GetDefaultHDRHeadroom(texture->colorspace)); - if (texture_is_fourcc_and_target == SDL_FALSE && IsSupportedFormat(renderer, format)) { + /* FOURCC format cannot be used directly by renderer back-ends for target texture */ + texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(format)); + + if (!texture_is_fourcc_and_target && IsSupportedFormat(renderer, format)) { if (renderer->CreateTexture(renderer, texture, props) < 0) { SDL_DestroyTexture(texture); return NULL; } } else { int closest_format; + SDL_PropertiesID native_props = SDL_CreateProperties(); - if (texture_is_fourcc_and_target == SDL_FALSE) { + if (!texture_is_fourcc_and_target) { closest_format = GetClosestSupportedFormat(renderer, format); } else { closest_format = renderer->info.texture_formats[0]; } - texture->native = SDL_CreateTexture(renderer, closest_format, access, w, h); + SDL_SetNumberProperty(native_props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, texture->colorspace); + SDL_SetNumberProperty(native_props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, closest_format); + SDL_SetNumberProperty(native_props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, texture->access); + SDL_SetNumberProperty(native_props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, texture->w); + SDL_SetNumberProperty(native_props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, texture->h); + + texture->native = SDL_CreateTextureWithProperties(renderer, native_props); + SDL_DestroyProperties(native_props); if (!texture->native) { SDL_DestroyTexture(texture); return NULL; } + SDL_SetProperty(SDL_GetTextureProperties(texture->native), SDL_PROP_TEXTURE_PARENT_POINTER, texture); + /* Swap textures to have texture before texture->native in the list */ texture->native->next = texture->next; if (texture->native->next) { @@ -1237,17 +1369,25 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert } } } + + /* Now set the properties for the new texture */ + props = SDL_GetTextureProperties(texture); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_COLORSPACE_NUMBER, texture->colorspace); + SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_SDR_WHITE_POINT_FLOAT, texture->SDR_white_point); + if (texture->HDR_headroom > 0.0f) { + SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_HDR_HEADROOM_FLOAT, texture->HDR_headroom); + } return texture; } -SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) +SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, SDL_PixelFormatEnum format, int access, int w, int h) { SDL_Texture *texture; SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER, format); - SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER, access); - SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER, w); - SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER, h); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, access); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, h); texture = SDL_CreateTextureWithProperties(renderer, props); SDL_DestroyProperties(props); return texture; @@ -1259,8 +1399,11 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s SDL_bool needAlpha; SDL_bool direct_update; int i; - Uint32 format = SDL_PIXELFORMAT_UNKNOWN; + SDL_PixelFormatEnum format = SDL_PIXELFORMAT_UNKNOWN; SDL_Texture *texture; + SDL_PropertiesID surface_props, props; + SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN; + SDL_Colorspace texture_colorspace = SDL_COLORSPACE_UNKNOWN; CHECK_RENDERER_MAGIC(renderer, NULL); @@ -1286,18 +1429,23 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s } } + if (SDL_GetSurfaceColorspace(surface, &surface_colorspace) < 0) { + return NULL; + } + texture_colorspace = surface_colorspace; + /* Try to have the best pixel format for the texture */ /* No alpha, but a colorkey => promote to alpha */ if (!fmt->Amask && SDL_SurfaceHasColorKey(surface)) { if (fmt->format == SDL_PIXELFORMAT_XRGB8888) { - for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ARGB8888) { format = SDL_PIXELFORMAT_ARGB8888; break; } } } else if (fmt->format == SDL_PIXELFORMAT_XBGR8888) { - for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ABGR8888) { format = SDL_PIXELFORMAT_ABGR8888; break; @@ -1306,7 +1454,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s } } else { /* Exact match would be fine */ - for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (renderer->info.texture_formats[i] == fmt->format) { format = fmt->format; break; @@ -1314,10 +1462,31 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s } } + /* Look for 10-bit pixel formats if needed */ + if (format == SDL_PIXELFORMAT_UNKNOWN && SDL_ISPIXELFORMAT_10BIT(fmt->format)) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { + if (SDL_ISPIXELFORMAT_10BIT(renderer->info.texture_formats[i])) { + format = renderer->info.texture_formats[i]; + break; + } + } + } + + /* Look for floating point pixel formats if needed */ + if (format == SDL_PIXELFORMAT_UNKNOWN && + (SDL_ISPIXELFORMAT_10BIT(fmt->format) || SDL_ISPIXELFORMAT_FLOAT(fmt->format))) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { + if (SDL_ISPIXELFORMAT_FLOAT(renderer->info.texture_formats[i])) { + format = renderer->info.texture_formats[i]; + break; + } + } + } + /* Fallback, choose a valid pixel format */ if (format == SDL_PIXELFORMAT_UNKNOWN) { format = renderer->info.texture_formats[0]; - for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) { + for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) && SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) { format = renderer->info.texture_formats[i]; @@ -1326,15 +1495,20 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s } } - texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, - surface->w, surface->h); - if (!texture) { - return NULL; + if (surface_colorspace == SDL_COLORSPACE_SRGB_LINEAR || + SDL_COLORSPACETRANSFER(surface_colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) { + if (SDL_ISPIXELFORMAT_FLOAT(format)) { + texture_colorspace = SDL_COLORSPACE_SRGB_LINEAR; + } else if (SDL_ISPIXELFORMAT_10BIT(format)) { + texture_colorspace = SDL_COLORSPACE_HDR10; + } else { + texture_colorspace = SDL_COLORSPACE_SRGB; + } } - if (format == surface->format->format) { + if (format == surface->format->format && texture_colorspace == surface_colorspace) { if (surface->format->Amask && SDL_SurfaceHasColorKey(surface)) { - /* Surface and Renderer formats are identicals. + /* Surface and Renderer formats are identical. * Intermediate conversion is needed to convert color key to alpha (SDL_ConvertColorkeyToAlpha()). */ direct_update = SDL_FALSE; } else { @@ -1346,6 +1520,30 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s direct_update = SDL_FALSE; } + if (surface->flags & SDL_SURFACE_USES_PROPERTIES) { + surface_props = SDL_GetSurfaceProperties(surface); + } else { + surface_props = 0; + } + + props = SDL_CreateProperties(); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, texture_colorspace); + if (surface_colorspace == texture_colorspace) { + SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT, + SDL_GetSurfaceSDRWhitePoint(surface, surface_colorspace)); + } + SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT, + SDL_GetSurfaceHDRHeadroom(surface, surface_colorspace)); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, surface->w); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, surface->h); + texture = SDL_CreateTextureWithProperties(renderer, props); + SDL_DestroyProperties(props); + if (!texture) { + return NULL; + } + if (direct_update) { if (SDL_MUSTLOCK(surface)) { SDL_LockSurface(surface); @@ -1355,17 +1553,10 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); } } else { - SDL_PixelFormat *dst_fmt; SDL_Surface *temp = NULL; /* Set up a destination surface for the texture update */ - dst_fmt = SDL_CreatePixelFormat(format); - if (!dst_fmt) { - SDL_DestroyTexture(texture); - return NULL; - } - temp = SDL_ConvertSurface(surface, dst_fmt); - SDL_DestroyPixelFormat(dst_fmt); + temp = SDL_ConvertSurfaceFormatAndColorspace(surface, format, texture_colorspace, surface_props); if (temp) { SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch); SDL_DestroySurface(temp); @@ -1432,6 +1623,15 @@ int SDL_QueryTexture(SDL_Texture *texture, Uint32 *format, int *access, int *w, } int SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b) +{ + const float fR = (float)r / 255.0f; + const float fG = (float)g / 255.0f; + const float fB = (float)b / 255.0f; + + return SDL_SetTextureColorModFloat(texture, fR, fG, fB); +} + +int SDL_SetTextureColorModFloat(SDL_Texture *texture, float r, float g, float b) { CHECK_TEXTURE_MAGIC(texture, -1); @@ -1439,39 +1639,84 @@ int SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b) texture->color.g = g; texture->color.b = b; if (texture->native) { - return SDL_SetTextureColorMod(texture->native, r, g, b); + return SDL_SetTextureColorModFloat(texture->native, r, g, b); } return 0; } int SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 *r, Uint8 *g, Uint8 *b) { - CHECK_TEXTURE_MAGIC(texture, -1); + float fR, fG, fB; + + if (SDL_GetTextureColorModFloat(texture, &fR, &fG, &fB) < 0) { + return -1; + } if (r) { - *r = texture->color.r; + *r = (Uint8)(fR * 255.0f); } if (g) { - *g = texture->color.g; + *g = (Uint8)(fG * 255.0f); } if (b) { - *b = texture->color.b; + *b = (Uint8)(fB * 255.0f); + } + return 0; +} + +int SDL_GetTextureColorModFloat(SDL_Texture *texture, float *r, float *g, float *b) +{ + SDL_FColor color; + + CHECK_TEXTURE_MAGIC(texture, -1); + + color = texture->color; + + if (r) { + *r = color.r; + } + if (g) { + *g = color.g; + } + if (b) { + *b = color.b; } return 0; } int SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha) +{ + const float fA = (float)alpha / 255.0f; + + return SDL_SetTextureAlphaModFloat(texture, fA); +} + +int SDL_SetTextureAlphaModFloat(SDL_Texture *texture, float alpha) { CHECK_TEXTURE_MAGIC(texture, -1); texture->color.a = alpha; if (texture->native) { - return SDL_SetTextureAlphaMod(texture->native, alpha); + return SDL_SetTextureAlphaModFloat(texture->native, alpha); } return 0; } int SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha) +{ + float fA; + + if (SDL_GetTextureAlphaModFloat(texture, &fA) < 0) { + return -1; + } + + if (alpha) { + *alpha = (Uint8)(fA * 255.0f); + } + return 0; +} + +int SDL_GetTextureAlphaModFloat(SDL_Texture *texture, float *alpha) { CHECK_TEXTURE_MAGIC(texture, -1); @@ -2115,7 +2360,7 @@ SDL_Texture *SDL_GetRenderTarget(SDL_Renderer *renderer) if (renderer->target == renderer->logical_target) { return NULL; } else { - return renderer->target; + return (SDL_Texture *)SDL_GetProperty(SDL_GetTextureProperties(renderer->target), SDL_PROP_TEXTURE_PARENT_POINTER, renderer->target); } } @@ -2291,10 +2536,10 @@ static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) if (dst->x > 0.0f || dst->y > 0.0f) { SDL_BlendMode saved_blend_mode = renderer->blendMode; - SDL_Color saved_color = renderer->color; + SDL_FColor saved_color = renderer->color; SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_SetRenderDrawColorFloat(renderer, 0.0f, 0.0f, 0.0f, 1.0f); if (dst->x > 0.0f) { SDL_FRect rect; @@ -2325,7 +2570,7 @@ static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) } SDL_SetRenderDrawBlendMode(renderer, saved_blend_mode); - SDL_SetRenderDrawColor(renderer, saved_color.r, saved_color.g, saved_color.b, saved_color.a); + SDL_SetRenderDrawColorFloat(renderer, saved_color.r, saved_color.g, saved_color.b, saved_color.a); } } @@ -2477,7 +2722,10 @@ int SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event } else if (event->type == SDL_EVENT_MOUSE_WHEEL) { SDL_Window *window = SDL_GetWindowFromID(event->wheel.windowID); if (window == renderer->window) { - SDL_RenderCoordinatesFromWindow(renderer, event->wheel.mouseX, event->wheel.mouseY, &event->wheel.mouseX, &event->wheel.mouseY); + SDL_RenderCoordinatesFromWindow(renderer, event->wheel.mouse_x, + event->wheel.mouse_y, + &event->wheel.mouse_x, + &event->wheel.mouse_y); } } else if (event->type == SDL_EVENT_FINGER_DOWN || event->type == SDL_EVENT_FINGER_UP || @@ -2541,6 +2789,17 @@ int SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) return 0; } +SDL_bool SDL_RenderViewportSet(SDL_Renderer *renderer) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (renderer->view->viewport.w >= 0 && + renderer->view->viewport.h >= 0) { + return SDL_TRUE; + } + return SDL_FALSE; +} + static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect) { rect->x = 0.0f; @@ -2628,6 +2887,16 @@ int SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY) } int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + const float fR = (float)r / 255.0f; + const float fG = (float)g / 255.0f; + const float fB = (float)b / 255.0f; + const float fA = (float)a / 255.0f; + + return SDL_SetRenderDrawColorFloat(renderer, fR, fG, fB, fA); +} + +int SDL_SetRenderDrawColorFloat(SDL_Renderer *renderer, float r, float g, float b, float a) { CHECK_RENDERER_MAGIC(renderer, -1); @@ -2640,19 +2909,64 @@ int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Ui int SDL_GetRenderDrawColor(SDL_Renderer *renderer, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) { - CHECK_RENDERER_MAGIC(renderer, -1); + float fR, fG, fB, fA; + + if (SDL_GetRenderDrawColorFloat(renderer, &fR, &fG, &fB, &fA) < 0) { + return -1; + } if (r) { - *r = renderer->color.r; + *r = (Uint8)(fR * 255.0f); } if (g) { - *g = renderer->color.g; + *g = (Uint8)(fG * 255.0f); } if (b) { - *b = renderer->color.b; + *b = (Uint8)(fB * 255.0f); } if (a) { - *a = renderer->color.a; + *a = (Uint8)(fA * 255.0f); + } + return 0; +} + +int SDL_GetRenderDrawColorFloat(SDL_Renderer *renderer, float *r, float *g, float *b, float *a) +{ + SDL_FColor color; + + CHECK_RENDERER_MAGIC(renderer, -1); + + color = renderer->color; + + if (r) { + *r = color.r; + } + if (g) { + *g = color.g; + } + if (b) { + *b = color.b; + } + if (a) { + *a = color.a; + } + return 0; +} + +int SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + renderer->color_scale = scale * renderer->SDR_white_point; + return 0; +} + +int SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (scale) { + *scale = renderer->color_scale / renderer->SDR_white_point; } return 0; } @@ -2776,6 +3090,8 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i just want a basic safety against generating millions of points for massive lines. */ GetRenderViewportInPixels(renderer, &viewport); + viewport.x = 0; + viewport.y = 0; if (!SDL_GetRectAndLineIntersection(&viewport, &x1, &y1, &x2, &y2)) { return 0; } @@ -3294,7 +3610,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR int 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_RendererFlip flip) + const double angle, const SDL_FPoint *center, const SDL_FlipMode flip) { SDL_FRect real_srcrect; SDL_FRect real_dstrect; @@ -3455,27 +3771,28 @@ int SDL_RenderGeometry(SDL_Renderer *renderer, if (vertices) { const float *xy = &vertices->position.x; int xy_stride = sizeof(SDL_Vertex); - const SDL_Color *color = &vertices->color; + const SDL_FColor *color = &vertices->color; int color_stride = sizeof(SDL_Vertex); const float *uv = &vertices->tex_coord.x; int uv_stride = sizeof(SDL_Vertex); int size_indices = 4; - return SDL_RenderGeometryRaw(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices); + return SDL_RenderGeometryRawFloat(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices); } else { return SDL_InvalidParamError("vertices"); } } +#if SDL_VIDEO_RENDER_SW static int remap_one_indice( int prev, int k, SDL_Texture *texture, const float *xy, int xy_stride, - const SDL_Color *color, int color_stride, + const SDL_FColor *color, int color_stride, const float *uv, int uv_stride) { const float *xy0_, *xy1_, *uv0_, *uv1_; - int col0_, col1_; + const SDL_FColor *col0_, *col1_; xy0_ = (const float *)((const char *)xy + prev * xy_stride); xy1_ = (const float *)((const char *)xy + k * xy_stride); if (xy0_[0] != xy1_[0]) { @@ -3494,10 +3811,10 @@ static int remap_one_indice( return k; } } - col0_ = *(const int *)((const char *)color + prev * color_stride); - col1_ = *(const int *)((const char *)color + k * color_stride); + col0_ = (const SDL_FColor *)((const char *)color + prev * color_stride); + col1_ = (const SDL_FColor *)((const char *)color + k * color_stride); - if (col0_ != col1_) { + if (SDL_memcmp(col0_, col1_, sizeof(*col0_)) != 0) { return k; } @@ -3509,7 +3826,7 @@ static int remap_indices( int k, SDL_Texture *texture, const float *xy, int xy_stride, - const SDL_Color *color, int color_stride, + const SDL_FColor *color, int color_stride, const float *uv, int uv_stride) { int i; @@ -3531,7 +3848,7 @@ static int remap_indices( static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, const float *xy, int xy_stride, - const SDL_Color *color, int color_stride, + const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices) @@ -3542,11 +3859,11 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, int prev[3]; /* Previous triangle vertex indices */ int texw = 0, texh = 0; SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; - Uint8 r = 0, g = 0, b = 0, a = 0; + float r = 0, g = 0, b = 0, a = 0; /* Save */ SDL_GetRenderDrawBlendMode(renderer, &blendMode); - SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a); + SDL_GetRenderDrawColorFloat(renderer, &r, &g, &b, &a); if (texture) { SDL_QueryTexture(texture, NULL, NULL, &texw, &texh); @@ -3709,11 +4026,13 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, /* Check if uniformly colored */ if (is_quad) { - const int col0_ = *(const int *)((const char *)color + A * color_stride); - const int col1_ = *(const int *)((const char *)color + B * color_stride); - const int col2_ = *(const int *)((const char *)color + C * color_stride); - const int col3_ = *(const int *)((const char *)color + C2 * color_stride); - if (col0_ == col1_ && col0_ == col2_ && col0_ == col3_) { + const SDL_FColor *col0_ = (const SDL_FColor *)((const char *)color + A * color_stride); + const SDL_FColor *col1_ = (const SDL_FColor *)((const char *)color + B * color_stride); + const SDL_FColor *col2_ = (const SDL_FColor *)((const char *)color + C * color_stride); + const SDL_FColor *col3_ = (const SDL_FColor *)((const char *)color + C2 * color_stride); + if (SDL_memcmp(col0_, col1_, sizeof(*col0_)) == 0 && + SDL_memcmp(col0_, col2_, sizeof(*col0_)) == 0 && + SDL_memcmp(col0_, col3_, sizeof(*col0_)) == 0) { /* ok */ } else { is_quad = 0; @@ -3728,7 +4047,7 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, SDL_FRect s; SDL_FRect d; const float *xy0_, *xy1_, *uv0_, *uv1_; - SDL_Color col0_ = *(const SDL_Color *)((const char *)color + k0 * color_stride); + const SDL_FColor *col0_ = (const SDL_FColor *)((const char *)color + k0 * color_stride); xy0_ = (const float *)((const char *)xy + A * xy_stride); xy1_ = (const float *)((const char *)xy + B * xy_stride); @@ -3751,8 +4070,8 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, /* Rect + texture */ if (texture && s.w != 0 && s.h != 0) { - SDL_SetTextureAlphaMod(texture, col0_.a); - SDL_SetTextureColorMod(texture, col0_.r, col0_.g, col0_.b); + SDL_SetTextureAlphaModFloat(texture, col0_->a); + SDL_SetTextureColorModFloat(texture, col0_->r, col0_->g, col0_->b); if (s.w > 0 && s.h > 0) { SDL_RenderTexture(renderer, texture, &s, &d); } else { @@ -3767,22 +4086,22 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, s.h *= -1; s.y -= s.h; } - SDL_RenderTextureRotated(renderer, texture, &s, &d, 0, NULL, flags); + SDL_RenderTextureRotated(renderer, texture, &s, &d, 0, NULL, (SDL_FlipMode)flags); } #if DEBUG_SW_RENDER_GEOMETRY - SDL_Log("Rect-COPY: RGB %d %d %d - Alpha:%d - texture=%p: src=(%d,%d, %d x %d) dst (%f, %f, %f x %f)", col0_.r, col0_.g, col0_.b, col0_.a, + SDL_Log("Rect-COPY: RGB %f %f %f - Alpha:%f - texture=%p: src=(%d,%d, %d x %d) dst (%f, %f, %f x %f)", col0_->r, col0_->g, col0_->b, col0_->a, (void *)texture, s.x, s.y, s.w, s.h, d.x, d.y, d.w, d.h); #endif } else if (d.w != 0.0f && d.h != 0.0f) { /* Rect, no texture */ SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); - SDL_SetRenderDrawColor(renderer, col0_.r, col0_.g, col0_.b, col0_.a); + SDL_SetRenderDrawColorFloat(renderer, col0_->r, col0_->g, col0_->b, col0_->a); SDL_RenderFillRect(renderer, &d); #if DEBUG_SW_RENDER_GEOMETRY - SDL_Log("Rect-FILL: RGB %d %d %d - Alpha:%d - texture=%p: dst (%f, %f, %f x %f)", col0_.r, col0_.g, col0_.b, col0_.a, + SDL_Log("Rect-FILL: RGB %f %f %f - Alpha:%f - texture=%p: dst (%f, %f, %f x %f)", col0_->r, col0_->g, col0_->b, col0_->a, (void *)texture, d.x, d.y, d.w, d.h); } else { - SDL_Log("Rect-DISMISS: RGB %d %d %d - Alpha:%d - texture=%p: src=(%d,%d, %d x %d) dst (%f, %f, %f x %f)", col0_.r, col0_.g, col0_.b, col0_.a, + SDL_Log("Rect-DISMISS: RGB %f %f %f - Alpha:%f - texture=%p: src=(%d,%d, %d x %d) dst (%f, %f, %f x %f)", col0_->r, col0_->g, col0_->b, col0_->a, (void *)texture, s.x, s.y, s.w, s.h, d.x, d.y, d.w, d.h); #endif } @@ -3828,21 +4147,21 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, end: /* Restore */ SDL_SetRenderDrawBlendMode(renderer, blendMode); - SDL_SetRenderDrawColor(renderer, r, g, b, a); + SDL_SetRenderDrawColorFloat(renderer, r, g, b, a); return retval; } +#endif /* SDL_VIDEO_RENDER_SW */ -int SDL_RenderGeometryRaw(SDL_Renderer *renderer, +int SDL_RenderGeometryRawFloat(SDL_Renderer *renderer, SDL_Texture *texture, const float *xy, int xy_stride, - const SDL_Color *color, int color_stride, + const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices) { int i; - int retval = 0; int count = indices ? num_indices : num_vertices; CHECK_RENDERER_MAGIC(renderer, -1); @@ -3930,59 +4249,117 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, } /* For the software renderer, try to reinterpret triangles as SDL_Rect */ +#if SDL_VIDEO_RENDER_SW if (renderer->info.flags & SDL_RENDERER_SOFTWARE) { return SDL_SW_RenderGeometryRaw(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices); } +#endif - retval = QueueCmdGeometry(renderer, texture, + return QueueCmdGeometry(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices, renderer->view->scale.x, renderer->view->scale.y); +} + +int 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) +{ + int i, retval, isstack; + const Uint8 *color2 = (const Uint8 *)color; + SDL_FColor *color3; + + if (num_vertices <= 0) { + return SDL_InvalidParamError("num_vertices"); + } + if (!color) { + return SDL_InvalidParamError("color"); + } + + color3 = (SDL_FColor *)SDL_small_alloc(SDL_FColor, num_vertices, &isstack); + if (!color3) { + return -1; + } + + for (i = 0; i < num_vertices; ++i) { + color3[i].r = color->r / 255.0f; + color3[i].g = color->g / 255.0f; + color3[i].b = color->b / 255.0f; + color3[i].a = color->a / 255.0f; + color2 += color_stride; + color = (const SDL_Color *)color2; + } + + retval = SDL_RenderGeometryRawFloat(renderer, texture, xy, xy_stride, color3, sizeof(*color3), uv, uv_stride, num_vertices, indices, num_indices, size_indices); + + SDL_small_free(color3, isstack); return retval; } -int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch) +SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) { SDL_Rect real_rect; + SDL_Surface *surface; - CHECK_RENDERER_MAGIC(renderer, -1); + CHECK_RENDERER_MAGIC(renderer, NULL); if (!renderer->RenderReadPixels) { - return SDL_Unsupported(); + SDL_Unsupported(); + return NULL; } FlushRenderCommands(renderer); /* we need to render before we read the results. */ - if (!format) { - if (!renderer->target) { - format = SDL_GetWindowPixelFormat(renderer->window); - } else { - format = renderer->target->format; - } - } - GetRenderViewportInPixels(renderer, &real_rect); if (rect) { if (!SDL_GetRectIntersection(rect, &real_rect, &real_rect)) { - return 0; - } - if (real_rect.y > rect->y) { - pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y); - } - if (real_rect.x > rect->x) { - int bpp = SDL_BYTESPERPIXEL(format); - pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x); + return NULL; } } - return renderer->RenderReadPixels(renderer, &real_rect, - format, pixels, pitch); + surface = renderer->RenderReadPixels(renderer, &real_rect); + if (surface) { + SDL_PropertiesID props = SDL_GetSurfaceProperties(surface); + + if (renderer->target) { + SDL_SetFloatProperty(props, SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT, renderer->target->SDR_white_point); + SDL_SetFloatProperty(props, SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, renderer->target->HDR_headroom); + } else { + SDL_SetFloatProperty(props, SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT, renderer->SDR_white_point); + SDL_SetFloatProperty(props, SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, renderer->HDR_headroom); + } + } + return surface; +} + +static void SDL_RenderApplyWindowShape(SDL_Renderer *renderer) +{ + SDL_Surface *shape = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_SHAPE_POINTER, NULL); + if (shape != renderer->shape_surface) { + if (renderer->shape_texture) { + SDL_DestroyTexture(renderer->shape_texture); + renderer->shape_texture = NULL; + } + + if (shape) { + /* There's nothing we can do if this fails, so just keep on going */ + renderer->shape_texture = SDL_CreateTextureFromSurface(renderer, shape); + + SDL_SetTextureBlendMode(renderer->shape_texture, + SDL_ComposeCustomBlendMode( + SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD, + SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD)); + } + renderer->shape_surface = shape; + } + + if (renderer->shape_texture) { + SDL_RenderTexture(renderer, renderer->shape_texture, NULL, NULL); + } } static void SDL_SimulateRenderVSync(SDL_Renderer *renderer) @@ -4023,6 +4400,10 @@ int SDL_RenderPresent(SDL_Renderer *renderer) SDL_RenderLogicalPresentation(renderer); } + if (renderer->transparent_window) { + SDL_RenderApplyWindowShape(renderer); + } + FlushRenderCommands(renderer); /* time to send everything to the GPU! */ #if DONT_DRAW_WHILE_HIDDEN @@ -4153,7 +4534,7 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer->vertex_data); if (renderer->window) { - SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_RENDERER); + SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_RENDERER_POINTER); } /* It's no longer magical... */ @@ -4189,6 +4570,16 @@ void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) return NULL; } +int SDL_AddVulkanRenderSemaphores(SDL_Renderer *renderer, Uint32 wait_stage_mask, Sint64 wait_semaphore, Sint64 signal_semaphore) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (!renderer->AddVulkanRenderSemaphores) { + return SDL_Unsupported(); + } + return renderer->AddVulkanRenderSemaphores(renderer, wait_stage_mask, wait_semaphore, signal_semaphore); +} + static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode) { if (blendMode == SDL_BLENDMODE_NONE_FULL) { @@ -4286,12 +4677,14 @@ int SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync) renderer->wanted_vsync = vsync ? SDL_TRUE : SDL_FALSE; /* for the software renderer, forward eventually the call to the WindowTexture renderer */ +#if SDL_VIDEO_RENDER_SW if (renderer->info.flags & SDL_RENDERER_SOFTWARE) { if (SDL_SetWindowTextureVSync(renderer->window, vsync) == 0) { renderer->simulate_vsync = SDL_FALSE; return 0; } } +#endif if (!renderer->SetVSync || renderer->SetVSync(renderer, vsync) != 0) { diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index ec4b34ab..d53751cd 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -63,13 +63,16 @@ typedef struct SDL_RenderViewState struct SDL_Texture { const void *magic; - Uint32 format; /**< The pixel format of the texture */ + SDL_Colorspace colorspace; /**< The colorspace of the texture */ + float SDR_white_point; /**< The SDR white point for this content */ + float HDR_headroom; /**< The HDR headroom needed by this content */ + SDL_PixelFormatEnum format; /**< The pixel format of the texture */ int access; /**< SDL_TextureAccess */ int w; /**< The width of the texture */ int h; /**< The height of the texture */ SDL_BlendMode blendMode; /**< The texture blend mode */ SDL_ScaleMode scaleMode; /**< The texture scale mode */ - SDL_Color color; /**< Texture modulation values */ + SDL_FColor color; /**< Texture modulation values */ SDL_RenderViewState view; /**< Target texture view state */ SDL_Renderer *renderer; @@ -126,14 +129,16 @@ typedef struct SDL_RenderCommand { size_t first; size_t count; - Uint8 r, g, b, a; + float color_scale; + SDL_FColor color; SDL_BlendMode blend; SDL_Texture *texture; } draw; struct { size_t first; - Uint8 r, g, b, a; + float color_scale; + SDL_FColor color; } color; } data; struct SDL_RenderCommand *next; @@ -142,7 +147,7 @@ typedef struct SDL_RenderCommand typedef struct SDL_VertexSolid { SDL_FPoint position; - SDL_Color color; + SDL_FColor color; } SDL_VertexSolid; typedef enum @@ -173,9 +178,9 @@ struct SDL_Renderer const SDL_FRect *srcrect, const SDL_FRect *dstrect); int (*QueueCopyEx)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcquad, const SDL_FRect *dstrect, - const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y); + const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y); int (*QueueGeometry)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, - const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride, + const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices, float scale_x, float scale_y); @@ -200,8 +205,7 @@ struct SDL_Renderer void (*UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture); void (*SetTextureScaleMode)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode); int (*SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture); - int (*RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, - Uint32 format, void *pixels, int pitch); + SDL_Surface *(*RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect); int (*RenderPresent)(SDL_Renderer *renderer); void (*DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture); @@ -212,6 +216,8 @@ struct SDL_Renderer void *(*GetMetalLayer)(SDL_Renderer *renderer); void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer); + int (*AddVulkanRenderSemaphores)(SDL_Renderer *renderer, Uint32 wait_stage_mask, Sint64 wait_semaphore, Sint64 signal_semaphore); + /* The current renderer info */ SDL_RendererInfo info; @@ -249,18 +255,25 @@ struct SDL_Renderer SDL_Texture *target; SDL_Mutex *target_mutex; - SDL_Color color; /**< Color for drawing operations values */ + SDL_Colorspace output_colorspace; + float SDR_white_point; + float HDR_headroom; + + float color_scale; + SDL_FColor color; /**< Color for drawing operations values */ SDL_BlendMode blendMode; /**< The drawing blend mode */ SDL_RenderCommand *render_commands; SDL_RenderCommand *render_commands_tail; SDL_RenderCommand *render_commands_pool; Uint32 render_command_generation; - Uint32 last_queued_color; + SDL_FColor last_queued_color; + float last_queued_color_scale; SDL_Rect last_queued_viewport; SDL_Rect last_queued_cliprect; SDL_bool last_queued_cliprect_enabled; SDL_bool color_queued; + SDL_bool color_scale_queued; SDL_bool viewport_queued; SDL_bool cliprect_queued; @@ -268,6 +281,11 @@ struct SDL_Renderer size_t vertex_data_used; size_t vertex_data_allocation; + /* Shaped window support */ + SDL_bool transparent_window; + SDL_Surface *shape_surface; + SDL_Texture *shape_texture; + SDL_PropertiesID props; void *driverdata; @@ -289,11 +307,20 @@ extern SDL_RenderDriver D3D12_RenderDriver; extern SDL_RenderDriver GL_RenderDriver; extern SDL_RenderDriver GLES2_RenderDriver; extern SDL_RenderDriver METAL_RenderDriver; +extern SDL_RenderDriver VULKAN_RenderDriver; extern SDL_RenderDriver PS2_RenderDriver; extern SDL_RenderDriver PSP_RenderDriver; extern SDL_RenderDriver SW_RenderDriver; extern SDL_RenderDriver VITA_GXM_RenderDriver; +/* Setup colorspace conversion */ +extern void SDL_SetupRendererColorspace(SDL_Renderer *renderer, SDL_PropertiesID props); + +/* Colorspace conversion functions */ +extern SDL_bool SDL_RenderingLinearSpace(SDL_Renderer *renderer); +extern void SDL_ConvertToLinear(SDL_FColor *color); +extern void SDL_ConvertFromLinear(SDL_FColor *color); + /* Blend mode functions */ extern SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode); extern SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode); diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c index 0257c5d6..a72f1e1a 100644 --- a/src/render/SDL_yuv_sw.c +++ b/src/render/SDL_yuv_sw.c @@ -27,7 +27,7 @@ #include "SDL_yuv_sw_c.h" #include "../video/SDL_yuv_c.h" -SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) +SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_PixelFormatEnum format, int w, int h) { SDL_SW_YUVTexture *swdata; @@ -94,7 +94,7 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) break; default: - SDL_assert(0 && "We should never get here (caught above)"); + SDL_assert(!"We should never get here (caught above)"); break; } @@ -211,7 +211,9 @@ int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, dst += 2 * ((swdata->w + 1) / 2); } } - } + } break; + default: + return SDL_SetError("Unsupported YUV format"); } return 0; } @@ -316,6 +318,8 @@ int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, return SDL_SetError("YV12, IYUV, NV12, NV21 textures only support full surface locks"); } break; + default: + return SDL_SetError("Unsupported YUV format"); } if (rect) { @@ -332,7 +336,7 @@ void SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture *swdata) } int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect, - Uint32 target_format, int w, int h, void *pixels, + SDL_PixelFormatEnum target_format, int w, int h, void *pixels, int pitch) { int stretch; diff --git a/src/render/SDL_yuv_sw_c.h b/src/render/SDL_yuv_sw_c.h index b3c0f5ef..25972d4c 100644 --- a/src/render/SDL_yuv_sw_c.h +++ b/src/render/SDL_yuv_sw_c.h @@ -28,8 +28,8 @@ struct SDL_SW_YUVTexture { - Uint32 format; - Uint32 target_format; + SDL_PixelFormatEnum format; + SDL_PixelFormatEnum target_format; int w, h; Uint8 *pixels; @@ -44,7 +44,7 @@ struct SDL_SW_YUVTexture typedef struct SDL_SW_YUVTexture SDL_SW_YUVTexture; -SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h); +SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_PixelFormatEnum format, int w, int h); int SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture *swdata, void **pixels, int *pitch); int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, @@ -60,7 +60,7 @@ int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, void **pixels, int *pitch); void SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture *swdata); int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect, - Uint32 target_format, int w, int h, void *pixels, + SDL_PixelFormatEnum target_format, int w, int h, void *pixels, int pitch); void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture *swdata); diff --git a/src/render/direct3d/D3D9_PixelShader_YUV.h b/src/render/direct3d/D3D9_PixelShader_YUV.h new file mode 100644 index 00000000..e6d91300 --- /dev/null +++ b/src/render/direct3d/D3D9_PixelShader_YUV.h @@ -0,0 +1,164 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// Parameters: +// +// float4 Bcoeff; +// float4 Gcoeff; +// float4 Rcoeff; +// float4 Yoffset; +// Texture2D theSampler+theTextureU; +// Texture2D theSampler+theTextureV; +// Texture2D theSampler+theTextureY; +// +// +// Registers: +// +// Name Reg Size +// ---------------------- ----- ---- +// Yoffset c0 1 +// Rcoeff c1 1 +// Gcoeff c2 1 +// Bcoeff c3 1 +// theSampler+theTextureY s0 1 +// theSampler+theTextureU s1 1 +// theSampler+theTextureV s2 1 +// + + ps_2_0 + def c4, 1, 0, 0, 0 + dcl t0.xy + dcl v0 + dcl_2d s0 + dcl_2d s1 + dcl_2d s2 + texld r0, t0, s0 + texld r1, t0, s1 + texld r2, t0, s2 + mov r0.y, r1.x + mov r0.z, r2.x + add r0.xyz, r0, c0 + dp3 r1.x, r0, c1 + dp3 r1.y, r0, c2 + dp3 r1.z, r0, c3 + mov r1.w, c4.x + mul r0, r1, v0 + mov oC0, r0 + +// approximately 12 instruction slots used (3 texture, 9 arithmetic) +#endif + +const BYTE g_ps20_main[] = +{ + 0, 2, 255, 255, 254, 255, + 97, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 87, 1, + 0, 0, 0, 2, 255, 255, + 7, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 80, 1, 0, 0, 168, 0, + 0, 0, 2, 0, 3, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 0, 0, 0, 0, + 192, 0, 0, 0, 2, 0, + 2, 0, 1, 0, 0, 0, + 176, 0, 0, 0, 0, 0, + 0, 0, 199, 0, 0, 0, + 2, 0, 1, 0, 1, 0, + 0, 0, 176, 0, 0, 0, + 0, 0, 0, 0, 206, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 176, 0, + 0, 0, 0, 0, 0, 0, + 214, 0, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 240, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, + 3, 0, 2, 0, 1, 0, + 0, 0, 24, 1, 0, 0, + 0, 0, 0, 0, 40, 1, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 64, 1, + 0, 0, 0, 0, 0, 0, + 66, 99, 111, 101, 102, 102, + 0, 171, 1, 0, 3, 0, + 1, 0, 4, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 71, 99, 111, 101, 102, 102, + 0, 82, 99, 111, 101, 102, + 102, 0, 89, 111, 102, 102, + 115, 101, 116, 0, 116, 104, + 101, 83, 97, 109, 112, 108, + 101, 114, 43, 116, 104, 101, + 84, 101, 120, 116, 117, 114, + 101, 85, 0, 171, 171, 171, + 4, 0, 7, 0, 1, 0, + 4, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 116, 104, + 101, 83, 97, 109, 112, 108, + 101, 114, 43, 116, 104, 101, + 84, 101, 120, 116, 117, 114, + 101, 86, 0, 171, 4, 0, + 7, 0, 1, 0, 4, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 116, 104, 101, 83, + 97, 109, 112, 108, 101, 114, + 43, 116, 104, 101, 84, 101, + 120, 116, 117, 114, 101, 89, + 0, 171, 4, 0, 7, 0, + 1, 0, 4, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 112, 115, 95, 50, 95, 48, + 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, 171, + 81, 0, 0, 5, 4, 0, + 15, 160, 0, 0, 128, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 15, 144, + 31, 0, 0, 2, 0, 0, + 0, 144, 0, 8, 15, 160, + 31, 0, 0, 2, 0, 0, + 0, 144, 1, 8, 15, 160, + 31, 0, 0, 2, 0, 0, + 0, 144, 2, 8, 15, 160, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 176, + 0, 8, 228, 160, 66, 0, + 0, 3, 1, 0, 15, 128, + 0, 0, 228, 176, 1, 8, + 228, 160, 66, 0, 0, 3, + 2, 0, 15, 128, 0, 0, + 228, 176, 2, 8, 228, 160, + 1, 0, 0, 2, 0, 0, + 2, 128, 1, 0, 0, 128, + 1, 0, 0, 2, 0, 0, + 4, 128, 2, 0, 0, 128, + 2, 0, 0, 3, 0, 0, + 7, 128, 0, 0, 228, 128, + 0, 0, 228, 160, 8, 0, + 0, 3, 1, 0, 1, 128, + 0, 0, 228, 128, 1, 0, + 228, 160, 8, 0, 0, 3, + 1, 0, 2, 128, 0, 0, + 228, 128, 2, 0, 228, 160, + 8, 0, 0, 3, 1, 0, + 4, 128, 0, 0, 228, 128, + 3, 0, 228, 160, 1, 0, + 0, 2, 1, 0, 8, 128, + 4, 0, 0, 160, 5, 0, + 0, 3, 0, 0, 15, 128, + 1, 0, 228, 128, 0, 0, + 228, 144, 1, 0, 0, 2, + 0, 8, 15, 128, 0, 0, + 228, 128, 255, 255, 0, 0 +}; diff --git a/src/render/direct3d/D3D9_PixelShader_YUV.hlsl b/src/render/direct3d/D3D9_PixelShader_YUV.hlsl new file mode 100644 index 00000000..88048480 --- /dev/null +++ b/src/render/direct3d/D3D9_PixelShader_YUV.hlsl @@ -0,0 +1,47 @@ + +Texture2D theTextureY : register(t0); +Texture2D theTextureU : register(t1); +Texture2D theTextureV : register(t2); + +SamplerState theSampler = sampler_state +{ + addressU = Clamp; + addressV = Clamp; + mipfilter = NONE; + minfilter = LINEAR; + magfilter = LINEAR; +}; + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +cbuffer Constants : register(b0) +{ + float4 Yoffset; + float4 Rcoeff; + float4 Gcoeff; + float4 Bcoeff; +}; + + +float4 main(PixelShaderInput input) : SV_TARGET +{ + float4 Output; + + float3 yuv; + yuv.x = theTextureY.Sample(theSampler, input.tex).r; + yuv.y = theTextureU.Sample(theSampler, input.tex).r; + yuv.z = theTextureV.Sample(theSampler, input.tex).r; + + yuv += Yoffset.xyz; + Output.r = dot(yuv, Rcoeff.xyz); + Output.g = dot(yuv, Gcoeff.xyz); + Output.b = dot(yuv, Bcoeff.xyz); + Output.a = 1.0f; + + return Output * input.color; +} diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 8c5ef457..053580d5 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -20,15 +20,16 @@ */ #include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D #include "../../core/windows/SDL_windows.h" #include "../SDL_sysrender.h" #include "../SDL_d3dmath.h" #include "../../video/windows/SDL_windowsvideo.h" +#include "../../video/SDL_pixels_c.h" -#ifdef SDL_VIDEO_RENDER_D3D +#if SDL_VIDEO_RENDER_D3D #define D3D_DEBUG_INFO #include #endif @@ -45,7 +46,8 @@ typedef struct SDL_bool cliprect_enabled_dirty; SDL_Rect cliprect; SDL_bool cliprect_dirty; - LPDIRECT3DPIXELSHADER9 shader; + D3D9_Shader shader; + const float *shader_params; } D3D_DrawStateCache; /* Direct3D renderer implementation */ @@ -89,6 +91,8 @@ typedef struct { D3D_TextureRep texture; D3DTEXTUREFILTERTYPE scaleMode; + D3D9_Shader shader; + const float *shader_params; #if SDL_HAVE_YUV /* YV12 texture support */ @@ -205,7 +209,7 @@ static D3DFORMAT PixelFormatToD3DFMT(Uint32 format) } } -static Uint32 D3DFMTToPixelFormat(D3DFORMAT format) +static SDL_PixelFormatEnum D3DFMTToPixelFormat(D3DFORMAT format) { switch (format) { case D3DFMT_R5G6B5: @@ -552,6 +556,12 @@ static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P if (D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), (texture->w + 1) / 2, (texture->h + 1) / 2) < 0) { return -1; } + + texturedata->shader = SHADER_YUV; + texturedata->shader_params = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8); + if (texturedata->shader_params == NULL) { + return SDL_SetError("Unsupported YUV colorspace"); + } } #endif return 0; @@ -716,7 +726,8 @@ static void D3D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) texturedata->texture.dirty = SDL_TRUE; if (data->drawstate.texture == texture) { data->drawstate.texture = NULL; - data->drawstate.shader = NULL; + data->drawstate.shader = SHADER_NONE; + data->drawstate.shader_params = NULL; IDirect3DDevice9_SetPixelShader(data->device, NULL); IDirect3DDevice9_SetTexture(data->device, 0, NULL); } @@ -797,14 +808,17 @@ static int D3D_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) return D3D_SetRenderTargetInternal(renderer, texture); } -static int D3D_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd) +static int D3D_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd) { return 0; /* nothing to do in this backend. */ } static int D3D_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) { - const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b); + const DWORD color = D3DCOLOR_COLORVALUE(cmd->data.draw.color.r * cmd->data.draw.color_scale, + cmd->data.draw.color.g * cmd->data.draw.color_scale, + cmd->data.draw.color.b * cmd->data.draw.color_scale, + cmd->data.draw.color.a); const size_t vertslen = count * sizeof(Vertex); Vertex *verts = (Vertex *)SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first); int i; @@ -826,13 +840,14 @@ static int D3D_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c } static int D3D_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, - const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride, + const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices, float scale_x, float scale_y) { int i; int count = indices ? num_indices : num_vertices; Vertex *verts = (Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(Vertex), 0, &cmd->data.draw.first); + const float color_scale = cmd->data.draw.color_scale; if (!verts) { return -1; @@ -844,7 +859,7 @@ static int D3D_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL for (i = 0; i < count; i++) { int j; float *xy_; - SDL_Color col_; + SDL_FColor *col_; if (size_indices == 4) { j = ((const Uint32 *)indices)[i]; } else if (size_indices == 2) { @@ -856,12 +871,12 @@ static int D3D_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL } xy_ = (float *)((char *)xy + j * xy_stride); - col_ = *(SDL_Color *)((char *)color + j * color_stride); + col_ = (SDL_FColor *)((char *)color + j * color_stride); verts->x = xy_[0] * scale_x - 0.5f; verts->y = xy_[1] * scale_y - 0.5f; verts->z = 0.0f; - verts->color = D3DCOLOR_ARGB(col_.a, col_.r, col_.g, col_.b); + verts->color = D3DCOLOR_COLORVALUE(col_->r * color_scale, col_->g * color_scale, col_->b * color_scale, col_->a); if (texture) { float *uv_ = (float *)((char *)uv + j * uv_stride); @@ -924,37 +939,24 @@ static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *textur } } -static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, LPDIRECT3DPIXELSHADER9 *shader) +static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Shader *shader, const float **shader_params) { D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; - SDL_assert(*shader == NULL); - if (!texturedata) { return SDL_SetError("Texture is not currently available"); } UpdateTextureScaleMode(data, texturedata, 0); + *shader = texturedata->shader; + *shader_params = texturedata->shader_params; + if (BindTextureRep(data->device, &texturedata->texture, 0) < 0) { return -1; } #if SDL_HAVE_YUV if (texturedata->yuv) { - switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) { - case SDL_YUV_CONVERSION_JPEG: - *shader = data->shaders[SHADER_YUV_JPEG]; - break; - case SDL_YUV_CONVERSION_BT601: - *shader = data->shaders[SHADER_YUV_BT601]; - break; - case SDL_YUV_CONVERSION_BT709: - *shader = data->shaders[SHADER_YUV_BT709]; - break; - default: - return SDL_SetError("Unsupported YUV conversion mode"); - } - UpdateTextureScaleMode(data, texturedata, 1); UpdateTextureScaleMode(data, texturedata, 2); @@ -979,7 +981,8 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd) D3D_TextureData *oldtexturedata = data->drawstate.texture ? (D3D_TextureData *)data->drawstate.texture->driverdata : NULL; D3D_TextureData *newtexturedata = texture ? (D3D_TextureData *)texture->driverdata : NULL; #endif - LPDIRECT3DPIXELSHADER9 shader = NULL; + D3D9_Shader shader = SHADER_NONE; + const float *shader_params = NULL; /* disable any enabled textures we aren't going to use, let SetupTextureState() do the rest. */ if (!texture) { @@ -991,18 +994,31 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd) IDirect3DDevice9_SetTexture(data->device, 2, NULL); } #endif - if (texture && SetupTextureState(data, texture, &shader) < 0) { + if (texture && SetupTextureState(data, texture, &shader, &shader_params) < 0) { return -1; } +#if SDL_HAVE_YUV if (shader != data->drawstate.shader) { - const HRESULT result = IDirect3DDevice9_SetPixelShader(data->device, shader); + const HRESULT result = IDirect3DDevice9_SetPixelShader(data->device, data->shaders[shader]); if (FAILED(result)) { return D3D_SetError("IDirect3DDevice9_SetPixelShader()", result); } data->drawstate.shader = shader; } + if (shader_params != data->drawstate.shader_params) { + if (shader_params) { + const UINT shader_params_length = 4; /* The YUV shader takes 4 float4 parameters */ + const HRESULT result = IDirect3DDevice9_SetPixelShaderConstantF(data->device, 0, shader_params, shader_params_length); + if (FAILED(result)) { + return D3D_SetError("IDirect3DDevice9_SetPixelShaderConstantF()", result); + } + } + data->drawstate.shader_params = shader_params; + } +#endif /* SDL_HAVE_YUV */ + data->drawstate.texture = texture; } else if (texture) { D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata; @@ -1094,7 +1110,8 @@ static void D3D_InvalidateCachedState(SDL_Renderer *renderer) data->drawstate.cliprect_dirty = SDL_TRUE; data->drawstate.blend = SDL_BLENDMODE_INVALID; data->drawstate.texture = NULL; - data->drawstate.shader = NULL; + data->drawstate.shader = SHADER_NONE; + data->drawstate.shader_params = NULL; } static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) @@ -1170,6 +1187,7 @@ static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) { SDL_copyp(viewport, &cmd->data.viewport.rect); data->drawstate.viewport_dirty = SDL_TRUE; + data->drawstate.cliprect_dirty = SDL_TRUE; } break; } @@ -1191,7 +1209,10 @@ static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v case SDL_RENDERCMD_CLEAR: { - const DWORD color = D3DCOLOR_ARGB(cmd->data.color.a, cmd->data.color.r, cmd->data.color.g, cmd->data.color.b); + const DWORD color = D3DCOLOR_COLORVALUE(cmd->data.color.color.r * cmd->data.color.color_scale, + cmd->data.color.color.g * cmd->data.color.color_scale, + cmd->data.color.color.b * cmd->data.color.color_scale, + cmd->data.color.color.a); const SDL_Rect *viewport = &data->drawstate.viewport; const int backw = istarget ? renderer->target->w : data->pparams.BackBufferWidth; const int backh = istarget ? renderer->target->h : data->pparams.BackBufferHeight; @@ -1292,8 +1313,7 @@ static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v return 0; } -static int D3D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, - Uint32 format, void *pixels, int pitch) +static SDL_Surface *D3D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) { D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; D3DSURFACE_DESC desc; @@ -1302,7 +1322,7 @@ static int D3D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, RECT d3drect; D3DLOCKED_RECT locked; HRESULT result; - int status; + SDL_Surface *output; if (data->currentRenderTarget) { backBuffer = data->currentRenderTarget; @@ -1312,18 +1332,21 @@ static int D3D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, result = IDirect3DSurface9_GetDesc(backBuffer, &desc); if (FAILED(result)) { - return D3D_SetError("GetDesc()", result); + D3D_SetError("GetDesc()", result); + return NULL; } result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL); if (FAILED(result)) { - return D3D_SetError("CreateOffscreenPlainSurface()", result); + D3D_SetError("CreateOffscreenPlainSurface()", result); + return NULL; } result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface); if (FAILED(result)) { IDirect3DSurface9_Release(surface); - return D3D_SetError("GetRenderTargetData()", result); + D3D_SetError("GetRenderTargetData()", result); + return NULL; } d3drect.left = rect->x; @@ -1334,18 +1357,17 @@ static int D3D_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY); if (FAILED(result)) { IDirect3DSurface9_Release(surface); - return D3D_SetError("LockRect()", result); + D3D_SetError("LockRect()", result); + return NULL; } - status = SDL_ConvertPixels(rect->w, rect->h, - D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch, - format, pixels, pitch); + output = SDL_DuplicatePixels(rect->w, rect->h, D3DFMTToPixelFormat(desc.Format), SDL_COLORSPACE_SRGB, locked.pBits, locked.Pitch); IDirect3DSurface9_UnlockRect(surface); IDirect3DSurface9_Release(surface); - return status; + return output; } static int D3D_RenderPresent(SDL_Renderer *renderer) @@ -1380,7 +1402,8 @@ static void D3D_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) if (renderdata->drawstate.texture == texture) { renderdata->drawstate.texture = NULL; - renderdata->drawstate.shader = NULL; + renderdata->drawstate.shader = SHADER_NONE; + renderdata->drawstate.shader_params = NULL; IDirect3DDevice9_SetPixelShader(renderdata->device, NULL); IDirect3DDevice9_SetTexture(renderdata->device, 0, NULL); #if SDL_HAVE_YUV @@ -1529,7 +1552,7 @@ static int D3D_Reset(SDL_Renderer *renderer) static int D3D_SetVSync(SDL_Renderer *renderer, const int vsync) { - D3D_RenderData *data = renderer->driverdata; + D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata; if (vsync) { data->pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; @@ -1563,6 +1586,14 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro } renderer->magic = &SDL_renderer_magic; + SDL_SetupRendererColorspace(renderer, create_props); + + if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { + SDL_SetError("Unsupported output colorspace"); + SDL_free(renderer); + return NULL; + } + data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); @@ -1570,9 +1601,9 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro } if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) { + SDL_SetError("Unable to create Direct3D interface"); SDL_free(renderer); SDL_free(data); - SDL_SetError("Unable to create Direct3D interface"); return NULL; } @@ -1587,8 +1618,8 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro renderer->UnlockTexture = D3D_UnlockTexture; renderer->SetTextureScaleMode = D3D_SetTextureScaleMode; renderer->SetRenderTarget = D3D_SetRenderTarget; - renderer->QueueSetViewport = D3D_QueueSetViewport; - renderer->QueueSetDrawColor = D3D_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ + renderer->QueueSetViewport = D3D_QueueNoOp; + renderer->QueueSetDrawColor = D3D_QueueNoOp; renderer->QueueDrawPoints = D3D_QueueDrawPoints; renderer->QueueDrawLines = D3D_QueueDrawPoints; /* lines and points queue vertices the same way. */ renderer->QueueGeometry = D3D_QueueGeometry; @@ -1610,7 +1641,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro } SDL_zero(pparams); - pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); + pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); pparams.BackBufferWidth = w; pparams.BackBufferHeight = h; pparams.BackBufferCount = 1; @@ -1625,7 +1656,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro pparams.BackBufferFormat = D3DFMT_UNKNOWN; pparams.FullScreen_RefreshRateInHz = 0; } - if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; @@ -1696,20 +1727,20 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro #if SDL_HAVE_YUV if (caps.MaxSimultaneousTextures >= 3) { int i; - for (i = 0; i < SDL_arraysize(data->shaders); ++i) { + for (i = SHADER_NONE + 1; i < SDL_arraysize(data->shaders); ++i) { result = D3D9_CreatePixelShader(data->device, (D3D9_Shader)i, &data->shaders[i]); if (FAILED(result)) { D3D_SetError("CreatePixelShader()", result); } } - if (data->shaders[SHADER_YUV_JPEG] && data->shaders[SHADER_YUV_BT601] && data->shaders[SHADER_YUV_BT709]) { + if (data->shaders[SHADER_YUV]) { renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; } } #endif - SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER, data->device); + SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D9_DEVICE_POINTER, data->device); return renderer; } diff --git a/src/render/direct3d/SDL_shaders_d3d.c b/src/render/direct3d/SDL_shaders_d3d.c index a05d23da..4b468d84 100644 --- a/src/render/direct3d/SDL_shaders_d3d.c +++ b/src/render/direct3d/SDL_shaders_d3d.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D #include "../../core/windows/SDL_windows.h" @@ -28,241 +28,21 @@ #include "SDL_shaders_d3d.h" -/* The shaders here were compiled with: +/* The shaders here were compiled with compile_shaders.bat */ - fxc /T ps_2_0 /Fo"" "" +#define g_ps20_main D3D9_PixelShader_YUV +#include "D3D9_PixelShader_YUV.h" +#undef g_ps20_main - Shader object code was converted to a list of DWORDs via the following - *nix style command (available separately from Windows + MSVC): - - hexdump -v -e '6/4 "0x%08.8x, " "\n"' -*/ - -/* --- D3D9_PixelShader_YUV_JPEG.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureU : register(t1); - Texture2D theTextureV : register(t2); - SamplerState theSampler = sampler_state - { - addressU = Clamp; - addressV = Clamp; - mipfilter = NONE; - minfilter = LINEAR; - magfilter = LINEAR; - }; - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } -*/ -static const DWORD D3D9_PixelShader_YUV_JPEG[] = { - 0xffff0200, 0x0044fffe, 0x42415443, 0x0000001c, 0x000000d7, 0xffff0200, - 0x00000003, 0x0000001c, 0x00000100, 0x000000d0, 0x00000058, 0x00010003, - 0x00000001, 0x00000070, 0x00000000, 0x00000080, 0x00020003, 0x00000001, - 0x00000098, 0x00000000, 0x000000a8, 0x00000003, 0x00000001, 0x000000c0, - 0x00000000, 0x53656874, 0x6c706d61, 0x742b7265, 0x65546568, 0x72757478, - 0xab005565, 0x00070004, 0x00040001, 0x00000001, 0x00000000, 0x53656874, - 0x6c706d61, 0x742b7265, 0x65546568, 0x72757478, 0xab005665, 0x00070004, - 0x00040001, 0x00000001, 0x00000000, 0x53656874, 0x6c706d61, 0x742b7265, - 0x65546568, 0x72757478, 0xab005965, 0x00070004, 0x00040001, 0x00000001, - 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, - 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e362072, - 0x36392e33, 0x312e3030, 0x34383336, 0xababab00, 0x05000051, 0xa00f0000, - 0x00000000, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f800000, 0x00000000, 0x3fb374bc, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, 0x90000000, - 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000042, - 0x800f0001, 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0002, 0xb0e40000, - 0xa0e40802, 0x02000001, 0x80020000, 0x80000001, 0x02000001, 0x80040000, - 0x80000002, 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, 0x03000008, - 0x80010001, 0x80e40000, 0xa0e40001, 0x03000008, 0x80020001, 0x80e40000, - 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, - 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, - 0x90e40000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff -}; - -/* --- D3D9_PixelShader_YUV_BT601.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureU : register(t1); - Texture2D theTextureV : register(t2); - SamplerState theSampler = sampler_state - { - addressU = Clamp; - addressV = Clamp; - mipfilter = NONE; - minfilter = LINEAR; - magfilter = LINEAR; - }; - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } -*/ -static const DWORD D3D9_PixelShader_YUV_BT601[] = { - 0xffff0200, 0x0044fffe, 0x42415443, 0x0000001c, 0x000000d7, 0xffff0200, - 0x00000003, 0x0000001c, 0x00000100, 0x000000d0, 0x00000058, 0x00010003, - 0x00000001, 0x00000070, 0x00000000, 0x00000080, 0x00020003, 0x00000001, - 0x00000098, 0x00000000, 0x000000a8, 0x00000003, 0x00000001, 0x000000c0, - 0x00000000, 0x53656874, 0x6c706d61, 0x742b7265, 0x65546568, 0x72757478, - 0xab005565, 0x00070004, 0x00040001, 0x00000001, 0x00000000, 0x53656874, - 0x6c706d61, 0x742b7265, 0x65546568, 0x72757478, 0xab005665, 0x00070004, - 0x00040001, 0x00000001, 0x00000000, 0x53656874, 0x6c706d61, 0x742b7265, - 0x65546568, 0x72757478, 0xab005965, 0x00070004, 0x00040001, 0x00000001, - 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, - 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e362072, - 0x36392e33, 0x312e3030, 0x34383336, 0xababab00, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x00000000, 0x3fcc49ba, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, 0x90000000, - 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000042, - 0x800f0001, 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0002, 0xb0e40000, - 0xa0e40802, 0x02000001, 0x80020000, 0x80000001, 0x02000001, 0x80040000, - 0x80000002, 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, 0x03000008, - 0x80010001, 0x80e40000, 0xa0e40001, 0x03000008, 0x80020001, 0x80e40000, - 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, - 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, - 0x90e40000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff -}; - -/* --- D3D9_PixelShader_YUV_BT709.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureU : register(t1); - Texture2D theTextureV : register(t2); - SamplerState theSampler = sampler_state - { - addressU = Clamp; - addressV = Clamp; - mipfilter = NONE; - minfilter = LINEAR; - magfilter = LINEAR; - }; - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } -*/ -static const DWORD D3D9_PixelShader_YUV_BT709[] = { - 0xffff0200, 0x0044fffe, 0x42415443, 0x0000001c, 0x000000d7, 0xffff0200, - 0x00000003, 0x0000001c, 0x00000100, 0x000000d0, 0x00000058, 0x00010003, - 0x00000001, 0x00000070, 0x00000000, 0x00000080, 0x00020003, 0x00000001, - 0x00000098, 0x00000000, 0x000000a8, 0x00000003, 0x00000001, 0x000000c0, - 0x00000000, 0x53656874, 0x6c706d61, 0x742b7265, 0x65546568, 0x72757478, - 0xab005565, 0x00070004, 0x00040001, 0x00000001, 0x00000000, 0x53656874, - 0x6c706d61, 0x742b7265, 0x65546568, 0x72757478, 0xab005665, 0x00070004, - 0x00040001, 0x00000001, 0x00000000, 0x53656874, 0x6c706d61, 0x742b7265, - 0x65546568, 0x72757478, 0xab005965, 0x00070004, 0x00040001, 0x00000001, - 0x00000000, 0x325f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, - 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e362072, - 0x36392e33, 0x312e3030, 0x34383336, 0xababab00, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x00000000, 0x3fe57732, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, 0x90000000, - 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000042, - 0x800f0001, 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0002, 0xb0e40000, - 0xa0e40802, 0x02000001, 0x80020000, 0x80000001, 0x02000001, 0x80040000, - 0x80000002, 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, 0x03000008, - 0x80010001, 0x80e40000, 0xa0e40001, 0x03000008, 0x80020001, 0x80e40000, - 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, - 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, - 0x90e40000, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff -}; - -static const DWORD *D3D9_shaders[] = { - D3D9_PixelShader_YUV_JPEG, - D3D9_PixelShader_YUV_BT601, - D3D9_PixelShader_YUV_BT709, +static const BYTE *D3D9_shaders[] = { + NULL, + D3D9_PixelShader_YUV }; +SDL_COMPILE_TIME_ASSERT(D3D9_shaders, SDL_arraysize(D3D9_shaders) == NUM_SHADERS); HRESULT D3D9_CreatePixelShader(IDirect3DDevice9 *d3dDevice, D3D9_Shader shader, IDirect3DPixelShader9 **pixelShader) { - return IDirect3DDevice9_CreatePixelShader(d3dDevice, D3D9_shaders[shader], pixelShader); + return IDirect3DDevice9_CreatePixelShader(d3dDevice, (const DWORD *)D3D9_shaders[shader], pixelShader); } -#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */ +#endif /* SDL_VIDEO_RENDER_D3D */ diff --git a/src/render/direct3d/SDL_shaders_d3d.h b/src/render/direct3d/SDL_shaders_d3d.h index 13ecf6fc..41d9fdc7 100644 --- a/src/render/direct3d/SDL_shaders_d3d.h +++ b/src/render/direct3d/SDL_shaders_d3d.h @@ -24,9 +24,8 @@ typedef enum { - SHADER_YUV_JPEG, - SHADER_YUV_BT601, - SHADER_YUV_BT709, + SHADER_NONE, + SHADER_YUV, NUM_SHADERS } D3D9_Shader; diff --git a/src/render/direct3d/compile_shaders.bat b/src/render/direct3d/compile_shaders.bat new file mode 100644 index 00000000..81d513e2 --- /dev/null +++ b/src/render/direct3d/compile_shaders.bat @@ -0,0 +1 @@ +fxc /T ps_2_0 /Fh D3D9_PixelShader_YUV.h D3D9_PixelShader_YUV.hlsl diff --git a/src/render/direct3d11/D3D11_PixelShader_Advanced.h b/src/render/direct3d11/D3D11_PixelShader_Advanced.h new file mode 100644 index 00000000..a1297c98 --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Advanced.h @@ -0,0 +1,1060 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer Constants +// { +// +// float scRGB_output; // Offset: 0 Size: 4 +// float texture_type; // Offset: 4 Size: 4 +// float input_type; // Offset: 8 Size: 4 +// float color_scale; // Offset: 12 Size: 4 +// float tonemap_method; // Offset: 16 Size: 4 +// float tonemap_factor1; // Offset: 20 Size: 4 +// float tonemap_factor2; // Offset: 24 Size: 4 +// float sdr_white_point; // Offset: 28 Size: 4 +// float4 Yoffset; // Offset: 32 Size: 16 +// float4 Rcoeff; // Offset: 48 Size: 16 +// float4 Gcoeff; // Offset: 64 Size: 16 +// float4 Bcoeff; // Offset: 80 Size: 16 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sampler0 sampler NA NA s0 1 +// texture0 texture float4 2d t0 1 +// texture1 texture float4 2d t1 1 +// texture2 texture float4 2d t2 1 +// Constants cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// 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[6], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texture2d (float,float,float,float) t1 +dcl_resource_texture2d (float,float,float,float) t2 +dcl_input_ps linear v1.xy +dcl_input_ps linear v2.xyzw +dcl_output o0.xyzw +dcl_temps 7 +eq r0.xyzw, cb0[0].yzzz, l(0.000000, 3.000000, 2.000000, 1.000000) +if_nz r0.x + mov r1.xyzw, l(1.000000,1.000000,1.000000,1.000000) +else + eq r0.x, cb0[0].y, l(1.000000) + if_nz r0.x + sample_indexable(texture2d)(float,float,float,float) r1.xyzw, v1.xyxx, t0.xyzw, s0 + else + eq r0.x, cb0[0].y, l(2.000000) + if_nz r0.x + sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0 + sample_indexable(texture2d)(float,float,float,float) r2.yz, v1.xyxx, t1.zxyw, s0 + add r2.xyz, r2.xyzx, cb0[2].xyzx + dp3 r1.x, r2.xyzx, cb0[3].xyzx + dp3 r1.y, r2.xyzx, cb0[4].xyzx + dp3 r1.z, r2.xyzx, cb0[5].xyzx + else + eq r0.x, cb0[0].y, l(3.000000) + if_nz r0.x + sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0 + sample_indexable(texture2d)(float,float,float,float) r2.yz, v1.xyxx, t1.zyxw, s0 + add r2.xyz, r2.xyzx, cb0[2].xyzx + dp3 r1.x, r2.xyzx, cb0[3].xyzx + dp3 r1.y, r2.xyzx, cb0[4].xyzx + dp3 r1.z, r2.xyzx, cb0[5].xyzx + else + eq r0.x, cb0[0].y, l(4.000000) + if_nz r0.x + sample_indexable(texture2d)(float,float,float,float) r2.x, v1.xyxx, t0.xyzw, s0 + sample_indexable(texture2d)(float,float,float,float) r2.y, v1.xyxx, t1.yxzw, s0 + sample_indexable(texture2d)(float,float,float,float) r2.z, v1.xyxx, t2.yzxw, s0 + add r2.xyz, r2.xyzx, cb0[2].xyzx + dp3 r1.x, r2.xyzx, cb0[3].xyzx + dp3 r1.y, r2.xyzx, cb0[4].xyzx + dp3 r1.z, r2.xyzx, cb0[5].xyzx + else + mov r1.xyz, l(1.000000,0,0,0) + endif + endif + endif + mov r1.w, l(1.000000) + endif +endif +log r2.xyz, |r1.xyzx| +mul r2.xyz, r2.xyzx, l(0.012683, 0.012683, 0.012683, 0.000000) +exp r2.xyz, r2.xyzx +add r3.xyz, r2.xyzx, l(-0.835938, -0.835938, -0.835938, 0.000000) +max r3.xyz, r3.xyzx, l(0.000000, 0.000000, 0.000000, 0.000000) +mad r2.xyz, -r2.xyzx, l(18.687500, 18.687500, 18.687500, 0.000000), l(18.851562, 18.851562, 18.851562, 0.000000) +div r2.xyz, r3.xyzx, r2.xyzx +log r2.xyz, |r2.xyzx| +mul r2.xyz, r2.xyzx, l(6.277395, 6.277395, 6.277395, 0.000000) +exp r2.xyz, r2.xyzx +mul r2.xyz, r2.xyzx, l(10000.000000, 10000.000000, 10000.000000, 0.000000) +div r2.xyz, r2.xyzx, cb0[1].wwww +movc r2.xyz, r0.yyyy, r2.xyzx, r1.xyzx +ne r0.x, cb0[1].x, l(0.000000) +mul r3.xyz, r2.xyzx, cb0[1].yyyy +eq r4.xy, cb0[1].xxxx, l(1.000000, 2.000000, 0.000000, 0.000000) +dp3 r5.x, l(0.627404, 0.329283, 0.043313, 0.000000), r2.xyzx +dp3 r5.y, l(0.069097, 0.919541, 0.011362, 0.000000), r2.xyzx +dp3 r5.z, l(0.016391, 0.088013, 0.895595, 0.000000), r2.xyzx +movc r5.xyz, r0.zzzz, r5.xyzx, r2.xyzx +max r2.w, r5.z, r5.y +max r2.w, r2.w, r5.x +lt r3.w, l(0.000000), r2.w +mad r4.zw, cb0[1].yyyz, r2.wwww, l(0.000000, 0.000000, 1.000000, 1.000000) +div r2.w, r4.z, r4.w +mul r6.xyz, r2.wwww, r5.xyzx +movc r5.xyz, r3.wwww, r6.xyzx, r5.xyzx +dp3 r6.x, l(1.660496, -0.587656, -0.072840, 0.000000), r5.xyzx +dp3 r6.y, l(-0.124547, 1.132895, -0.008348, 0.000000), r5.xyzx +dp3 r6.z, l(-0.018154, -0.100597, 1.118751, 0.000000), r5.xyzx +movc r5.xyz, r0.zzzz, r6.xyzx, r5.xyzx +movc r4.yzw, r4.yyyy, r5.xxyz, r2.xxyz +movc r3.xyz, r4.xxxx, r3.xyzx, r4.yzwy +movc r2.xyz, r0.xxxx, r3.xyzx, r2.xyzx +if_nz r0.w + ne r0.x, l(0.000000, 0.000000, 0.000000, 0.000000), cb0[0].x + if_nz r0.x + ge r3.xyz, l(0.040450, 0.040450, 0.040450, 0.000000), r2.xyzx + mul r4.xyz, r2.xyzx, l(0.077399, 0.077399, 0.077399, 0.000000) + add r5.xyz, r2.xyzx, l(0.055000, 0.055000, 0.055000, 0.000000) + mul r5.xyz, |r5.xyzx|, l(0.947867, 0.947867, 0.947867, 0.000000) + log r5.xyz, r5.xyzx + mul r5.xyz, r5.xyzx, l(2.400000, 2.400000, 2.400000, 0.000000) + exp r5.xyz, r5.xyzx + movc r2.xyz, r3.xyzx, r4.xyzx, r5.xyzx + endif + mul r1.xyz, r2.xyzx, cb0[0].wwww +else + if_nz r0.z + mul r1.xyz, r2.xyzx, cb0[0].wwww + ne r0.x, l(0.000000, 0.000000, 0.000000, 0.000000), cb0[0].x + if_z r0.x + ge r0.xzw, l(0.003131, 0.000000, 0.003131, 0.003131), r1.xxyz + mul r3.xyz, r1.xyzx, l(12.920000, 12.920000, 12.920000, 0.000000) + log r4.xyz, |r1.xyzx| + mul r4.xyz, r4.xyzx, l(0.416667, 0.416667, 0.416667, 0.000000) + exp r4.xyz, r4.xyzx + mad r4.xyz, r4.xyzx, l(1.055000, 1.055000, 1.055000, 0.000000), l(-0.055000, -0.055000, -0.055000, 0.000000) + movc_sat r1.xyz, r0.xzwx, r3.xyzx, r4.xyzx + endif + else + if_nz r0.y + dp3 r0.x, l(1.660496, -0.587656, -0.072840, 0.000000), r2.xyzx + dp3 r0.y, l(-0.124547, 1.132895, -0.008348, 0.000000), r2.xyzx + dp3 r0.z, l(-0.018154, -0.100597, 1.118751, 0.000000), r2.xyzx + mul r1.xyz, r0.xyzx, cb0[0].wwww + ne r0.x, l(0.000000, 0.000000, 0.000000, 0.000000), cb0[0].x + if_z r0.x + ge r0.xyz, l(0.003131, 0.003131, 0.003131, 0.000000), r1.xyzx + mul r3.xyz, r1.xyzx, l(12.920000, 12.920000, 12.920000, 0.000000) + log r4.xyz, |r1.xyzx| + mul r4.xyz, r4.xyzx, l(0.416667, 0.416667, 0.416667, 0.000000) + exp r4.xyz, r4.xyzx + mad r4.xyz, r4.xyzx, l(1.055000, 1.055000, 1.055000, 0.000000), l(-0.055000, -0.055000, -0.055000, 0.000000) + movc_sat r1.xyz, r0.xyzx, r3.xyzx, r4.xyzx + endif + else + mul r1.xyz, r2.xyzx, cb0[0].wwww + endif + endif +endif +mul o0.xyzw, r1.xyzw, v2.xyzw +ret +// Approximately 126 instruction slots used +#endif + +const BYTE g_main[] = +{ + 68, 88, 66, 67, 154, 200, + 28, 25, 30, 140, 0, 183, + 251, 32, 6, 185, 210, 29, + 251, 110, 1, 0, 0, 0, + 64, 20, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 80, 4, 0, 0, 196, 4, + 0, 0, 248, 4, 0, 0, + 164, 19, 0, 0, 82, 68, + 69, 70, 20, 4, 0, 0, + 1, 0, 0, 0, 12, 1, + 0, 0, 5, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 233, 3, 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, + 220, 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, 229, 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, 238, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 247, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 2, 0, 0, 0, + 1, 0, 0, 0, 13, 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, 1, 0, 0, 0, + 1, 0, 0, 0, 115, 97, + 109, 112, 108, 101, 114, 48, + 0, 116, 101, 120, 116, 117, + 114, 101, 48, 0, 116, 101, + 120, 116, 117, 114, 101, 49, + 0, 116, 101, 120, 116, 117, + 114, 101, 50, 0, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 171, 171, 0, 1, + 0, 0, 12, 0, 0, 0, + 36, 1, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 3, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 24, 3, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 60, 3, 0, 0, + 4, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 24, 3, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 73, 3, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 24, 3, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 84, 3, + 0, 0, 12, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 24, 3, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 96, 3, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 24, 3, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 111, 3, 0, 0, 20, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 24, 3, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 127, 3, + 0, 0, 24, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 24, 3, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 143, 3, 0, 0, + 28, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 24, 3, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 159, 3, 0, 0, 32, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 3, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 212, 3, + 0, 0, 48, 0, 0, 0, + 16, 0, 0, 0, 2, 0, + 0, 0, 176, 3, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 219, 3, 0, 0, + 64, 0, 0, 0, 16, 0, + 0, 0, 2, 0, 0, 0, + 176, 3, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 226, 3, 0, 0, 80, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 3, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 115, 99, + 82, 71, 66, 95, 111, 117, + 116, 112, 117, 116, 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, 3, 0, 0, + 116, 101, 120, 116, 117, 114, + 101, 95, 116, 121, 112, 101, + 0, 105, 110, 112, 117, 116, + 95, 116, 121, 112, 101, 0, + 99, 111, 108, 111, 114, 95, + 115, 99, 97, 108, 101, 0, + 116, 111, 110, 101, 109, 97, + 112, 95, 109, 101, 116, 104, + 111, 100, 0, 116, 111, 110, + 101, 109, 97, 112, 95, 102, + 97, 99, 116, 111, 114, 49, + 0, 116, 111, 110, 101, 109, + 97, 112, 95, 102, 97, 99, + 116, 111, 114, 50, 0, 115, + 100, 114, 95, 119, 104, 105, + 116, 101, 95, 112, 111, 105, + 110, 116, 0, 89, 111, 102, + 102, 115, 101, 116, 0, 102, + 108, 111, 97, 116, 52, 0, + 171, 171, 1, 0, 3, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 167, 3, + 0, 0, 82, 99, 111, 101, + 102, 102, 0, 71, 99, 111, + 101, 102, 102, 0, 66, 99, + 111, 101, 102, 102, 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, 171, 171, 171, + 73, 83, 71, 78, 108, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 101, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 15, 15, 0, 0, 83, 86, + 95, 80, 79, 83, 73, 84, + 73, 79, 78, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 67, 79, 76, 79, 82, + 0, 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, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 69, 88, 164, 14, + 0, 0, 80, 0, 0, 0, + 169, 3, 0, 0, 106, 8, + 0, 1, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 6, 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, 88, 24, + 0, 4, 0, 112, 16, 0, + 1, 0, 0, 0, 85, 85, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 2, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 7, 0, + 0, 0, 24, 0, 0, 11, + 242, 0, 16, 0, 0, 0, + 0, 0, 150, 138, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 64, 64, 0, 0, 0, 64, + 0, 0, 128, 63, 31, 0, + 4, 3, 10, 0, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 242, 0, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 18, 0, 0, 1, 24, 0, + 0, 8, 18, 0, 16, 0, + 0, 0, 0, 0, 26, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 31, 0, 4, 3, 10, 0, + 16, 0, 0, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 18, 0, 0, 1, + 24, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 64, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 69, 0, + 0, 139, 194, 0, 0, 128, + 67, 85, 21, 0, 98, 0, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 38, 125, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 16, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 8, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 16, 0, 0, 8, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 18, 0, 0, 1, + 24, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 64, 64, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 69, 0, + 0, 139, 194, 0, 0, 128, + 67, 85, 21, 0, 98, 0, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 102, 124, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 16, 0, 0, 8, + 18, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 16, 0, + 0, 8, 34, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 16, 0, 0, 8, 66, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 18, 0, 0, 1, + 24, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 64, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 69, 0, 0, 139, + 194, 0, 0, 128, 67, 85, + 21, 0, 18, 0, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 69, 0, + 0, 139, 194, 0, 0, 128, + 67, 85, 21, 0, 34, 0, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 22, 126, 16, 0, + 1, 0, 0, 0, 0, 96, + 16, 0, 0, 0, 0, 0, + 69, 0, 0, 139, 194, 0, + 0, 128, 67, 85, 21, 0, + 66, 0, 16, 0, 2, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 150, 124, + 16, 0, 2, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 8, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 16, 0, + 0, 8, 18, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 70, 130, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 16, 0, 0, 8, 34, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 70, 130, 32, 0, + 0, 0, 0, 0, 4, 0, + 0, 0, 16, 0, 0, 8, + 66, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 130, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 18, 0, + 0, 1, 54, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 54, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 21, 0, 0, 1, 21, 0, + 0, 1, 47, 0, 0, 6, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 128, + 129, 0, 0, 0, 1, 0, + 0, 0, 56, 0, 0, 10, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 172, 205, 79, 60, + 172, 205, 79, 60, 172, 205, + 79, 60, 0, 0, 0, 0, + 25, 0, 0, 5, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 86, 191, + 0, 0, 86, 191, 0, 0, + 86, 191, 0, 0, 0, 0, + 52, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 16, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 128, 65, 0, 0, 0, + 2, 0, 0, 0, 2, 64, + 0, 0, 0, 128, 149, 65, + 0, 128, 149, 65, 0, 128, + 149, 65, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 208, + 150, 65, 0, 208, 150, 65, + 0, 208, 150, 65, 0, 0, + 0, 0, 14, 0, 0, 7, + 114, 0, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 47, 0, 0, 6, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 128, 129, 0, + 0, 0, 2, 0, 0, 0, + 56, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 107, 224, 200, 64, 107, 224, + 200, 64, 107, 224, 200, 64, + 0, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 10, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 64, 28, 70, 0, 64, + 28, 70, 0, 64, 28, 70, + 0, 0, 0, 0, 14, 0, + 0, 8, 114, 0, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 143, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 1, 0, 0, 0, + 57, 0, 0, 8, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 86, 133, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 24, 0, + 0, 11, 50, 0, 16, 0, + 4, 0, 0, 0, 6, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 16, 0, 0, 10, 18, 0, + 16, 0, 5, 0, 0, 0, + 2, 64, 0, 0, 140, 157, + 32, 63, 200, 151, 168, 62, + 249, 104, 49, 61, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 10, 34, 0, 16, 0, + 5, 0, 0, 0, 2, 64, + 0, 0, 186, 130, 141, 61, + 10, 103, 107, 63, 175, 39, + 58, 60, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 10, + 66, 0, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 107, 70, 134, 60, 41, 64, + 180, 61, 183, 69, 101, 63, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 5, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 52, 0, 0, 7, 130, 0, + 16, 0, 2, 0, 0, 0, + 42, 0, 16, 0, 5, 0, + 0, 0, 26, 0, 16, 0, + 5, 0, 0, 0, 52, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 5, 0, + 0, 0, 49, 0, 0, 7, + 130, 0, 16, 0, 3, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 0, 0, 58, 0, + 16, 0, 2, 0, 0, 0, + 50, 0, 0, 13, 194, 0, + 16, 0, 4, 0, 0, 0, + 86, 137, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 63, + 0, 0, 128, 63, 14, 0, + 0, 7, 130, 0, 16, 0, + 2, 0, 0, 0, 42, 0, + 16, 0, 4, 0, 0, 0, + 58, 0, 16, 0, 4, 0, + 0, 0, 56, 0, 0, 7, + 114, 0, 16, 0, 6, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 5, 0, 0, 0, + 246, 15, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 16, 0, 0, 10, 18, 0, + 16, 0, 6, 0, 0, 0, + 2, 64, 0, 0, 34, 139, + 212, 63, 160, 112, 22, 191, + 35, 45, 149, 189, 0, 0, + 0, 0, 70, 2, 16, 0, + 5, 0, 0, 0, 16, 0, + 0, 10, 34, 0, 16, 0, + 6, 0, 0, 0, 2, 64, + 0, 0, 127, 18, 255, 189, + 180, 2, 145, 63, 13, 198, + 8, 188, 0, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 16, 0, 0, 10, + 66, 0, 16, 0, 6, 0, + 0, 0, 2, 64, 0, 0, + 179, 183, 148, 188, 205, 5, + 206, 189, 60, 51, 143, 63, + 0, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 5, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 6, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 226, 0, + 16, 0, 4, 0, 0, 0, + 86, 5, 16, 0, 4, 0, + 0, 0, 6, 9, 16, 0, + 5, 0, 0, 0, 6, 9, + 16, 0, 2, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 3, 0, 0, 0, + 6, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 150, 7, + 16, 0, 4, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 58, 0, + 16, 0, 0, 0, 0, 0, + 57, 0, 0, 11, 18, 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, 10, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 4, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 2, 64, 0, 0, + 230, 174, 37, 61, 230, 174, + 37, 61, 230, 174, 37, 61, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 10, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 2, 64, 0, 0, + 145, 131, 158, 61, 145, 131, + 158, 61, 145, 131, 158, 61, + 0, 0, 0, 0, 0, 0, + 0, 10, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 2, 64, 0, 0, 174, 71, + 97, 61, 174, 71, 97, 61, + 174, 71, 97, 61, 0, 0, + 0, 0, 56, 0, 0, 11, + 114, 0, 16, 0, 5, 0, + 0, 0, 70, 2, 16, 128, + 129, 0, 0, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 111, 167, 114, 63, 111, 167, + 114, 63, 111, 167, 114, 63, + 0, 0, 0, 0, 47, 0, + 0, 5, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 56, 0, 0, 10, 114, 0, + 16, 0, 5, 0, 0, 0, + 70, 2, 16, 0, 5, 0, + 0, 0, 2, 64, 0, 0, + 154, 153, 25, 64, 154, 153, + 25, 64, 154, 153, 25, 64, + 0, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 5, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 55, 0, 0, 9, 114, 0, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 5, 0, 0, 0, + 21, 0, 0, 1, 56, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 143, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 18, 0, 0, 1, 31, 0, + 4, 3, 42, 0, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 246, 143, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 57, 0, 0, 11, 18, 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, 10, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 3, + 10, 0, 16, 0, 0, 0, + 0, 0, 29, 0, 0, 10, + 210, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 28, 46, 77, 59, 0, 0, + 0, 0, 28, 46, 77, 59, + 28, 46, 77, 59, 6, 9, + 16, 0, 1, 0, 0, 0, + 56, 0, 0, 10, 114, 0, + 16, 0, 3, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 82, 184, 78, 65, 82, 184, + 78, 65, 82, 184, 78, 65, + 0, 0, 0, 0, 47, 0, + 0, 6, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 128, 129, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 10, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 85, 85, + 213, 62, 85, 85, 213, 62, + 85, 85, 213, 62, 0, 0, + 0, 0, 25, 0, 0, 5, + 114, 0, 16, 0, 4, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 50, 0, + 0, 15, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 2, 64, 0, 0, 61, 10, + 135, 63, 61, 10, 135, 63, + 61, 10, 135, 63, 0, 0, + 0, 0, 2, 64, 0, 0, + 174, 71, 97, 189, 174, 71, + 97, 189, 174, 71, 97, 189, + 0, 0, 0, 0, 55, 32, + 0, 9, 114, 0, 16, 0, + 1, 0, 0, 0, 134, 3, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 4, 0, 0, 0, 21, 0, + 0, 1, 18, 0, 0, 1, + 31, 0, 4, 3, 26, 0, + 16, 0, 0, 0, 0, 0, + 16, 0, 0, 10, 18, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 34, 139, + 212, 63, 160, 112, 22, 191, + 35, 45, 149, 189, 0, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 16, 0, + 0, 10, 34, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 127, 18, 255, 189, + 180, 2, 145, 63, 13, 198, + 8, 188, 0, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 16, 0, 0, 10, + 66, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 179, 183, 148, 188, 205, 5, + 206, 189, 60, 51, 143, 63, + 0, 0, 0, 0, 70, 2, + 16, 0, 2, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 143, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 57, 0, 0, 11, + 18, 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, 10, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, + 0, 3, 10, 0, 16, 0, + 0, 0, 0, 0, 29, 0, + 0, 10, 114, 0, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 28, 46, 77, 59, + 28, 46, 77, 59, 28, 46, + 77, 59, 0, 0, 0, 0, + 70, 2, 16, 0, 1, 0, + 0, 0, 56, 0, 0, 10, + 114, 0, 16, 0, 3, 0, + 0, 0, 70, 2, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 82, 184, 78, 65, + 82, 184, 78, 65, 82, 184, + 78, 65, 0, 0, 0, 0, + 47, 0, 0, 6, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 128, 129, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 10, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 85, 85, 213, 62, 85, 85, + 213, 62, 85, 85, 213, 62, + 0, 0, 0, 0, 25, 0, + 0, 5, 114, 0, 16, 0, + 4, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 50, 0, 0, 15, 114, 0, + 16, 0, 4, 0, 0, 0, + 70, 2, 16, 0, 4, 0, + 0, 0, 2, 64, 0, 0, + 61, 10, 135, 63, 61, 10, + 135, 63, 61, 10, 135, 63, + 0, 0, 0, 0, 2, 64, + 0, 0, 174, 71, 97, 189, + 174, 71, 97, 189, 174, 71, + 97, 189, 0, 0, 0, 0, + 55, 32, 0, 9, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 3, 0, 0, 0, 70, 2, + 16, 0, 4, 0, 0, 0, + 21, 0, 0, 1, 18, 0, + 0, 1, 56, 0, 0, 8, + 114, 0, 16, 0, 1, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 246, 143, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, + 0, 1, 21, 0, 0, 1, + 21, 0, 0, 1, 56, 0, + 0, 7, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 30, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 148, 0, + 0, 0, 126, 0, 0, 0, + 7, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 71, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 10, 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/src/render/direct3d11/D3D11_PixelShader_Advanced.hlsl b/src/render/direct3d11/D3D11_PixelShader_Advanced.hlsl new file mode 100644 index 00000000..aad7b77a --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Advanced.hlsl @@ -0,0 +1,7 @@ + +#include "D3D11_PixelShader_Common.hlsli" + +float4 main(PixelShaderInput input) : SV_TARGET +{ + return AdvancedPixelShader(input); +} diff --git a/src/render/direct3d11/D3D11_PixelShader_Colors.h b/src/render/direct3d11/D3D11_PixelShader_Colors.h new file mode 100644 index 00000000..6658e4d1 --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Colors.h @@ -0,0 +1,284 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer Constants +// { +// +// float scRGB_output; // Offset: 0 Size: 4 [unused] +// float texture_type; // Offset: 4 Size: 4 [unused] +// float input_type; // Offset: 8 Size: 4 [unused] +// float color_scale; // Offset: 12 Size: 4 +// float tonemap_method; // Offset: 16 Size: 4 [unused] +// float tonemap_factor1; // Offset: 20 Size: 4 [unused] +// float tonemap_factor2; // Offset: 24 Size: 4 [unused] +// float sdr_white_point; // Offset: 28 Size: 4 [unused] +// float4 Yoffset; // Offset: 32 Size: 16 [unused] +// float4 Rcoeff; // Offset: 48 Size: 16 [unused] +// float4 Gcoeff; // Offset: 64 Size: 16 [unused] +// float4 Bcoeff; // Offset: 80 Size: 16 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// Constants cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +// +// Constant buffer to DX9 shader constant mappings: +// +// Target Reg Buffer Start Reg # of Regs Data Conversion +// ---------- ------- --------- --------- ---------------------- +// c0 cb0 0 1 ( FLT, FLT, FLT, FLT) +// +// +// Level9 shader bytecode: +// + ps_2_0 + dcl t1 + mul r0.xyz, t1, c0.w + mov r0.w, t1.w + mov oC0, r0 + +// approximately 3 instruction slots used +ps_4_0 +dcl_constantbuffer CB0[1], immediateIndexed +dcl_input_ps linear v2.xyzw +dcl_output o0.xyzw +dcl_temps 1 +mov r0.x, cb0[0].w +mov r0.w, l(1.000000) +mul o0.xyzw, r0.xxxw, v2.xyzw +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_main[] = +{ + 68, 88, 66, 67, 78, 223, + 23, 23, 93, 184, 255, 26, + 153, 0, 220, 179, 25, 194, + 30, 249, 1, 0, 0, 0, + 192, 4, 0, 0, 6, 0, + 0, 0, 56, 0, 0, 0, + 172, 0, 0, 0, 56, 1, + 0, 0, 180, 1, 0, 0, + 24, 4, 0, 0, 140, 4, + 0, 0, 65, 111, 110, 57, + 108, 0, 0, 0, 108, 0, + 0, 0, 0, 2, 255, 255, + 60, 0, 0, 0, 48, 0, + 0, 0, 1, 0, 36, 0, + 0, 0, 48, 0, 0, 0, + 48, 0, 0, 0, 36, 0, + 0, 0, 48, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 2, + 255, 255, 31, 0, 0, 2, + 0, 0, 0, 128, 1, 0, + 15, 176, 5, 0, 0, 3, + 0, 0, 7, 128, 1, 0, + 228, 176, 0, 0, 255, 160, + 1, 0, 0, 2, 0, 0, + 8, 128, 1, 0, 255, 176, + 1, 0, 0, 2, 0, 8, + 15, 128, 0, 0, 228, 128, + 255, 255, 0, 0, 83, 72, + 68, 82, 132, 0, 0, 0, + 64, 0, 0, 0, 33, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 54, 0, 0, 6, + 18, 0, 16, 0, 0, 0, + 0, 0, 58, 128, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 242, 32, 16, 0, + 0, 0, 0, 0, 6, 12, + 16, 0, 0, 0, 0, 0, + 70, 30, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 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, 82, 68, + 69, 70, 92, 2, 0, 0, + 1, 0, 0, 0, 72, 0, + 0, 0, 1, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 49, 2, 0, 0, 60, 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, + 67, 111, 110, 115, 116, 97, + 110, 116, 115, 0, 171, 171, + 60, 0, 0, 0, 12, 0, + 0, 0, 96, 0, 0, 0, + 96, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 128, 1, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 160, 1, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 173, 1, 0, 0, 8, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 184, 1, 0, 0, 12, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 196, 1, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 211, 1, 0, 0, 20, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 227, 1, 0, 0, 24, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 243, 1, 0, 0, 28, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 3, 2, 0, 0, 32, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 12, 2, + 0, 0, 0, 0, 0, 0, + 28, 2, 0, 0, 48, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 12, 2, + 0, 0, 0, 0, 0, 0, + 35, 2, 0, 0, 64, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 12, 2, + 0, 0, 0, 0, 0, 0, + 42, 2, 0, 0, 80, 0, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 12, 2, + 0, 0, 0, 0, 0, 0, + 115, 99, 82, 71, 66, 95, + 111, 117, 116, 112, 117, 116, + 0, 171, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 116, 101, 120, 116, + 117, 114, 101, 95, 116, 121, + 112, 101, 0, 105, 110, 112, + 117, 116, 95, 116, 121, 112, + 101, 0, 99, 111, 108, 111, + 114, 95, 115, 99, 97, 108, + 101, 0, 116, 111, 110, 101, + 109, 97, 112, 95, 109, 101, + 116, 104, 111, 100, 0, 116, + 111, 110, 101, 109, 97, 112, + 95, 102, 97, 99, 116, 111, + 114, 49, 0, 116, 111, 110, + 101, 109, 97, 112, 95, 102, + 97, 99, 116, 111, 114, 50, + 0, 115, 100, 114, 95, 119, + 104, 105, 116, 101, 95, 112, + 111, 105, 110, 116, 0, 89, + 111, 102, 102, 115, 101, 116, + 0, 171, 1, 0, 3, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 82, 99, 111, 101, 102, 102, + 0, 71, 99, 111, 101, 102, + 102, 0, 66, 99, 111, 101, + 102, 102, 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, 171, 171, 171, 73, 83, + 71, 78, 108, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 101, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 15, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 79, 82, 68, 0, 67, + 79, 76, 79, 82, 0, 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, 65, 82, 71, 69, + 84, 0, 171, 171 +}; diff --git a/src/render/direct3d11/D3D11_PixelShader_Colors.hlsl b/src/render/direct3d11/D3D11_PixelShader_Colors.hlsl new file mode 100644 index 00000000..5757491b --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Colors.hlsl @@ -0,0 +1,7 @@ + +#include "D3D11_PixelShader_Common.hlsli" + +float4 main(PixelShaderInput input) : SV_TARGET +{ + return GetOutputColor(1.0) * input.color; +} diff --git a/src/render/direct3d11/D3D11_PixelShader_Common.hlsli b/src/render/direct3d11/D3D11_PixelShader_Common.hlsli new file mode 100644 index 00000000..61053d8c --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Common.hlsli @@ -0,0 +1,235 @@ + +Texture2D texture0 : register(t0); +Texture2D texture1 : register(t1); +Texture2D texture2 : register(t2); +SamplerState sampler0 : register(s0); + +struct PixelShaderInput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +// These should mirror the definitions in SDL_render_d3d12.c +static const float TONEMAP_NONE = 0; +static const float TONEMAP_LINEAR = 1; +static const float TONEMAP_CHROME = 2; + +static const float TEXTURETYPE_NONE = 0; +static const float TEXTURETYPE_RGB = 1; +static const float TEXTURETYPE_NV12 = 2; +static const float TEXTURETYPE_NV21 = 3; +static const float TEXTURETYPE_YUV = 4; + +static const float INPUTTYPE_UNSPECIFIED = 0; +static const float INPUTTYPE_SRGB = 1; +static const float INPUTTYPE_SCRGB = 2; +static const float INPUTTYPE_HDR10 = 3; + +cbuffer Constants : register(b0) +{ + float scRGB_output; + float texture_type; + float input_type; + float color_scale; + + float tonemap_method; + float tonemap_factor1; + float tonemap_factor2; + float sdr_white_point; + + float4 Yoffset; + float4 Rcoeff; + float4 Gcoeff; + float4 Bcoeff; +}; + +static const float3x3 mat709to2020 = { + { 0.627404, 0.329283, 0.043313 }, + { 0.069097, 0.919541, 0.011362 }, + { 0.016391, 0.088013, 0.895595 } +}; + +static const float3x3 mat2020to709 = { + { 1.660496, -0.587656, -0.072840 }, + { -0.124547, 1.132895, -0.008348 }, + { -0.018154, -0.100597, 1.118751 } +}; + +float sRGBtoLinear(float v) +{ + if (v <= 0.04045) { + v = (v / 12.92); + } else { + v = pow(abs(v + 0.055) / 1.055, 2.4); + } + return v; +} + +float sRGBfromLinear(float v) +{ + if (v <= 0.0031308) { + v = (v * 12.92); + } else { + v = (pow(abs(v), 1.0 / 2.4) * 1.055 - 0.055); + } + return v; +} + +float3 PQtoLinear(float3 v) +{ + const float c1 = 0.8359375; + const float c2 = 18.8515625; + const float c3 = 18.6875; + const float oo_m1 = 1.0 / 0.1593017578125; + const float oo_m2 = 1.0 / 78.84375; + + float3 num = max(pow(abs(v), oo_m2) - c1, 0.0); + float3 den = c2 - c3 * pow(abs(v), oo_m2); + return (10000.0 * pow(abs(num / den), oo_m1) / sdr_white_point); +} + +float3 ApplyTonemap(float3 v) +{ + if (tonemap_method == TONEMAP_LINEAR) { + v *= tonemap_factor1; + } else if (tonemap_method == TONEMAP_CHROME) { + if (input_type == INPUTTYPE_SCRGB) { + // Convert to BT.2020 colorspace for tone mapping + v = mul(mat709to2020, v); + } + + float vmax = max(v.r, max(v.g, v.b)); + if (vmax > 0.0) { + float scale = (1.0 + tonemap_factor1 * vmax) / (1.0 + tonemap_factor2 * vmax); + v *= scale; + } + + if (input_type == INPUTTYPE_SCRGB) { + // Convert to BT.709 colorspace after tone mapping + v = mul(mat2020to709, v); + } + } + return v; +} + +float4 GetInputColor(PixelShaderInput input) +{ + float4 rgba; + + if (texture_type == TEXTURETYPE_NONE) { + rgba = 1.0; + } else if (texture_type == TEXTURETYPE_RGB) { + rgba = texture0.Sample(sampler0, input.tex); + } else if (texture_type == TEXTURETYPE_NV12) { + float3 yuv; + yuv.x = texture0.Sample(sampler0, input.tex).r; + yuv.yz = texture1.Sample(sampler0, input.tex).rg; + + yuv += Yoffset.xyz; + rgba.r = dot(yuv, Rcoeff.xyz); + rgba.g = dot(yuv, Gcoeff.xyz); + rgba.b = dot(yuv, Bcoeff.xyz); + rgba.a = 1.0; + } else if (texture_type == TEXTURETYPE_NV21) { + float3 yuv; + yuv.x = texture0.Sample(sampler0, input.tex).r; + yuv.yz = texture1.Sample(sampler0, input.tex).gr; + + yuv += Yoffset.xyz; + rgba.r = dot(yuv, Rcoeff.xyz); + rgba.g = dot(yuv, Gcoeff.xyz); + rgba.b = dot(yuv, Bcoeff.xyz); + rgba.a = 1.0; + } else if (texture_type == TEXTURETYPE_YUV) { + float3 yuv; + yuv.x = texture0.Sample(sampler0, input.tex).r; + yuv.y = texture1.Sample(sampler0, input.tex).r; + yuv.z = texture2.Sample(sampler0, input.tex).r; + + yuv += Yoffset.xyz; + rgba.r = dot(yuv, Rcoeff.xyz); + rgba.g = dot(yuv, Gcoeff.xyz); + rgba.b = dot(yuv, Bcoeff.xyz); + rgba.a = 1.0; + } else { + // Error! + rgba.r = 1.0; + rgba.g = 0.0; + rgba.b = 0.0; + rgba.a = 1.0; + } + return rgba; +} + +float4 GetOutputColor(float4 rgba) +{ + float4 output; + + output.rgb = rgba.rgb * color_scale; + output.a = rgba.a; + + return output; +} + +float3 GetOutputColorFromSRGB(float3 rgb) +{ + float3 output; + + if (scRGB_output) { + rgb.r = sRGBtoLinear(rgb.r); + rgb.g = sRGBtoLinear(rgb.g); + rgb.b = sRGBtoLinear(rgb.b); + } + + output.rgb = rgb * color_scale; + + return output; +} + +float3 GetOutputColorFromLinear(float3 rgb) +{ + float3 output; + + output.rgb = rgb * color_scale; + + if (!scRGB_output) { + output.r = sRGBfromLinear(output.r); + output.g = sRGBfromLinear(output.g); + output.b = sRGBfromLinear(output.b); + output.rgb = saturate(output.rgb); + } + + return output; +} + +float4 AdvancedPixelShader(PixelShaderInput input) +{ + float4 rgba = GetInputColor(input); + float4 output; + + if (input_type == INPUTTYPE_HDR10) { + rgba.rgb = PQtoLinear(rgba.rgb); + } + + if (tonemap_method != TONEMAP_NONE) { + rgba.rgb = ApplyTonemap(rgba.rgb); + } + + if (input_type == INPUTTYPE_SRGB) { + output.rgb = GetOutputColorFromSRGB(rgba.rgb); + output.a = rgba.a; + } else if (input_type == INPUTTYPE_SCRGB) { + output.rgb = GetOutputColorFromLinear(rgba.rgb); + output.a = rgba.a; + } else if (input_type == INPUTTYPE_HDR10) { + rgba.rgb = mul(mat2020to709, rgba.rgb); + output.rgb = GetOutputColorFromLinear(rgba.rgb); + output.a = rgba.a; + } else { + output = GetOutputColor(rgba); + } + + return output * input.color; +} diff --git a/src/render/direct3d11/D3D11_PixelShader_Textures.h b/src/render/direct3d11/D3D11_PixelShader_Textures.h new file mode 100644 index 00000000..996cac62 --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Textures.h @@ -0,0 +1,332 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer Constants +// { +// +// float scRGB_output; // Offset: 0 Size: 4 [unused] +// float texture_type; // Offset: 4 Size: 4 [unused] +// float input_type; // Offset: 8 Size: 4 [unused] +// float color_scale; // Offset: 12 Size: 4 +// float tonemap_method; // Offset: 16 Size: 4 [unused] +// float tonemap_factor1; // Offset: 20 Size: 4 [unused] +// float tonemap_factor2; // Offset: 24 Size: 4 [unused] +// float sdr_white_point; // Offset: 28 Size: 4 [unused] +// float4 Yoffset; // Offset: 32 Size: 16 [unused] +// float4 Rcoeff; // Offset: 48 Size: 16 [unused] +// float4 Gcoeff; // Offset: 64 Size: 16 [unused] +// float4 Bcoeff; // Offset: 80 Size: 16 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// theSampler sampler NA NA s0 1 +// theTexture texture float4 2d t0 1 +// Constants cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +// +// Constant buffer to DX9 shader constant mappings: +// +// Target Reg Buffer Start Reg # of Regs Data Conversion +// ---------- ------- --------- --------- ---------------------- +// c0 cb0 0 1 ( FLT, FLT, FLT, FLT) +// +// +// Sampler/Resource to DX9 shader sampler mappings: +// +// Target Sampler Source Sampler Source Resource +// -------------- --------------- ---------------- +// s0 s0 t0 +// +// +// Level9 shader bytecode: +// + ps_2_0 + dcl t0.xy + dcl t1 + dcl_2d s0 + texld r0, t0, s0 + mul r0.xyz, r0, c0.w + mul r0, r0, t1 + mov oC0, r0 + +// approximately 4 instruction slots used (1 texture, 3 arithmetic) +ps_4_0 +dcl_constantbuffer CB0[1], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_input_ps linear v2.xyzw +dcl_output o0.xyzw +dcl_temps 1 +sample r0.xyzw, v1.xyxx, t0.xyzw, s0 +mul r0.xyz, r0.xyzx, cb0[0].wwww +mul o0.xyzw, r0.xyzw, v2.xyzw +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_main[] = +{ + 68, 88, 66, 67, 8, 152, + 224, 210, 182, 254, 37, 89, + 68, 213, 13, 174, 95, 42, + 2, 11, 1, 0, 0, 0, + 132, 5, 0, 0, 6, 0, + 0, 0, 56, 0, 0, 0, + 220, 0, 0, 0, 168, 1, + 0, 0, 36, 2, 0, 0, + 220, 4, 0, 0, 80, 5, + 0, 0, 65, 111, 110, 57, + 156, 0, 0, 0, 156, 0, + 0, 0, 0, 2, 255, 255, + 104, 0, 0, 0, 52, 0, + 0, 0, 1, 0, 40, 0, + 0, 0, 52, 0, 0, 0, + 52, 0, 1, 0, 36, 0, + 0, 0, 52, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 255, 255, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 128, 1, 0, 15, 176, + 31, 0, 0, 2, 0, 0, + 0, 144, 0, 8, 15, 160, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 176, + 0, 8, 228, 160, 5, 0, + 0, 3, 0, 0, 7, 128, + 0, 0, 228, 128, 0, 0, + 255, 160, 5, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 128, 1, 0, 228, 176, + 1, 0, 0, 2, 0, 8, + 15, 128, 0, 0, 228, 128, + 255, 255, 0, 0, 83, 72, + 68, 82, 196, 0, 0, 0, + 64, 0, 0, 0, 49, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 1, 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, + 1, 0, 0, 0, 98, 16, + 0, 3, 242, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 69, 0, 0, 9, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 70, 126, 16, 0, + 0, 0, 0, 0, 0, 96, + 16, 0, 0, 0, 0, 0, + 56, 0, 0, 8, 114, 0, + 16, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 143, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 30, + 16, 0, 2, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 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, 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, 82, 68, 69, 70, + 176, 2, 0, 0, 1, 0, + 0, 0, 156, 0, 0, 0, + 3, 0, 0, 0, 28, 0, + 0, 0, 0, 4, 255, 255, + 0, 1, 0, 0, 133, 2, + 0, 0, 124, 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, 135, 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, + 146, 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, 116, 104, 101, 83, + 97, 109, 112, 108, 101, 114, + 0, 116, 104, 101, 84, 101, + 120, 116, 117, 114, 101, 0, + 67, 111, 110, 115, 116, 97, + 110, 116, 115, 0, 146, 0, + 0, 0, 12, 0, 0, 0, + 180, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 1, + 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 244, 1, + 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 1, 2, + 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 12, 2, + 0, 0, 12, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 24, 2, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 39, 2, + 0, 0, 20, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 55, 2, + 0, 0, 24, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 71, 2, + 0, 0, 28, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 228, 1, 0, 0, + 0, 0, 0, 0, 87, 2, + 0, 0, 32, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 96, 2, 0, 0, + 0, 0, 0, 0, 112, 2, + 0, 0, 48, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 96, 2, 0, 0, + 0, 0, 0, 0, 119, 2, + 0, 0, 64, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 96, 2, 0, 0, + 0, 0, 0, 0, 126, 2, + 0, 0, 80, 0, 0, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 96, 2, 0, 0, + 0, 0, 0, 0, 115, 99, + 82, 71, 66, 95, 111, 117, + 116, 112, 117, 116, 0, 171, + 171, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 116, 101, 120, 116, 117, 114, + 101, 95, 116, 121, 112, 101, + 0, 105, 110, 112, 117, 116, + 95, 116, 121, 112, 101, 0, + 99, 111, 108, 111, 114, 95, + 115, 99, 97, 108, 101, 0, + 116, 111, 110, 101, 109, 97, + 112, 95, 109, 101, 116, 104, + 111, 100, 0, 116, 111, 110, + 101, 109, 97, 112, 95, 102, + 97, 99, 116, 111, 114, 49, + 0, 116, 111, 110, 101, 109, + 97, 112, 95, 102, 97, 99, + 116, 111, 114, 50, 0, 115, + 100, 114, 95, 119, 104, 105, + 116, 101, 95, 112, 111, 105, + 110, 116, 0, 89, 111, 102, + 102, 115, 101, 116, 0, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 99, + 111, 101, 102, 102, 0, 71, + 99, 111, 101, 102, 102, 0, + 66, 99, 111, 101, 102, 102, + 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, 171, + 171, 171, 73, 83, 71, 78, + 108, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 3, 0, 0, + 101, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 15, 0, 0, + 83, 86, 95, 80, 79, 83, + 73, 84, 73, 79, 78, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 67, 79, 76, + 79, 82, 0, 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, + 65, 82, 71, 69, 84, 0, + 171, 171 +}; diff --git a/src/render/direct3d11/D3D11_PixelShader_Textures.hlsl b/src/render/direct3d11/D3D11_PixelShader_Textures.hlsl new file mode 100644 index 00000000..f2ecf18a --- /dev/null +++ b/src/render/direct3d11/D3D11_PixelShader_Textures.hlsl @@ -0,0 +1,9 @@ +Texture2D theTexture : register(t0); +SamplerState theSampler : register(s0); + +#include "D3D11_PixelShader_Common.hlsli" + +float4 main(PixelShaderInput input) : SV_TARGET +{ + return GetOutputColor(theTexture.Sample(theSampler, input.tex)) * input.color; +} diff --git a/src/render/direct3d11/D3D11_VertexShader.h b/src/render/direct3d11/D3D11_VertexShader.h new file mode 100644 index 00000000..97beaa39 --- /dev/null +++ b/src/render/direct3d11/D3D11_VertexShader.h @@ -0,0 +1,339 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer VertexShaderConstants +// { +// +// row_major float4x4 model; // Offset: 0 Size: 64 +// row_major float4x4 projectionAndView;// Offset: 64 Size: 64 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// VertexShaderConstants cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// POSITION 0 xyz 0 NONE float xyz +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float xyzw +// TEXCOORD 0 xy 1 NONE float xy +// COLOR 0 xyzw 2 NONE float xyzw +// +// +// Constant buffer to DX9 shader constant mappings: +// +// Target Reg Buffer Start Reg # of Regs Data Conversion +// ---------- ------- --------- --------- ---------------------- +// c1 cb0 0 8 ( FLT, FLT, FLT, FLT) +// +// +// Runtime generated constant mappings: +// +// Target Reg Constant Description +// ---------- -------------------------------------------------- +// c0 Vertex Shader position offset +// +// +// Level9 shader bytecode: +// + vs_2_0 + dcl_texcoord v0 + dcl_texcoord1 v1 + dcl_texcoord2 v2 + mul r0, v0.y, c2 + mad r0, v0.x, c1, r0 + mad r0, v0.z, c3, r0 + add r0, r0, c4 + mul r1, r0.y, c6 + mad r1, r0.x, c5, r1 + mad r1, r0.z, c7, r1 + mad r0, r0.w, c8, r1 + mad oPos.xy, r0.w, c0, r0 + mov oPos.zw, r0 + mov oT0.xy, v1 + mov oT1, v2 + +// approximately 12 instruction slots used +vs_4_0 +dcl_constantbuffer CB0[8], immediateIndexed +dcl_input v0.xyz +dcl_input v1.xy +dcl_input v2.xyzw +dcl_output_siv o0.xyzw, position +dcl_output o1.xy +dcl_output o2.xyzw +dcl_temps 2 +mul r0.xyzw, v0.yyyy, cb0[1].xyzw +mad r0.xyzw, v0.xxxx, cb0[0].xyzw, r0.xyzw +mad r0.xyzw, v0.zzzz, cb0[2].xyzw, r0.xyzw +add r0.xyzw, r0.xyzw, cb0[3].xyzw +mul r1.xyzw, r0.yyyy, cb0[5].xyzw +mad r1.xyzw, r0.xxxx, cb0[4].xyzw, r1.xyzw +mad r1.xyzw, r0.zzzz, cb0[6].xyzw, r1.xyzw +mad o0.xyzw, r0.wwww, cb0[7].xyzw, r1.xyzw +mov o1.xy, v1.xyxx +mov o2.xyzw, v2.xyzw +ret +// Approximately 11 instruction slots used +#endif + +const BYTE g_main[] = +{ + 68, 88, 66, 67, 152, 172, + 81, 45, 198, 200, 12, 38, + 143, 4, 178, 228, 158, 175, + 169, 64, 1, 0, 0, 0, + 140, 5, 0, 0, 6, 0, + 0, 0, 56, 0, 0, 0, + 108, 1, 0, 0, 52, 3, + 0, 0, 176, 3, 0, 0, + 168, 4, 0, 0, 24, 5, + 0, 0, 65, 111, 110, 57, + 44, 1, 0, 0, 44, 1, + 0, 0, 0, 2, 254, 255, + 248, 0, 0, 0, 52, 0, + 0, 0, 1, 0, 36, 0, + 0, 0, 48, 0, 0, 0, + 48, 0, 0, 0, 36, 0, + 1, 0, 48, 0, 0, 0, + 0, 0, 8, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 254, 255, + 31, 0, 0, 2, 5, 0, + 0, 128, 0, 0, 15, 144, + 31, 0, 0, 2, 5, 0, + 1, 128, 1, 0, 15, 144, + 31, 0, 0, 2, 5, 0, + 2, 128, 2, 0, 15, 144, + 5, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 85, 144, + 2, 0, 228, 160, 4, 0, + 0, 4, 0, 0, 15, 128, + 0, 0, 0, 144, 1, 0, + 228, 160, 0, 0, 228, 128, + 4, 0, 0, 4, 0, 0, + 15, 128, 0, 0, 170, 144, + 3, 0, 228, 160, 0, 0, + 228, 128, 2, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 128, 4, 0, 228, 160, + 5, 0, 0, 3, 1, 0, + 15, 128, 0, 0, 85, 128, + 6, 0, 228, 160, 4, 0, + 0, 4, 1, 0, 15, 128, + 0, 0, 0, 128, 5, 0, + 228, 160, 1, 0, 228, 128, + 4, 0, 0, 4, 1, 0, + 15, 128, 0, 0, 170, 128, + 7, 0, 228, 160, 1, 0, + 228, 128, 4, 0, 0, 4, + 0, 0, 15, 128, 0, 0, + 255, 128, 8, 0, 228, 160, + 1, 0, 228, 128, 4, 0, + 0, 4, 0, 0, 3, 192, + 0, 0, 255, 128, 0, 0, + 228, 160, 0, 0, 228, 128, + 1, 0, 0, 2, 0, 0, + 12, 192, 0, 0, 228, 128, + 1, 0, 0, 2, 0, 0, + 3, 224, 1, 0, 228, 144, + 1, 0, 0, 2, 1, 0, + 15, 224, 2, 0, 228, 144, + 255, 255, 0, 0, 83, 72, + 68, 82, 192, 1, 0, 0, + 64, 0, 1, 0, 112, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 95, 0, 0, 3, 114, 16, + 16, 0, 0, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 95, 0, 0, 3, 242, 16, + 16, 0, 2, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 2, 0, 0, 0, 104, 0, + 0, 2, 2, 0, 0, 0, + 56, 0, 0, 8, 242, 0, + 16, 0, 0, 0, 0, 0, + 86, 21, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 50, 0, 0, 10, + 242, 0, 16, 0, 0, 0, + 0, 0, 6, 16, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 50, 0, 0, 10, 242, 0, + 16, 0, 0, 0, 0, 0, + 166, 26, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 8, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 56, 0, 0, 8, 242, 0, + 16, 0, 1, 0, 0, 0, + 86, 5, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 5, 0, + 0, 0, 50, 0, 0, 10, + 242, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 50, 0, 0, 10, 242, 0, + 16, 0, 1, 0, 0, 0, + 166, 10, 16, 0, 0, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 50, 0, + 0, 10, 242, 32, 16, 0, + 0, 0, 0, 0, 246, 15, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 1, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 242, 32, 16, 0, + 2, 0, 0, 0, 70, 30, + 16, 0, 2, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 11, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 8, 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, 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, 82, 68, 69, 70, + 240, 0, 0, 0, 1, 0, + 0, 0, 84, 0, 0, 0, + 1, 0, 0, 0, 28, 0, + 0, 0, 0, 4, 254, 255, + 0, 1, 0, 0, 198, 0, + 0, 0, 60, 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, 86, 101, + 114, 116, 101, 120, 83, 104, + 97, 100, 101, 114, 67, 111, + 110, 115, 116, 97, 110, 116, + 115, 0, 171, 171, 60, 0, + 0, 0, 2, 0, 0, 0, + 108, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 2, 0, + 0, 0, 164, 0, 0, 0, + 0, 0, 0, 0, 180, 0, + 0, 0, 64, 0, 0, 0, + 64, 0, 0, 0, 2, 0, + 0, 0, 164, 0, 0, 0, + 0, 0, 0, 0, 109, 111, + 100, 101, 108, 0, 171, 171, + 2, 0, 3, 0, 4, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 112, 114, + 111, 106, 101, 99, 116, 105, + 111, 110, 65, 110, 100, 86, + 105, 101, 119, 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, 171, 171, 73, 83, + 71, 78, 104, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 7, 7, + 0, 0, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 98, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 2, 0, 0, 0, 15, 15, + 0, 0, 80, 79, 83, 73, + 84, 73, 79, 78, 0, 84, + 69, 88, 67, 79, 79, 82, + 68, 0, 67, 79, 76, 79, + 82, 0, 79, 83, 71, 78, + 108, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 101, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 2, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 80, 79, 83, + 73, 84, 73, 79, 78, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 67, 79, 76, + 79, 82, 0, 171 +}; diff --git a/src/render/direct3d11/D3D11_VertexShader.hlsl b/src/render/direct3d11/D3D11_VertexShader.hlsl new file mode 100644 index 00000000..63e51726 --- /dev/null +++ b/src/render/direct3d11/D3D11_VertexShader.hlsl @@ -0,0 +1,38 @@ +#pragma pack_matrix( row_major ) + +cbuffer VertexShaderConstants : register(b0) +{ + matrix model; + matrix projectionAndView; +}; + +struct VertexShaderInput +{ + float3 pos : POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +struct VertexShaderOutput +{ + float4 pos : SV_POSITION; + float2 tex : TEXCOORD0; + float4 color : COLOR0; +}; + +VertexShaderOutput main(VertexShaderInput input) +{ + VertexShaderOutput output; + float4 pos = float4(input.pos, 1.0f); + + // Transform the vertex position into projected space. + pos = mul(pos, model); + pos = mul(pos, projectionAndView); + output.pos = pos; + + // Pass through texture coordinates and color values without transformation + output.tex = input.tex; + output.color = input.color; + + return output; +} diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 007f833c..1bd0d0cb 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -20,24 +20,27 @@ */ #include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D11 #define COBJMACROS #include "../../core/windows/SDL_windows.h" -#ifndef __WINRT__ +#ifndef SDL_PLATFORM_WINRT #include "../../video/windows/SDL_windowswindow.h" #endif #include "../SDL_sysrender.h" #include "../SDL_d3dmath.h" +#include "../../video/SDL_pixels_c.h" #include +#include +#include #include "SDL_shaders_d3d11.h" -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT #if NTDDI_VERSION > NTDDI_WIN8 -#include +#include #endif #include "SDL_render_winrt.h" @@ -48,7 +51,7 @@ extern ISwapChainBackgroundPanelNative *WINRT_GlobalSwapChainBackgroundPanelNative; #endif /* WINAPI_FAMILY == WINAPI_FAMILY_APP */ -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ #if defined(_MSC_VER) && !defined(__clang__) #define SDL_COMPOSE_ERROR(str) __FUNCTION__ ", " str @@ -72,17 +75,55 @@ typedef struct Float4X4 projectionAndView; } VertexShaderConstants; +/* These should mirror the definitions in D3D11_PixelShader_Common.hlsli */ +//static const float TONEMAP_NONE = 0; +//static const float TONEMAP_LINEAR = 1; +static const float TONEMAP_CHROME = 2; + +//static const float TEXTURETYPE_NONE = 0; +static const float TEXTURETYPE_RGB = 1; +static const float TEXTURETYPE_NV12 = 2; +static const float TEXTURETYPE_NV21 = 3; +static const float TEXTURETYPE_YUV = 4; + +static const float INPUTTYPE_UNSPECIFIED = 0; +static const float INPUTTYPE_SRGB = 1; +static const float INPUTTYPE_SCRGB = 2; +static const float INPUTTYPE_HDR10 = 3; + +typedef struct +{ + float scRGB_output; + float texture_type; + float input_type; + float color_scale; + + float tonemap_method; + float tonemap_factor1; + float tonemap_factor2; + float sdr_white_point; + + float YCbCr_matrix[16]; +} PixelShaderConstants; + +typedef struct +{ + ID3D11Buffer *constants; + PixelShaderConstants shader_constants; +} PixelShaderState; + /* Per-vertex data */ typedef struct { Float2 pos; Float2 tex; - SDL_Color color; + SDL_FColor color; } VertexPositionColor; /* Per-texture data */ typedef struct { + int w, h; ID3D11Texture2D *mainTexture; ID3D11ShaderResourceView *mainTextureResourceView; ID3D11RenderTargetView *mainTextureRenderTargetView; @@ -90,6 +131,8 @@ typedef struct int lockedTexturePositionX; int lockedTexturePositionY; D3D11_FILTER scaleMode; + D3D11_Shader shader; + const float *YCbCr_matrix; #if SDL_HAVE_YUV /* YV12 texture support */ SDL_bool yuv; @@ -122,6 +165,7 @@ typedef struct void *hD3D11Mod; IDXGIFactory2 *dxgiFactory; IDXGIAdapter *dxgiAdapter; + IDXGIDebug *dxgiDebug; ID3D11Device1 *d3dDevice; ID3D11DeviceContext1 *d3dContext; IDXGISwapChain1 *swapChain; @@ -153,7 +197,8 @@ typedef struct ID3D11RenderTargetView *currentRenderTargetView; ID3D11RasterizerState *currentRasterizerState; ID3D11BlendState *currentBlendState; - ID3D11PixelShader *currentShader; + D3D11_Shader currentShader; + PixelShaderState currentShaderState[NUM_SHADERS]; ID3D11ShaderResourceView *currentShaderResource; ID3D11SamplerState *currentSampler; SDL_bool cliprectDirty; @@ -182,36 +227,55 @@ typedef struct static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } }; static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } }; -#if defined(__WINRT__) && NTDDI_VERSION > NTDDI_WIN8 +#if defined(SDL_PLATFORM_WINRT) && NTDDI_VERSION > NTDDI_WIN8 static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } }; #endif static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } }; static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } }; static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } }; -/*static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };*/ +static const GUID SDL_IID_IDXGISwapChain2 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } }; +static const GUID SDL_IID_IDXGIDebug1 = { 0xc5a05f0c, 0x16f2, 0x4adf, { 0x9f, 0x4d, 0xa8, 0xc4, 0xd5, 0x8a, 0xc5, 0x50 } }; +static const GUID SDL_IID_IDXGIInfoQueue = { 0xD67441C7, 0x672A, 0x476f, { 0x9E, 0x82, 0xCD, 0x55, 0xB4, 0x49, 0x49, 0xCE } }; +static const GUID SDL_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8 } }; #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop #endif -Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) +SDL_PixelFormatEnum D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat) { switch (dxgiFormat) { case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return SDL_PIXELFORMAT_ARGB8888; case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return SDL_PIXELFORMAT_XRGB8888; + case DXGI_FORMAT_R10G10B10A2_UNORM: + return SDL_PIXELFORMAT_XBGR2101010; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return SDL_PIXELFORMAT_RGBA64_FLOAT; default: return SDL_PIXELFORMAT_UNKNOWN; } } -static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat) +static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 format, Uint32 colorspace) { - switch (sdlFormat) { + switch (format) { + case SDL_PIXELFORMAT_RGBA64_FLOAT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case SDL_PIXELFORMAT_XBGR2101010: + return DXGI_FORMAT_R10G10B10A2_UNORM; case SDL_PIXELFORMAT_ARGB8888: + if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + } return DXGI_FORMAT_B8G8R8A8_UNORM; case SDL_PIXELFORMAT_XRGB8888: + if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + } return DXGI_FORMAT_B8G8R8X8_UNORM; case SDL_PIXELFORMAT_YV12: case SDL_PIXELFORMAT_IYUV: @@ -219,23 +283,37 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat) case SDL_PIXELFORMAT_NV12: case SDL_PIXELFORMAT_NV21: return DXGI_FORMAT_NV12; + case SDL_PIXELFORMAT_P010: + return DXGI_FORMAT_P010; default: return DXGI_FORMAT_UNKNOWN; } } -static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat) +static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 format, Uint32 colorspace) { - switch (sdlFormat) { + switch (format) { + case SDL_PIXELFORMAT_RGBA64_FLOAT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + case SDL_PIXELFORMAT_XBGR2101010: + return DXGI_FORMAT_R10G10B10A2_UNORM; case SDL_PIXELFORMAT_ARGB8888: + if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + } return DXGI_FORMAT_B8G8R8A8_UNORM; case SDL_PIXELFORMAT_XRGB8888: + if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; + } return DXGI_FORMAT_B8G8R8X8_UNORM; case SDL_PIXELFORMAT_YV12: case SDL_PIXELFORMAT_IYUV: case SDL_PIXELFORMAT_NV12: /* For the Y texture */ case SDL_PIXELFORMAT_NV21: /* For the Y texture */ return DXGI_FORMAT_R8_UNORM; + case SDL_PIXELFORMAT_P010: /* For the Y texture */ + return DXGI_FORMAT_R16_UNORM; default: return DXGI_FORMAT_UNKNOWN; } @@ -257,21 +335,18 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer) if (data) { int i; - SAFE_RELEASE(data->dxgiFactory); - SAFE_RELEASE(data->dxgiAdapter); - SAFE_RELEASE(data->d3dDevice); - SAFE_RELEASE(data->d3dContext); - SAFE_RELEASE(data->swapChain); - SAFE_RELEASE(data->mainRenderTargetView); - SAFE_RELEASE(data->currentOffscreenRenderTargetView); - SAFE_RELEASE(data->inputLayout); - for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) { - SAFE_RELEASE(data->vertexBuffers[i]); - } - SAFE_RELEASE(data->vertexShader); - for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) { - SAFE_RELEASE(data->pixelShaders[i]); + /* Make sure the swap chain is fully released */ + if (data->d3dContext) { + ID3D11DeviceContext_ClearState(data->d3dContext); + ID3D11DeviceContext_Flush(data->d3dContext); } + + SAFE_RELEASE(data->vertexShaderConstants); + SAFE_RELEASE(data->clippedRasterizer); + SAFE_RELEASE(data->mainRasterizer); + SAFE_RELEASE(data->linearSampler); + SAFE_RELEASE(data->nearestPixelSampler); + if (data->blendModesCount > 0) { for (i = 0; i < data->blendModesCount; ++i) { SAFE_RELEASE(data->blendModes[i].blendState); @@ -280,21 +355,43 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer) data->blendModesCount = 0; } - SAFE_RELEASE(data->nearestPixelSampler); - SAFE_RELEASE(data->linearSampler); - SAFE_RELEASE(data->mainRasterizer); - SAFE_RELEASE(data->clippedRasterizer); - SAFE_RELEASE(data->vertexShaderConstants); + for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) { + SAFE_RELEASE(data->pixelShaders[i]); + } + for (i = 0; i < SDL_arraysize(data->currentShaderState); ++i) { + SAFE_RELEASE(data->currentShaderState[i].constants); + } + SAFE_RELEASE(data->vertexShader); + for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) { + SAFE_RELEASE(data->vertexBuffers[i]); + } + SAFE_RELEASE(data->inputLayout); + SAFE_RELEASE(data->mainRenderTargetView); + SAFE_RELEASE(data->swapChain); + + SAFE_RELEASE(data->d3dContext); + SAFE_RELEASE(data->d3dDevice); + SAFE_RELEASE(data->dxgiAdapter); + SAFE_RELEASE(data->dxgiFactory); data->swapEffect = (DXGI_SWAP_EFFECT)0; data->rotation = DXGI_MODE_ROTATION_UNSPECIFIED; + data->currentOffscreenRenderTargetView = NULL; data->currentRenderTargetView = NULL; data->currentRasterizerState = NULL; data->currentBlendState = NULL; - data->currentShader = NULL; + data->currentShader = SHADER_NONE; + SDL_zero(data->currentShaderState); data->currentShaderResource = NULL; data->currentSampler = NULL; + /* Check for any leaks if in debug mode */ + if (data->dxgiDebug) { + DXGI_DEBUG_RLO_FLAGS rloFlags = (DXGI_DEBUG_RLO_FLAGS)(DXGI_DEBUG_RLO_DETAIL | DXGI_DEBUG_RLO_IGNORE_INTERNAL); + IDXGIDebug_ReportLiveObjects(data->dxgiDebug, SDL_DXGI_DEBUG_ALL, rloFlags); + SAFE_RELEASE(data->dxgiDebug); + } + /* Unload the D3D libraries. This should be done last, in order * to prevent IUnknown::Release() calls from crashing. */ @@ -413,15 +510,17 @@ static ID3D11BlendState *D3D11_CreateBlendState(SDL_Renderer *renderer, SDL_Blen static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) { typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); - PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc; + typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY2)(UINT flags, REFIID riid, void **ppFactory); + PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc = NULL; + PFN_CREATE_DXGI_FACTORY2 CreateDXGIFactory2Func = NULL; D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; ID3D11Device *d3dDevice = NULL; ID3D11DeviceContext *d3dContext = NULL; IDXGIDevice1 *dxgiDevice = NULL; HRESULT result = S_OK; - UINT creationFlags; - int i; + UINT creationFlags = 0; + SDL_bool createDebug; /* This array defines the set of DirectX hardware feature levels this app will support. * Note the ordering should be preserved. @@ -442,8 +541,11 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) D3D11_SAMPLER_DESC samplerDesc; D3D11_RASTERIZER_DESC rasterDesc; -#ifdef __WINRT__ - CreateDXGIFactoryFunc = CreateDXGIFactory1; + /* See if we need debug interfaces */ + createDebug = SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE); + +#ifdef SDL_PLATFORM_WINRT + CreateDXGIFactory2Func = CreateDXGIFactory2; D3D11CreateDeviceFunc = D3D11CreateDevice; #else data->hDXGIMod = SDL_LoadObject("dxgi.dll"); @@ -452,10 +554,13 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) goto done; } - CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory"); - if (!CreateDXGIFactoryFunc) { - result = E_FAIL; - goto done; + CreateDXGIFactory2Func = (PFN_CREATE_DXGI_FACTORY2)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory2"); + if (!CreateDXGIFactory2Func) { + CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory"); + if (!CreateDXGIFactoryFunc) { + result = E_FAIL; + goto done; + } } data->hD3D11Mod = SDL_LoadObject("d3d11.dll"); @@ -469,9 +574,44 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) result = E_FAIL; goto done; } -#endif /* __WINRT__ */ +#endif /* SDL_PLATFORM_WINRT */ - result = CreateDXGIFactoryFunc(&SDL_IID_IDXGIFactory2, (void **)&data->dxgiFactory); + if (createDebug) { +#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__ + IDXGIInfoQueue *dxgiInfoQueue = NULL; + PFN_CREATE_DXGI_FACTORY2 DXGIGetDebugInterfaceFunc; + + /* If the debug hint is set, also create the DXGI factory in debug mode */ + DXGIGetDebugInterfaceFunc = (PFN_CREATE_DXGI_FACTORY2)SDL_LoadFunction(data->hDXGIMod, "DXGIGetDebugInterface1"); + if (!DXGIGetDebugInterfaceFunc) { + result = E_FAIL; + goto done; + } + + result = DXGIGetDebugInterfaceFunc(0, &SDL_IID_IDXGIDebug1, (void **)&data->dxgiDebug); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("DXGIGetDebugInterface1"), result); + goto done; + } + + result = DXGIGetDebugInterfaceFunc(0, &SDL_IID_IDXGIInfoQueue, (void **)&dxgiInfoQueue); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("DXGIGetDebugInterface1"), result); + goto done; + } + + IDXGIInfoQueue_SetBreakOnSeverity(dxgiInfoQueue, SDL_DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE); + IDXGIInfoQueue_SetBreakOnSeverity(dxgiInfoQueue, SDL_DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE); + SAFE_RELEASE(dxgiInfoQueue); +#endif /* __IDXGIInfoQueue_INTERFACE_DEFINED__ */ + creationFlags = DXGI_CREATE_FACTORY_DEBUG; + } + + if (CreateDXGIFactory2Func) { + result = CreateDXGIFactory2Func(creationFlags, &SDL_IID_IDXGIFactory2, (void **)&data->dxgiFactory); + } else { + result = CreateDXGIFactoryFunc(&SDL_IID_IDXGIFactory2, (void **)&data->dxgiFactory); + } if (FAILED(result)) { WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("CreateDXGIFactory"), result); goto done; @@ -490,7 +630,7 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; /* Make sure Direct3D's debugging feature gets used, if the app requests it. */ - if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE)) { + if (createDebug) { creationFlags |= D3D11_CREATE_DEVICE_DEBUG; } @@ -578,12 +718,6 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) goto done; } - for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) { - if (D3D11_CreatePixelShader(data->d3dDevice, (D3D11_Shader)i, &data->pixelShaders[i]) < 0) { - goto done; - } - } - /* Setup space to hold vertex shader constants: */ SDL_zero(constantBufferDesc); constantBufferDesc.ByteWidth = sizeof(VertexShaderConstants); @@ -665,7 +799,7 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0); ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants); - SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER, data->d3dDevice); + SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D11_DEVICE_POINTER, data->d3dDevice); done: SAFE_RELEASE(d3dDevice); @@ -674,7 +808,7 @@ done: return result; } -#if defined(__WIN32__) || defined(__WINGDK__) +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) static DXGI_MODE_ROTATION D3D11_GetCurrentRotation() { @@ -682,7 +816,7 @@ static DXGI_MODE_ROTATION D3D11_GetCurrentRotation() return DXGI_MODE_ROTATION_IDENTITY; } -#endif /* defined(__WIN32__) || defined(__WINGDK__) */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ static BOOL D3D11_IsDisplayRotated90Degrees(DXGI_MODE_ROTATION rotation) { @@ -751,13 +885,14 @@ static int D3D11_GetViewportAlignedD3DRect(SDL_Renderer *renderer, const SDL_Rec static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) { D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT IUnknown *coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer); const BOOL usingXAML = (!coreWindow); #else IUnknown *coreWindow = NULL; const BOOL usingXAML = FALSE; #endif + IDXGISwapChain3 *swapChain3 = NULL; HRESULT result = S_OK; /* Create a swap chain using the same adapter as the existing Direct3D device. */ @@ -765,7 +900,17 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) SDL_zero(swapChainDesc); swapChainDesc.Width = w; swapChainDesc.Height = h; - swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */ + switch (renderer->output_colorspace) { + case SDL_COLORSPACE_SRGB_LINEAR: + swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + break; + case SDL_COLORSPACE_HDR10: + swapChainDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + break; + default: + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */ + break; + } swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; /* Don't use multi-sampling. */ swapChainDesc.SampleDesc.Quality = 0; @@ -828,8 +973,8 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) goto done; #endif } else { -#if defined(__WIN32__) || defined(__WINGDK__) - HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL); +#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) + HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory, (IUnknown *)data->d3dDevice, @@ -847,11 +992,41 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h) #else SDL_SetError(__FUNCTION__ ", Unable to find something to attach a swap chain to"); goto done; -#endif /* defined(__WIN32__) || defined(__WINGDK__) / else */ +#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) / else */ } data->swapEffect = swapChainDesc.SwapEffect; + if (SUCCEEDED(IDXGISwapChain1_QueryInterface(data->swapChain, &SDL_IID_IDXGISwapChain2, (void **)&swapChain3))) { + UINT colorspace_support = 0; + DXGI_COLOR_SPACE_TYPE colorspace; + switch (renderer->output_colorspace) { + case SDL_COLORSPACE_SRGB_LINEAR: + colorspace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; + break; + case SDL_COLORSPACE_HDR10: + colorspace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + break; + default: + /* sRGB */ + colorspace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + break; + } + if (SUCCEEDED(IDXGISwapChain3_CheckColorSpaceSupport(swapChain3, colorspace, &colorspace_support)) && + (colorspace_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) { + result = IDXGISwapChain3_SetColorSpace1(swapChain3, colorspace); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain3::SetColorSpace1"), result); + goto done; + } + } else if (colorspace != DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709) { + /* Not the default, we're not going to be able to present in this colorspace */ + SDL_SetError("Unsupported output colorspace"); + result = DXGI_ERROR_UNSUPPORTED; + } + } + done: + SAFE_RELEASE(swapChain3); SAFE_RELEASE(coreWindow); return result; } @@ -908,7 +1083,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer) /* The width and height of the swap chain must be based on the display's * non-rotated size. */ -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT SDL_GetWindowSize(renderer->window, &w, &h); #else SDL_GetWindowSizeInPixels(renderer->window, &w, &h); @@ -923,7 +1098,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer) if (data->swapChain) { /* IDXGISwapChain::ResizeBuffers is not available on Windows Phone 8. */ -#if !defined(__WINRT__) || !SDL_WINAPI_FAMILY_PHONE +#if !defined(SDL_PLATFORM_WINRT) || !SDL_WINAPI_FAMILY_PHONE /* If the swap chain already exists, resize it. */ result = IDXGISwapChain_ResizeBuffers(data->swapChain, 0, @@ -1021,7 +1196,7 @@ static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer) void D3D11_Trim(SDL_Renderer *renderer) { -#ifdef __WINRT__ +#ifdef SDL_PLATFORM_WINRT #if NTDDI_VERSION > NTDDI_WIN8 D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; HRESULT result = S_OK; @@ -1083,7 +1258,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData; HRESULT result; - DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format); + DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format, renderer->output_colorspace); D3D11_TEXTURE2D_DESC textureDesc; D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; @@ -1110,6 +1285,21 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL textureDesc.SampleDesc.Quality = 0; textureDesc.MiscFlags = 0; + /* NV12 textures must have even width and height */ + if (texture->format == SDL_PIXELFORMAT_NV12 || + texture->format == SDL_PIXELFORMAT_NV21 || + texture->format == SDL_PIXELFORMAT_P010) { + textureDesc.Width = (textureDesc.Width + 1) & ~1; + textureDesc.Height = (textureDesc.Height + 1) & ~1; + } + textureData->w = (int)textureDesc.Width; + textureData->h = (int)textureDesc.Height; + if (SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_SRGB) { + textureData->shader = SHADER_RGB; + } else { + textureData->shader = SHADER_ADVANCED; + } + if (texture->access == SDL_TEXTUREACCESS_STREAMING) { textureDesc.Usage = D3D11_USAGE_DYNAMIC; textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -1133,11 +1323,10 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL NULL, &textureData->mainTexture); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER, textureData->mainTexture); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, textureData->mainTexture); #if SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_IYUV) { @@ -1155,11 +1344,10 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL NULL, &textureData->mainTextureU); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER, textureData->mainTextureU); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_U_POINTER, textureData->mainTextureU); if (GetTextureProperty(create_props, "d3d11.texture_v", &textureData->mainTextureV) < 0) { return -1; @@ -1170,19 +1358,39 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL NULL, &textureData->mainTextureV); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result); } } - SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER, textureData->mainTextureV); + SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_V_POINTER, textureData->mainTextureV); + + textureData->YCbCr_matrix = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8); + if (!textureData->YCbCr_matrix) { + return SDL_SetError("Unsupported YUV colorspace"); + } } if (texture->format == SDL_PIXELFORMAT_NV12 || - texture->format == SDL_PIXELFORMAT_NV21) { + texture->format == SDL_PIXELFORMAT_NV21 || + texture->format == SDL_PIXELFORMAT_P010) { + int bits_per_pixel; + textureData->nv12 = SDL_TRUE; + + switch (texture->format) { + case SDL_PIXELFORMAT_P010: + bits_per_pixel = 10; + break; + default: + bits_per_pixel = 8; + break; + } + textureData->YCbCr_matrix = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, bits_per_pixel); + if (!textureData->YCbCr_matrix) { + return SDL_SetError("Unsupported YUV colorspace"); + } } #endif /* SDL_HAVE_YUV */ SDL_zero(resourceViewDesc); - resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format); + resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format, renderer->output_colorspace); resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; resourceViewDesc.Texture2D.MostDetailedMip = 0; resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels; @@ -1191,7 +1399,6 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL &resourceViewDesc, &textureData->mainTextureResourceView); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result); } #if SDL_HAVE_YUV @@ -1201,7 +1408,6 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL &resourceViewDesc, &textureData->mainTextureResourceViewU); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result); } result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice, @@ -1209,7 +1415,6 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL &resourceViewDesc, &textureData->mainTextureResourceViewV); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result); } } @@ -1217,14 +1422,17 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL if (textureData->nv12) { D3D11_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc; - nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; + if (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21) { + nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM; + } else if (texture->format == SDL_PIXELFORMAT_P010) { + nvResourceViewDesc.Format = DXGI_FORMAT_R16G16_UNORM; + } result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice, (ID3D11Resource *)textureData->mainTexture, &nvResourceViewDesc, &textureData->mainTextureResourceViewNV); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result); } } @@ -1242,7 +1450,6 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL &renderTargetViewDesc, &textureData->mainTextureRenderTargetView); if (FAILED(result)) { - D3D11_DestroyTexture(renderer, texture); return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result); } } @@ -1294,6 +1501,11 @@ static int D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Tex stagingTextureDesc.MiscFlags = 0; stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; stagingTextureDesc.Usage = D3D11_USAGE_STAGING; + if (stagingTextureDesc.Format == DXGI_FORMAT_NV12 || + stagingTextureDesc.Format == DXGI_FORMAT_P010) { + stagingTextureDesc.Width = (stagingTextureDesc.Width + 1) & ~1; + stagingTextureDesc.Height = (stagingTextureDesc.Height + 1) & ~1; + } result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice, &stagingTextureDesc, NULL, @@ -1314,13 +1526,8 @@ static int D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Tex return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result); } - if (stagingTextureDesc.Format == DXGI_FORMAT_NV12) { - /* Copy the UV plane as well */ - h += (h + 1) / 2; - } - src = (const Uint8 *)pixels; - dst = textureMemory.pData; + dst = (Uint8 *)textureMemory.pData; length = w * bpp; if (length == (UINT)pitch && length == textureMemory.RowPitch) { SDL_memcpy(dst, src, (size_t)length * h); @@ -1338,6 +1545,25 @@ static int D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Tex } } + if (stagingTextureDesc.Format == DXGI_FORMAT_NV12 || + stagingTextureDesc.Format == DXGI_FORMAT_P010) { + /* Copy the UV plane as well */ + h = (h + 1) / 2; + if (stagingTextureDesc.Format == DXGI_FORMAT_P010) { + length = (length + 3) & ~3; + pitch = (pitch + 3) & ~3; + } else { + length = (length + 1) & ~1; + pitch = (pitch + 1) & ~1; + } + dst = (Uint8 *)textureMemory.pData + stagingTextureDesc.Height * textureMemory.RowPitch; + for (row = 0; row < h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += textureMemory.RowPitch; + } + } + /* Commit the pixel buffer's changes back to the staging texture: */ ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)stagingTexture, @@ -1685,7 +1911,7 @@ static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) return 0; } -static int D3D11_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd) +static int D3D11_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd) { return 0; /* nothing to do in this backend. */ } @@ -1694,11 +1920,8 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, { VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first); int i; - SDL_Color color; - color.r = cmd->data.draw.r; - color.g = cmd->data.draw.g; - color.b = cmd->data.draw.b; - color.a = cmd->data.draw.a; + SDL_FColor color = cmd->data.draw.color; + SDL_bool convert_color = SDL_RenderingLinearSpace(renderer); if (!verts) { return -1; @@ -1706,6 +1929,10 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, cmd->data.draw.count = count; + if (convert_color) { + SDL_ConvertToLinear(&color); + } + for (i = 0; i < count; i++) { verts->pos.x = points[i].x + 0.5f; verts->pos.y = points[i].y + 0.5f; @@ -1719,13 +1946,17 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, } static int D3D11_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, - const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride, + const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices, float scale_x, float scale_y) { int i; int count = indices ? num_indices : num_vertices; VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first); + SDL_bool convert_color = SDL_RenderingLinearSpace(renderer); + D3D11_TextureData *textureData = texture ? (D3D11_TextureData *)texture->driverdata : NULL; + float u_scale = textureData ? (float)texture->w / textureData->w : 0.0f; + float v_scale = textureData ? (float)texture->h / textureData->h : 0.0f; if (!verts) { return -1; @@ -1751,12 +1982,15 @@ static int D3D11_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S verts->pos.x = xy_[0] * scale_x; verts->pos.y = xy_[1] * scale_y; - verts->color = *(SDL_Color *)((char *)color + j * color_stride); + verts->color = *(SDL_FColor *)((char *)color + j * color_stride); + if (convert_color) { + SDL_ConvertToLinear(&verts->color); + } if (texture) { float *uv_ = (float *)((char *)uv + j * uv_stride); - verts->tex.x = uv_[0]; - verts->tex.y = uv_[1]; + verts->tex.x = uv_[0] * u_scale; + verts->tex.y = uv_[1] * v_scale; } else { verts->tex.x = 0.0f; verts->tex.y = 0.0f; @@ -1938,7 +2172,70 @@ static ID3D11RenderTargetView *D3D11_GetCurrentRenderTargetView(SDL_Renderer *re } } -static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, ID3D11PixelShader *shader, +static void D3D11_SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Texture *texture, PixelShaderConstants *constants) +{ + float output_headroom; + + SDL_zerop(constants); + + constants->scRGB_output = (float)SDL_RenderingLinearSpace(renderer); + constants->color_scale = cmd->data.draw.color_scale; + + if (texture) { + D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; + + switch (texture->format) { + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + constants->texture_type = TEXTURETYPE_YUV; + constants->input_type = INPUTTYPE_SRGB; + break; + case SDL_PIXELFORMAT_NV12: + constants->texture_type = TEXTURETYPE_NV12; + constants->input_type = INPUTTYPE_SRGB; + break; + case SDL_PIXELFORMAT_NV21: + constants->texture_type = TEXTURETYPE_NV21; + constants->input_type = INPUTTYPE_SRGB; + break; + case SDL_PIXELFORMAT_P010: + constants->texture_type = TEXTURETYPE_NV12; + constants->input_type = INPUTTYPE_HDR10; + break; + default: + constants->texture_type = TEXTURETYPE_RGB; + if (texture->colorspace == SDL_COLORSPACE_SRGB_LINEAR) { + constants->input_type = INPUTTYPE_SCRGB; + } else if (texture->colorspace == SDL_COLORSPACE_HDR10) { + constants->input_type = INPUTTYPE_HDR10; + } else { + constants->input_type = INPUTTYPE_UNSPECIFIED; + } + break; + } + + constants->sdr_white_point = texture->SDR_white_point; + + if (renderer->target) { + output_headroom = renderer->target->HDR_headroom; + } else { + output_headroom = renderer->HDR_headroom; + } + + if (texture->HDR_headroom > output_headroom) { + constants->tonemap_method = TONEMAP_CHROME; + constants->tonemap_factor1 = (output_headroom / (texture->HDR_headroom * texture->HDR_headroom)); + constants->tonemap_factor2 = (1.0f / output_headroom); + } + + if (textureData->YCbCr_matrix) { + SDL_memcpy(constants->YCbCr_matrix, textureData->YCbCr_matrix, sizeof(constants->YCbCr_matrix)); + } + } +} + +static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, + D3D11_Shader shader, const PixelShaderConstants *shader_constants, const int numShaderResources, ID3D11ShaderResourceView **shaderResources, ID3D11SamplerState *sampler, const Float4X4 *matrix) @@ -1951,6 +2248,21 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c const SDL_BlendMode blendMode = cmd->data.draw.blend; ID3D11BlendState *blendState = NULL; SDL_bool updateSubresource = SDL_FALSE; + PixelShaderState *shader_state = &rendererData->currentShaderState[shader]; + PixelShaderConstants solid_constants; + + if (numShaderResources > 0) { + shaderResource = shaderResources[0]; + } else { + shaderResource = NULL; + } + + /* Make sure the render target isn't bound to a shader */ + if (shaderResource != rendererData->currentShaderResource) { + ID3D11ShaderResourceView *pNullResource = NULL; + ID3D11DeviceContext_PSSetShaderResources(rendererData->d3dContext, 0, 1, &pNullResource); + rendererData->currentShaderResource = NULL; + } if (renderTargetView != rendererData->currentRenderTargetView) { ID3D11DeviceContext_OMSetRenderTargets(rendererData->d3dContext, @@ -2011,14 +2323,46 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c rendererData->currentBlendState = blendState; } - if (shader != rendererData->currentShader) { - ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, shader, NULL, 0); - rendererData->currentShader = shader; + if (!shader_constants) { + D3D11_SetupShaderConstants(renderer, cmd, NULL, &solid_constants); + shader_constants = &solid_constants; } - if (numShaderResources > 0) { - shaderResource = shaderResources[0]; - } else { - shaderResource = NULL; + + if (!shader_state->constants || + SDL_memcmp(shader_constants, &shader_state->shader_constants, sizeof(*shader_constants)) != 0) { + SAFE_RELEASE(shader_state->constants); + + D3D11_BUFFER_DESC desc; + SDL_zero(desc); + desc.Usage = D3D11_USAGE_DEFAULT; + desc.ByteWidth = sizeof(*shader_constants); + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + D3D11_SUBRESOURCE_DATA data; + SDL_zero(data); + data.pSysMem = shader_constants; + + HRESULT result = ID3D11Device_CreateBuffer(rendererData->d3dDevice, &desc, &data, &shader_state->constants); + if (FAILED(result)) { + WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device::CreateBuffer [create shader constants]"), result); + return -1; + } + SDL_memcpy(&shader_state->shader_constants, shader_constants, sizeof(*shader_constants)); + + /* Force the shader parameters to be re-set */ + rendererData->currentShader = SHADER_NONE; + } + if (shader != rendererData->currentShader) { + if (!rendererData->pixelShaders[shader]) { + if (D3D11_CreatePixelShader(rendererData->d3dDevice, shader, &rendererData->pixelShaders[shader]) < 0) { + return -1; + } + } + ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, rendererData->pixelShaders[shader], NULL, 0); + if (shader_state->constants) { + ID3D11DeviceContext_PSSetConstantBuffers(rendererData->d3dContext, 0, 1, &shader_state->constants); + } + rendererData->currentShader = shader; } if (shaderResource != rendererData->currentShaderResource) { ID3D11DeviceContext_PSSetShaderResources(rendererData->d3dContext, 0, numShaderResources, shaderResources); @@ -2049,6 +2393,9 @@ static int D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata; D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata; ID3D11SamplerState *textureSampler; + PixelShaderConstants constants; + + D3D11_SetupShaderConstants(renderer, cmd, texture, &constants); switch (textureData->scaleMode) { case D3D11_FILTER_MIN_MAG_MIP_POINT: @@ -2062,56 +2409,26 @@ static int D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c } #if SDL_HAVE_YUV if (textureData->yuv) { - ID3D11ShaderResourceView *shaderResources[] = { - textureData->mainTextureResourceView, - textureData->mainTextureResourceViewU, - textureData->mainTextureResourceViewV - }; - D3D11_Shader shader; + ID3D11ShaderResourceView *shaderResources[3]; - switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) { - case SDL_YUV_CONVERSION_JPEG: - shader = SHADER_YUV_JPEG; - break; - case SDL_YUV_CONVERSION_BT601: - shader = SHADER_YUV_BT601; - break; - case SDL_YUV_CONVERSION_BT709: - shader = SHADER_YUV_BT709; - break; - default: - return SDL_SetError("Unsupported YUV conversion mode"); - } + shaderResources[0] = textureData->mainTextureResourceView; + shaderResources[1] = textureData->mainTextureResourceViewU; + shaderResources[2] = textureData->mainTextureResourceViewV; - return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader], + return D3D11_SetDrawState(renderer, cmd, textureData->shader, &constants, SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix); } else if (textureData->nv12) { - ID3D11ShaderResourceView *shaderResources[] = { - textureData->mainTextureResourceView, - textureData->mainTextureResourceViewNV, - }; - D3D11_Shader shader; + ID3D11ShaderResourceView *shaderResources[2]; - switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) { - case SDL_YUV_CONVERSION_JPEG: - shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_JPEG : SHADER_NV21_JPEG; - break; - case SDL_YUV_CONVERSION_BT601: - shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT601 : SHADER_NV21_BT601; - break; - case SDL_YUV_CONVERSION_BT709: - shader = texture->format == SDL_PIXELFORMAT_NV12 ? SHADER_NV12_BT709 : SHADER_NV21_BT709; - break; - default: - return SDL_SetError("Unsupported YUV conversion mode"); - } + shaderResources[0] = textureData->mainTextureResourceView; + shaderResources[1] = textureData->mainTextureResourceViewNV; - return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[shader], + return D3D11_SetDrawState(renderer, cmd, textureData->shader, &constants, SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix); } #endif /* SDL_HAVE_YUV */ - return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_RGB], + return D3D11_SetDrawState(renderer, cmd, textureData->shader, &constants, 1, &textureData->mainTextureResourceView, textureSampler, matrix); } @@ -2128,7 +2445,7 @@ static void D3D11_InvalidateCachedState(SDL_Renderer *renderer) data->currentRenderTargetView = NULL; data->currentRasterizerState = NULL; data->currentBlendState = NULL; - data->currentShader = NULL; + data->currentShader = SHADER_NONE; data->currentShaderResource = NULL; data->currentSampler = NULL; data->cliprectDirty = SDL_TRUE; @@ -2167,6 +2484,7 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) { SDL_copyp(viewport, &cmd->data.viewport.rect); rendererData->viewportDirty = SDL_TRUE; + rendererData->cliprectDirty = SDL_TRUE; } break; } @@ -2187,13 +2505,15 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, case SDL_RENDERCMD_CLEAR: { - const float colorRGBA[] = { - (cmd->data.color.r / 255.0f), - (cmd->data.color.g / 255.0f), - (cmd->data.color.b / 255.0f), - (cmd->data.color.a / 255.0f) - }; - ID3D11DeviceContext_ClearRenderTargetView(rendererData->d3dContext, D3D11_GetCurrentRenderTargetView(renderer), colorRGBA); + SDL_bool convert_color = SDL_RenderingLinearSpace(renderer); + SDL_FColor color = cmd->data.color.color; + if (convert_color) { + SDL_ConvertToLinear(&color); + } + color.r *= cmd->data.color.color_scale; + color.g *= cmd->data.color.color_scale; + color.b *= cmd->data.color.color_scale; + ID3D11DeviceContext_ClearRenderTargetView(rendererData->d3dContext, D3D11_GetCurrentRenderTargetView(renderer), &color.r); break; } @@ -2202,7 +2522,7 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const size_t count = cmd->data.draw.count; const size_t first = cmd->data.draw.first; const size_t start = first / sizeof(VertexPositionColor); - D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL); + D3D11_SetDrawState(renderer, cmd, SHADER_SOLID, NULL, 0, NULL, NULL, NULL); D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start, count); break; } @@ -2213,7 +2533,7 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const size_t first = cmd->data.draw.first; const size_t start = first / sizeof(VertexPositionColor); const VertexPositionColor *verts = (VertexPositionColor *)(((Uint8 *)vertices) + first); - D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL); + D3D11_SetDrawState(renderer, cmd, SHADER_SOLID, NULL, 0, NULL, NULL, NULL); D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count); if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) { D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count - 1), 1); @@ -2240,7 +2560,7 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, if (texture) { D3D11_SetCopyState(renderer, cmd, NULL); } else { - D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL); + D3D11_SetDrawState(renderer, cmd, SHADER_SOLID, NULL, 0, NULL, NULL, NULL); } D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, start, count); @@ -2257,19 +2577,18 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, return 0; } -static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, - Uint32 format, void *pixels, int pitch) +static SDL_Surface *D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) { D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata; ID3D11RenderTargetView *renderTargetView = NULL; ID3D11Texture2D *backBuffer = NULL; ID3D11Texture2D *stagingTexture = NULL; HRESULT result; - int status = -1; D3D11_TEXTURE2D_DESC stagingTextureDesc; D3D11_RECT srcRect = { 0, 0, 0, 0 }; D3D11_BOX srcBox; D3D11_MAPPED_SUBRESOURCE textureMemory; + SDL_Surface *output = NULL; renderTargetView = D3D11_GetCurrentRenderTargetView(renderer); if (!renderTargetView) { @@ -2332,17 +2651,12 @@ static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, goto done; } - /* Copy the data into the desired buffer, converting pixels to the - * desired format at the same time: - */ - status = SDL_ConvertPixels( + output = SDL_DuplicatePixels( rect->w, rect->h, D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format), + renderer->target ? renderer->target->colorspace : renderer->output_colorspace, textureMemory.pData, - textureMemory.RowPitch, - format, - pixels, - pitch); + textureMemory.RowPitch); /* Unmap the texture: */ ID3D11DeviceContext_Unmap(data->d3dContext, @@ -2352,7 +2666,7 @@ static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, done: SAFE_RELEASE(backBuffer); SAFE_RELEASE(stagingTexture); - return status; + return output; } static int D3D11_RenderPresent(SDL_Renderer *renderer) @@ -2438,6 +2752,16 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p } renderer->magic = &SDL_renderer_magic; + SDL_SetupRendererColorspace(renderer, create_props); + + if (renderer->output_colorspace != SDL_COLORSPACE_SRGB && + renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR + /*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) { + SDL_SetError("Unsupported output colorspace"); + SDL_free(renderer); + return NULL; + } + data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); @@ -2458,8 +2782,8 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p renderer->UnlockTexture = D3D11_UnlockTexture; renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode; renderer->SetRenderTarget = D3D11_SetRenderTarget; - renderer->QueueSetViewport = D3D11_QueueSetViewport; - renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ + renderer->QueueSetViewport = D3D11_QueueNoOp; + renderer->QueueSetDrawColor = D3D11_QueueNoOp; renderer->QueueDrawPoints = D3D11_QueueDrawPoints; renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */ renderer->QueueGeometry = D3D11_QueueGeometry; @@ -2488,7 +2812,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p */ renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; #else - if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { + if (SDL_GetBooleanProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } renderer->SetVSync = D3D11_SetVSync; @@ -2518,14 +2842,17 @@ SDL_RenderDriver D3D11_RenderDriver = { "direct3d11", (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), /* flags. see SDL_RendererFlags */ - 6, /* num_texture_formats */ + 9, /* num_texture_formats */ { /* texture_formats */ SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_XRGB8888, + SDL_PIXELFORMAT_XBGR2101010, + SDL_PIXELFORMAT_RGBA64_FLOAT, SDL_PIXELFORMAT_YV12, SDL_PIXELFORMAT_IYUV, SDL_PIXELFORMAT_NV12, - SDL_PIXELFORMAT_NV21 }, + SDL_PIXELFORMAT_NV21, + SDL_PIXELFORMAT_P010 }, 0, /* max_texture_width: will be filled in later */ 0 /* max_texture_height: will be filled in later */ } diff --git a/src/render/direct3d11/SDL_render_winrt.cpp b/src/render/direct3d11/SDL_render_winrt.cpp index 0378ee28..a2bfb5ce 100644 --- a/src/render/direct3d11/SDL_render_winrt.cpp +++ b/src/render/direct3d11/SDL_render_winrt.cpp @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D11 #include "../../video/winrt/SDL_winrtvideo_cpp.h" extern "C" { @@ -44,7 +44,7 @@ using namespace Windows::Graphics::Display; extern "C" void * D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer *renderer) { - IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER, NULL); + IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROP_WINDOW_WINRT_WINDOW_POINTER, NULL); ABI::Windows::UI::Core::ICoreWindow *coreWindow = NULL; if (!window || FAILED(window->QueryInterface(&coreWindow))) { return NULL; @@ -90,4 +90,4 @@ D3D11_GetCurrentRotation() return DXGI_MODE_ROTATION_IDENTITY; } -#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */ +#endif /* SDL_VIDEO_RENDER_D3D11 */ diff --git a/src/render/direct3d11/SDL_render_winrt.h b/src/render/direct3d11/SDL_render_winrt.h index cee20b51..31acdcfa 100644 --- a/src/render/direct3d11/SDL_render_winrt.h +++ b/src/render/direct3d11/SDL_render_winrt.h @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D11 #ifdef __cplusplus extern "C" { @@ -33,4 +33,4 @@ DXGI_MODE_ROTATION D3D11_GetCurrentRotation(); } #endif -#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */ +#endif /* SDL_VIDEO_RENDER_D3D11 */ diff --git a/src/render/direct3d11/SDL_shaders_d3d11.c b/src/render/direct3d11/SDL_shaders_d3d11.c index 66f7c8ce..7a88999f 100644 --- a/src/render/direct3d11/SDL_shaders_d3d11.c +++ b/src/render/direct3d11/SDL_shaders_d3d11.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED) +#if SDL_VIDEO_RENDER_D3D11 #define COBJMACROS #include "../../core/windows/SDL_windows.h" @@ -30,1874 +30,40 @@ #define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str -/* Direct3D 11.x shaders - - SDL's shaders are compiled into SDL itself, to simplify distribution. - - All Direct3D 11.x shaders were compiled with the following: - - fxc /E"main" /T "" /Fo"" "" - - Variables: - - : the type of shader. A table of utilized shader types is - listed below. - - : where to store compiled output - - : where to read shader source code from - - Shader types: - - ps_4_0_level_9_1: Pixel shader for Windows 8+, including Windows RT - - vs_4_0_level_9_1: Vertex shader for Windows 8+, including Windows RT - - ps_4_0_level_9_3: Pixel shader for Windows Phone 8 - - vs_4_0_level_9_3: Vertex shader for Windows Phone 8 - - - Shader object code was converted to a list of DWORDs via the following - *nix style command (available separately from Windows + MSVC): - - hexdump -v -e '6/4 "0x%08.8x, " "\n"' - */ #if SDL_WINAPI_FAMILY_PHONE -#define D3D11_USE_SHADER_MODEL_4_0_level_9_3 -#else -#define D3D11_USE_SHADER_MODEL_4_0_level_9_1 +#error Need to build shaders with level_9_3 #endif -/* The color-only-rendering pixel shader: +/* The shaders here were compiled with compile_shaders.bat */ - --- D3D11_PixelShader_Colors.hlsl --- - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; +#define g_main D3D11_PixelShader_Colors +#include "D3D11_PixelShader_Colors.h" +#undef g_main - float4 main(PixelShaderInput input) : SV_TARGET - { - return input.color; - } -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_Colors[] = { - 0x43425844, 0xd74c28fe, 0xa1eb8804, 0x269d512a, 0x7699723d, 0x00000001, - 0x00000240, 0x00000006, 0x00000038, 0x00000084, 0x000000c4, 0x00000140, - 0x00000198, 0x0000020c, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200, - 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, - 0x00240000, 0xffff0200, 0x0200001f, 0x80000000, 0xb00f0001, 0x02000001, - 0x800f0800, 0xb0e40001, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040, - 0x0000000e, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, - 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x00000050, 0x00000000, 0x00000000, - 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, - 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, - 0x6c69706d, 0x39207265, 0x2e30332e, 0x30303239, 0x3336312e, 0xab003438, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_Colors[] = { - 0x43425844, 0x93f6ccfc, 0x5f919270, 0x7a11aa4f, 0x9148e931, 0x00000001, - 0x00000240, 0x00000006, 0x00000038, 0x00000084, 0x000000c4, 0x00000140, - 0x00000198, 0x0000020c, 0x396e6f41, 0x00000044, 0x00000044, 0xffff0200, - 0x00000020, 0x00000024, 0x00240000, 0x00240000, 0x00240000, 0x00240000, - 0x00240000, 0xffff0201, 0x0200001f, 0x80000000, 0xb00f0001, 0x02000001, - 0x800f0800, 0xb0e40001, 0x0000ffff, 0x52444853, 0x00000038, 0x00000040, - 0x0000000e, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, - 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x00000050, 0x00000000, 0x00000000, - 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, - 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, - 0x6c69706d, 0x39207265, 0x2e30332e, 0x30303239, 0x3336312e, 0xab003438, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'colors' pixel shader is not defined." -#endif +#define g_main D3D11_PixelShader_Textures +#include "D3D11_PixelShader_Textures.h" +#undef g_main -/* The texture-rendering pixel shader: +#define g_main D3D11_PixelShader_Advanced +#include "D3D11_PixelShader_Advanced.h" +#undef g_main - --- D3D11_PixelShader_Textures.hlsl --- - Texture2D theTexture : register(t0); - SamplerState theSampler : register(s0); +#define g_main D3D11_VertexShader +#include "D3D11_VertexShader.h" +#undef g_main - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - return theTexture.Sample(theSampler, input.tex) * input.color; - } -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_Textures[] = { - 0x43425844, 0x6299b59f, 0x155258f2, 0x873ab86a, 0xfcbb6dcd, 0x00000001, - 0x00000330, 0x00000006, 0x00000038, 0x000000c0, 0x0000015c, 0x000001d8, - 0x00000288, 0x000002fc, 0x396e6f41, 0x00000080, 0x00000080, 0xffff0200, - 0x00000058, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001, - 0x00280000, 0x00000000, 0xffff0200, 0x0200001f, 0x80000000, 0xb0030000, - 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, 0xa00f0800, - 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000005, 0x800f0000, - 0x80e40000, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, - 0x52444853, 0x00000094, 0x00000040, 0x00000025, 0x0300005a, 0x00106000, - 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, - 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x00000003, - 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000a8, - 0x00000000, 0x00000000, 0x00000002, 0x0000001c, 0xffff0400, 0x00000100, - 0x00000072, 0x0000005c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000001, 0x00000067, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x53656874, - 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x694d0065, 0x736f7263, - 0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564, 0x706d6f43, - 0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336, 0xababab00, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_Textures[] = { - 0x43425844, 0x5876569a, 0x01b6c87e, 0x8447454f, 0xc7f3ef10, 0x00000001, - 0x00000330, 0x00000006, 0x00000038, 0x000000c0, 0x0000015c, 0x000001d8, - 0x00000288, 0x000002fc, 0x396e6f41, 0x00000080, 0x00000080, 0xffff0200, - 0x00000058, 0x00000028, 0x00280000, 0x00280000, 0x00280000, 0x00240001, - 0x00280000, 0x00000000, 0xffff0201, 0x0200001f, 0x80000000, 0xb0030000, - 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, 0xa00f0800, - 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, 0x03000005, 0x800f0000, - 0x80e40000, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, - 0x52444853, 0x00000094, 0x00000040, 0x00000025, 0x0300005a, 0x00106000, - 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, - 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x00000003, - 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000a8, - 0x00000000, 0x00000000, 0x00000002, 0x0000001c, 0xffff0400, 0x00000100, - 0x00000072, 0x0000005c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000001, 0x00000067, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x53656874, - 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x694d0065, 0x736f7263, - 0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564, 0x706d6f43, - 0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336, 0xababab00, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'textures' pixel shader is not defined" -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_YUV_JPEG.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureU : register(t1); - Texture2D theTextureV : register(t2); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_YUV_JPEG[] = { - 0x43425844, 0x10359e9c, 0x92c3d2c4, 0x00bf0cd5, 0x5ce8c499, 0x00000001, - 0x000005e8, 0x00000006, 0x00000038, 0x000001dc, 0x000003bc, 0x00000438, - 0x00000540, 0x000005b4, 0x396e6f41, 0x0000019c, 0x0000019c, 0xffff0200, - 0x0000016c, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003, - 0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0200, 0x05000051, - 0xa00f0000, 0x00000000, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, - 0xa00f0001, 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, 0x05000051, - 0xa00f0002, 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, - 0xa00f0003, 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, - 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, - 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, - 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0002, - 0xb0e40000, 0xa0e40802, 0x02000001, 0x80020000, 0x80000001, 0x02000001, - 0x80040000, 0x80000002, 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, - 0x03000005, 0x80080000, 0x80000000, 0xa0000001, 0x04000004, 0x80010001, - 0x80aa0000, 0xa0550001, 0x80ff0000, 0x03000008, 0x80020001, 0x80e40000, - 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, - 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, - 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, - 0x000001d8, 0x00000040, 0x00000076, 0x0300005a, 0x00106000, 0x00000000, - 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000, - 0x00000001, 0x00005555, 0x04001858, 0x00107000, 0x00000002, 0x00005555, - 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, - 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, - 0x001000f2, 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, - 0x00106000, 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, - 0x00000001, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, - 0x00100022, 0x00000000, 0x0010000a, 0x00000001, 0x09000045, 0x001000f2, - 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000002, 0x00106000, - 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x0010000a, 0x00000001, - 0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, 0x00004002, - 0x00000000, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012, - 0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f800000, 0x3fb374bc, - 0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, 0x00100246, - 0x00000000, 0x00004002, 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, - 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, 0x00000000, 0x00004002, - 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x05000036, 0x00100082, - 0x00000001, 0x00004001, 0x3f800000, 0x07000038, 0x001020f2, 0x00000000, - 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, - 0x00000074, 0x0000000c, 0x00000002, 0x00000000, 0x00000003, 0x00000005, - 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x46454452, 0x00000100, 0x00000000, 0x00000000, 0x00000004, 0x0000001c, - 0xffff0400, 0x00000100, 0x000000cb, 0x0000009c, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x000000a7, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, 0x00000001, - 0x0000000d, 0x000000b3, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, - 0x00000001, 0x00000001, 0x0000000d, 0x000000bf, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000002, 0x00000001, 0x0000000d, 0x53656874, - 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, 0x65546568, - 0x72757478, 0x74005565, 0x65546568, 0x72757478, 0x4d005665, 0x6f726369, - 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, - 0x656c6970, 0x2e362072, 0x36392e33, 0x312e3030, 0x34383336, 0xababab00, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_YUV_JPEG[] = { - 0x43425844, 0x616d6673, 0x83174178, 0x15aac25d, 0x2a340487, 0x00000001, - 0x000005c0, 0x00000006, 0x00000038, 0x000001b4, 0x00000394, 0x00000410, - 0x00000518, 0x0000058c, 0x396e6f41, 0x00000174, 0x00000174, 0xffff0200, - 0x00000144, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003, - 0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0201, 0x05000051, - 0xa00f0000, 0x00000000, 0xbf008081, 0x3f800000, 0x3fb374bc, 0x05000051, - 0xa00f0001, 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, - 0xa00f0002, 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, - 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, - 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40801, - 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, 0x02000001, 0x80020001, - 0x80000000, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40802, 0x02000001, - 0x80040001, 0x80000000, 0x03000002, 0x80070000, 0x80e40001, 0xa0d40000, - 0x0400005a, 0x80010001, 0x80e80000, 0xa0ee0000, 0xa0000000, 0x03000008, - 0x80020001, 0x80e40000, 0xa0e40001, 0x0400005a, 0x80040001, 0x80e40000, - 0xa0e40002, 0xa0aa0002, 0x02000001, 0x80080001, 0xa0aa0000, 0x03000005, - 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, - 0x0000ffff, 0x52444853, 0x000001d8, 0x00000040, 0x00000076, 0x0300005a, - 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, - 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04001858, 0x00107000, - 0x00000002, 0x00005555, 0x03001062, 0x00101032, 0x00000001, 0x03001062, - 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, - 0x00000002, 0x09000045, 0x001000f2, 0x00000000, 0x00101046, 0x00000001, - 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x09000045, 0x001000f2, - 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000001, 0x00106000, - 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x0010000a, 0x00000001, - 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46, - 0x00000002, 0x00106000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, - 0x0010000a, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246, - 0x00000000, 0x00004002, 0x00000000, 0xbf008081, 0xbf008081, 0x00000000, - 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002, - 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, 0x0a000010, 0x00100022, - 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f800000, 0xbeb02de0, - 0xbf36cf42, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, - 0x00000000, 0x00004002, 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, - 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, 0x07000038, - 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x0000000c, 0x00000002, 0x00000000, - 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x00000100, 0x00000000, 0x00000000, - 0x00000004, 0x0000001c, 0xffff0400, 0x00000100, 0x000000cb, 0x0000009c, - 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, - 0x00000001, 0x000000a7, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, - 0x00000000, 0x00000001, 0x0000000d, 0x000000b3, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, 0x000000bf, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000002, 0x00000001, - 0x0000000d, 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, - 0x74005965, 0x65546568, 0x72757478, 0x74005565, 0x65546568, 0x72757478, - 0x4d005665, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, - 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e362072, 0x36392e33, 0x312e3030, - 0x34383336, 0xababab00, 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, - 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, - 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, - 0x00000065, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, - 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, - 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_YUV_BT601.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureU : register(t1); - Texture2D theTextureV : register(t2); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_YUV_BT601[] = { - 0x43425844, 0x628ec838, 0xbe9cec6a, 0xc9ee10bb, 0x63283218, 0x00000001, - 0x000005e8, 0x00000006, 0x00000038, 0x000001dc, 0x000003bc, 0x00000438, - 0x00000540, 0x000005b4, 0x396e6f41, 0x0000019c, 0x0000019c, 0xffff0200, - 0x0000016c, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003, - 0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0200, 0x05000051, - 0xa00f0000, 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, - 0xa00f0001, 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, 0x05000051, - 0xa00f0002, 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x05000051, - 0xa00f0003, 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, - 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, - 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, - 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0002, - 0xb0e40000, 0xa0e40802, 0x02000001, 0x80020000, 0x80000001, 0x02000001, - 0x80040000, 0x80000002, 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, - 0x03000005, 0x80080000, 0x80000000, 0xa0000001, 0x04000004, 0x80010001, - 0x80aa0000, 0xa0550001, 0x80ff0000, 0x03000008, 0x80020001, 0x80e40000, - 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, - 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, - 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, - 0x000001d8, 0x00000040, 0x00000076, 0x0300005a, 0x00106000, 0x00000000, - 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000, - 0x00000001, 0x00005555, 0x04001858, 0x00107000, 0x00000002, 0x00005555, - 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, - 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, - 0x001000f2, 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, - 0x00106000, 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, - 0x00000001, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, - 0x00100022, 0x00000000, 0x0010000a, 0x00000001, 0x09000045, 0x001000f2, - 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000002, 0x00106000, - 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x0010000a, 0x00000001, - 0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, 0x00004002, - 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012, - 0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f950b0f, 0x3fcc49ba, - 0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, 0x00100246, - 0x00000000, 0x00004002, 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, - 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, 0x00000000, 0x00004002, - 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, 0x05000036, 0x00100082, - 0x00000001, 0x00004001, 0x3f800000, 0x07000038, 0x001020f2, 0x00000000, - 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, - 0x00000074, 0x0000000c, 0x00000002, 0x00000000, 0x00000003, 0x00000005, - 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x46454452, 0x00000100, 0x00000000, 0x00000000, 0x00000004, 0x0000001c, - 0xffff0400, 0x00000100, 0x000000cb, 0x0000009c, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x000000a7, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, 0x00000001, - 0x0000000d, 0x000000b3, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, - 0x00000001, 0x00000001, 0x0000000d, 0x000000bf, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000002, 0x00000001, 0x0000000d, 0x53656874, - 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, 0x65546568, - 0x72757478, 0x74005565, 0x65546568, 0x72757478, 0x4d005665, 0x6f726369, - 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, - 0x656c6970, 0x2e362072, 0x36392e33, 0x312e3030, 0x34383336, 0xababab00, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_YUV_BT601[] = { - 0x43425844, 0x692b159b, 0xf58723cc, 0xf4ceac9e, 0x35eec738, 0x00000001, - 0x000005c0, 0x00000006, 0x00000038, 0x000001b4, 0x00000394, 0x00000410, - 0x00000518, 0x0000058c, 0x396e6f41, 0x00000174, 0x00000174, 0xffff0200, - 0x00000144, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003, - 0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0201, 0x05000051, - 0xa00f0000, 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051, - 0xa00f0001, 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x400119ce, 0x05000051, - 0xa00f0002, 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, - 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, - 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40801, - 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, 0x02000001, 0x80020001, - 0x80000000, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40802, 0x02000001, - 0x80040001, 0x80000000, 0x03000002, 0x80070000, 0x80e40001, 0xa0d40000, - 0x0400005a, 0x80010001, 0x80e80000, 0xa0e40001, 0xa0aa0001, 0x03000008, - 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, - 0xa0ec0001, 0xa0aa0001, 0x02000001, 0x80080001, 0xa0aa0000, 0x03000005, - 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, - 0x0000ffff, 0x52444853, 0x000001d8, 0x00000040, 0x00000076, 0x0300005a, - 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, - 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04001858, 0x00107000, - 0x00000002, 0x00005555, 0x03001062, 0x00101032, 0x00000001, 0x03001062, - 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, - 0x00000002, 0x09000045, 0x001000f2, 0x00000000, 0x00101046, 0x00000001, - 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x09000045, 0x001000f2, - 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000001, 0x00106000, - 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x0010000a, 0x00000001, - 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46, - 0x00000002, 0x00106000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, - 0x0010000a, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246, - 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, - 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002, - 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, 0x0a000010, 0x00100022, - 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, 0xbec89a02, - 0xbf5020c5, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, - 0x00000000, 0x00004002, 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, - 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, 0x07000038, - 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x0000000c, 0x00000002, 0x00000000, - 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x00000100, 0x00000000, 0x00000000, - 0x00000004, 0x0000001c, 0xffff0400, 0x00000100, 0x000000cb, 0x0000009c, - 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, - 0x00000001, 0x000000a7, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, - 0x00000000, 0x00000001, 0x0000000d, 0x000000b3, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, 0x000000bf, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000002, 0x00000001, - 0x0000000d, 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, - 0x74005965, 0x65546568, 0x72757478, 0x74005565, 0x65546568, 0x72757478, - 0x4d005665, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, - 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e362072, 0x36392e33, 0x312e3030, - 0x34383336, 0xababab00, 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, - 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, - 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, - 0x00000065, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, - 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, - 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_YUV_BT709.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureU : register(t1); - Texture2D theTextureV : register(t2); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.y = theTextureU.Sample(theSampler, input.tex).r; - yuv.z = theTextureV.Sample(theSampler, input.tex).r; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_YUV_BT709[] = { - 0x43425844, 0x5045fa84, 0xc2908cce, 0x278dacc3, 0xd4276f8f, 0x00000001, - 0x000005e8, 0x00000006, 0x00000038, 0x000001dc, 0x000003bc, 0x00000438, - 0x00000540, 0x000005b4, 0x396e6f41, 0x0000019c, 0x0000019c, 0xffff0200, - 0x0000016c, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003, - 0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0200, 0x05000051, - 0xa00f0000, 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, - 0xa00f0001, 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, 0x05000051, - 0xa00f0002, 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x05000051, - 0xa00f0003, 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, - 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, - 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, - 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0002, - 0xb0e40000, 0xa0e40802, 0x02000001, 0x80020000, 0x80000001, 0x02000001, - 0x80040000, 0x80000002, 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, - 0x03000005, 0x80080000, 0x80000000, 0xa0000001, 0x04000004, 0x80010001, - 0x80aa0000, 0xa0550001, 0x80ff0000, 0x03000008, 0x80020001, 0x80e40000, - 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, - 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, - 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, - 0x000001d8, 0x00000040, 0x00000076, 0x0300005a, 0x00106000, 0x00000000, - 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, 0x00107000, - 0x00000001, 0x00005555, 0x04001858, 0x00107000, 0x00000002, 0x00005555, - 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, - 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, - 0x001000f2, 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, - 0x00106000, 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, - 0x00000001, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, - 0x00100022, 0x00000000, 0x0010000a, 0x00000001, 0x09000045, 0x001000f2, - 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000002, 0x00106000, - 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x0010000a, 0x00000001, - 0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, 0x00004002, - 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012, - 0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f950b0f, 0x3fe57732, - 0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, 0x00100246, - 0x00000000, 0x00004002, 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, - 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, 0x00000000, 0x00004002, - 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, 0x05000036, 0x00100082, - 0x00000001, 0x00004001, 0x3f800000, 0x07000038, 0x001020f2, 0x00000000, - 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, - 0x00000074, 0x0000000c, 0x00000002, 0x00000000, 0x00000003, 0x00000005, - 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x46454452, 0x00000100, 0x00000000, 0x00000000, 0x00000004, 0x0000001c, - 0xffff0400, 0x00000100, 0x000000cb, 0x0000009c, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x000000a7, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, 0x00000001, - 0x0000000d, 0x000000b3, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, - 0x00000001, 0x00000001, 0x0000000d, 0x000000bf, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000002, 0x00000001, 0x0000000d, 0x53656874, - 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, 0x65546568, - 0x72757478, 0x74005565, 0x65546568, 0x72757478, 0x4d005665, 0x6f726369, - 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, - 0x656c6970, 0x2e362072, 0x36392e33, 0x312e3030, 0x34383336, 0xababab00, - 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, - 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, - 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, - 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, - 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, - 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, - 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_YUV_BT709[] = { - 0x43425844, 0x72d13260, 0xf6c36f65, 0x8b9b28f5, 0x5010733c, 0x00000001, - 0x000005c0, 0x00000006, 0x00000038, 0x000001b4, 0x00000394, 0x00000410, - 0x00000518, 0x0000058c, 0x396e6f41, 0x00000174, 0x00000174, 0xffff0200, - 0x00000144, 0x00000030, 0x00300000, 0x00300000, 0x00300000, 0x00240003, - 0x00300000, 0x00000000, 0x00010001, 0x00020002, 0xffff0201, 0x05000051, - 0xa00f0000, 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051, - 0xa00f0001, 0x3f950b0f, 0x3fe57732, 0x00000000, 0x40073190, 0x05000051, - 0xa00f0002, 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x0200001f, - 0x80000000, 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, - 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, - 0x90000000, 0xa00f0802, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40801, - 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, 0x02000001, 0x80020001, - 0x80000000, 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40802, 0x02000001, - 0x80040001, 0x80000000, 0x03000002, 0x80070000, 0x80e40001, 0xa0d40000, - 0x0400005a, 0x80010001, 0x80e80000, 0xa0e40001, 0xa0aa0001, 0x03000008, - 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, - 0xa0ec0001, 0xa0aa0001, 0x02000001, 0x80080001, 0xa0aa0000, 0x03000005, - 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, - 0x0000ffff, 0x52444853, 0x000001d8, 0x00000040, 0x00000076, 0x0300005a, - 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, - 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04001858, 0x00107000, - 0x00000002, 0x00005555, 0x03001062, 0x00101032, 0x00000001, 0x03001062, - 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, - 0x00000002, 0x09000045, 0x001000f2, 0x00000000, 0x00101046, 0x00000001, - 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x09000045, 0x001000f2, - 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000001, 0x00106000, - 0x00000000, 0x05000036, 0x00100022, 0x00000000, 0x0010000a, 0x00000001, - 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46, - 0x00000002, 0x00106000, 0x00000000, 0x05000036, 0x00100042, 0x00000000, - 0x0010000a, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246, - 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, - 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002, - 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, 0x0a000010, 0x00100022, - 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, 0xbe5a511a, - 0xbf086c22, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, - 0x00000000, 0x00004002, 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, - 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, 0x07000038, - 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x0000000c, 0x00000002, 0x00000000, - 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x00000100, 0x00000000, 0x00000000, - 0x00000004, 0x0000001c, 0xffff0400, 0x00000100, 0x000000cb, 0x0000009c, - 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, - 0x00000001, 0x000000a7, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, - 0x00000000, 0x00000001, 0x0000000d, 0x000000b3, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, 0x000000bf, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000002, 0x00000001, - 0x0000000d, 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, - 0x74005965, 0x65546568, 0x72757478, 0x74005565, 0x65546568, 0x72757478, - 0x4d005665, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, - 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e362072, 0x36392e33, 0x312e3030, - 0x34383336, 0xababab00, 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, - 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, - 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, - 0x00000065, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, - 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, - 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_NV12_JPEG.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureUV : register(t1); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_NV12_JPEG[] = { - 0x43425844, 0x8fb9c77a, 0xe9e39686, 0x62b0e0e9, 0xd2bf8183, 0x00000001, - 0x00000548, 0x00000006, 0x00000038, 0x000001b0, 0x00000348, 0x000003c4, - 0x000004a0, 0x00000514, 0x396e6f41, 0x00000170, 0x00000170, 0xffff0200, - 0x00000144, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0200, 0x05000051, 0xa00f0000, - 0x00000000, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, - 0x02000001, 0x80060000, 0x80d20001, 0x03000002, 0x80070000, 0x80e40000, - 0xa0e40000, 0x03000005, 0x80080000, 0x80000000, 0xa0000001, 0x04000004, - 0x80010001, 0x80aa0000, 0xa0550001, 0x80ff0000, 0x03000008, 0x80020001, - 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, - 0xa0aa0003, 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, - 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, - 0x52444853, 0x00000190, 0x00000040, 0x00000064, 0x0300005a, 0x00106000, - 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, - 0x00107000, 0x00000001, 0x00005555, 0x03001062, 0x00101032, 0x00000001, - 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, - 0x02000068, 0x00000002, 0x09000045, 0x001000f2, 0x00000000, 0x00101046, - 0x00000001, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x09000045, - 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000001, - 0x00106000, 0x00000000, 0x05000036, 0x00100062, 0x00000000, 0x00100106, - 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, - 0x00004002, 0x00000000, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, - 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f800000, - 0x3fb374bc, 0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, - 0x00100246, 0x00000000, 0x00004002, 0x3f800000, 0xbeb02de0, 0xbf36cf42, - 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, 0x00000000, - 0x00004002, 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x05000036, - 0x00100082, 0x00000001, 0x00004001, 0x3f800000, 0x07000038, 0x001020f2, - 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, 0x0100003e, - 0x54415453, 0x00000074, 0x0000000a, 0x00000002, 0x00000000, 0x00000003, - 0x00000005, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x46454452, 0x000000d4, 0x00000000, 0x00000000, 0x00000003, - 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, 0x0000007c, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, - 0x00000087, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, - 0x00000001, 0x0000000d, 0x00000093, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, 0x53656874, 0x6c706d61, - 0x74007265, 0x65546568, 0x72757478, 0x74005965, 0x65546568, 0x72757478, - 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, - 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, 0x392e332e, 0x2e303036, - 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, - 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, - 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, - 0x00000065, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, - 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, - 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_NV12_JPEG[] = { - 0x43425844, 0xe33e5d8b, 0x1b5f6461, 0x1afee99f, 0xcc345c04, 0x00000001, - 0x00000520, 0x00000006, 0x00000038, 0x00000188, 0x00000320, 0x0000039c, - 0x00000478, 0x000004ec, 0x396e6f41, 0x00000148, 0x00000148, 0xffff0200, - 0x0000011c, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0201, 0x05000051, 0xa00f0000, - 0x00000000, 0xbf008081, 0x3f800000, 0x3fb374bc, 0x05000051, 0xa00f0001, - 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, - 0x02000001, 0x80060001, 0x80d00000, 0x03000002, 0x80070000, 0x80e40001, - 0xa0d40000, 0x0400005a, 0x80010001, 0x80e80000, 0xa0ee0000, 0xa0000000, - 0x03000008, 0x80020001, 0x80e40000, 0xa0e40001, 0x0400005a, 0x80040001, - 0x80e40000, 0xa0e40002, 0xa0aa0002, 0x02000001, 0x80080001, 0xa0aa0000, - 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, - 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, 0x00000064, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, - 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, - 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, 0x00100062, - 0x00000000, 0x00100106, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, - 0x00100246, 0x00000000, 0x00004002, 0x00000000, 0xbf008081, 0xbf008081, - 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, - 0x00004002, 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, 0x0a000010, - 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f800000, - 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, - 0x00100046, 0x00000000, 0x00004002, 0x3f800000, 0x3fe2d0e5, 0x00000000, - 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, - 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, - 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, 0x00000002, - 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, 0x00000000, - 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, - 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, 0x00000002, - 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, - 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, - 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, - 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, - 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, - 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, - 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, 0x00000003, - 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, - 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_NV12_BT601.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureUV : register(t1); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_NV12_BT601[] = { - 0x43425844, 0xd1d24a0c, 0x337c447a, 0x22b55cff, 0xb5c9c74b, 0x00000001, - 0x00000548, 0x00000006, 0x00000038, 0x000001b0, 0x00000348, 0x000003c4, - 0x000004a0, 0x00000514, 0x396e6f41, 0x00000170, 0x00000170, 0xffff0200, - 0x00000144, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0200, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, - 0x02000001, 0x80060000, 0x80d20001, 0x03000002, 0x80070000, 0x80e40000, - 0xa0e40000, 0x03000005, 0x80080000, 0x80000000, 0xa0000001, 0x04000004, - 0x80010001, 0x80aa0000, 0xa0550001, 0x80ff0000, 0x03000008, 0x80020001, - 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, - 0xa0aa0003, 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, - 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, - 0x52444853, 0x00000190, 0x00000040, 0x00000064, 0x0300005a, 0x00106000, - 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, - 0x00107000, 0x00000001, 0x00005555, 0x03001062, 0x00101032, 0x00000001, - 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, - 0x02000068, 0x00000002, 0x09000045, 0x001000f2, 0x00000000, 0x00101046, - 0x00000001, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x09000045, - 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000001, - 0x00106000, 0x00000000, 0x05000036, 0x00100062, 0x00000000, 0x00100106, - 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, - 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, - 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f950b0f, - 0x3fcc49ba, 0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, - 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, 0xbec89a02, 0xbf5020c5, - 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, 0x00000000, - 0x00004002, 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, 0x05000036, - 0x00100082, 0x00000001, 0x00004001, 0x3f800000, 0x07000038, 0x001020f2, - 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, 0x0100003e, - 0x54415453, 0x00000074, 0x0000000a, 0x00000002, 0x00000000, 0x00000003, - 0x00000005, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x46454452, 0x000000d4, 0x00000000, 0x00000000, 0x00000003, - 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, 0x0000007c, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, - 0x00000087, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, - 0x00000001, 0x0000000d, 0x00000093, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, 0x53656874, 0x6c706d61, - 0x74007265, 0x65546568, 0x72757478, 0x74005965, 0x65546568, 0x72757478, - 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, - 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, 0x392e332e, 0x2e303036, - 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, - 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, - 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, - 0x00000065, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, - 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, - 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_NV12_BT601[] = { - 0x43425844, 0x84b8b692, 0x589b9edd, 0x51ef2f0b, 0xf7247962, 0x00000001, - 0x00000520, 0x00000006, 0x00000038, 0x00000188, 0x00000320, 0x0000039c, - 0x00000478, 0x000004ec, 0x396e6f41, 0x00000148, 0x00000148, 0xffff0200, - 0x0000011c, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0201, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x400119ce, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, - 0x02000001, 0x80060001, 0x80d00000, 0x03000002, 0x80070000, 0x80e40001, - 0xa0d40000, 0x0400005a, 0x80010001, 0x80e80000, 0xa0e40001, 0xa0aa0001, - 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, - 0x80e40000, 0xa0ec0001, 0xa0aa0001, 0x02000001, 0x80080001, 0xa0aa0000, - 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, - 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, 0x00000064, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, - 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, - 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, 0x00100062, - 0x00000000, 0x00100106, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, - 0x00100246, 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, - 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, - 0x00004002, 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, 0x0a000010, - 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, - 0xbec89a02, 0xbf5020c5, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, - 0x00100046, 0x00000000, 0x00004002, 0x3f950b0f, 0x400119ce, 0x00000000, - 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, - 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, - 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, 0x00000002, - 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, 0x00000000, - 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, - 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, 0x00000002, - 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, - 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, - 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, - 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, - 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, - 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, - 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, 0x00000003, - 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, - 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_NV12_BT709.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureUV : register(t1); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).rg; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_NV12_BT709[] = { - 0x43425844, 0x40d1b8d5, 0xaf4b78b5, 0x907fd0b5, 0xa2d23686, 0x00000001, - 0x00000548, 0x00000006, 0x00000038, 0x000001b0, 0x00000348, 0x000003c4, - 0x000004a0, 0x00000514, 0x396e6f41, 0x00000170, 0x00000170, 0xffff0200, - 0x00000144, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0200, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, - 0x02000001, 0x80060000, 0x80d20001, 0x03000002, 0x80070000, 0x80e40000, - 0xa0e40000, 0x03000005, 0x80080000, 0x80000000, 0xa0000001, 0x04000004, - 0x80010001, 0x80aa0000, 0xa0550001, 0x80ff0000, 0x03000008, 0x80020001, - 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, 0x80e40000, 0xa0e40003, - 0xa0aa0003, 0x02000001, 0x80080001, 0xa0ff0000, 0x03000005, 0x800f0000, - 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, 0x80e40000, 0x0000ffff, - 0x52444853, 0x00000190, 0x00000040, 0x00000064, 0x0300005a, 0x00106000, - 0x00000000, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858, - 0x00107000, 0x00000001, 0x00005555, 0x03001062, 0x00101032, 0x00000001, - 0x03001062, 0x001010f2, 0x00000002, 0x03000065, 0x001020f2, 0x00000000, - 0x02000068, 0x00000002, 0x09000045, 0x001000f2, 0x00000000, 0x00101046, - 0x00000001, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x09000045, - 0x001000f2, 0x00000001, 0x00101046, 0x00000001, 0x00107e46, 0x00000001, - 0x00106000, 0x00000000, 0x05000036, 0x00100062, 0x00000000, 0x00100106, - 0x00000001, 0x0a000000, 0x00100072, 0x00000000, 0x00100246, 0x00000000, - 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, 0x00000000, 0x0a00000f, - 0x00100012, 0x00000001, 0x00100086, 0x00000000, 0x00004002, 0x3f950b0f, - 0x3fe57732, 0x00000000, 0x00000000, 0x0a000010, 0x00100022, 0x00000001, - 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, 0xbe5a511a, 0xbf086c22, - 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, 0x00100046, 0x00000000, - 0x00004002, 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, 0x05000036, - 0x00100082, 0x00000001, 0x00004001, 0x3f800000, 0x07000038, 0x001020f2, - 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, 0x00000002, 0x0100003e, - 0x54415453, 0x00000074, 0x0000000a, 0x00000002, 0x00000000, 0x00000003, - 0x00000005, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x46454452, 0x000000d4, 0x00000000, 0x00000000, 0x00000003, - 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, 0x0000007c, 0x00000003, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, - 0x00000087, 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000000, - 0x00000001, 0x0000000d, 0x00000093, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, 0x53656874, 0x6c706d61, - 0x74007265, 0x65546568, 0x72757478, 0x74005965, 0x65546568, 0x72757478, - 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, - 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, 0x392e332e, 0x2e303036, - 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, 0x00000003, 0x00000008, - 0x00000050, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, - 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, - 0x00000065, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, - 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0x4c4f4300, - 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_NV12_BT709[] = { - 0x43425844, 0xa3bba187, 0x71b6afa9, 0x15998682, 0x2d545cae, 0x00000001, - 0x00000520, 0x00000006, 0x00000038, 0x00000188, 0x00000320, 0x0000039c, - 0x00000478, 0x000004ec, 0x396e6f41, 0x00000148, 0x00000148, 0xffff0200, - 0x0000011c, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0201, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fe57732, 0x00000000, 0x40073190, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, - 0x02000001, 0x80060001, 0x80d00000, 0x03000002, 0x80070000, 0x80e40001, - 0xa0d40000, 0x0400005a, 0x80010001, 0x80e80000, 0xa0e40001, 0xa0aa0001, - 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, - 0x80e40000, 0xa0ec0001, 0xa0aa0001, 0x02000001, 0x80080001, 0xa0aa0000, - 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, - 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, 0x00000064, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, - 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, - 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, 0x00100062, - 0x00000000, 0x00100106, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, - 0x00100246, 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, - 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, - 0x00004002, 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, 0x0a000010, - 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, - 0xbe5a511a, 0xbf086c22, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, - 0x00100046, 0x00000000, 0x00004002, 0x3f950b0f, 0x40073190, 0x00000000, - 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, - 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, - 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, 0x00000002, - 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, 0x00000000, - 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, - 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, 0x00000002, - 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, - 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, - 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, - 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, - 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, - 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, - 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, 0x00000003, - 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, - 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_NV21_JPEG.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureUV : register(t1); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {0.0, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.0000, 0.0000, 1.4020}; - const float3 Gcoeff = {1.0000, -0.3441, -0.7141}; - const float3 Bcoeff = {1.0000, 1.7720, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_NV21_JPEG[] = { - 0x43425844, 0x9c41f579, 0xfd1019d8, 0x7c27e3ae, 0x52e3a5ff, 0x00000001, - 0x00000554, 0x00000006, 0x00000038, 0x000001bc, 0x00000354, 0x000003d0, - 0x000004ac, 0x00000520, 0x396e6f41, 0x0000017c, 0x0000017c, 0xffff0200, - 0x00000150, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0200, 0x05000051, 0xa00f0000, - 0x00000000, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, - 0x02000001, 0x80020000, 0x80550001, 0x02000001, 0x80040000, 0x80000001, - 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, 0x03000005, 0x80080000, - 0x80000000, 0xa0000001, 0x04000004, 0x80010001, 0x80aa0000, 0xa0550001, - 0x80ff0000, 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, - 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, 0x02000001, 0x80080001, - 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, - 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, - 0x00000064, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, - 0x00000000, 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, - 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, - 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, - 0x001000f2, 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, - 0x00106000, 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, - 0x00000001, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, - 0x00100062, 0x00000000, 0x00100456, 0x00000001, 0x0a000000, 0x00100072, - 0x00000000, 0x00100246, 0x00000000, 0x00004002, 0x00000000, 0xbf008081, - 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, - 0x00000000, 0x00004002, 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, - 0x0a000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, - 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x0a00000f, 0x00100042, - 0x00000001, 0x00100046, 0x00000000, 0x00004002, 0x3f800000, 0x3fe2d0e5, - 0x00000000, 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, - 0x3f800000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, - 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, - 0x00000002, 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, - 0x00000000, 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, - 0x000000a0, 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, - 0x0000000d, 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, - 0x74005965, 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, - 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, - 0x36207265, 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, - 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, - 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, - 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, - 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, - 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, - 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_NV21_JPEG[] = { - 0x43425844, 0x5705ccc9, 0xeb57571d, 0x8ce556e0, 0x2adef743, 0x00000001, - 0x00000520, 0x00000006, 0x00000038, 0x00000188, 0x00000320, 0x0000039c, - 0x00000478, 0x000004ec, 0x396e6f41, 0x00000148, 0x00000148, 0xffff0200, - 0x0000011c, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0201, 0x05000051, 0xa00f0000, - 0x00000000, 0xbf008081, 0x3f800000, 0x3fb374bc, 0x05000051, 0xa00f0001, - 0x3f800000, 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f800000, 0x3fe2d0e5, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, - 0x02000001, 0x80060001, 0x80c40000, 0x03000002, 0x80070000, 0x80e40001, - 0xa0d40000, 0x0400005a, 0x80010001, 0x80e80000, 0xa0ee0000, 0xa0000000, - 0x03000008, 0x80020001, 0x80e40000, 0xa0e40001, 0x0400005a, 0x80040001, - 0x80e40000, 0xa0e40002, 0xa0aa0002, 0x02000001, 0x80080001, 0xa0aa0000, - 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, - 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, 0x00000064, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, - 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, - 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, 0x00100062, - 0x00000000, 0x00100456, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, - 0x00100246, 0x00000000, 0x00004002, 0x00000000, 0xbf008081, 0xbf008081, - 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, - 0x00004002, 0x3f800000, 0x3fb374bc, 0x00000000, 0x00000000, 0x0a000010, - 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f800000, - 0xbeb02de0, 0xbf36cf42, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, - 0x00100046, 0x00000000, 0x00004002, 0x3f800000, 0x3fe2d0e5, 0x00000000, - 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, - 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, - 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, 0x00000002, - 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, 0x00000000, - 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, - 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, 0x00000002, - 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, - 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, - 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, - 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, - 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, - 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, - 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, 0x00000003, - 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, - 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_NV21_BT601.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureUV : register(t1); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.5960}; - const float3 Gcoeff = {1.1644, -0.3918, -0.8130}; - const float3 Bcoeff = {1.1644, 2.0172, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_NV21_BT601[] = { - 0x43425844, 0x7fc6cfdc, 0xba87a4ff, 0xa72685a6, 0xa051b38c, 0x00000001, - 0x00000554, 0x00000006, 0x00000038, 0x000001bc, 0x00000354, 0x000003d0, - 0x000004ac, 0x00000520, 0x396e6f41, 0x0000017c, 0x0000017c, 0xffff0200, - 0x00000150, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0200, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f950b0f, 0x400119ce, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, - 0x02000001, 0x80020000, 0x80550001, 0x02000001, 0x80040000, 0x80000001, - 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, 0x03000005, 0x80080000, - 0x80000000, 0xa0000001, 0x04000004, 0x80010001, 0x80aa0000, 0xa0550001, - 0x80ff0000, 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, - 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, 0x02000001, 0x80080001, - 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, - 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, - 0x00000064, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, - 0x00000000, 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, - 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, - 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, - 0x001000f2, 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, - 0x00106000, 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, - 0x00000001, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, - 0x00100062, 0x00000000, 0x00100456, 0x00000001, 0x0a000000, 0x00100072, - 0x00000000, 0x00100246, 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, - 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, - 0x00000000, 0x00004002, 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, - 0x0a000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, - 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x0a00000f, 0x00100042, - 0x00000001, 0x00100046, 0x00000000, 0x00004002, 0x3f950b0f, 0x400119ce, - 0x00000000, 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, - 0x3f800000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, - 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, - 0x00000002, 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, - 0x00000000, 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, - 0x000000a0, 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, - 0x0000000d, 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, - 0x74005965, 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, - 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, - 0x36207265, 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, - 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, - 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, - 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, - 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, - 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, - 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_NV21_BT601[] = { - 0x43425844, 0x1e92bca4, 0xfeb04e20, 0x3f4226b1, 0xc89c58ad, 0x00000001, - 0x00000520, 0x00000006, 0x00000038, 0x00000188, 0x00000320, 0x0000039c, - 0x00000478, 0x000004ec, 0x396e6f41, 0x00000148, 0x00000148, 0xffff0200, - 0x0000011c, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0201, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x400119ce, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbec89a02, 0xbf5020c5, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, - 0x02000001, 0x80060001, 0x80c40000, 0x03000002, 0x80070000, 0x80e40001, - 0xa0d40000, 0x0400005a, 0x80010001, 0x80e80000, 0xa0e40001, 0xa0aa0001, - 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, - 0x80e40000, 0xa0ec0001, 0xa0aa0001, 0x02000001, 0x80080001, 0xa0aa0000, - 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, - 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, 0x00000064, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, - 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, - 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, 0x00100062, - 0x00000000, 0x00100456, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, - 0x00100246, 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, - 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, - 0x00004002, 0x3f950b0f, 0x3fcc49ba, 0x00000000, 0x00000000, 0x0a000010, - 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, - 0xbec89a02, 0xbf5020c5, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, - 0x00100046, 0x00000000, 0x00004002, 0x3f950b0f, 0x400119ce, 0x00000000, - 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, - 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, - 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, 0x00000002, - 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, 0x00000000, - 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, - 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, 0x00000002, - 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, - 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, - 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, - 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, - 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, - 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, - 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, 0x00000003, - 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, - 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The yuv-rendering pixel shader: - - --- D3D11_PixelShader_NV21_BT709.hlsl --- - Texture2D theTextureY : register(t0); - Texture2D theTextureUV : register(t1); - SamplerState theSampler : register(s0); - - struct PixelShaderInput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - float4 main(PixelShaderInput input) : SV_TARGET - { - const float3 offset = {-0.0627451017, -0.501960814, -0.501960814}; - const float3 Rcoeff = {1.1644, 0.0000, 1.7927}; - const float3 Gcoeff = {1.1644, -0.2132, -0.5329}; - const float3 Bcoeff = {1.1644, 2.1124, 0.0000}; - - float4 Output; - - float3 yuv; - yuv.x = theTextureY.Sample(theSampler, input.tex).r; - yuv.yz = theTextureUV.Sample(theSampler, input.tex).gr; - - yuv += offset; - Output.r = dot(yuv, Rcoeff); - Output.g = dot(yuv, Gcoeff); - Output.b = dot(yuv, Bcoeff); - Output.a = 1.0f; - - return Output * input.color; - } - -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_PixelShader_NV21_BT709[] = { - 0x43425844, 0x754ba6c4, 0xe321a747, 0x23680787, 0x6bb1bdcc, 0x00000001, - 0x00000554, 0x00000006, 0x00000038, 0x000001bc, 0x00000354, 0x000003d0, - 0x000004ac, 0x00000520, 0x396e6f41, 0x0000017c, 0x0000017c, 0xffff0200, - 0x00000150, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0200, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0xbf008081, 0x3f800000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x05000051, 0xa00f0003, - 0x3f950b0f, 0x40073190, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40800, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40801, - 0x02000001, 0x80020000, 0x80550001, 0x02000001, 0x80040000, 0x80000001, - 0x03000002, 0x80070000, 0x80e40000, 0xa0e40000, 0x03000005, 0x80080000, - 0x80000000, 0xa0000001, 0x04000004, 0x80010001, 0x80aa0000, 0xa0550001, - 0x80ff0000, 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, - 0x80040001, 0x80e40000, 0xa0e40003, 0xa0aa0003, 0x02000001, 0x80080001, - 0xa0ff0000, 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, - 0x800f0800, 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, - 0x00000064, 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, - 0x00000000, 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, - 0x03001062, 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, - 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, - 0x001000f2, 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, - 0x00106000, 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, - 0x00000001, 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, - 0x00100062, 0x00000000, 0x00100456, 0x00000001, 0x0a000000, 0x00100072, - 0x00000000, 0x00100246, 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, - 0xbf008081, 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, - 0x00000000, 0x00004002, 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, - 0x0a000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, - 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x0a00000f, 0x00100042, - 0x00000001, 0x00100046, 0x00000000, 0x00004002, 0x3f950b0f, 0x40073190, - 0x00000000, 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, - 0x3f800000, 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, - 0x00101e46, 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, - 0x00000002, 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, - 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, - 0x00000000, 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, - 0x000000a0, 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, - 0x00000004, 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, - 0x00000002, 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, - 0x0000000d, 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, - 0x74005965, 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, - 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, - 0x36207265, 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, - 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, - 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, - 0x00000003, 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, - 0x00000003, 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, - 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, - 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, - 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_PixelShader_NV21_BT709[] = { - 0x43425844, 0xb6219b20, 0xb71bbcf7, 0xf361cc45, 0xc4d5f5be, 0x00000001, - 0x00000520, 0x00000006, 0x00000038, 0x00000188, 0x00000320, 0x0000039c, - 0x00000478, 0x000004ec, 0x396e6f41, 0x00000148, 0x00000148, 0xffff0200, - 0x0000011c, 0x0000002c, 0x002c0000, 0x002c0000, 0x002c0000, 0x00240002, - 0x002c0000, 0x00000000, 0x00010001, 0xffff0201, 0x05000051, 0xa00f0000, - 0xbd808081, 0xbf008081, 0x3f800000, 0x00000000, 0x05000051, 0xa00f0001, - 0x3f950b0f, 0x3fe57732, 0x00000000, 0x40073190, 0x05000051, 0xa00f0002, - 0x3f950b0f, 0xbe5a511a, 0xbf086c22, 0x00000000, 0x0200001f, 0x80000000, - 0xb0030000, 0x0200001f, 0x80000000, 0xb00f0001, 0x0200001f, 0x90000000, - 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, 0x03000042, 0x800f0000, - 0xb0e40000, 0xa0e40801, 0x03000042, 0x800f0001, 0xb0e40000, 0xa0e40800, - 0x02000001, 0x80060001, 0x80c40000, 0x03000002, 0x80070000, 0x80e40001, - 0xa0d40000, 0x0400005a, 0x80010001, 0x80e80000, 0xa0e40001, 0xa0aa0001, - 0x03000008, 0x80020001, 0x80e40000, 0xa0e40002, 0x0400005a, 0x80040001, - 0x80e40000, 0xa0ec0001, 0xa0aa0001, 0x02000001, 0x80080001, 0xa0aa0000, - 0x03000005, 0x800f0000, 0x80e40001, 0xb0e40001, 0x02000001, 0x800f0800, - 0x80e40000, 0x0000ffff, 0x52444853, 0x00000190, 0x00000040, 0x00000064, - 0x0300005a, 0x00106000, 0x00000000, 0x04001858, 0x00107000, 0x00000000, - 0x00005555, 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x03001062, - 0x00101032, 0x00000001, 0x03001062, 0x001010f2, 0x00000002, 0x03000065, - 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x09000045, 0x001000f2, - 0x00000000, 0x00101046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, - 0x00000000, 0x09000045, 0x001000f2, 0x00000001, 0x00101046, 0x00000001, - 0x00107e46, 0x00000001, 0x00106000, 0x00000000, 0x05000036, 0x00100062, - 0x00000000, 0x00100456, 0x00000001, 0x0a000000, 0x00100072, 0x00000000, - 0x00100246, 0x00000000, 0x00004002, 0xbd808081, 0xbf008081, 0xbf008081, - 0x00000000, 0x0a00000f, 0x00100012, 0x00000001, 0x00100086, 0x00000000, - 0x00004002, 0x3f950b0f, 0x3fe57732, 0x00000000, 0x00000000, 0x0a000010, - 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00004002, 0x3f950b0f, - 0xbe5a511a, 0xbf086c22, 0x00000000, 0x0a00000f, 0x00100042, 0x00000001, - 0x00100046, 0x00000000, 0x00004002, 0x3f950b0f, 0x40073190, 0x00000000, - 0x00000000, 0x05000036, 0x00100082, 0x00000001, 0x00004001, 0x3f800000, - 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00101e46, - 0x00000002, 0x0100003e, 0x54415453, 0x00000074, 0x0000000a, 0x00000002, - 0x00000000, 0x00000003, 0x00000005, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x46454452, 0x000000d4, 0x00000000, - 0x00000000, 0x00000003, 0x0000001c, 0xffff0400, 0x00000100, 0x000000a0, - 0x0000007c, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000001, 0x00000001, 0x00000087, 0x00000002, 0x00000005, 0x00000004, - 0xffffffff, 0x00000000, 0x00000001, 0x0000000d, 0x00000093, 0x00000002, - 0x00000005, 0x00000004, 0xffffffff, 0x00000001, 0x00000001, 0x0000000d, - 0x53656874, 0x6c706d61, 0x74007265, 0x65546568, 0x72757478, 0x74005965, - 0x65546568, 0x72757478, 0x00565565, 0x7263694d, 0x666f736f, 0x52282074, - 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x36207265, - 0x392e332e, 0x2e303036, 0x38333631, 0xabab0034, 0x4e475349, 0x0000006c, - 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, - 0x00000001, 0x00000303, 0x00000065, 0x00000000, 0x00000000, 0x00000003, - 0x00000002, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, - 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054 -}; -#else -#error "An appropriate 'yuv' pixel shader is not defined." -#endif - -/* The sole vertex shader: - - --- D3D11_VertexShader.hlsl --- - #pragma pack_matrix( row_major ) - - cbuffer VertexShaderConstants : register(b0) - { - matrix model; - matrix projectionAndView; - }; - - struct VertexShaderInput - { - float3 pos : POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - struct VertexShaderOutput - { - float4 pos : SV_POSITION; - float2 tex : TEXCOORD0; - float4 color : COLOR0; - }; - - VertexShaderOutput main(VertexShaderInput input) - { - VertexShaderOutput output; - float4 pos = float4(input.pos, 1.0f); - - // Transform the vertex position into projected space. - pos = mul(pos, model); - pos = mul(pos, projectionAndView); - output.pos = pos; - - // Pass through texture coordinates and color values without transformation - output.tex = input.tex; - output.color = input.color; - - return output; - } -*/ -#ifdef D3D11_USE_SHADER_MODEL_4_0_level_9_1 -static const DWORD D3D11_VertexShader[] = { - 0x43425844, 0x62dfae5f, 0x3e8bd8df, 0x9ec97127, 0x5044eefb, 0x00000001, - 0x00000598, 0x00000006, 0x00000038, 0x0000016c, 0x00000334, 0x000003b0, - 0x000004b4, 0x00000524, 0x396e6f41, 0x0000012c, 0x0000012c, 0xfffe0200, - 0x000000f8, 0x00000034, 0x00240001, 0x00300000, 0x00300000, 0x00240000, - 0x00300001, 0x00000000, 0x00010008, 0x00000000, 0x00000000, 0xfffe0200, - 0x0200001f, 0x80000005, 0x900f0000, 0x0200001f, 0x80010005, 0x900f0001, - 0x0200001f, 0x80020005, 0x900f0002, 0x03000005, 0x800f0000, 0x90550000, - 0xa0e40002, 0x04000004, 0x800f0000, 0x90000000, 0xa0e40001, 0x80e40000, - 0x04000004, 0x800f0000, 0x90aa0000, 0xa0e40003, 0x80e40000, 0x03000002, - 0x800f0000, 0x80e40000, 0xa0e40004, 0x03000005, 0x800f0001, 0x80550000, - 0xa0e40006, 0x04000004, 0x800f0001, 0x80000000, 0xa0e40005, 0x80e40001, - 0x04000004, 0x800f0001, 0x80aa0000, 0xa0e40007, 0x80e40001, 0x04000004, - 0x800f0000, 0x80ff0000, 0xa0e40008, 0x80e40001, 0x04000004, 0xc0030000, - 0x80ff0000, 0xa0e40000, 0x80e40000, 0x02000001, 0xc00c0000, 0x80e40000, - 0x02000001, 0xe0030000, 0x90e40001, 0x02000001, 0xe00f0001, 0x90e40002, - 0x0000ffff, 0x52444853, 0x000001c0, 0x00010040, 0x00000070, 0x04000059, - 0x00208e46, 0x00000000, 0x00000008, 0x0300005f, 0x00101072, 0x00000000, - 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002, - 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032, - 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x02000068, 0x00000002, - 0x08000038, 0x001000f2, 0x00000000, 0x00101556, 0x00000000, 0x00208e46, - 0x00000000, 0x00000001, 0x0a000032, 0x001000f2, 0x00000000, 0x00101006, - 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000, - 0x0a000032, 0x001000f2, 0x00000000, 0x00101aa6, 0x00000000, 0x00208e46, - 0x00000000, 0x00000002, 0x00100e46, 0x00000000, 0x08000000, 0x001000f2, - 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000003, - 0x08000038, 0x001000f2, 0x00000001, 0x00100556, 0x00000000, 0x00208e46, - 0x00000000, 0x00000005, 0x0a000032, 0x001000f2, 0x00000001, 0x00100006, - 0x00000000, 0x00208e46, 0x00000000, 0x00000004, 0x00100e46, 0x00000001, - 0x0a000032, 0x001000f2, 0x00000001, 0x00100aa6, 0x00000000, 0x00208e46, - 0x00000000, 0x00000006, 0x00100e46, 0x00000001, 0x0a000032, 0x001020f2, - 0x00000000, 0x00100ff6, 0x00000000, 0x00208e46, 0x00000000, 0x00000007, - 0x00100e46, 0x00000001, 0x05000036, 0x00102032, 0x00000001, 0x00101046, - 0x00000001, 0x05000036, 0x001020f2, 0x00000002, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x0000000b, 0x00000002, 0x00000000, - 0x00000006, 0x00000003, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x000000fc, 0x00000001, 0x00000054, - 0x00000001, 0x0000001c, 0xfffe0400, 0x00000100, 0x000000c6, 0x0000003c, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, - 0x00000001, 0x74726556, 0x68537865, 0x72656461, 0x736e6f43, 0x746e6174, - 0xabab0073, 0x0000003c, 0x00000002, 0x0000006c, 0x00000080, 0x00000000, - 0x00000000, 0x0000009c, 0x00000000, 0x00000040, 0x00000002, 0x000000a4, - 0x00000000, 0x000000b4, 0x00000040, 0x00000040, 0x00000002, 0x000000a4, - 0x00000000, 0x65646f6d, 0xabab006c, 0x00030002, 0x00040004, 0x00000000, - 0x00000000, 0x6a6f7270, 0x69746365, 0x6e416e6f, 0x65695664, 0x694d0077, - 0x736f7263, 0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564, - 0x706d6f43, 0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336, - 0xababab00, 0x4e475349, 0x00000068, 0x00000003, 0x00000008, 0x00000050, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000707, 0x00000059, - 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000062, - 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50, - 0x4e4f4954, 0x58455400, 0x524f4f43, 0x4f430044, 0x00524f4c, 0x4e47534f, - 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, - 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, - 0x00000003, 0x00000001, 0x00000c03, 0x00000065, 0x00000000, 0x00000000, - 0x00000003, 0x00000002, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, - 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f -}; -#elif defined(D3D11_USE_SHADER_MODEL_4_0_level_9_3) -static const DWORD D3D11_VertexShader[] = { - 0x43425844, 0x01a24e41, 0x696af551, 0x4b2a87d1, 0x82ea03f6, 0x00000001, - 0x00000598, 0x00000006, 0x00000038, 0x0000016c, 0x00000334, 0x000003b0, - 0x000004b4, 0x00000524, 0x396e6f41, 0x0000012c, 0x0000012c, 0xfffe0200, - 0x000000f8, 0x00000034, 0x00240001, 0x00300000, 0x00300000, 0x00240000, - 0x00300001, 0x00000000, 0x00010008, 0x00000000, 0x00000000, 0xfffe0201, - 0x0200001f, 0x80000005, 0x900f0000, 0x0200001f, 0x80010005, 0x900f0001, - 0x0200001f, 0x80020005, 0x900f0002, 0x03000005, 0x800f0000, 0x90550000, - 0xa0e40002, 0x04000004, 0x800f0000, 0x90000000, 0xa0e40001, 0x80e40000, - 0x04000004, 0x800f0000, 0x90aa0000, 0xa0e40003, 0x80e40000, 0x03000002, - 0x800f0000, 0x80e40000, 0xa0e40004, 0x03000005, 0x800f0001, 0x80550000, - 0xa0e40006, 0x04000004, 0x800f0001, 0x80000000, 0xa0e40005, 0x80e40001, - 0x04000004, 0x800f0001, 0x80aa0000, 0xa0e40007, 0x80e40001, 0x04000004, - 0x800f0000, 0x80ff0000, 0xa0e40008, 0x80e40001, 0x04000004, 0xc0030000, - 0x80ff0000, 0xa0e40000, 0x80e40000, 0x02000001, 0xc00c0000, 0x80e40000, - 0x02000001, 0xe0030000, 0x90e40001, 0x02000001, 0xe00f0001, 0x90e40002, - 0x0000ffff, 0x52444853, 0x000001c0, 0x00010040, 0x00000070, 0x04000059, - 0x00208e46, 0x00000000, 0x00000008, 0x0300005f, 0x00101072, 0x00000000, - 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x001010f2, 0x00000002, - 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032, - 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x02000068, 0x00000002, - 0x08000038, 0x001000f2, 0x00000000, 0x00101556, 0x00000000, 0x00208e46, - 0x00000000, 0x00000001, 0x0a000032, 0x001000f2, 0x00000000, 0x00101006, - 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x00100e46, 0x00000000, - 0x0a000032, 0x001000f2, 0x00000000, 0x00101aa6, 0x00000000, 0x00208e46, - 0x00000000, 0x00000002, 0x00100e46, 0x00000000, 0x08000000, 0x001000f2, - 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000003, - 0x08000038, 0x001000f2, 0x00000001, 0x00100556, 0x00000000, 0x00208e46, - 0x00000000, 0x00000005, 0x0a000032, 0x001000f2, 0x00000001, 0x00100006, - 0x00000000, 0x00208e46, 0x00000000, 0x00000004, 0x00100e46, 0x00000001, - 0x0a000032, 0x001000f2, 0x00000001, 0x00100aa6, 0x00000000, 0x00208e46, - 0x00000000, 0x00000006, 0x00100e46, 0x00000001, 0x0a000032, 0x001020f2, - 0x00000000, 0x00100ff6, 0x00000000, 0x00208e46, 0x00000000, 0x00000007, - 0x00100e46, 0x00000001, 0x05000036, 0x00102032, 0x00000001, 0x00101046, - 0x00000001, 0x05000036, 0x001020f2, 0x00000002, 0x00101e46, 0x00000002, - 0x0100003e, 0x54415453, 0x00000074, 0x0000000b, 0x00000002, 0x00000000, - 0x00000006, 0x00000003, 0x00000000, 0x00000000, 0x00000001, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x46454452, 0x000000fc, 0x00000001, 0x00000054, - 0x00000001, 0x0000001c, 0xfffe0400, 0x00000100, 0x000000c6, 0x0000003c, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, - 0x00000001, 0x74726556, 0x68537865, 0x72656461, 0x736e6f43, 0x746e6174, - 0xabab0073, 0x0000003c, 0x00000002, 0x0000006c, 0x00000080, 0x00000000, - 0x00000000, 0x0000009c, 0x00000000, 0x00000040, 0x00000002, 0x000000a4, - 0x00000000, 0x000000b4, 0x00000040, 0x00000040, 0x00000002, 0x000000a4, - 0x00000000, 0x65646f6d, 0xabab006c, 0x00030002, 0x00040004, 0x00000000, - 0x00000000, 0x6a6f7270, 0x69746365, 0x6e416e6f, 0x65695664, 0x694d0077, - 0x736f7263, 0x2074666f, 0x20295228, 0x4c534c48, 0x61685320, 0x20726564, - 0x706d6f43, 0x72656c69, 0x332e3920, 0x32392e30, 0x312e3030, 0x34383336, - 0xababab00, 0x4e475349, 0x00000068, 0x00000003, 0x00000008, 0x00000050, - 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000707, 0x00000059, - 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x00000062, - 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000f0f, 0x49534f50, - 0x4e4f4954, 0x58455400, 0x524f4f43, 0x4f430044, 0x00524f4c, 0x4e47534f, - 0x0000006c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000001, - 0x00000003, 0x00000000, 0x0000000f, 0x0000005c, 0x00000000, 0x00000000, - 0x00000003, 0x00000001, 0x00000c03, 0x00000065, 0x00000000, 0x00000000, - 0x00000003, 0x00000002, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, - 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f -}; -#else -#error "An appropriate vertex shader is not defined." -#endif static struct { const void *shader_data; SIZE_T shader_size; -} D3D11_shaders[NUM_SHADERS] = { +} D3D11_shaders[] = { + { NULL, 0 }, { D3D11_PixelShader_Colors, sizeof(D3D11_PixelShader_Colors) }, { D3D11_PixelShader_Textures, sizeof(D3D11_PixelShader_Textures) }, -#if SDL_HAVE_YUV - { D3D11_PixelShader_YUV_JPEG, sizeof(D3D11_PixelShader_YUV_JPEG) }, - { D3D11_PixelShader_YUV_BT601, sizeof(D3D11_PixelShader_YUV_BT601) }, - { D3D11_PixelShader_YUV_BT709, sizeof(D3D11_PixelShader_YUV_BT709) }, - { D3D11_PixelShader_NV12_JPEG, sizeof(D3D11_PixelShader_NV12_JPEG) }, - { D3D11_PixelShader_NV12_BT601, sizeof(D3D11_PixelShader_NV12_BT601) }, - { D3D11_PixelShader_NV12_BT709, sizeof(D3D11_PixelShader_NV12_BT709) }, - { D3D11_PixelShader_NV21_JPEG, sizeof(D3D11_PixelShader_NV21_JPEG) }, - { D3D11_PixelShader_NV21_BT601, sizeof(D3D11_PixelShader_NV21_BT601) }, - { D3D11_PixelShader_NV21_BT709, sizeof(D3D11_PixelShader_NV21_BT709) }, -#endif + { D3D11_PixelShader_Advanced, sizeof(D3D11_PixelShader_Advanced) }, }; +SDL_COMPILE_TIME_ASSERT(D3D11_shaders, SDL_arraysize(D3D11_shaders) == NUM_SHADERS); int D3D11_CreateVertexShader(ID3D11Device1 *d3dDevice, ID3D11VertexShader **vertexShader, ID3D11InputLayout **inputLayout) { @@ -1905,7 +71,7 @@ int D3D11_CreateVertexShader(ID3D11Device1 *d3dDevice, ID3D11VertexShader **vert const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; HRESULT result; @@ -1947,4 +113,4 @@ int D3D11_CreatePixelShader(ID3D11Device1 *d3dDevice, D3D11_Shader shader, ID3D1 return 0; } -#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */ +#endif /* SDL_VIDEO_RENDER_D3D11 */ diff --git a/src/render/direct3d11/SDL_shaders_d3d11.h b/src/render/direct3d11/SDL_shaders_d3d11.h index 14cbe0e5..53ce2625 100644 --- a/src/render/direct3d11/SDL_shaders_d3d11.h +++ b/src/render/direct3d11/SDL_shaders_d3d11.h @@ -24,19 +24,10 @@ typedef enum { + SHADER_NONE, SHADER_SOLID, SHADER_RGB, -#if SDL_HAVE_YUV - SHADER_YUV_JPEG, - SHADER_YUV_BT601, - SHADER_YUV_BT709, - SHADER_NV12_JPEG, - SHADER_NV12_BT601, - SHADER_NV12_BT709, - SHADER_NV21_JPEG, - SHADER_NV21_BT601, - SHADER_NV21_BT709, -#endif + SHADER_ADVANCED, NUM_SHADERS } D3D11_Shader; diff --git a/src/render/direct3d11/compile_shaders.bat b/src/render/direct3d11/compile_shaders.bat new file mode 100644 index 00000000..51d2a34c --- /dev/null +++ b/src/render/direct3d11/compile_shaders.bat @@ -0,0 +1,4 @@ +fxc /T ps_4_0_level_9_1 /Fh D3D11_PixelShader_Colors.h D3D11_PixelShader_Colors.hlsl +fxc /T ps_4_0_level_9_1 /Fh D3D11_PixelShader_Textures.h D3D11_PixelShader_Textures.hlsl +fxc /T ps_5_0 /Fh D3D11_PixelShader_Advanced.h D3D11_PixelShader_Advanced.hlsl +fxc /T vs_4_0_level_9_1 /Fh D3D11_VertexShader.h D3D11_VertexShader.hlsl diff --git a/src/render/direct3d12/D3D12_PixelShader_Advanced.h b/src/render/direct3d12/D3D12_PixelShader_Advanced.h new file mode 100644 index 00000000..e795a0c5 --- /dev/null +++ b/src/render/direct3d12/D3D12_PixelShader_Advanced.h @@ -0,0 +1,1387 @@ +#if 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Position 0 xyzw 0 POS float +; TEXCOORD 0 xy 1 NONE float xy +; COLOR 0 xyzw 2 NONE float xyzw +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Target 0 xyzw 0 TARGET float xyzw +; +; shader hash: f6874446eaee41c102142c02d5bb3ab7 +; +; Pipeline Runtime Information: +; +; Pixel Shader +; DepthOutput=0 +; SampleFrequency=0 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Position 0 noperspective +; TEXCOORD 0 linear +; COLOR 0 linear +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Target 0 +; +; Buffer Definitions: +; +; cbuffer Constants +; { +; +; struct Constants +; { +; +; float scRGB_output; ; Offset: 0 +; float texture_type; ; Offset: 4 +; float input_type; ; Offset: 8 +; float color_scale; ; Offset: 12 +; float tonemap_method; ; Offset: 16 +; float tonemap_factor1; ; Offset: 20 +; float tonemap_factor2; ; Offset: 24 +; float sdr_white_point; ; Offset: 28 +; float4 Yoffset; ; Offset: 32 +; float4 Rcoeff; ; Offset: 48 +; float4 Gcoeff; ; Offset: 64 +; float4 Bcoeff; ; Offset: 80 +; +; } Constants; ; Offset: 0 Size: 96 +; +; } +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; Constants cbuffer NA NA CB0 cb1 1 +; sampler0 sampler NA NA S0 s0 1 +; texture0 texture f32 2d T0 t0 1 +; texture1 texture f32 2d T1 t1 1 +; texture2 texture f32 2d T2 t2 1 +; +; +; ViewId state: +; +; Number of inputs: 12, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 4, 5, 8 } +; output 1 depends on inputs: { 4, 5, 9 } +; output 2 depends on inputs: { 4, 5, 10 } +; output 3 depends on inputs: { 4, 5, 11 } +; +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.ResRet.f32 = type { float, float, float, float, i32 } +%"class.Texture2D >" = type { <4 x float>, %"class.Texture2D >::mips_type" } +%"class.Texture2D >::mips_type" = type { i32 } +%Constants = type { float, float, float, float, float, float, float, float, <4 x float>, <4 x float>, <4 x float>, <4 x float> } +%struct.SamplerState = type { i32 } + +define void @main() { + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 2, i32 2, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 1, i32 1, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %4 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %5 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 1, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %6 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %7 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %8 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 2, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %9 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 3, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %10 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %11 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %12 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %5, i32 0) ; CBufferLoadLegacy(handle,regIndex) + %13 = extractvalue %dx.types.CBufRet.f32 %12, 1 + %14 = fcmp fast oeq float %13, 0.000000e+00 + br i1 %14, label %114, label %15 + +;