diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 34749a762..167f95900 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,7 +2,7 @@ name: continuous-integration on: [push, pull_request] jobs: - linux-os: + Linux: runs-on: ubuntu-22.04 permissions: checks: write @@ -25,12 +25,12 @@ jobs: libcurl4-openssl-dev libfuse2 wmctrl openbox mesa-vulkan-drivers \ libvulkan1 vulkan-tools vulkan-validationlayers - name: Checkout love-appimage-source - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: love2d/love-appimage-source ref: 12.x - name: Checkout LÖVE - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: love2d-${{ github.sha }} - name: Get Dependencies for AppImage @@ -61,60 +61,63 @@ jobs: - name: Run Test Suite (opengl) run: | chmod a+x love-${{ github.sha }}.AppImage - ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --isRunner + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --all --isRunner - name: Love Test Report (opengl) id: report1 uses: ellraiser/love-test-report@main with: name: Love Testsuite Linux title: test-report-linux-opengl - path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md + path: love2d-${{ github.sha }}/testing/output/lovetest_all.md token: ${{ secrets.GITHUB_TOKEN }} - name: Zip Test Output (opengl) run: | 7z a -tzip test-output-linux-opengl.zip love2d-${{ github.sha }}/testing/output/ - name: Artifact Test Output (opengl) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-output-linux-opengl-${{ steps.report1.outputs.conclusion }} path: test-output-linux-opengl.zip # linux opengles tests - name: Run Test Suite (opengles) + env: + LOVE_GRAPHICS_DEBUG: 1 run: | export LOVE_GRAPHICS_USE_OPENGLES=1 - ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --isRunner + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --all --isRunner - name: Love Test Report (opengles) uses: ellraiser/love-test-report@main id: report2 with: name: Love Testsuite Linux title: test-report-linux-opengles - path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md + path: love2d-${{ github.sha }}/testing/output/lovetest_all.md token: ${{ secrets.GITHUB_TOKEN }} - name: Zip Test Output (opengles) run: | 7z a -tzip test-output-linux-opengles.zip love2d-${{ github.sha }}/testing/output/ - name: Artifact Test Output (opengles) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-output-linux-opengles-${{ steps.report2.outputs.conclusion }} path: test-output-linux-opengles.zip # # linux vulkan tests # - name: Run Test Suite (vulkan) +# env: +# LOVE_GRAPHICS_DEBUG: 1 # run: | -# export LOVE_GRAPHICS_DEBUG=1 -# ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --isRunner --renderers vulkan +# ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --all --isRunner --renderers vulkan # - name: Love Test Report (vulkan) # uses: ellraiser/love-test-report@main # with: # name: Love Testsuite Linux # title: test-report-linux-vulkan -# path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md +# path: love2d-${{ github.sha }}/testing/output/lovetest_all.md # - name: Zip Test Output (vulkan) # run: | # 7z a -tzip test-output-linux-vulkan.zip love2d-${{ github.sha }}/testing/output/ # - name: Artifact Test Output (vulkan) -# uses: actions/upload-artifact@v3 +# uses: actions/upload-artifact@v4 # with: # name: test-output-linux-vulkan # path: test-output-linux-vulkan.zip @@ -125,12 +128,12 @@ jobs: kill $XVFBPID kill $OPENBOXPID - name: Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: love-linux-x86_64.AppImage path: love-${{ github.sha }}.AppImage - name: Artifact Debug Symbols - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: love-x86_64-AppImage-debug path: love-${{ github.sha }}.AppImage-debug.tar.gz @@ -140,7 +143,7 @@ jobs: echo "${{ steps.report1.outputs.failed }} opengl tests failed" echo "${{ steps.report2.outputs.failed }} opengles tests failed" exit 1 - windows-os: + Windows: runs-on: windows-latest permissions: checks: write @@ -202,31 +205,32 @@ jobs: echo nofiles=ignore>> "%GITHUB_OUTPUT%" echo moredef=-DLOVE_EXTRA_DLLS=%CD%\angle\libEGL.dll;%CD%\angle\libGLESv2.dll>> "%GITHUB_OUTPUT%" exit /b 0 - - name: Download Windows SDK Setup 10.0.20348 - run: curl -Lo winsdksetup.exe https://go.microsoft.com/fwlink/?linkid=2164145 - - name: Install Debugging Tools for Windows - id: windbg + - name: Download pdbstr + run: curl -Lfo pdbstr.nupkg https://www.nuget.org/api/v2/package/Microsoft.Debugging.Tools.PdbStr/20230731.1609.0 + - name: Download srctool + run: curl -Lfo srctool.nupkg https://www.nuget.org/api/v2/package/Microsoft.Debugging.Tools.SrcTool/20230731.1609.0 + - name: Extract Tools and Add to PATH run: | - setlocal enabledelayedexpansion - start /WAIT %CD%\winsdksetup.exe /features OptionId.WindowsDesktopDebuggers /q /log %CD%\log.txt - echo ERRORLEVEL=!ERRORLEVEL! >> %GITHUB_OUTPUT% - - name: Print Debugging Tools Install Log - if: always() - run: | - type log.txt - exit /b ${{ steps.windbg.outputs.ERRORLEVEL }} + mkdir debugtools + cd debugtools + if errorlevel 1 exit /b 1 + 7z e ..\srctool.nupkg content/amd64/srctool.exe + if errorlevel 1 exit /b 1 + 7z e ..\pdbstr.nupkg content/amd64/pdbstr.exe + if errorlevel 1 exit /b 1 + echo %CD%>>%GITHUB_PATH% - name: Setup Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" - name: Download source_index.py - run: curl -Lo source_index.py https://gist.github.com/MikuAuahDark/d9c099f5714e09a765496471c2827a55/raw/df34956052035f3473c5f01861dfb53930d06843/source_index.py + run: curl -Lfo source_index.py https://gist.github.com/MikuAuahDark/d9c099f5714e09a765496471c2827a55/raw/df34956052035f3473c5f01861dfb53930d06843/source_index.py - name: Clone Megasource - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: megasource repository: love2d/megasource - ref: 12.x + ref: main - id: megasource name: Get Megasource Commit SHA shell: python @@ -238,11 +242,11 @@ jobs: commit = result.stdout.split()[0] with open(os.environ["GITHUB_OUTPUT"], "w", encoding="UTF-8") as f: f.write(f"commit={commit}") - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: megasource/libs/love - name: Download ANGLE - uses: robinraju/release-downloader@v1.7 + uses: robinraju/release-downloader@v1.9 if: steps.vars.outputs.angle == '1' with: repository: MikuAuahDark/angle-winbuild @@ -255,19 +259,19 @@ jobs: if: steps.vars.outputs.angle == '1' working-directory: angle run: 7z x angle-win-${{ steps.vars.outputs.arch }}.zip - - name: Delete Strawbery Perl + - name: Remove Strawbery Perl From Path # https://github.com/actions/runner-images/issues/6627 # In particular, this is not pretty, but even CMAKE_IGNORE_PREFIX_PATH - # cannot help in this case. Delete the whole folder! + # cannot help in this case. run: | - rmdir /s /q C:\Strawberry + move /y C:\Strawberry C:\Strawberry_not_in_PATH exit /b 0 - name: Configure env: CFLAGS: /Zi CXXFLAGS: /Zi LDFLAGS: /DEBUG:FULL /OPT:REF /OPT:ICF - run: cmake -Bbuild -Smegasource -T v142 -A ${{ matrix.platform }} --install-prefix %CD%\install -DCMAKE_PDB_OUTPUT_DIRECTORY=%CD%\pdb ${{ steps.vars.outputs.moredef }} + run: cmake -Bbuild -Smegasource -T v143 -A ${{ matrix.platform }} --install-prefix %CD%\install -DCMAKE_PDB_OUTPUT_DIRECTORY=%CD%\pdb ${{ steps.vars.outputs.moredef }} - name: Install run: cmake --build build --target PACKAGE --config Release -j2 - name: Copy LuaJIT lua51.pdb @@ -285,7 +289,7 @@ jobs: --source %CD%\build\libs\LuaJIT https://raw.githubusercontent.com/love2d/megasource/${{ steps.megasource.outputs.commit }}/libs/LuaJIT ^ pdb\Release\*.pdb - name: Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }} path: | @@ -294,12 +298,12 @@ jobs: if-no-files-found: ${{ steps.vars.outputs.nofiles }} - name: Artifact JIT Modules if: steps.vars.outputs.jitmodules == '1' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: love-windows-jitmodules path: build/libs/LuaJIT/src/jit/*.lua - name: Artifact PDB - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb @@ -317,10 +321,12 @@ jobs: # windows opengl tests - name: Run Tests (opengl) if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' + env: + LOVE_GRAPHICS_DEBUG: 1 run: | echo 'check dir' ls - powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --isRunner + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --all --isRunner - name: Love Test Report (opengl) id: report1 if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' @@ -328,7 +334,7 @@ jobs: with: name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (opengl) title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl - path: megasource/libs/love/testing/output/lovetest_runAllTests.md + path: megasource/libs/love/testing/output/lovetest_all.md token: ${{ secrets.GITHUB_TOKEN }} - name: Zip Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' @@ -336,16 +342,18 @@ jobs: 7z a -tzip test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl.zip megasource/libs/love/testing/output/ - name: Artifact Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-output-windows-${{ steps.vars.outputs.arch }}-opengl-${{ steps.report1.outputs.conclusion }} path: test-output-windows-${{ steps.vars.outputs.arch }}-opengl.zip # windows opengles tests - name: Run Tests (opengles) if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' + env: + LOVE_GRAPHICS_DEBUG: 1 + LOVE_GRAPHICS_USE_OPENGLES: 1 run: | - $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 - powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --isRunner + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --all --isRunner - name: Love Test Report (opengles) id: report2 if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' @@ -353,7 +361,7 @@ jobs: with: name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (opengles) title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles - path: megasource/libs/love/testing/output/lovetest_runAllTests.md + path: megasource/libs/love/testing/output/lovetest_all.md token: ${{ secrets.GITHUB_TOKEN }} - name: Zip Test Output (opengles) if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' @@ -361,7 +369,7 @@ jobs: 7z a -tzip test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles.zip megasource/libs/love/testing/output/ - name: Artifact Test Output (opengles) if: steps.vars.outputs.arch != 'ARM64' && steps.vars.outputs.compatname != '-compat' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-output-windows-${{ steps.vars.outputs.arch }}-opengles-${{ steps.report2.outputs.conclusion }} path: test-output-windows-${{ steps.vars.outputs.arch }}-opengles.zip @@ -387,23 +395,24 @@ jobs: # # windows vulkan tests # - name: Run Tests (vulkan) # if: steps.vars.outputs.arch != 'ARM64' +# env: +# LOVE_GRAPHICS_DEBUG: 1 # run: | -# $ENV:LOVE_GRAPHICS_DEBUG=1 -# powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --isRunner --renderers vulkan +# powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --all --isRunner --renderers vulkan # - name: Love Test Report (vulkan) # if: steps.vars.outputs.arch != 'ARM64' # uses: ellraiser/love-test-report@main # with: # name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (vulkan) # title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan -# path: megasource/libs/love/testing/output/lovetest_runAllTests.md +# path: megasource/libs/love/testing/output/lovetest_all.md # - name: Zip Test Output (vulkan) # if: steps.vars.outputs.arch != 'ARM64' # run: | # 7z a -tzip test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan.zip megasource/libs/love/testing/output/ # - name: Artifact Test Output (vulkan) # if: steps.vars.outputs.arch != 'ARM64' -# uses: actions/upload-artifact@v3 +# uses: actions/upload-artifact@v4 # with: # name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan # path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan.zip @@ -414,9 +423,9 @@ jobs: pull-requests: write steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Clone Dependencies - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: apple-dependencies repository: love2d/love-apple-dependencies @@ -434,28 +443,30 @@ jobs: run: ditto -c -k --sequesterRsrc --keepParent love-macos/love.app love-macos.zip - name: Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: love-macos path: love-macos.zip # macos opengl tests (metal not supported on runners) - name: Run Test Suite + env: + LOVE_GRAPHICS_DEBUG: 1 run: | ls - love-macos/love.app/Contents/MacOS/love ./testing/main.lua --runAllTests --isRunner + love-macos/love.app/Contents/MacOS/love ./testing/main.lua --all --isRunner - name: Love Test Report id: report1 uses: ellraiser/love-test-report@main with: name: Love Testsuite MacOS title: test-report-macos - path: testing/output/lovetest_runAllTests.md + path: testing/output/lovetest_all.md token: ${{ secrets.GITHUB_TOKEN }} - name: Zip Test Output run: | 7z a -tzip test-output-macos-opengl.zip ./testing/output/ - name: Artifact Test Output - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-output-macos-opengl-${{ steps.report1.outputs.conclusion }} path: test-output-macos-opengl.zip @@ -468,9 +479,9 @@ jobs: runs-on: macos-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Clone Dependencies - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: apple-dependencies repository: love2d/love-apple-dependencies @@ -481,3 +492,76 @@ jobs: - name: Build run: xcodebuild -project platform/xcode/love.xcodeproj -scheme love-ios -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11' + Android: + runs-on: ubuntu-latest + strategy: + matrix: + build_type: [Debug, Release] + env: + GRADLE_OPTS: "-Dorg.gradle.jvmargs='-Xmx4G'" + steps: + - name: Prepare Environment + run: sudo apt-get update && curl -Lfo kitware-archive.sh https://apt.kitware.com/kitware-archive.sh && sudo bash ./kitware-archive.sh + - name: Install Dependencies + run: sudo apt-get install ninja-build cmake + - name: Checkout love-android + uses: actions/checkout@v4 + with: + repository: love2d/love-android + submodules: false + - name: Setup Java 17 + uses: actions/setup-java@v4 + with: + distribution: adopt-hotspot + java-version: 17 + cache: gradle + - name: Clone Megasource + uses: actions/checkout@v4 + with: + path: app/src/main/cpp/megasource + repository: love2d/megasource + ref: main + - name: Checkout + uses: actions/checkout@v4 + with: + path: app/src/main/cpp/love + - name: Build Normal Flavor + run: bash ./gradlew assembleNormalRecord${{ matrix.build_type }} + - name: Build Release-specific Binaries + if: ${{ matrix.build_type == 'Release' }} + run: bash ./gradlew bundleNormalNoRecordRelease bundleEmbedRecordRelease bundleEmbedNoRecordRelease + - name: Artifact (Normal debug APK) + if: ${{ matrix.build_type == 'Debug' }} + uses: actions/upload-artifact@v4 + with: + name: love-android-debug.apk + path: app/build/outputs/apk/normalRecord/debug/app-normal-record-debug.apk + - name: Artifact (Normal unsigned APK) + if: ${{ matrix.build_type == 'Release' }} + uses: actions/upload-artifact@v4 + with: + name: love-android.apk + path: app/build/outputs/apk/normalRecord/release/app-normal-record-release-unsigned.apk + - name: Artifact (Normal AAB w/o recording) + if: ${{ matrix.build_type == 'Release' }} + uses: actions/upload-artifact@v4 + with: + name: love-android-ps.aab + path: app/build/outputs/bundle/normalNoRecordRelease/app-normal-noRecord-release.aab + - name: Artifact (Embed AAB) + if: ${{ matrix.build_type == 'Release' }} + uses: actions/upload-artifact@v4 + with: + name: love-android-embed-record.aab + path: app/build/outputs/bundle/embedRecordRelease/app-embed-record-release.aab + - name: Artifact (Embed AAB w/o recording) + if: ${{ matrix.build_type == 'Release' }} + uses: actions/upload-artifact@v4 + with: + name: love-android-embed.aab + path: app/build/outputs/bundle/embedNoRecordRelease/app-embed-noRecord-release.aab + - name: Artifact (Debug symbols) + uses: actions/upload-artifact@v4 + with: + name: love-android-unstripped-debugsyms-${{ matrix.build_type }} + path: app/build/intermediates/cxx diff --git a/.gitignore b/.gitignore index 3f5288d45..2721f6963 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ stamp-h1 /testing/output/*.html /testing/output/*.md /testing/output/actual/*.png +/testing/output/difference/*.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e9494965..fc463561c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2006-2023 LOVE Development Team +# Copyright (c) 2006-2024 LOVE Development Team # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages @@ -60,7 +60,7 @@ else() endif() -if(APPLE OR MEGA_ARM64) +if(APPLE) set(LOVE_DEFAULT_JIT FALSE) else() set(LOVE_DEFAULT_JIT TRUE) diff --git a/changes.txt b/changes.txt index 83966c68f..359a4cb34 100644 --- a/changes.txt +++ b/changes.txt @@ -101,6 +101,7 @@ Released: N/A * Changed RevoluteJoint:getMotorTorque and WheelJoint:getMotorTorque to take 'dt' as a parameter instead of 'inverse_dt'. * Changed love.math.perlinNoise and simplexNoise to use higher precision numbers for its internal calculations. * Changed t.accelerometerjoystick startup flag in love.conf to unset by default. +* Changed love.data.hash to take in a container type. * Renamed 'display' field to 'displayindex' in love.window.setMode/updateMode/getMode and love.conf. * Renamed love.graphics Text objects to TextBatch. @@ -120,6 +121,7 @@ Released: N/A * Deprecated t.accelerometerjoystick in love.conf (replaced by love.sensor module). * Deprecated the variants of Mesh:attachAttribute and SpriteBatch:attachAttribute which accept a Mesh (replaced by variants which accept a Buffer). * Deprecated Texture:newImageData (replaced by love.graphics.readbackTexture). +* Deprecated love.data.hash (replaced by function variant, which takes container type). * Removed the variant of SpriteBatch:setColor() which turns off all previously set colors. * Removed the no-argument variant of love.graphics.setColorMask. diff --git a/extra/windows/love.rc b/extra/windows/love.rc index f7e150a58..fd42991c2 100644 Binary files a/extra/windows/love.rc and b/extra/windows/love.rc differ diff --git a/license.txt b/license.txt index a430dab12..f8d51334e 100644 --- a/license.txt +++ b/license.txt @@ -6,7 +6,7 @@ This distribution contains code from the following projects (full license text b - LOVE Website: https://love2d.org/ License: zlib - Copyright (c) 2006-2023 LOVE Development Team + Copyright (c) 2006-2024 LOVE Development Team - ENet Website: http://enet.bespin.org/index.html diff --git a/platform/xcode/macosx/love-macosx.plist b/platform/xcode/macosx/love-macosx.plist index 197188f38..e11e7e3dd 100644 --- a/platform/xcode/macosx/love-macosx.plist +++ b/platform/xcode/macosx/love-macosx.plist @@ -70,7 +70,7 @@ NSHighResolutionCapable NSHumanReadableCopyright - © 2006-2023 LÖVE Development Team + © 2006-2024 LÖVE Development Team NSPrincipalClass NSApplication NSSupportsAutomaticGraphicsSwitching diff --git a/readme.md b/readme.md index 13947320e..cf11f6f80 100644 --- a/readme.md +++ b/readme.md @@ -11,12 +11,13 @@ If you need further help, feel free to ask on our [forums][forums], our [Discord Repository ---------- -We use the 'main' branch for patch development of the current major release, and therefore it should not be considered stable. -There may also be a branch for the next major version in development, which is named after that version. +We use the 'main' branch for development of the next major release, and therefore it should not be considered stable. + +There are also branches for currently released major versions, which may have fixes and changes meant for upcoming patch releases within that major version. We tag all our releases (since we started using mercurial and git), and have binary downloads available for them. -Experimental changes are developed in a separate [love-experiments][love-experiments] repository. +Experimental changes are sometimes developed in a separate [love-experiments][love-experiments] repository. Builds ------ @@ -32,12 +33,11 @@ There are also unstable/nightly builds: Test Suite ---------- -The test suite in `testing/` covers all the LÖVE APIs, and tests them the same way developers use them. You can view current test coverage from any [12.0-dev action][12devworkflows]. -You can run the suite locally like you would run a normal LÖVE project, i.e.: -`love testing/main.lua` +The test suite in `testing/` covers all the LÖVE APIs, and tests them the same way developers use them. You can view current test coverage from any [action][workflows]. +You can run the suite locally like you would run a normal LÖVE project, e.g.: +`love testing` See the [readme][testsuite] in the testing folder for more info. -You can contribute to the test suite [here][testsuitemain] Contributing ------------ @@ -70,7 +70,6 @@ Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the ### iOS Building for iOS requires macOS and Xcode. -#### LÖVE 11.4 and newer Download the `love-apple-dependencies` zip file corresponding to the LÖVE version being used from the [Releases page][dependencies-ios], unzip it, and place the `iOS/libraries` subfolder into love's `platform/xcode/ios` folder. @@ -80,14 +79,6 @@ Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the See `readme-iOS.rtf` for more information. -#### LÖVE 11.3 and older -Download the `ios-libraries` zip file corresponding to the LÖVE version being used from the [Releases page][dependencies-ios], -unzip it, and place the `include` and `libraries` subfolders into love's `platform/xcode/ios` folder. - -Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the `love-ios` target. - -See `readme-iOS.rtf` for more information. - ### Android Visit the [Android build repository][android-repository] for build instructions. @@ -117,6 +108,5 @@ Dependencies [codestyle]: https://love2d.org/wiki/Code_Style [android-repository]: https://github.com/love2d/love-android [releases]: https://github.com/love2d/love/releases -[testsuite]: https://github.com/love2d/love/tree/12.0-development/testing -[testsuitemain]: https://github.com/ellraiser/love-test -[12devworkflows]: https://github.com/love2d/love/actions/workflows/main.yml?query=branch%3A12.0-development +[testsuite]: https://github.com/love2d/love/tree/main/testing +[workflows]: https://github.com/love2d/love/actions/workflows/main.yml?query=branch%3Amain diff --git a/src/common/Color.h b/src/common/Color.h index dcd4f3c0e..1518553d7 100644 --- a/src/common/Color.h +++ b/src/common/Color.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Data.cpp b/src/common/Data.cpp index 8b31599f4..d3f7bdd6d 100644 --- a/src/common/Data.cpp +++ b/src/common/Data.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,10 +20,27 @@ // LOVE #include "Data.h" +#include "thread/threads.h" namespace love { love::Type Data::type("Data", &Object::type); +Data::~Data() +{ + delete mutex; +} + +static void createMutex(love::thread::Mutex **mutexAddress) +{ + *mutexAddress = love::thread::newMutex(); +} + +love::thread::Mutex *Data::getMutex() +{ + std::call_once(mutexCreated, createMutex, &mutex); + return mutex; +} + } // love diff --git a/src/common/Data.h b/src/common/Data.h index 57ffa4b14..bb19b66cb 100644 --- a/src/common/Data.h +++ b/src/common/Data.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -22,15 +22,20 @@ #define LOVE_DATA_H // LOVE -#include "config.h" #include "Object.h" // C #include +#include namespace love { +namespace thread +{ +class Mutex; +} + /** * This class is a simple abstraction over all objects which contain data. **/ @@ -40,10 +45,8 @@ public: static love::Type type; - /** - * Destructor. - **/ - virtual ~Data() {} + Data() {}; + virtual ~Data(); /** * Creates a duplicate of Data derived class instance. @@ -60,6 +63,17 @@ public: **/ virtual size_t getSize() const = 0; + /** + * Gets the Mutex associated with this Data object. Creates it in a thread- + * safe manner if necessary. + **/ + love::thread::Mutex *getMutex(); + +private: + + love::thread::Mutex *mutex = nullptr; + std::once_flag mutexCreated; + }; // Data } // love diff --git a/src/common/EnumMap.h b/src/common/EnumMap.h index 118cf389d..4a1bdd3d0 100644 --- a/src/common/EnumMap.h +++ b/src/common/EnumMap.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Exception.cpp b/src/common/Exception.cpp index eb240e381..f605d08da 100644 --- a/src/common/Exception.cpp +++ b/src/common/Exception.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Exception.h b/src/common/Exception.h index d42c5d180..28942d069 100644 --- a/src/common/Exception.h +++ b/src/common/Exception.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Matrix.cpp b/src/common/Matrix.cpp index e4f57a3d9..fa5e95757 100644 --- a/src/common/Matrix.cpp +++ b/src/common/Matrix.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Matrix.h b/src/common/Matrix.h index 4c7fe5d39..83b607839 100644 --- a/src/common/Matrix.h +++ b/src/common/Matrix.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Module.cpp b/src/common/Module.cpp index f82aad662..6c168df1e 100644 --- a/src/common/Module.cpp +++ b/src/common/Module.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -62,9 +62,12 @@ namespace love love::Type Module::type("Module", &Object::type); Module *Module::instances[] = {}; -Module::Module() +Module::Module(Module::ModuleType moduleType, const char *name) + : moduleType(moduleType) + , name(name) { initDeprecation(); + registerInstance(this); } Module::~Module() diff --git a/src/common/Module.h b/src/common/Module.h index 603c0e0c2..77e95d565 100644 --- a/src/common/Module.h +++ b/src/common/Module.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -62,13 +62,13 @@ public: M_MAX_ENUM }; - Module(); + Module(ModuleType moduleType, const char *name); virtual ~Module(); /** * Gets the base type of the module. **/ - virtual ModuleType getModuleType() const = 0; + ModuleType getModuleType() const { return moduleType; } /** * Gets the name of the module. This is used in case of errors @@ -76,14 +76,7 @@ public: * * @return The full name of the module, eg. love.graphics.opengl. **/ - virtual const char *getName() const = 0; - - /** - * Add module to internal registry. To be used /only/ in - * runtime.cpp:luax_register_module() - * @param instance The module instance. - */ - static void registerInstance(Module *instance); + const char *getName() const { return name.c_str(); } /** * Retrieve module instance from internal registry. May return NULL @@ -106,6 +99,11 @@ public: private: + static void registerInstance(Module *instance); + + ModuleType moduleType; + std::string name; + static Module *instances[M_MAX_ENUM]; }; // Module diff --git a/src/common/Object.cpp b/src/common/Object.cpp index 8d2bc4027..a8bb7fe85 100644 --- a/src/common/Object.cpp +++ b/src/common/Object.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Object.h b/src/common/Object.h index 805f5c0b6..36b8f7a8c 100644 --- a/src/common/Object.h +++ b/src/common/Object.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Optional.h b/src/common/Optional.h index d0fc11ea9..5a3c347b0 100644 --- a/src/common/Optional.h +++ b/src/common/Optional.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Range.h b/src/common/Range.h index 4a2b27a0d..14e274f59 100644 --- a/src/common/Range.h +++ b/src/common/Range.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -61,7 +61,7 @@ struct Range return first <= other.first && last >= other.last; } - bool intersects(const Range &other) + bool intersects(const Range &other) const { return !(first > other.last || last < other.first); } diff --git a/src/common/Reference.cpp b/src/common/Reference.cpp index 54e42e67f..37e6113d6 100644 --- a/src/common/Reference.cpp +++ b/src/common/Reference.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Reference.h b/src/common/Reference.h index 512ba9a51..28d218b90 100644 --- a/src/common/Reference.h +++ b/src/common/Reference.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Stream.cpp b/src/common/Stream.cpp index deffefe93..00b4ab005 100644 --- a/src/common/Stream.cpp +++ b/src/common/Stream.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Stream.h b/src/common/Stream.h index 6b75be7c1..6e4b36553 100644 --- a/src/common/Stream.h +++ b/src/common/Stream.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/StringMap.cpp b/src/common/StringMap.cpp index 0c018bf40..4d6169e1e 100644 --- a/src/common/StringMap.cpp +++ b/src/common/StringMap.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/StringMap.h b/src/common/StringMap.h index 49c1a06ac..1260249f2 100644 --- a/src/common/StringMap.h +++ b/src/common/StringMap.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Variant.cpp b/src/common/Variant.cpp index e75f765b1..8684b9c48 100644 --- a/src/common/Variant.cpp +++ b/src/common/Variant.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Variant.h b/src/common/Variant.h index 45e9fd6b2..e2c274515 100644 --- a/src/common/Variant.h +++ b/src/common/Variant.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Vector.cpp b/src/common/Vector.cpp index 1870b6a58..890528123 100644 --- a/src/common/Vector.cpp +++ b/src/common/Vector.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/Vector.h b/src/common/Vector.h index d0821679b..e74ad2441 100644 --- a/src/common/Vector.h +++ b/src/common/Vector.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/android.cpp b/src/common/android.cpp index 266793594..1ec823536 100644 --- a/src/common/android.cpp +++ b/src/common/android.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -385,18 +385,20 @@ struct AssetInfo: public love::filesystem::physfs::PhysfsIo return 1; } - AssetInfo *duplicate() const + AssetInfo(const AssetInfo &other) + : assetManager(other.assetManager) + , size(strlen(other.filename) + 1) { - AAsset *newAsset = AAssetManager_open(assetManager, filename, AASSET_MODE_RANDOM); + asset = AAssetManager_open(assetManager, other.filename, AASSET_MODE_RANDOM); - if (newAsset == nullptr) + if (asset == nullptr) { PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); - return nullptr; + throw new love::Exception("Unable to duplicate AssetInfo"); } - AAsset_seek64(asset, tell(), SEEK_SET); - return fromAAsset(assetManager, filename, asset); + filename = new (std::nothrow) char[size]; + memcpy(filename, other.filename, size); } ~AssetInfo() override diff --git a/src/common/android.h b/src/common/android.h index db7fd5fe2..1969d3bd4 100644 --- a/src/common/android.h +++ b/src/common/android.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/apple.h b/src/common/apple.h index c41681c39..5855a9636 100644 --- a/src/common/apple.h +++ b/src/common/apple.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/apple.mm b/src/common/apple.mm index 7025085ee..0d0dd0444 100644 --- a/src/common/apple.mm +++ b/src/common/apple.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/b64.cpp b/src/common/b64.cpp index ff196cd88..57ce775b1 100644 --- a/src/common/b64.cpp +++ b/src/common/b64.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/b64.h b/src/common/b64.h index a748a0de5..471650de5 100644 --- a/src/common/b64.h +++ b/src/common/b64.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/config.h b/src/common/config.h index 7d9d8a4c9..11ede38c9 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/delay.cpp b/src/common/delay.cpp index ee35559df..e6b0c43a4 100644 --- a/src/common/delay.cpp +++ b/src/common/delay.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/delay.h b/src/common/delay.h index 98976485c..1f8122e8d 100644 --- a/src/common/delay.h +++ b/src/common/delay.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/deprecation.cpp b/src/common/deprecation.cpp index 84f1b264f..e68e1a27d 100644 --- a/src/common/deprecation.cpp +++ b/src/common/deprecation.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/deprecation.h b/src/common/deprecation.h index 55b0e89e2..a7154777d 100644 --- a/src/common/deprecation.h +++ b/src/common/deprecation.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/floattypes.cpp b/src/common/floattypes.cpp index a387e1cbb..ae30462bb 100644 --- a/src/common/floattypes.cpp +++ b/src/common/floattypes.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/floattypes.h b/src/common/floattypes.h index 79938eab1..7572c06ac 100644 --- a/src/common/floattypes.h +++ b/src/common/floattypes.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/int.h b/src/common/int.h index 11a413607..8700eee9e 100644 --- a/src/common/int.h +++ b/src/common/int.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/ios.h b/src/common/ios.h index 8066aa983..7e6e0685b 100644 --- a/src/common/ios.h +++ b/src/common/ios.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/ios.mm b/src/common/ios.mm index 99639a899..4d5065aac 100644 --- a/src/common/ios.mm +++ b/src/common/ios.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/macos.h b/src/common/macos.h index f3697f616..f8f67395f 100644 --- a/src/common/macos.h +++ b/src/common/macos.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/macos.mm b/src/common/macos.mm index f63925b55..bdb980490 100644 --- a/src/common/macos.mm +++ b/src/common/macos.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/math.h b/src/common/math.h index 50ff5ad8a..5f2b5e7a9 100644 --- a/src/common/math.h +++ b/src/common/math.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/memory.cpp b/src/common/memory.cpp index 81afca87b..6d883002f 100644 --- a/src/common/memory.cpp +++ b/src/common/memory.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/memory.h b/src/common/memory.h index 924b5e5f9..97cf456a8 100644 --- a/src/common/memory.h +++ b/src/common/memory.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index ce8a3a690..205694d01 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -342,6 +342,10 @@ PixelFormat getSRGBPixelFormat(PixelFormat format) { case PIXELFORMAT_RGBA8_UNORM: return PIXELFORMAT_RGBA8_sRGB; case PIXELFORMAT_BGRA8_UNORM: return PIXELFORMAT_BGRA8_sRGB; + case PIXELFORMAT_DXT1_UNORM: return PIXELFORMAT_DXT1_sRGB; + case PIXELFORMAT_DXT3_UNORM: return PIXELFORMAT_DXT3_sRGB; + case PIXELFORMAT_DXT5_UNORM: return PIXELFORMAT_DXT5_sRGB; + case PIXELFORMAT_BC7_UNORM: return PIXELFORMAT_BC7_sRGB; case PIXELFORMAT_PVR1_RGB2_UNORM: return PIXELFORMAT_PVR1_RGB2_sRGB; case PIXELFORMAT_PVR1_RGB4_UNORM: return PIXELFORMAT_PVR1_RGB4_sRGB; case PIXELFORMAT_PVR1_RGBA2_UNORM: return PIXELFORMAT_PVR1_RGBA2_sRGB; @@ -374,6 +378,10 @@ PixelFormat getLinearPixelFormat(PixelFormat format) { case PIXELFORMAT_RGBA8_sRGB: return PIXELFORMAT_RGBA8_UNORM; case PIXELFORMAT_BGRA8_sRGB: return PIXELFORMAT_BGRA8_UNORM; + case PIXELFORMAT_DXT1_sRGB: return PIXELFORMAT_DXT1_UNORM; + case PIXELFORMAT_DXT3_sRGB: return PIXELFORMAT_DXT3_UNORM; + case PIXELFORMAT_DXT5_sRGB: return PIXELFORMAT_DXT5_UNORM; + case PIXELFORMAT_BC7_sRGB: return PIXELFORMAT_BC7_UNORM; case PIXELFORMAT_PVR1_RGB2_sRGB: return PIXELFORMAT_PVR1_RGB2_UNORM; case PIXELFORMAT_PVR1_RGB4_sRGB: return PIXELFORMAT_PVR1_RGB4_UNORM; case PIXELFORMAT_PVR1_RGBA2_sRGB: return PIXELFORMAT_PVR1_RGBA2_UNORM; diff --git a/src/common/pixelformat.h b/src/common/pixelformat.h index b928f92d7..37ddc93e6 100644 --- a/src/common/pixelformat.h +++ b/src/common/pixelformat.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index 633da62a1..d9f2570dc 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -473,9 +473,6 @@ int luax_register_module(lua_State *L, const WrappedModule &m) lua_setfield(L, -3, m.name); // love.graphics = table lua_remove(L, -2); // love - // Register module instance - Module::registerInstance(m.module); - return 1; } diff --git a/src/common/runtime.h b/src/common/runtime.h index a851de2fd..747c38e86 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -629,22 +629,29 @@ T *luax_optmodule(lua_State *L) } /** - * Converts the value at idx to the specified type without checking that - * this conversion is valid. If the type has been previously verified with - * luax_istype, then this can be safely used. Otherwise, use luax_checktype. + * Converts the value at idx to the specified type. Returns null if the type + * doesn't match. * @param L The Lua state. * @param idx The index on the stack. * @param type The type of the object. **/ template -T *luax_totype(lua_State *L, int idx, const love::Type& /*type*/) +T *luax_totype(lua_State *L, int idx, const love::Type &type) { - T *o = (T *)(((Proxy *)lua_touserdata(L, idx))->object); + if (lua_type(L, idx) != LUA_TUSERDATA) + return nullptr; - if (o == nullptr) - luaL_error(L, "Cannot use object after it has been released."); + Proxy *p = (Proxy *) lua_touserdata(L, idx); - return o; + if (p->type != nullptr && p->type->isa(type)) + { + if (p->object == nullptr) + luaL_error(L, "Cannot use object after it has been released."); + + return (T *) p->object; + } + + return nullptr; } template diff --git a/src/common/types.cpp b/src/common/types.cpp index d188321f7..69a4f703d 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/types.h b/src/common/types.h index d9948b984..536bc0590 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/utf8.cpp b/src/common/utf8.cpp index dfc1909f6..20daa9bc7 100644 --- a/src/common/utf8.cpp +++ b/src/common/utf8.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/utf8.h b/src/common/utf8.h index ff17ac1c2..fc5bcfbb3 100644 --- a/src/common/utf8.h +++ b/src/common/utf8.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/common/version.h b/src/common/version.h index aa34b0117..72742ba10 100644 --- a/src/common/version.h +++ b/src/common/version.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/ddsparse/ddsinfo.h b/src/libraries/ddsparse/ddsinfo.h index 929a13b92..81c1b98fd 100644 --- a/src/libraries/ddsparse/ddsinfo.h +++ b/src/libraries/ddsparse/ddsinfo.h @@ -1,7 +1,7 @@ /** * Simple DDS data parser for compressed 2D textures. * - * Copyright (c) 2013-2023 Sasha Szpakowski + * Copyright (c) 2013-2024 Sasha Szpakowski * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/ddsparse/ddsparse.cpp b/src/libraries/ddsparse/ddsparse.cpp index 59d770aa7..5827ceeb9 100644 --- a/src/libraries/ddsparse/ddsparse.cpp +++ b/src/libraries/ddsparse/ddsparse.cpp @@ -1,7 +1,7 @@ /** * Simple DDS data parser for compressed 2D textures. * - * Copyright (c) 2013-2023 Sasha Szpakowski + * Copyright (c) 2013-2024 Sasha Szpakowski * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/ddsparse/ddsparse.h b/src/libraries/ddsparse/ddsparse.h index 17d8b7f38..8b9544a2e 100644 --- a/src/libraries/ddsparse/ddsparse.h +++ b/src/libraries/ddsparse/ddsparse.h @@ -1,7 +1,7 @@ /** * Simple DDS data parser for compressed 2D textures. * - * Copyright (c) 2013-2023 Sasha Szpakowski + * Copyright (c) 2013-2024 Sasha Szpakowski * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/enet/lua-enet.h b/src/libraries/enet/lua-enet.h index 2112c8dd5..b2fe08152 100644 --- a/src/libraries/enet/lua-enet.h +++ b/src/libraries/enet/lua-enet.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2006-2023 LOVE Development Team +* Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/ftp.lua.h b/src/libraries/luasocket/libluasocket/ftp.lua.h index affb67c4f..6d6b2cfa0 100644 --- a/src/libraries/luasocket/libluasocket/ftp.lua.h +++ b/src/libraries/luasocket/libluasocket/ftp.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/headers.lua.h b/src/libraries/luasocket/libluasocket/headers.lua.h index b09fafa6d..7764f796d 100644 --- a/src/libraries/luasocket/libluasocket/headers.lua.h +++ b/src/libraries/luasocket/libluasocket/headers.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/http.lua b/src/libraries/luasocket/libluasocket/http.lua index 1330355f4..259eb2b5d 100644 --- a/src/libraries/luasocket/libluasocket/http.lua +++ b/src/libraries/luasocket/libluasocket/http.lua @@ -54,7 +54,7 @@ local function receiveheaders(sock, headers) while line ~= "" do -- get field-name and value name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) - if not (name and value) then return nil, "malformed reponse headers" end + if not (name and value) then return nil, "malformed response headers" end name = string.lower(name) -- get next line (value might be folded) line, err = sock:receive() @@ -62,7 +62,7 @@ local function receiveheaders(sock, headers) -- unfold any folded values while string.find(line, "^%s") do value = value .. line - line = sock:receive() + line, err = sock:receive() if err then return nil, err end end -- save pair in table @@ -81,7 +81,7 @@ socket.sourcet["http-chunked"] = function(sock, headers) dirty = function() return sock:dirty() end }, { __call = function() - -- get chunk size, skip extention + -- get chunk size, skip extension local line, err = sock:receive() if err then return nil, err end local size = base.tonumber(string.gsub(line, ";.*", ""), 16) @@ -219,9 +219,11 @@ local function adjustproxy(reqt) local proxy = reqt.proxy or _M.PROXY if proxy then proxy = url.parse(proxy) - return proxy.host, proxy.port or 3128 + proxy.port = proxy.port or 3128 + proxy.create = SCHEMES[proxy.scheme].create(reqt) + return proxy.host, proxy.port, proxy.create else - return reqt.host, reqt.port + return reqt.host, reqt.port, reqt.create end end @@ -279,7 +281,7 @@ local function adjustrequest(reqt) if not (host and host ~= "") then socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") end - -- compute uri if user hasn't overriden + -- compute uri if user hasn't overridden nreqt.uri = reqt.uri or adjusturi(nreqt) -- adjust headers in request nreqt.headers = adjustheaders(nreqt) @@ -291,7 +293,10 @@ local function adjustrequest(reqt) end -- ajust host and port if there is a proxy - nreqt.host, nreqt.port = adjustproxy(nreqt) + local proxy_create + nreqt.host, nreqt.port, proxy_create = adjustproxy(nreqt) + if not reqt.create then nreqt.create = proxy_create end + return nreqt end @@ -300,6 +305,8 @@ local function shouldredirect(reqt, code, headers) if not location then return false end location = string.gsub(location, "%s", "") if location == "" then return false end + -- the RFC says the redirect URL may be relative + location = url.absolute(reqt.url, location) local scheme = url.parse(location).scheme if scheme and (not SCHEMES[scheme]) then return false end -- avoid https downgrades @@ -323,8 +330,7 @@ end local trequest, tredirect --[[local]] function tredirect(reqt, location) - -- the RFC says the redirect URL has to be absolute, but some - -- servers do not respect that + -- the RFC says the redirect URL may be relative local newurl = url.absolute(reqt.url, location) -- if switching schemes, reset port and create function if url.parse(newurl).scheme ~= reqt.scheme then diff --git a/src/libraries/luasocket/libluasocket/http.lua.h b/src/libraries/luasocket/libluasocket/http.lua.h index 2807690a0..70620ec39 100644 --- a/src/libraries/luasocket/libluasocket/http.lua.h +++ b/src/libraries/luasocket/libluasocket/http.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -167,8 +167,8 @@ const unsigned char http_lua[] = 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x22, 0x6d, 0x61, 0x6c, 0x66, - 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x22, 0x20, 0x65, 0x6e, 0x64, 0x0a, + 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x73, 0x22, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6e, 0x65, 0x78, @@ -186,8 +186,9 @@ const unsigned char http_lua[] = 0x22, 0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x3d, - 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x29, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2c, 0x20, + 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x65, 0x72, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x20, 0x65, 0x6e, 0x64, 0x0a, @@ -235,7 +236,7 @@ const unsigned char http_lua[] = 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x67, 0x65, 0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x6b, 0x69, 0x70, 0x20, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x0a, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x28, 0x29, 0x0a, @@ -570,12 +571,20 @@ const unsigned char http_lua[] = 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x3d, 0x20, 0x75, 0x72, 0x6c, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x29, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x70, 0x6f, 0x72, 0x74, + 0x20, 0x3d, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x33, + 0x31, 0x32, 0x38, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x20, 0x3d, 0x20, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x45, 0x53, 0x5b, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x5d, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28, 0x72, 0x65, + 0x71, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x70, 0x6f, 0x72, - 0x74, 0x20, 0x6f, 0x72, 0x20, 0x33, 0x31, 0x32, 0x38, 0x0a, + 0x74, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x71, - 0x74, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x2c, 0x20, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x0a, + 0x74, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x2c, 0x20, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x2c, + 0x20, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, @@ -710,7 +719,7 @@ const unsigned char http_lua[] = 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x20, 0x75, 0x72, 0x69, 0x20, 0x69, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x68, 0x61, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x6f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x0a, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x75, 0x72, 0x69, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x75, 0x72, 0x69, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x75, 0x72, 0x69, 0x28, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x29, 0x0a, @@ -736,9 +745,17 @@ const unsigned char http_lua[] = 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x61, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x2c, 0x20, 0x6e, 0x72, - 0x65, 0x71, 0x74, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x28, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x29, 0x0a, + 0x65, 0x71, 0x74, 0x2e, 0x70, 0x6f, 0x72, 0x74, 0x2c, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x28, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x29, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x72, 0x65, 0x71, 0x74, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, @@ -757,6 +774,12 @@ const unsigned char http_lua[] = 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x46, 0x43, 0x20, 0x73, 0x61, 0x79, + 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x55, 0x52, 0x4c, + 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x75, 0x72, 0x6c, + 0x2e, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x28, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x75, 0x72, 0x6c, + 0x2c, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x75, 0x72, 0x6c, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x0a, @@ -820,10 +843,7 @@ const unsigned char http_lua[] = 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x46, 0x43, 0x20, 0x73, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x55, 0x52, 0x4c, - 0x20, 0x68, 0x61, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, - 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x20, 0x64, 0x6f, 0x20, - 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, + 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x65, 0x77, 0x75, 0x72, 0x6c, 0x20, 0x3d, 0x20, 0x75, 0x72, 0x6c, 0x2e, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x28, 0x72, 0x65, 0x71, 0x74, 0x2e, 0x75, 0x72, 0x6c, 0x2c, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0a, diff --git a/src/libraries/luasocket/libluasocket/inet.c b/src/libraries/luasocket/libluasocket/inet.c index 138c9abe8..afef5f45b 100644 --- a/src/libraries/luasocket/libluasocket/inet.c +++ b/src/libraries/luasocket/libluasocket/inet.c @@ -290,7 +290,7 @@ int inet_meth_getsockname(lua_State *L, p_socket ps, int family) return 2; } lua_pushstring(L, name); - lua_pushstring(L, port); + lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); switch (family) { case AF_INET: lua_pushliteral(L, "inet"); break; case AF_INET6: lua_pushliteral(L, "inet6"); break; diff --git a/src/libraries/luasocket/libluasocket/ltn12.lua.h b/src/libraries/luasocket/libluasocket/ltn12.lua.h index 659ad726c..46a417b64 100644 --- a/src/libraries/luasocket/libluasocket/ltn12.lua.h +++ b/src/libraries/luasocket/libluasocket/ltn12.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/luasocket.h b/src/libraries/luasocket/libluasocket/luasocket.h index 1017fbaab..1e3d3588c 100644 --- a/src/libraries/luasocket/libluasocket/luasocket.h +++ b/src/libraries/luasocket/libluasocket/luasocket.h @@ -10,7 +10,7 @@ /*-------------------------------------------------------------------------* \ * Current socket library version \*-------------------------------------------------------------------------*/ -#define LUASOCKET_VERSION "LuaSocket 3.0.0" +#define LUASOCKET_VERSION "LuaSocket 3.1.0" #define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2013 Diego Nehab" /*-------------------------------------------------------------------------*\ diff --git a/src/libraries/luasocket/libluasocket/makefile b/src/libraries/luasocket/libluasocket/makefile index 06f4d1927..25b293c72 100644 --- a/src/libraries/luasocket/libluasocket/makefile +++ b/src/libraries/luasocket/libluasocket/makefile @@ -1,6 +1,6 @@ # luasocket src/makefile # -# Definitions in this section can be overriden on the command line or in the +# Definitions in this section can be overridden on the command line or in the # environment. # # These are equivalent: @@ -272,7 +272,7 @@ SOCKET_win64=wsocket.obj # SO=$(SO_$(PLAT)) O=$(O_$(PLAT)) -SOCKET_V=3.0.0 +SOCKET_V=3.1.0 MIME_V=1.0.3 SOCKET_SO=socket-$(SOCKET_V).$(SO) MIME_SO=mime-$(MIME_V).$(SO) diff --git a/src/libraries/luasocket/libluasocket/mbox.lua.h b/src/libraries/luasocket/libluasocket/mbox.lua.h index 6af5c4de6..d11b4a063 100644 --- a/src/libraries/luasocket/libluasocket/mbox.lua.h +++ b/src/libraries/luasocket/libluasocket/mbox.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/mime.lua.h b/src/libraries/luasocket/libluasocket/mime.lua.h index 222efa219..27daf0d2c 100644 --- a/src/libraries/luasocket/libluasocket/mime.lua.h +++ b/src/libraries/luasocket/libluasocket/mime.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/options.c b/src/libraries/luasocket/libluasocket/options.c index 3280c51d7..9dea6bda2 100644 --- a/src/libraries/luasocket/libluasocket/options.c +++ b/src/libraries/luasocket/libluasocket/options.c @@ -54,6 +54,33 @@ int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps) return opt->func(L, ps); } +/*------------------------------------------------------*/ +/* binds socket to network interface */ +int opt_set_bindtodevice(lua_State *L, p_socket ps) +{ +#ifndef SO_BINDTODEVICE + return luaL_error(L, "SO_BINDTODEVICE is not supported on this operating system"); +#else + const char *dev = luaL_checkstring(L, 3); + return opt_set(L, ps, SOL_SOCKET, SO_BINDTODEVICE, (char*)dev, strlen(dev)+1); +#endif +} + +int opt_get_bindtodevice(lua_State *L, p_socket ps) +{ +#ifndef SO_BINDTODEVICE + return luaL_error(L, "SO_BINDTODEVICE is not supported on this operating system"); +#else + char dev[IFNAMSIZ]; + int len = sizeof(dev); + int err = opt_get(L, ps, SOL_SOCKET, SO_BINDTODEVICE, &dev, &len); + if (err) + return err; + lua_pushstring(L, dev); + return 1; +#endif +} + /*------------------------------------------------------*/ /* enables reuse of local address */ int opt_set_reuseaddr(lua_State *L, p_socket ps) @@ -190,7 +217,7 @@ int opt_set_send_buf_size(lua_State *L, p_socket ps) return opt_setint(L, ps, SOL_SOCKET, SO_SNDBUF); } -// /*------------------------------------------------------*/ +/*------------------------------------------------------*/ #ifdef TCP_FASTOPEN int opt_set_tcp_fastopen(lua_State *L, p_socket ps) diff --git a/src/libraries/luasocket/libluasocket/options.h b/src/libraries/luasocket/libluasocket/options.h index 456eeb5f4..26d6f0250 100644 --- a/src/libraries/luasocket/libluasocket/options.h +++ b/src/libraries/luasocket/libluasocket/options.h @@ -53,6 +53,9 @@ int opt_get_tcp_keepintvl(lua_State *L, p_socket ps); int opt_set_tcp_defer_accept(lua_State *L, p_socket ps); #endif +int opt_set_bindtodevice(lua_State *L, p_socket ps); +int opt_get_bindtodevice(lua_State *L, p_socket ps); + int opt_set_keepalive(lua_State *L, p_socket ps); int opt_get_keepalive(lua_State *L, p_socket ps); diff --git a/src/libraries/luasocket/libluasocket/smtp.lua b/src/libraries/luasocket/libluasocket/smtp.lua index b113d0067..c26ce44f4 100644 --- a/src/libraries/luasocket/libluasocket/smtp.lua +++ b/src/libraries/luasocket/libluasocket/smtp.lua @@ -225,7 +225,7 @@ local function adjust_headers(mesgt) lower["date"] = lower["date"] or os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE) lower["x-mailer"] = lower["x-mailer"] or socket._VERSION - -- this can't be overriden + -- this can't be overridden lower["mime-version"] = "1.0" return lower end @@ -253,4 +253,4 @@ _M.send = socket.protect(function(mailt) return s:close() end) -return _M \ No newline at end of file +return _M diff --git a/src/libraries/luasocket/libluasocket/smtp.lua.h b/src/libraries/luasocket/libluasocket/smtp.lua.h index 2f9929ad3..6bb022090 100644 --- a/src/libraries/luasocket/libluasocket/smtp.lua.h +++ b/src/libraries/luasocket/libluasocket/smtp.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -543,7 +543,7 @@ const unsigned char smtp_lua[] = 0x6c, 0x65, 0x72, 0x22, 0x5d, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x27, 0x74, 0x20, - 0x62, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x0a, + 0x62, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5b, 0x22, 0x6d, 0x69, 0x6d, 0x65, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x0a, diff --git a/src/libraries/luasocket/libluasocket/socket.lua.h b/src/libraries/luasocket/libluasocket/socket.lua.h index b6986c743..f3f22f20a 100644 --- a/src/libraries/luasocket/libluasocket/socket.lua.h +++ b/src/libraries/luasocket/libluasocket/socket.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/tcp.c b/src/libraries/luasocket/libluasocket/tcp.c index e84db8454..f00120640 100644 --- a/src/libraries/luasocket/libluasocket/tcp.c +++ b/src/libraries/luasocket/libluasocket/tcp.c @@ -71,6 +71,7 @@ static luaL_Reg tcp_methods[] = { /* socket option handlers */ static t_opt optget[] = { + {"bindtodevice", opt_get_bindtodevice}, {"keepalive", opt_get_keepalive}, {"reuseaddr", opt_get_reuseaddr}, {"reuseport", opt_get_reuseport}, @@ -92,6 +93,7 @@ static t_opt optget[] = { }; static t_opt optset[] = { + {"bindtodevice", opt_set_bindtodevice}, {"keepalive", opt_set_keepalive}, {"reuseaddr", opt_set_reuseaddr}, {"reuseport", opt_set_reuseport}, diff --git a/src/libraries/luasocket/libluasocket/tp.lua.h b/src/libraries/luasocket/libluasocket/tp.lua.h index 2514af0ac..85b1e2c7f 100644 --- a/src/libraries/luasocket/libluasocket/tp.lua.h +++ b/src/libraries/luasocket/libluasocket/tp.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/libluasocket/url.lua b/src/libraries/luasocket/libluasocket/url.lua index 8e0dc5ceb..aef16984c 100644 --- a/src/libraries/luasocket/libluasocket/url.lua +++ b/src/libraries/luasocket/libluasocket/url.lua @@ -152,7 +152,7 @@ function _M.parse(url, default) url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", function(s) parsed.scheme = s; return "" end) -- get authority - url = string.gsub(url, "^//([^/]*)", function(n) + url = string.gsub(url, "^//([^/%?#]*)", function(n) parsed.authority = n return "" end) diff --git a/src/libraries/luasocket/libluasocket/url.lua.h b/src/libraries/luasocket/libluasocket/url.lua.h index b0e2ca092..7db3e665c 100644 --- a/src/libraries/luasocket/libluasocket/url.lua.h +++ b/src/libraries/luasocket/libluasocket/url.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -402,8 +402,9 @@ const unsigned char url_lua[] = 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x67, 0x65, 0x74, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x72, 0x6c, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, - 0x73, 0x75, 0x62, 0x28, 0x75, 0x72, 0x6c, 0x2c, 0x20, 0x22, 0x5e, 0x2f, 0x2f, 0x28, 0x5b, 0x5e, 0x2f, 0x5d, - 0x2a, 0x29, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x29, 0x0a, + 0x73, 0x75, 0x62, 0x28, 0x75, 0x72, 0x6c, 0x2c, 0x20, 0x22, 0x5e, 0x2f, 0x2f, 0x28, 0x5b, 0x5e, 0x2f, 0x25, + 0x3f, 0x23, 0x5d, 0x2a, 0x29, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, + 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x64, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x22, 0x22, 0x0a, diff --git a/src/libraries/luasocket/libluasocket/usocket.c b/src/libraries/luasocket/libluasocket/usocket.c index 69635daa6..7965db6c4 100644 --- a/src/libraries/luasocket/libluasocket/usocket.c +++ b/src/libraries/luasocket/libluasocket/usocket.c @@ -236,7 +236,7 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, *sent = 0; if (*ps == SOCKET_INVALID) return IO_CLOSED; for ( ;; ) { - long put = (long) sendto(*ps, data, count, 0, addr, len); + long put = (long) sendto(*ps, data, count, 0, addr, len); if (put >= 0) { *sent = put; return IO_DONE; diff --git a/src/libraries/luasocket/libluasocket/wsocket.c b/src/libraries/luasocket/libluasocket/wsocket.c index 6cb1e415c..d3af9d4a1 100644 --- a/src/libraries/luasocket/libluasocket/wsocket.c +++ b/src/libraries/luasocket/libluasocket/wsocket.c @@ -262,6 +262,7 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, if (err != WSAEWOULDBLOCK) { if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; prev = err; + continue; } if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; } @@ -291,6 +292,7 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, if (err != WSAEWOULDBLOCK) { if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; prev = err; + continue; } if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; } diff --git a/src/libraries/luasocket/luasocket.cpp b/src/libraries/luasocket/luasocket.cpp index e1aa845cf..d5cd26ed4 100644 --- a/src/libraries/luasocket/luasocket.cpp +++ b/src/libraries/luasocket/luasocket.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/libraries/luasocket/luasocket.h b/src/libraries/luasocket/luasocket.h index 26865bb07..b6225dd3f 100644 --- a/src/libraries/luasocket/luasocket.h +++ b/src/libraries/luasocket/luasocket.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/love.cpp b/src/love.cpp index abac4d618..a94779753 100644 --- a/src/love.cpp +++ b/src/love.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -150,11 +150,11 @@ enum DoneAction static void print_usage() { // when editing this message, change it at boot.lua too - printf("LÖVE is an *awesome* framework you can use to make 2D games in Lua\n" + printf("LOVE is an *awesome* framework you can use to make 2D games in Lua\n" "https://love2d.org\n" "\n" "usage:\n" - " love --version prints LÖVE version and quits\n" + " love --version prints LOVE version and quits\n" " love --help prints this message and quits\n" " love path/to/gamedir runs the game from the given directory which contains a main.lua file\n" " love path/to/packagedgame.love runs the packaged game from the provided .love file\n" diff --git a/src/modules/audio/Audio.cpp b/src/modules/audio/Audio.cpp index 6b357c9c2..336e9dff3 100644 --- a/src/modules/audio/Audio.cpp +++ b/src/modules/audio/Audio.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -68,6 +68,10 @@ void showRecordingPermissionMissingDialog() #endif } +Audio::Audio(const char *name) + : Module(M_AUDIO, name) +{} + bool Audio::setMixWithSystem(bool mix) { #ifdef LOVE_IOS diff --git a/src/modules/audio/Audio.h b/src/modules/audio/Audio.h index ef5a644a1..8b6eae670 100644 --- a/src/modules/audio/Audio.h +++ b/src/modules/audio/Audio.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -101,9 +101,6 @@ public: virtual ~Audio() {} - // Implements Module. - virtual ModuleType getModuleType() const { return M_AUDIO; } - virtual Source *newSource(love::sound::Decoder *decoder) = 0; virtual Source *newSource(love::sound::SoundData *soundData) = 0; virtual Source *newSource(int sampleRate, int bitDepth, int channels, int buffers) = 0; @@ -312,6 +309,10 @@ public: */ virtual void setPlaybackDevice(const char *name); +protected: + + Audio(const char *name); + private: static StringMap::Entry distanceModelEntries[]; diff --git a/src/modules/audio/Effect.cpp b/src/modules/audio/Effect.cpp index 0a3bd1243..aa2f18122 100644 --- a/src/modules/audio/Effect.cpp +++ b/src/modules/audio/Effect.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/Effect.h b/src/modules/audio/Effect.h index 2d93d6a57..0eb4e307e 100644 --- a/src/modules/audio/Effect.h +++ b/src/modules/audio/Effect.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/Filter.cpp b/src/modules/audio/Filter.cpp index beced0fe5..6ec622870 100644 --- a/src/modules/audio/Filter.cpp +++ b/src/modules/audio/Filter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/Filter.h b/src/modules/audio/Filter.h index f2c1344c8..de1f64d11 100644 --- a/src/modules/audio/Filter.h +++ b/src/modules/audio/Filter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/RecordingDevice.cpp b/src/modules/audio/RecordingDevice.cpp index 9ceefa6bc..f9123eb87 100644 --- a/src/modules/audio/RecordingDevice.cpp +++ b/src/modules/audio/RecordingDevice.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/RecordingDevice.h b/src/modules/audio/RecordingDevice.h index 4d85c2f14..7ee367863 100644 --- a/src/modules/audio/RecordingDevice.h +++ b/src/modules/audio/RecordingDevice.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/Source.cpp b/src/modules/audio/Source.cpp index 4877f9dcb..5e69457cb 100644 --- a/src/modules/audio/Source.cpp +++ b/src/modules/audio/Source.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/Source.h b/src/modules/audio/Source.h index a61ef043b..3f45ce06d 100644 --- a/src/modules/audio/Source.h +++ b/src/modules/audio/Source.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/null/Audio.cpp b/src/modules/audio/null/Audio.cpp index 1be9ed5d5..29f814be5 100644 --- a/src/modules/audio/null/Audio.cpp +++ b/src/modules/audio/null/Audio.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -28,7 +28,8 @@ namespace null { Audio::Audio() - : distanceModel(DISTANCE_NONE) + : love::audio::Audio("love.audio.null") + , distanceModel(DISTANCE_NONE) { } @@ -36,11 +37,6 @@ Audio::~Audio() { } -const char *Audio::getName() const -{ - return "love.audio.null"; -} - love::audio::Source *Audio::newSource(love::sound::Decoder *) { return new Source(); diff --git a/src/modules/audio/null/Audio.h b/src/modules/audio/null/Audio.h index 5559517d8..8d38d4523 100644 --- a/src/modules/audio/null/Audio.h +++ b/src/modules/audio/null/Audio.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -41,9 +41,6 @@ public: Audio(); virtual ~Audio(); - // Implements Module. - const char *getName() const; - // Implements Audio. love::audio::Source *newSource(love::sound::Decoder *decoder); love::audio::Source *newSource(love::sound::SoundData *soundData); diff --git a/src/modules/audio/null/RecordingDevice.cpp b/src/modules/audio/null/RecordingDevice.cpp index fbf80f86f..e206d87b6 100644 --- a/src/modules/audio/null/RecordingDevice.cpp +++ b/src/modules/audio/null/RecordingDevice.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/null/RecordingDevice.h b/src/modules/audio/null/RecordingDevice.h index 48d3fde7c..501007209 100644 --- a/src/modules/audio/null/RecordingDevice.h +++ b/src/modules/audio/null/RecordingDevice.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/null/Source.cpp b/src/modules/audio/null/Source.cpp index d529b0ce9..b38e97a27 100644 --- a/src/modules/audio/null/Source.cpp +++ b/src/modules/audio/null/Source.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/null/Source.h b/src/modules/audio/null/Source.h index 2b4880c50..03071a9db 100644 --- a/src/modules/audio/null/Source.h +++ b/src/modules/audio/null/Source.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Audio.cpp b/src/modules/audio/openal/Audio.cpp index 93dd08f12..262b60eb2 100644 --- a/src/modules/audio/openal/Audio.cpp +++ b/src/modules/audio/openal/Audio.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -106,7 +106,8 @@ static const char *getDeviceSpecifier(ALCdevice *device) } Audio::Audio() - : device(nullptr) + : love::audio::Audio("love.audio.openal") + , device(nullptr) , context(nullptr) , pool(nullptr) , poolThread(nullptr) @@ -256,11 +257,6 @@ Audio::~Audio() alcCloseDevice(device); } -const char *Audio::getName() const -{ - return "love.audio.openal"; -} - love::audio::Source *Audio::newSource(love::sound::Decoder *decoder) { return new Source(pool, decoder); diff --git a/src/modules/audio/openal/Audio.h b/src/modules/audio/openal/Audio.h index c6b7efa15..970d9150a 100644 --- a/src/modules/audio/openal/Audio.h +++ b/src/modules/audio/openal/Audio.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -78,9 +78,6 @@ public: **/ static ALenum getFormat(int bitDepth, int channels); - // Implements Module. - const char *getName() const; - // Implements Audio. love::audio::Source *newSource(love::sound::Decoder *decoder); love::audio::Source *newSource(love::sound::SoundData *soundData); diff --git a/src/modules/audio/openal/Effect.cpp b/src/modules/audio/openal/Effect.cpp index fa1b9026b..78c257584 100644 --- a/src/modules/audio/openal/Effect.cpp +++ b/src/modules/audio/openal/Effect.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Effect.h b/src/modules/audio/openal/Effect.h index 9f67ce079..92729219d 100644 --- a/src/modules/audio/openal/Effect.h +++ b/src/modules/audio/openal/Effect.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Filter.cpp b/src/modules/audio/openal/Filter.cpp index 7b0528aed..7c890b6d8 100644 --- a/src/modules/audio/openal/Filter.cpp +++ b/src/modules/audio/openal/Filter.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Filter.h b/src/modules/audio/openal/Filter.h index dc6532018..e626b89fe 100644 --- a/src/modules/audio/openal/Filter.h +++ b/src/modules/audio/openal/Filter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Pool.cpp b/src/modules/audio/openal/Pool.cpp index cc01b77c1..7d08f6572 100644 --- a/src/modules/audio/openal/Pool.cpp +++ b/src/modules/audio/openal/Pool.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Pool.h b/src/modules/audio/openal/Pool.h index fff1820b7..df3f4e7ca 100644 --- a/src/modules/audio/openal/Pool.h +++ b/src/modules/audio/openal/Pool.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/RecordingDevice.cpp b/src/modules/audio/openal/RecordingDevice.cpp index 6b6c86326..56a74428b 100644 --- a/src/modules/audio/openal/RecordingDevice.cpp +++ b/src/modules/audio/openal/RecordingDevice.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/RecordingDevice.h b/src/modules/audio/openal/RecordingDevice.h index 09e8b41a1..fc3964cff 100644 --- a/src/modules/audio/openal/RecordingDevice.h +++ b/src/modules/audio/openal/RecordingDevice.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index bbec6827d..dcb5f3674 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/openal/Source.h b/src/modules/audio/openal/Source.h index ecceaf151..f719feb9e 100644 --- a/src/modules/audio/openal/Source.h +++ b/src/modules/audio/openal/Source.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index c8253eef4..0541be892 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/wrap_Audio.h b/src/modules/audio/wrap_Audio.h index 8ddc2e027..a24687deb 100644 --- a/src/modules/audio/wrap_Audio.h +++ b/src/modules/audio/wrap_Audio.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/wrap_RecordingDevice.cpp b/src/modules/audio/wrap_RecordingDevice.cpp index 6b3f37902..cd0b691e8 100644 --- a/src/modules/audio/wrap_RecordingDevice.cpp +++ b/src/modules/audio/wrap_RecordingDevice.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/wrap_RecordingDevice.h b/src/modules/audio/wrap_RecordingDevice.h index 51753ec8e..0a8f9547d 100644 --- a/src/modules/audio/wrap_RecordingDevice.h +++ b/src/modules/audio/wrap_RecordingDevice.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/wrap_Source.cpp b/src/modules/audio/wrap_Source.cpp index 72204f663..8d4042d54 100644 --- a/src/modules/audio/wrap_Source.cpp +++ b/src/modules/audio/wrap_Source.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/audio/wrap_Source.h b/src/modules/audio/wrap_Source.h index 54f90aa88..d223dd0e3 100644 --- a/src/modules/audio/wrap_Source.h +++ b/src/modules/audio/wrap_Source.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/ByteData.cpp b/src/modules/data/ByteData.cpp index d99789611..2c4a18bd2 100644 --- a/src/modules/data/ByteData.cpp +++ b/src/modules/data/ByteData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/ByteData.h b/src/modules/data/ByteData.h index 0e1fdaa50..3606bc1e7 100644 --- a/src/modules/data/ByteData.h +++ b/src/modules/data/ByteData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/CompressedData.cpp b/src/modules/data/CompressedData.cpp index f94c67758..14b7b2426 100644 --- a/src/modules/data/CompressedData.cpp +++ b/src/modules/data/CompressedData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/CompressedData.h b/src/modules/data/CompressedData.h index 53ed19aa1..a7b33f49a 100644 --- a/src/modules/data/CompressedData.h +++ b/src/modules/data/CompressedData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/Compressor.cpp b/src/modules/data/Compressor.cpp index 2df1a1154..2a55e604b 100644 --- a/src/modules/data/Compressor.cpp +++ b/src/modules/data/Compressor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/Compressor.h b/src/modules/data/Compressor.h index fd4d49ad0..64570c29a 100644 --- a/src/modules/data/Compressor.h +++ b/src/modules/data/Compressor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/DataModule.cpp b/src/modules/data/DataModule.cpp index 9bda2cebb..a3b27ed89 100644 --- a/src/modules/data/DataModule.cpp +++ b/src/modules/data/DataModule.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -214,6 +214,7 @@ void hash(HashFunction::Function function, const char *input, uint64_t size, Has } DataModule::DataModule() + : Module(M_DATA, "love.data") { } diff --git a/src/modules/data/DataModule.h b/src/modules/data/DataModule.h index d7dd2f00d..f255cf07f 100644 --- a/src/modules/data/DataModule.h +++ b/src/modules/data/DataModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -117,10 +117,6 @@ public: DataModule(); virtual ~DataModule(); - // Implements Module. - ModuleType getModuleType() const override { return M_DATA; } - const char *getName() const override { return "love.data"; } - DataView *newDataView(Data *data, size_t offset, size_t size); ByteData *newByteData(size_t size); ByteData *newByteData(const void *d, size_t size); diff --git a/src/modules/data/DataStream.cpp b/src/modules/data/DataStream.cpp index ad7d7b275..bfa1873ee 100644 --- a/src/modules/data/DataStream.cpp +++ b/src/modules/data/DataStream.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/DataStream.h b/src/modules/data/DataStream.h index da4d27977..05c032e5f 100644 --- a/src/modules/data/DataStream.h +++ b/src/modules/data/DataStream.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/DataView.cpp b/src/modules/data/DataView.cpp index 645638e7f..cb60f1e78 100644 --- a/src/modules/data/DataView.cpp +++ b/src/modules/data/DataView.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/DataView.h b/src/modules/data/DataView.h index 56ac4eff0..c253979a7 100644 --- a/src/modules/data/DataView.h +++ b/src/modules/data/DataView.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/HashFunction.cpp b/src/modules/data/HashFunction.cpp index 2ada4b19f..fdb1e9beb 100644 --- a/src/modules/data/HashFunction.cpp +++ b/src/modules/data/HashFunction.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/HashFunction.h b/src/modules/data/HashFunction.h index 372852678..e42d9c559 100644 --- a/src/modules/data/HashFunction.h +++ b/src/modules/data/HashFunction.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_ByteData.cpp b/src/modules/data/wrap_ByteData.cpp index 57ff5f975..e15924d64 100644 --- a/src/modules/data/wrap_ByteData.cpp +++ b/src/modules/data/wrap_ByteData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -135,16 +135,6 @@ int w_ByteData_setUInt32(lua_State *L) return w_ByteData_setT(L); } -int w_ByteData_setInt64(lua_State *L) -{ - return w_ByteData_setT(L); -} - -int w_ByteData_setUInt64(lua_State *L) -{ - return w_ByteData_setT(L); -} - static const luaL_Reg w_ByteData_functions[] = { { "clone", w_ByteData_clone }, @@ -157,8 +147,6 @@ static const luaL_Reg w_ByteData_functions[] = { "setUInt16", w_ByteData_setUInt16 }, { "setInt32", w_ByteData_setInt32 }, { "setUInt32", w_ByteData_setUInt32 }, - { "setInt64", w_ByteData_setInt64 }, - { "setUInt64", w_ByteData_setUInt64 }, { 0, 0 } }; diff --git a/src/modules/data/wrap_ByteData.h b/src/modules/data/wrap_ByteData.h index 4e13de0a8..b8c340df3 100644 --- a/src/modules/data/wrap_ByteData.h +++ b/src/modules/data/wrap_ByteData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_CompressedData.cpp b/src/modules/data/wrap_CompressedData.cpp index 2d2d537cd..c01d69eee 100644 --- a/src/modules/data/wrap_CompressedData.cpp +++ b/src/modules/data/wrap_CompressedData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_CompressedData.h b/src/modules/data/wrap_CompressedData.h index a16d27501..661492938 100644 --- a/src/modules/data/wrap_CompressedData.h +++ b/src/modules/data/wrap_CompressedData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_Data.cpp b/src/modules/data/wrap_Data.cpp index ceab57242..97ff37469 100644 --- a/src/modules/data/wrap_Data.cpp +++ b/src/modules/data/wrap_Data.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -20,6 +20,7 @@ #include "wrap_Data.h" #include "common/int.h" +#include "thread/threads.h" // Put the Lua code directly into a raw string literal. static const char data_lua[] = @@ -78,6 +79,26 @@ int w_Data_getSize(lua_State *L) return 1; } +int w_Data_performAtomic(lua_State *L) +{ + Data *t = luax_checkdata(L, 1); + int err = 0; + + { + love::thread::Lock lock(t->getMutex()); + // call the function, passing any user-specified arguments. + err = lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 0); + } + + // Unfortunately, this eats the stack trace, too bad. + if (err != 0) + return lua_error(L); + + // The function and everything after it in the stack are eaten by the pcall, + // leaving only the Data object. Everything else is a return value. + return lua_gettop(L) - 1; +} + template static int w_Data_getT(lua_State* L) { @@ -139,16 +160,6 @@ int w_Data_getUInt32(lua_State* L) return w_Data_getT(L); } -int w_Data_getInt64(lua_State* L) -{ - return w_Data_getT(L); -} - -int w_Data_getUInt64(lua_State* L) -{ - return w_Data_getT(L); -} - // C functions in a struct, necessary for the FFI versions of Data methods. struct FFI_Data { @@ -170,6 +181,7 @@ const luaL_Reg w_Data_functions[] = { "getPointer", w_Data_getPointer }, { "getFFIPointer", w_Data_getFFIPointer }, { "getSize", w_Data_getSize }, + { "performAtomic", w_Data_performAtomic }, { "getFloat", w_Data_getFloat }, { "getDouble", w_Data_getDouble }, { "getInt8", w_Data_getInt8 }, @@ -178,8 +190,6 @@ const luaL_Reg w_Data_functions[] = { "getUInt16", w_Data_getUInt16 }, { "getInt32", w_Data_getInt32 }, { "getUInt32", w_Data_getUInt32 }, - { "getInt64", w_Data_getInt64 }, - { "getUInt64", w_Data_getUInt64 }, { 0, 0 } }; diff --git a/src/modules/data/wrap_Data.h b/src/modules/data/wrap_Data.h index c9447a0be..d66a3e645 100644 --- a/src/modules/data/wrap_Data.h +++ b/src/modules/data/wrap_Data.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_Data.lua b/src/modules/data/wrap_Data.lua index f15090a6e..eb18e66c8 100644 --- a/src/modules/data/wrap_Data.lua +++ b/src/modules/data/wrap_Data.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_DataModule.cpp b/src/modules/data/wrap_DataModule.cpp index 0b6ecff16..b9feda515 100644 --- a/src/modules/data/wrap_DataModule.cpp +++ b/src/modules/data/wrap_DataModule.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -302,25 +302,52 @@ int w_decode(lua_State *L) int w_hash(lua_State *L) { - const char *fstr = luaL_checkstring(L, 1); + int narg = 0; // used to change the arg position when using the deprecated function variant + + ContainerType ctype = CONTAINER_STRING; HashFunction::Function function; + + const char *str = luaL_checkstring(L, 1); + if (!getConstant(str, ctype)) + { + if (HashFunction::getConstant(str, function)) + { // check if the argument at 1 is a hash function; deprecated function variant + luax_markdeprecated(L, 1, "love.data.hash", API_FUNCTION_VARIANT, DEPRECATED_REPLACED, "variant with container return type parameter"); + narg = -1; + } + else + luax_enumerror(L, "container type", getConstants(ctype), str); + } + + const char *fstr = luaL_checkstring(L, 2 + narg); if (!HashFunction::getConstant(fstr, function)) return luax_enumerror(L, "hash function", HashFunction::getConstants(function), fstr); HashFunction::Value hashvalue; - if (lua_isstring(L, 2)) + if (lua_isstring(L, 3 + narg)) { size_t rawsize = 0; - const char *rawbytes = luaL_checklstring(L, 2, &rawsize); + const char *rawbytes = luaL_checklstring(L, 3 + narg, &rawsize); luax_catchexcept(L, [&](){ love::data::hash(function, rawbytes, rawsize, hashvalue); }); } else { - Data *rawdata = luax_checktype(L, 2); + Data *rawdata = luax_checktype(L, 3 + narg); luax_catchexcept(L, [&](){ love::data::hash(function, rawdata, hashvalue); }); } - lua_pushlstring(L, hashvalue.data, hashvalue.size); + if (ctype == CONTAINER_DATA) + { + Data* d = nullptr; + luax_catchexcept(L, [&]() { d = instance()->newByteData(hashvalue.size); }); + memcpy(d->getData(), hashvalue.data, hashvalue.size); + + luax_pushtype(L, Data::type, d); + d->release(); + } + else + lua_pushlstring(L, hashvalue.data, hashvalue.size); + return 1; } diff --git a/src/modules/data/wrap_DataModule.h b/src/modules/data/wrap_DataModule.h index c8614240e..046101d13 100644 --- a/src/modules/data/wrap_DataModule.h +++ b/src/modules/data/wrap_DataModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_DataView.cpp b/src/modules/data/wrap_DataView.cpp index 9c574bb67..b756eff0b 100644 --- a/src/modules/data/wrap_DataView.cpp +++ b/src/modules/data/wrap_DataView.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/data/wrap_DataView.h b/src/modules/data/wrap_DataView.h index a255fa255..fbcfc2efb 100644 --- a/src/modules/data/wrap_DataView.h +++ b/src/modules/data/wrap_DataView.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/event/Event.cpp b/src/modules/event/Event.cpp index 9f0df49d8..45b7c2c2b 100644 --- a/src/modules/event/Event.cpp +++ b/src/modules/event/Event.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -38,6 +38,11 @@ Message::~Message() { } +Event::Event(const char *name) + : Module(M_EVENT, name) +{ +} + Event::~Event() { } diff --git a/src/modules/event/Event.h b/src/modules/event/Event.h index 181c0b131..3b3c33d44 100644 --- a/src/modules/event/Event.h +++ b/src/modules/event/Event.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -54,10 +54,8 @@ public: class Event : public Module { public: - virtual ~Event(); - // Implements Module. - virtual ModuleType getModuleType() const { return M_EVENT; } + virtual ~Event(); void push(Message *msg); bool poll(Message *&msg); @@ -67,6 +65,9 @@ public: virtual Message *wait() = 0; protected: + + Event(const char *name); + love::thread::MutexRef mutex; std::queue queue; diff --git a/src/modules/event/sdl/Event.cpp b/src/modules/event/sdl/Event.cpp index 31a5ba2ac..08977f354 100644 --- a/src/modules/event/sdl/Event.cpp +++ b/src/modules/event/sdl/Event.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -156,12 +156,8 @@ static int SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event) return 1; } -const char *Event::getName() const -{ - return "love.event.sdl"; -} - Event::Event() + : love::event::Event("love.event.sdl") { if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) throw love::Exception("Could not initialize SDL events subsystem (%s)", SDL_GetError()); diff --git a/src/modules/event/sdl/Event.h b/src/modules/event/sdl/Event.h index 3c1649b5c..8b9ab9ad7 100644 --- a/src/modules/event/sdl/Event.h +++ b/src/modules/event/sdl/Event.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -42,9 +42,6 @@ class Event : public love::event::Event { public: - // Implements Module. - const char *getName() const; - Event(); virtual ~Event(); diff --git a/src/modules/event/wrap_Event.cpp b/src/modules/event/wrap_Event.cpp index ed293a1ca..e51ff9557 100644 --- a/src/modules/event/wrap_Event.cpp +++ b/src/modules/event/wrap_Event.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/event/wrap_Event.h b/src/modules/event/wrap_Event.h index ce7d9ed89..cc7cb7eb2 100644 --- a/src/modules/event/wrap_Event.h +++ b/src/modules/event/wrap_Event.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/event/wrap_Event.lua b/src/modules/event/wrap_Event.lua index a8f392d5c..52cf3bf11 100644 --- a/src/modules/event/wrap_Event.lua +++ b/src/modules/event/wrap_Event.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/File.cpp b/src/modules/filesystem/File.cpp index e1e2a726f..399a891f0 100644 --- a/src/modules/filesystem/File.cpp +++ b/src/modules/filesystem/File.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/File.h b/src/modules/filesystem/File.h index 57137e792..4ab3fe3d6 100644 --- a/src/modules/filesystem/File.h +++ b/src/modules/filesystem/File.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/FileData.cpp b/src/modules/filesystem/FileData.cpp index bc61cd5fd..806fcd7c6 100644 --- a/src/modules/filesystem/FileData.cpp +++ b/src/modules/filesystem/FileData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/FileData.h b/src/modules/filesystem/FileData.h index 0a64ca93c..c438b176f 100644 --- a/src/modules/filesystem/FileData.h +++ b/src/modules/filesystem/FileData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/Filesystem.cpp b/src/modules/filesystem/Filesystem.cpp index 542514dea..026209c41 100644 --- a/src/modules/filesystem/Filesystem.cpp +++ b/src/modules/filesystem/Filesystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -45,7 +45,8 @@ namespace filesystem love::Type Filesystem::type("filesystem", &Module::type); -Filesystem::Filesystem() +Filesystem::Filesystem(const char *name) + : Module(M_FILESYSTEM, name) { } diff --git a/src/modules/filesystem/Filesystem.h b/src/modules/filesystem/Filesystem.h index db1435e95..91359635d 100644 --- a/src/modules/filesystem/Filesystem.h +++ b/src/modules/filesystem/Filesystem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -108,12 +108,8 @@ public: static love::Type type; - Filesystem(); virtual ~Filesystem(); - // Implements Module. - virtual ModuleType getModuleType() const { return M_FILESYSTEM; } - virtual void init(const char *arg0) = 0; virtual void setFused(bool fused) = 0; @@ -317,6 +313,10 @@ public: STRINGMAP_CLASS_DECLARE(MountPermissions); STRINGMAP_CLASS_DECLARE(LoadMode); +protected: + + Filesystem(const char *name); + private: bool getRealPathType(const std::string &path, FileType &ftype) const; diff --git a/src/modules/filesystem/NativeFile.cpp b/src/modules/filesystem/NativeFile.cpp index addf6ffd6..8760a594f 100644 --- a/src/modules/filesystem/NativeFile.cpp +++ b/src/modules/filesystem/NativeFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/NativeFile.h b/src/modules/filesystem/NativeFile.h index 23d6e9667..7b46f5c01 100644 --- a/src/modules/filesystem/NativeFile.h +++ b/src/modules/filesystem/NativeFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/physfs/File.cpp b/src/modules/filesystem/physfs/File.cpp index 421278753..99ee0a80c 100644 --- a/src/modules/filesystem/physfs/File.cpp +++ b/src/modules/filesystem/physfs/File.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/physfs/File.h b/src/modules/filesystem/physfs/File.h index 8c485015e..bc0b04cb7 100644 --- a/src/modules/filesystem/physfs/File.h +++ b/src/modules/filesystem/physfs/File.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/physfs/Filesystem.cpp b/src/modules/filesystem/physfs/Filesystem.cpp index ef96149a9..52e190c56 100644 --- a/src/modules/filesystem/physfs/Filesystem.cpp +++ b/src/modules/filesystem/physfs/Filesystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -107,7 +107,8 @@ static bool isAppCommonPath(Filesystem::CommonPath path) } Filesystem::Filesystem() - : appendIdentityToPath(false) + : love::filesystem::Filesystem("love.filesystem.physfs") + , appendIdentityToPath(false) , fused(false) , fusedSet(false) , fullPaths() @@ -128,11 +129,6 @@ Filesystem::~Filesystem() PHYSFS_deinit(); } -const char *Filesystem::getName() const -{ - return "love.filesystem.physfs"; -} - void Filesystem::init(const char *arg0) { #ifdef LOVE_ANDROID @@ -249,8 +245,14 @@ bool Filesystem::setSource(const char *source) if (hasFusedGame) { if (gameLoveIO) - // Actually we should just be able to mount gameLoveIO, but that's experimental. + { + if (PHYSFS_mountIo(gameLoveIO, ".zip", nullptr, 0)) { + gameSource = new_search_path; + return true; + } + gameLoveIO->destroy(gameLoveIO); + } else { if (!love::android::initializeVirtualArchive()) @@ -278,6 +280,8 @@ bool Filesystem::setSource(const char *source) gameSource = new_search_path; return true; } + + io->destroy(io); } } #endif diff --git a/src/modules/filesystem/physfs/Filesystem.h b/src/modules/filesystem/physfs/Filesystem.h index be12d2cc0..beffe3bab 100644 --- a/src/modules/filesystem/physfs/Filesystem.h +++ b/src/modules/filesystem/physfs/Filesystem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,9 +43,6 @@ public: Filesystem(); virtual ~Filesystem(); - // Implements Module. - const char *getName() const override; - void init(const char *arg0) override; void setFused(bool fused) override; diff --git a/src/modules/filesystem/physfs/PhysfsIo.cpp b/src/modules/filesystem/physfs/PhysfsIo.cpp index cdcea8dd2..ec48f5d73 100644 --- a/src/modules/filesystem/physfs/PhysfsIo.cpp +++ b/src/modules/filesystem/physfs/PhysfsIo.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -18,7 +18,6 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#include #include #include "PhysfsIo.h" @@ -32,14 +31,15 @@ namespace physfs bool StripSuffixIo::determineStrippedLength() { - if (!file) { + if (!file) return false; - } - const int64_t fullSize = fullLength(); - int64_t chunkSize = std::min(fullSize, (int64_t)8192); + + const int64 fullSize = file->getSize(); + + int64 chunkSize = std::min(fullSize, (int64) 8192); std::string buffer; buffer.reserve(chunkSize); - int64_t i = fullSize - chunkSize; + int64 i = fullSize - chunkSize; // I don't think we really need to go through the whole file. The main known use // case for this functionality is to skip windows codesign signatures, which are // from what I have seen ~12KB or so, but trying is better than just failing. @@ -64,7 +64,7 @@ bool StripSuffixIo::determineStrippedLength() } if (i == 0) break; - i = std::max((int64_t)0, i - chunkSize); + i = std::max((int64)0, i - chunkSize); } if (i > 0) @@ -75,7 +75,7 @@ bool StripSuffixIo::determineStrippedLength() // The comment length (u16) is located 20 bytes from the start of the EOCD record if (seek(i + 20) == 0) return false; - uint8_t buffer[2]; + uint8 buffer[2]; const auto n = read(buffer, 2); if (n <= 0) return false; @@ -96,17 +96,17 @@ bool StripSuffixIo::determineStrippedLength() return true; } -int64_t StripSuffixIo::read(void* buf, uint64_t len) +int64 StripSuffixIo::read(void *buf, uint64 len) { if (!file) { PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); return -1; } - const auto ret = std::fread(buf, 1, len, file); - if (ret == 0) + int64 r = file->read(buf, (int64) len); + if (r == 0) { - if (std::feof(file)) + if (file->isEOF()) { PHYSFS_setErrorCode(PHYSFS_ERR_OK); return 0; @@ -117,85 +117,59 @@ int64_t StripSuffixIo::read(void* buf, uint64_t len) return -1; } } - else if (ret < len && std::ferror(file)) - { - PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); - return -1; - } PHYSFS_setErrorCode(PHYSFS_ERR_OK); - return ret; + return r; } -int64_t StripSuffixIo::write(const void* /*buf*/, uint64_t /*len*/) +int64 StripSuffixIo::write(const void */*buf*/, uint64 /*len*/) { PHYSFS_setErrorCode(PHYSFS_ERR_READ_ONLY); return -1; } -int64_t StripSuffixIo::seek(uint64_t offset) +int64 StripSuffixIo::seek(uint64 offset) { if (!file) { PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); return 0; } - const auto ret = std::fseek(file, offset, SEEK_SET); - PHYSFS_setErrorCode(ret != 0 ? PHYSFS_ERR_OS_ERROR : PHYSFS_ERR_OK); - return ret == 0 ? 1 : 0; + bool success = file->seek(offset, Stream::SEEKORIGIN_BEGIN); + PHYSFS_setErrorCode(success ? PHYSFS_ERR_OK : PHYSFS_ERR_OS_ERROR); + return success ? 1 : 0; } -int64_t StripSuffixIo::tell() +int64 StripSuffixIo::tell() { if (!file) { PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); return -1; } - return std::ftell(file); + return file->tell(); } -int64_t StripSuffixIo::length() +int64 StripSuffixIo::length() { return strippedLength_; } -int64_t StripSuffixIo::flush() +int64 StripSuffixIo::flush() { if (!file) { PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); return 0; } - return std::fflush(file) == 0 ? 1 : 0; -} - -int64_t StripSuffixIo::fullLength() -{ - assert(file); - const auto cur = std::ftell(file); - if (cur == -1) + try + { + return file->flush() ? 1 : 0; + } + catch (love::Exception &) { PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); - return -1; + return 0; } - if (std::fseek(file, 0, SEEK_END) != 0) - { - PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); - return -1; - } - const auto len = std::ftell(file); - if (len == -1) - { - PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); - return -1; - } - if (std::fseek(file, cur, SEEK_SET) != 0) - { - // We do have the length now, but something is wrong, so we return an error anyways - PHYSFS_setErrorCode(PHYSFS_ERR_OS_ERROR); - return -1; - } - return len; } } // physfs diff --git a/src/modules/filesystem/physfs/PhysfsIo.h b/src/modules/filesystem/physfs/PhysfsIo.h index 35b92cc6c..764df9390 100644 --- a/src/modules/filesystem/physfs/PhysfsIo.h +++ b/src/modules/filesystem/physfs/PhysfsIo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -21,11 +21,11 @@ #ifndef LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H #define LOVE_FILESYSTEM_PHYSFS_PHYSFSIO_H -#include -#include -#include - #include "libraries/physfs/physfs.h" +#include "common/int.h" +#include "filesystem/NativeFile.h" + +#include namespace love { @@ -61,54 +61,54 @@ protected: private: // Returns: number of bytes read, 0 on EOF, -1 on failure - static PHYSFS_sint64 staticRead(struct PHYSFS_Io* io, void* buf, PHYSFS_uint64 len) + static PHYSFS_sint64 staticRead(struct PHYSFS_Io *io, void *buf, PHYSFS_uint64 len) { return derived(io)->read(buf, len); } // Returns: number of bytes written, -1 on failure - static PHYSFS_sint64 staticWrite(struct PHYSFS_Io* io, const void* buf, PHYSFS_uint64 len) + static PHYSFS_sint64 staticWrite(struct PHYSFS_Io *io, const void *buf, PHYSFS_uint64 len) { return derived(io)->write(buf, len); } // Returns: non-zero on success, zero on error - static int staticSeek(struct PHYSFS_Io* io, PHYSFS_uint64 offset) + static int staticSeek(struct PHYSFS_Io *io, PHYSFS_uint64 offset) { return derived(io)->seek(offset); } // Returns: current offset from start, -1 on error - static PHYSFS_sint64 staticTell(struct PHYSFS_Io* io) + static PHYSFS_sint64 staticTell(struct PHYSFS_Io *io) { return derived(io)->tell(); } // Returns: total size in bytes, -1 on error - static PHYSFS_sint64 staticLength(struct PHYSFS_Io* io) + static PHYSFS_sint64 staticLength(struct PHYSFS_Io *io) { return derived(io)->length(); } - static struct PHYSFS_Io* staticDuplicate(struct PHYSFS_Io* io) + static struct PHYSFS_Io *staticDuplicate(struct PHYSFS_Io *io) { // Just use copy constructor return new Derived(*derived(io)); } // Returns: non-zero on success, zero on error - static int staticFlush(struct PHYSFS_Io* io) + static int staticFlush(struct PHYSFS_Io *io) { return derived(io)->flush(); } - static void staticDestroy(struct PHYSFS_Io* io) + static void staticDestroy(struct PHYSFS_Io *io) { // Just use destructor delete derived(io); } - static Derived* derived(PHYSFS_Io* io) + static Derived* derived(PHYSFS_Io *io) { return static_cast(reinterpret_cast(io->opaque)); } @@ -116,47 +116,52 @@ private: struct StripSuffixIo : public PhysfsIo { - static const uint32_t version = 0; + static const uint32 version = 0; std::string filename; - FILE* file = nullptr; + NativeFile *file = nullptr; // The constructor is private in favor of this function to prevent stack allocation // because Physfs will take ownership of this object and call destroy on it later. - static StripSuffixIo* create(std::string f) { return new StripSuffixIo(f); } + static StripSuffixIo *create(const std::string &f) { return new StripSuffixIo(f); } virtual ~StripSuffixIo() { if (file) { - std::fclose(file); + file->release(); } } - StripSuffixIo(const StripSuffixIo& other) + StripSuffixIo(const StripSuffixIo &other) : StripSuffixIo(other.filename) { } bool determineStrippedLength(); - int64_t read(void* buf, uint64_t len); - int64_t write(const void* buf, uint64_t len); - int64_t seek(uint64_t offset); - int64_t tell(); - int64_t length(); - int64_t flush(); + int64 read(void *buf, uint64 len); + int64 write(const void *buf, uint64 len); + int64 seek(uint64 offset); + int64 tell(); + int64 length(); + int64 flush(); private: - StripSuffixIo(std::string f) - : filename(std::move(f)) - , file(std::fopen(filename.c_str(), "rb")) + StripSuffixIo(const std::string &f) + : filename(f) + , file(nullptr) { + try + { + file = new NativeFile(f, File::MODE_READ); + } + catch (love::Exception &) + { + } } - int64_t fullLength(); - int64_t strippedLength_ = -1; }; diff --git a/src/modules/filesystem/wrap_File.cpp b/src/modules/filesystem/wrap_File.cpp index 998133047..4fa851a76 100644 --- a/src/modules/filesystem/wrap_File.cpp +++ b/src/modules/filesystem/wrap_File.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_File.h b/src/modules/filesystem/wrap_File.h index e935436bc..10277996f 100644 --- a/src/modules/filesystem/wrap_File.h +++ b/src/modules/filesystem/wrap_File.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_FileData.cpp b/src/modules/filesystem/wrap_FileData.cpp index 1135a5c1a..00e288fe4 100644 --- a/src/modules/filesystem/wrap_FileData.cpp +++ b/src/modules/filesystem/wrap_FileData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_FileData.h b/src/modules/filesystem/wrap_FileData.h index 0f036f365..58b870df0 100644 --- a/src/modules/filesystem/wrap_FileData.h +++ b/src/modules/filesystem/wrap_FileData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp index cb4e25dbe..65ed25eec 100644 --- a/src/modules/filesystem/wrap_Filesystem.cpp +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_Filesystem.h b/src/modules/filesystem/wrap_Filesystem.h index c32f794d9..d092ffac0 100644 --- a/src/modules/filesystem/wrap_Filesystem.h +++ b/src/modules/filesystem/wrap_Filesystem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_NativeFile.cpp b/src/modules/filesystem/wrap_NativeFile.cpp index 7dacb76c9..ca5a39130 100644 --- a/src/modules/filesystem/wrap_NativeFile.cpp +++ b/src/modules/filesystem/wrap_NativeFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/filesystem/wrap_NativeFile.h b/src/modules/filesystem/wrap_NativeFile.h index 8121f598a..aaa62569c 100644 --- a/src/modules/filesystem/wrap_NativeFile.h +++ b/src/modules/filesystem/wrap_NativeFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/BMFontRasterizer.cpp b/src/modules/font/BMFontRasterizer.cpp index 660c4ce35..b08c2a621 100644 --- a/src/modules/font/BMFontRasterizer.cpp +++ b/src/modules/font/BMFontRasterizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -343,6 +343,7 @@ GlyphData *BMFontRasterizer::getGlyphDataForIndex(int index) const uint8 *pixels = (uint8 *) g->getData(); const uint8 *ipixels = (const uint8 *) imagedata->getData(); + // Always lock the mutex since the user can't know when to do it. love::thread::Lock lock(imagedata->getMutex()); // Copy the subsection of the texture from the ImageData to the GlyphData. diff --git a/src/modules/font/BMFontRasterizer.h b/src/modules/font/BMFontRasterizer.h index 3d4a452f8..43b5a84c4 100644 --- a/src/modules/font/BMFontRasterizer.h +++ b/src/modules/font/BMFontRasterizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/Font.cpp b/src/modules/font/Font.cpp index f3f85bfa5..e81b06a75 100644 --- a/src/modules/font/Font.cpp +++ b/src/modules/font/Font.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -34,7 +34,8 @@ namespace font // Default TrueType font, gzip-compressed. #include "NotoSans-Regular.ttf.gzip.h" -Font::Font() +Font::Font(const char *name) + : Module(M_FONT, name) { auto compressedbytes = (const char *) NotoSans_Regular_ttf_gzip; size_t compressedsize = NotoSans_Regular_ttf_gzip_len; diff --git a/src/modules/font/Font.h b/src/modules/font/Font.h index 3b217a33a..2fb1a69ea 100644 --- a/src/modules/font/Font.h +++ b/src/modules/font/Font.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,7 +43,6 @@ class Font : public Module public: - Font(); virtual ~Font() {} virtual Rasterizer *newRasterizer(love::filesystem::FileData *data) = 0; @@ -58,9 +57,9 @@ public: virtual GlyphData *newGlyphData(Rasterizer *r, const std::string &glyph); virtual GlyphData *newGlyphData(Rasterizer *r, uint32 glyph); - // Implement Module. - virtual ModuleType getModuleType() const { return M_FONT; } - virtual const char *getName() const = 0; +protected: + + Font(const char *name); private: diff --git a/src/modules/font/GenericShaper.cpp b/src/modules/font/GenericShaper.cpp index d96e8f90f..813f31a0a 100644 --- a/src/modules/font/GenericShaper.cpp +++ b/src/modules/font/GenericShaper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/GenericShaper.h b/src/modules/font/GenericShaper.h index c77b5b309..49763d789 100644 --- a/src/modules/font/GenericShaper.h +++ b/src/modules/font/GenericShaper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/GlyphData.cpp b/src/modules/font/GlyphData.cpp index 8b1d4c285..8db2e9ea2 100644 --- a/src/modules/font/GlyphData.cpp +++ b/src/modules/font/GlyphData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/GlyphData.h b/src/modules/font/GlyphData.h index 0f214cb4f..4e4791538 100644 --- a/src/modules/font/GlyphData.h +++ b/src/modules/font/GlyphData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/ImageRasterizer.cpp b/src/modules/font/ImageRasterizer.cpp index 93b71b894..00adc5f96 100644 --- a/src/modules/font/ImageRasterizer.cpp +++ b/src/modules/font/ImageRasterizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -90,7 +90,7 @@ GlyphData *ImageRasterizer::getGlyphDataForIndex(int index) const if (gm.width == 0) return g; - // We don't want another thread modifying our ImageData mid-copy. + // Always lock the mutex since the user can't know when to do it. love::thread::Lock lock(imageData->getMutex()); Color32 *gdpixels = (Color32 *) g->getData(); @@ -118,9 +118,6 @@ void ImageRasterizer::load(const uint32 *glyphs, int glyphcount) int imgw = imageData->getWidth(); int imgh = imageData->getHeight(); - // We don't want another thread modifying our ImageData mid-parse. - love::thread::Lock lock(imageData->getMutex()); - // Set the only metric that matters metrics.height = imgh; diff --git a/src/modules/font/ImageRasterizer.h b/src/modules/font/ImageRasterizer.h index 538b6dbd5..266a61a24 100644 --- a/src/modules/font/ImageRasterizer.h +++ b/src/modules/font/ImageRasterizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/Rasterizer.cpp b/src/modules/font/Rasterizer.cpp index 53fa2d7f3..c5ff73f84 100644 --- a/src/modules/font/Rasterizer.cpp +++ b/src/modules/font/Rasterizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/Rasterizer.h b/src/modules/font/Rasterizer.h index 67575edd6..20174e498 100644 --- a/src/modules/font/Rasterizer.h +++ b/src/modules/font/Rasterizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/TextShaper.cpp b/src/modules/font/TextShaper.cpp index 8abf2b19c..555ef598e 100644 --- a/src/modules/font/TextShaper.cpp +++ b/src/modules/font/TextShaper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/TextShaper.h b/src/modules/font/TextShaper.h index b5417514c..9ddf7f9e1 100644 --- a/src/modules/font/TextShaper.h +++ b/src/modules/font/TextShaper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/TrueTypeRasterizer.cpp b/src/modules/font/TrueTypeRasterizer.cpp index eb9a1740d..e91523281 100644 --- a/src/modules/font/TrueTypeRasterizer.cpp +++ b/src/modules/font/TrueTypeRasterizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/TrueTypeRasterizer.h b/src/modules/font/TrueTypeRasterizer.h index 62d7253ab..eebfac6a3 100644 --- a/src/modules/font/TrueTypeRasterizer.h +++ b/src/modules/font/TrueTypeRasterizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/freetype/Font.cpp b/src/modules/font/freetype/Font.cpp index 9a52f7b08..1e8f61b46 100644 --- a/src/modules/font/freetype/Font.cpp +++ b/src/modules/font/freetype/Font.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -36,6 +36,7 @@ namespace freetype { Font::Font() + : love::font::Font("love.font.freetype") { if (FT_Init_FreeType(&library)) throw love::Exception("TrueTypeFont Loading error: FT_Init_FreeType failed"); @@ -66,11 +67,6 @@ Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, const font:: return new TrueTypeRasterizer(library, data, size, settings, defaultdpiscale); } -const char *Font::getName() const -{ - return "love.font.freetype"; -} - } // freetype } // font } // love diff --git a/src/modules/font/freetype/Font.h b/src/modules/font/freetype/Font.h index 0a4c70e86..c946925ad 100644 --- a/src/modules/font/freetype/Font.h +++ b/src/modules/font/freetype/Font.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -47,9 +47,6 @@ public: Rasterizer *newRasterizer(love::filesystem::FileData *data) override; Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings) override; - // Implement Module - const char *getName() const override; - private: // FreeType library diff --git a/src/modules/font/freetype/HarfbuzzShaper.cpp b/src/modules/font/freetype/HarfbuzzShaper.cpp index f7828cecf..cd595c888 100644 --- a/src/modules/font/freetype/HarfbuzzShaper.cpp +++ b/src/modules/font/freetype/HarfbuzzShaper.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/freetype/HarfbuzzShaper.h b/src/modules/font/freetype/HarfbuzzShaper.h index 8324b0a7c..81e4f3c65 100644 --- a/src/modules/font/freetype/HarfbuzzShaper.h +++ b/src/modules/font/freetype/HarfbuzzShaper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/freetype/TrueTypeRasterizer.cpp b/src/modules/font/freetype/TrueTypeRasterizer.cpp index 1baed329a..bd236aabe 100644 --- a/src/modules/font/freetype/TrueTypeRasterizer.cpp +++ b/src/modules/font/freetype/TrueTypeRasterizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/freetype/TrueTypeRasterizer.h b/src/modules/font/freetype/TrueTypeRasterizer.h index e26b79646..534034ab3 100644 --- a/src/modules/font/freetype/TrueTypeRasterizer.h +++ b/src/modules/font/freetype/TrueTypeRasterizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/wrap_Font.cpp b/src/modules/font/wrap_Font.cpp index 8a843c413..a43377bb0 100644 --- a/src/modules/font/wrap_Font.cpp +++ b/src/modules/font/wrap_Font.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/wrap_Font.h b/src/modules/font/wrap_Font.h index ddbe327eb..a52de0ed0 100644 --- a/src/modules/font/wrap_Font.h +++ b/src/modules/font/wrap_Font.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/wrap_GlyphData.cpp b/src/modules/font/wrap_GlyphData.cpp index 68a232531..a411957dd 100644 --- a/src/modules/font/wrap_GlyphData.cpp +++ b/src/modules/font/wrap_GlyphData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/wrap_GlyphData.h b/src/modules/font/wrap_GlyphData.h index e71062fe3..59a6d257e 100644 --- a/src/modules/font/wrap_GlyphData.h +++ b/src/modules/font/wrap_GlyphData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/wrap_Rasterizer.cpp b/src/modules/font/wrap_Rasterizer.cpp index 2340b6abe..88a063c15 100644 --- a/src/modules/font/wrap_Rasterizer.cpp +++ b/src/modules/font/wrap_Rasterizer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/font/wrap_Rasterizer.h b/src/modules/font/wrap_Rasterizer.h index 0359656a9..83c8a6009 100644 --- a/src/modules/font/wrap_Rasterizer.h +++ b/src/modules/font/wrap_Rasterizer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 9b46218f6..1657251b6 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Buffer.h b/src/modules/graphics/Buffer.h index 6e1245502..67fc6757e 100644 --- a/src/modules/graphics/Buffer.h +++ b/src/modules/graphics/Buffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Deprecations.cpp b/src/modules/graphics/Deprecations.cpp index 6e43a9350..7200dd32a 100644 --- a/src/modules/graphics/Deprecations.cpp +++ b/src/modules/graphics/Deprecations.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Deprecations.h b/src/modules/graphics/Deprecations.h index 6014d1fe1..e2aeae419 100644 --- a/src/modules/graphics/Deprecations.h +++ b/src/modules/graphics/Deprecations.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Drawable.cpp b/src/modules/graphics/Drawable.cpp index 44762c9c1..5e4880913 100644 --- a/src/modules/graphics/Drawable.cpp +++ b/src/modules/graphics/Drawable.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Drawable.h b/src/modules/graphics/Drawable.h index 0703d3c62..6eb573aa8 100644 --- a/src/modules/graphics/Drawable.h +++ b/src/modules/graphics/Drawable.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Font.cpp b/src/modules/graphics/Font.cpp index a4e3485b0..c5303b6ad 100644 --- a/src/modules/graphics/Font.cpp +++ b/src/modules/graphics/Font.cpp @@ -1,5 +1,5 @@ /** -* Copyright (c) 2006-2023 LOVE Development Team +* Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Font.h b/src/modules/graphics/Font.h index 873fcc696..215c809e0 100644 --- a/src/modules/graphics/Font.h +++ b/src/modules/graphics/Font.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index d22da3338..7d58e4ed6 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -180,8 +180,9 @@ Graphics::DisplayState::DisplayState() defaultSamplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_LINEAR; } -Graphics::Graphics() - : width(0) +Graphics::Graphics(const char *name) + : Module(M_GRAPHICS, name) + , width(0) , height(0) , pixelWidth(0) , pixelHeight(0) @@ -1202,15 +1203,16 @@ bool Graphics::isRenderTargetActive() const bool Graphics::isRenderTargetActive(Texture *texture) const { + Texture *roottexture = texture->getRootViewInfo().texture; const auto &rts = states.back().renderTargets; for (const auto &rt : rts.colors) { - if (rt.texture.get() == texture) + if (rt.texture.get() && rt.texture->getRootViewInfo().texture == roottexture) return true; } - if (rts.depthStencil.texture.get() == texture) + if (rts.depthStencil.texture.get() && rts.depthStencil.texture->getRootViewInfo().texture == roottexture) return true; return false; @@ -1218,16 +1220,27 @@ bool Graphics::isRenderTargetActive(Texture *texture) const bool Graphics::isRenderTargetActive(Texture *texture, int slice) const { + const auto &rootinfo = texture->getRootViewInfo(); + slice += rootinfo.startLayer; + const auto &rts = states.back().renderTargets; for (const auto &rt : rts.colors) { - if (rt.texture.get() == texture && rt.slice == slice) - return true; + if (rt.texture.get()) + { + const auto &info = rt.texture->getRootViewInfo(); + if (rootinfo.texture == info.texture && rt.slice + info.startLayer == slice) + return true; + } } - if (rts.depthStencil.texture.get() == texture && rts.depthStencil.slice == slice) - return true; + if (rts.depthStencil.texture.get()) + { + const auto &info = rts.depthStencil.texture->getRootViewInfo(); + if (rootinfo.texture == info.texture && rts.depthStencil.slice + info.startLayer == slice) + return true; + } return false; } @@ -2576,21 +2589,42 @@ void Graphics::polygon(DrawMode mode, const Vector2 *coords, size_t count, bool BatchedDrawCommand cmd; cmd.formats[0] = getSinglePositionFormat(is2D); - cmd.formats[1] = CommonFormat::RGBAub; + cmd.formats[1] = CommonFormat::STf_RGBAub; cmd.indexMode = TRIANGLEINDEX_FAN; cmd.vertexCount = (int)count - (skipLastFilledVertex ? 1 : 0); BatchedVertexData data = requestBatchedDraw(cmd); - if (is2D) - t.transformXY((Vector2 *) data.stream[0], coords, cmd.vertexCount); - else - t.transformXY0((Vector3 *) data.stream[0], coords, cmd.vertexCount); + // Compute texture coordinates. + constexpr float inf = std::numeric_limits::infinity(); + Vector2 mincoord(inf, inf); + Vector2 maxcoord(-inf, -inf); + + for (int i = 0; i < cmd.vertexCount; i++) + { + Vector2 v = coords[i]; + mincoord.x = std::min(mincoord.x, v.x); + mincoord.y = std::min(mincoord.y, v.y); + maxcoord.x = std::max(maxcoord.x, v.x); + maxcoord.y = std::max(maxcoord.y, v.y); + } + + Vector2 invsize(1.0f / (maxcoord.x - mincoord.x), 1.0f / (maxcoord.y - mincoord.y)); + Vector2 start(mincoord.x * invsize.x, mincoord.y * invsize.y); Color32 c = toColor32(getColor()); - Color32 *colordata = (Color32 *) data.stream[1]; + STf_RGBAub *attributes = (STf_RGBAub *) data.stream[1]; for (int i = 0; i < cmd.vertexCount; i++) - colordata[i] = c; + { + attributes[i].s = coords[i].x * invsize.x - start.x; + attributes[i].t = coords[i].y * invsize.y - start.y; + attributes[i].color = c; + } + + if (is2D) + t.transformXY((Vector2*)data.stream[0], coords, cmd.vertexCount); + else + t.transformXY0((Vector3*)data.stream[0], coords, cmd.vertexCount); } } @@ -2768,27 +2802,6 @@ Vector2 Graphics::inverseTransformPoint(Vector2 point) return p; } -void Graphics::setOrthoProjection(float w, float h, float near, float far) -{ - if (near >= far) - throw love::Exception("Orthographic projection Z far value must be greater than the Z near value."); - - Matrix4 m = Matrix4::ortho(0.0f, w, 0.0f, h, near, far); - setCustomProjection(m); -} - -void Graphics::setPerspectiveProjection(float verticalfov, float aspect, float near, float far) -{ - if (near <= 0.0f) - throw love::Exception("Perspective projection Z near value must be greater than 0."); - - if (near >= far) - throw love::Exception("Perspective projection Z far value must be greater than the Z near value."); - - Matrix4 m = Matrix4::perspective(verticalfov, aspect, near, far); - setCustomProjection(m); -} - void Graphics::setCustomProjection(const Matrix4 &m) { flushBatchedDraws(); @@ -2818,29 +2831,14 @@ void Graphics::resetProjection() state.useCustomProjection = false; - updateDeviceProjection(Matrix4::ortho(0.0f, w, 0.0f, h, -10.0f, 10.0f)); + // NDC is y-up. The ortho() parameter names assume that as well. We want + // a y-down projection, so we set bottom to h and top to 0. + updateDeviceProjection(Matrix4::ortho(0.0f, w, h, 0.0f, -10.0f, 10.0f)); } void Graphics::updateDeviceProjection(const Matrix4 &projection) { - // Note: graphics implementations define computeDeviceProjection. - deviceProjectionMatrix = computeDeviceProjection(projection, isRenderTargetActive()); -} - -Matrix4 Graphics::calculateDeviceProjection(const Matrix4 &projection, uint32 flags) const -{ - Matrix4 m = projection; - bool reverseZ = (flags & DEVICE_PROJECTION_REVERSE_Z) != 0; - - if (flags & DEVICE_PROJECTION_FLIP_Y) - m.setRow(1, -m.getRow(1)); - - if (flags & DEVICE_PROJECTION_Z_01) // Go from Z [-1, 1] to Z [0, 1]. - m.setRow(2, m.getRow(2) * (reverseZ ? -0.5f : 0.5f) + m.getRow(3)); - else if (reverseZ) - m.setRow(2, -m.getRow(2)); - - return m; + deviceProjectionMatrix = projection; } STRINGMAP_CLASS_BEGIN(Graphics, Graphics::DrawMode, Graphics::DRAW_MAX_ENUM, drawMode) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 1968da453..50bc8e65a 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -451,13 +451,11 @@ public: } }; - Graphics(); + Graphics(const char *name); virtual ~Graphics(); - // Implements Module. - virtual ModuleType getModuleType() const { return M_GRAPHICS; } - virtual Texture *newTexture(const Texture::Settings &settings, const Texture::Slices *data = nullptr) = 0; + virtual Texture *newTextureView(Texture *base, const Texture::ViewSettings &viewsettings) = 0; Quad *newQuad(Quad::Viewport v, double sw, double sh); Font *newFont(love::font::Rasterizer *data); @@ -629,6 +627,9 @@ public: void setMeshCullMode(CullMode cull); CullMode getMeshCullMode() const; + // Note: These are meant to be relative to the y-down default projection, + // which may be flipped compared to device NDC. Implementations may have + // to flip the winding internally. virtual void setFrontFaceWinding(Winding winding) = 0; Winding getFrontFaceWinding() const; @@ -877,13 +878,9 @@ public: Vector2 transformPoint(Vector2 point); Vector2 inverseTransformPoint(Vector2 point); - void setOrthoProjection(float w, float h, float near, float far); - void setPerspectiveProjection(float verticalfov, float aspect, float near, float far); void setCustomProjection(const Matrix4 &m); void resetProjection(); - virtual Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const = 0; - virtual void draw(const DrawCommand &cmd) = 0; virtual void draw(const DrawIndexedCommand &cmd) = 0; virtual void drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, Texture *texture) = 0; @@ -926,14 +923,6 @@ public: protected: - enum DeviceProjectionFlags - { - DEVICE_PROJECTION_DEFAULT = 0, - DEVICE_PROJECTION_FLIP_Y = (1 << 0), - DEVICE_PROJECTION_Z_01 = (1 << 1), - DEVICE_PROJECTION_REVERSE_Z = (1 << 2), - }; - struct DisplayState { DisplayState(); @@ -1062,7 +1051,6 @@ protected: void popTransform(); void updateDeviceProjection(const Matrix4 &projection); - Matrix4 calculateDeviceProjection(const Matrix4 &projection, uint32 flags) const; int width; int height; diff --git a/src/modules/graphics/GraphicsReadback.cpp b/src/modules/graphics/GraphicsReadback.cpp index 0289bddf7..a1506d052 100644 --- a/src/modules/graphics/GraphicsReadback.cpp +++ b/src/modules/graphics/GraphicsReadback.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -192,6 +192,7 @@ GraphicsReadback::Status GraphicsReadback::readbackBuffer(Buffer *buffer, size_t if (imageData.get()) { + // Always lock the mutex since the user can't know when to do it. love::thread::Lock lock(imageData->getMutex()); if (imageData->getWidth() != rect.w) diff --git a/src/modules/graphics/GraphicsReadback.h b/src/modules/graphics/GraphicsReadback.h index 8990314d3..3e8a42e91 100644 --- a/src/modules/graphics/GraphicsReadback.h +++ b/src/modules/graphics/GraphicsReadback.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 381daf723..adbd8c896 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index 6002971a6..f48df211d 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/ParticleSystem.cpp b/src/modules/graphics/ParticleSystem.cpp index 0f51b1324..64db60f70 100644 --- a/src/modules/graphics/ParticleSystem.cpp +++ b/src/modules/graphics/ParticleSystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/ParticleSystem.h b/src/modules/graphics/ParticleSystem.h index 9343ad24f..05727d838 100644 --- a/src/modules/graphics/ParticleSystem.h +++ b/src/modules/graphics/ParticleSystem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Polyline.cpp b/src/modules/graphics/Polyline.cpp index 5e58d5b68..f9537067d 100644 --- a/src/modules/graphics/Polyline.cpp +++ b/src/modules/graphics/Polyline.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -424,7 +424,7 @@ void Polyline::draw(love::graphics::Graphics *gfx) Graphics::BatchedDrawCommand cmd; cmd.formats[0] = getSinglePositionFormat(is2D); - cmd.formats[1] = CommonFormat::RGBAub; + cmd.formats[1] = CommonFormat::STf_RGBAub; cmd.indexMode = triangle_mode; cmd.vertexCount = std::min(maxvertices, total_vertex_count - vertex_start); @@ -435,13 +435,19 @@ void Polyline::draw(love::graphics::Graphics *gfx) else t.transformXY0((Vector3 *) data.stream[0], verts, cmd.vertexCount); - Color32 *colordata = (Color32 *) data.stream[1]; + STf_RGBAub *attributes = (STf_RGBAub *) data.stream[1]; int draw_rough_count = std::min(cmd.vertexCount, (int) vertex_count - vertex_start); // Constant vertex color up to the overdraw vertices. + // Texture coordinates are a constant value, we only have them to keep auto-batching + // when drawing filled and line polygons together. for (int i = 0; i < draw_rough_count; i++) - colordata[i] = curcolor; + { + attributes[i].s = 0.0f; + attributes[i].t = 0.0f; + attributes[i].color = curcolor; + } if (overdraw) { @@ -456,30 +462,34 @@ void Polyline::draw(love::graphics::Graphics *gfx) if (draw_overdraw_count > 0) { - Color32 *colors = colordata + draw_overdraw_begin; - fill_color_array(curcolor, colors, draw_overdraw_count); + STf_RGBAub *c = attributes + draw_overdraw_begin; + fill_color_array(curcolor, c, draw_overdraw_count); } } } } -void Polyline::fill_color_array(Color32 constant_color, Color32 *colors, int count) +void Polyline::fill_color_array(Color32 constant_color, STf_RGBAub *attributes, int count) { for (int i = 0; i < count; ++i) { Color32 c = constant_color; c.a *= (i+1) % 2; // avoids branching. equiv to if (i%2 == 1) c.a = 0; - colors[i] = c; + attributes[i].s = 0.0f; + attributes[i].t = 0.0f; + attributes[i].color = c; } } -void NoneJoinPolyline::fill_color_array(Color32 constant_color, Color32 *colors, int count) +void NoneJoinPolyline::fill_color_array(Color32 constant_color, STf_RGBAub *attributes, int count) { for (int i = 0; i < count; ++i) { Color32 c = constant_color; c.a *= (i & 3) < 2; // if (i % 4 == 2 || i % 4 == 3) c.a = 0 - colors[i] = c; + attributes[i].s = 0.0f; + attributes[i].t = 0.0f; + attributes[i].color = c; } } diff --git a/src/modules/graphics/Polyline.h b/src/modules/graphics/Polyline.h index 7685efd12..2acf88382 100644 --- a/src/modules/graphics/Polyline.h +++ b/src/modules/graphics/Polyline.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -73,7 +73,7 @@ protected: virtual void calc_overdraw_vertex_count(bool is_looping); virtual void render_overdraw(const std::vector &normals, float pixel_size, bool is_looping); - virtual void fill_color_array(Color32 constant_color, Color32 *colors, int count); + virtual void fill_color_array(Color32 constant_color, STf_RGBAub *attributes, int count); /** Calculate line boundary points. * @@ -133,7 +133,7 @@ protected: void calc_overdraw_vertex_count(bool is_looping) override; void render_overdraw(const std::vector &normals, float pixel_size, bool is_looping) override; - void fill_color_array(Color32 constant_color, Color32 *colors, int count) override; + void fill_color_array(Color32 constant_color, STf_RGBAub *attributes, int count) override; void renderEdge(std::vector &anchors, std::vector &normals, Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q, const Vector2 &r, float hw) override; diff --git a/src/modules/graphics/Quad.cpp b/src/modules/graphics/Quad.cpp index 0d218dc38..40c7a9737 100644 --- a/src/modules/graphics/Quad.cpp +++ b/src/modules/graphics/Quad.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Quad.h b/src/modules/graphics/Quad.h index eba404432..8e7d08c53 100644 --- a/src/modules/graphics/Quad.h +++ b/src/modules/graphics/Quad.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Resource.h b/src/modules/graphics/Resource.h index 17d23e893..b277e22f5 100644 --- a/src/modules/graphics/Resource.h +++ b/src/modules/graphics/Resource.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp index ca708efe7..c3839a421 100644 --- a/src/modules/graphics/Shader.cpp +++ b/src/modules/graphics/Shader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -26,6 +26,7 @@ // glslang #include "libraries/glslang/glslang/Public/ShaderLang.h" +#include "libraries/glslang/glslang/Public/ResourceLimits.h" // Needed for reflection information. #include "libraries/glslang/glslang/Include/Types.h" @@ -91,10 +92,10 @@ static const char render_uniforms[] = R"( // but we can't guarantee that highp is always supported in fragment shaders... // We *really* don't want to use mediump for these in vertex shaders though. #ifdef LOVE_SPLIT_UNIFORMS_PER_DRAW -uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[12]; +uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13]; uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw2[1]; #else -uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13]; +uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[14]; #endif // Older GLSL doesn't support preprocessor line continuations... @@ -106,12 +107,15 @@ uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13]; #define CurrentDPIScale (love_UniformsPerDraw[8].w) #define ConstantPointSize (love_UniformsPerDraw[9].w) -#define ConstantColor (love_UniformsPerDraw[11]) + +#define love_ClipSpaceParams (love_UniformsPerDraw[11]) + +#define ConstantColor (love_UniformsPerDraw[12]) #ifdef LOVE_SPLIT_UNIFORMS_PER_DRAW #define love_ScreenSize (love_UniformsPerDraw2[0]) #else -#define love_ScreenSize (love_UniformsPerDraw[12]) +#define love_ScreenSize (love_UniformsPerDraw[13]) #endif // Alternate names @@ -123,16 +127,17 @@ uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13]; static const char global_functions[] = R"( #ifdef GL_ES + precision mediump sampler2D; #if __VERSION__ >= 300 || defined(LOVE_EXT_TEXTURE_ARRAY_ENABLED) - precision lowp sampler2DArray; + precision mediump sampler2DArray; #endif #if __VERSION__ >= 300 || defined(GL_OES_texture_3D) - precision lowp sampler3D; + precision mediump sampler3D; #endif #if __VERSION__ >= 300 && !defined(LOVE_GLSL1_ON_GLSL3) - precision lowp sampler2DShadow; - precision lowp samplerCubeShadow; - precision lowp sampler2DArrayShadow; + precision mediump sampler2DShadow; + precision mediump samplerCubeShadow; + precision mediump sampler2DArrayShadow; #endif #endif @@ -246,7 +251,13 @@ static const char vertex_header[] = R"( #endif )"; -static const char vertex_functions[] = R"()"; +static const char vertex_functions[] = R"( +vec4 love_clipSpaceTransform(vec4 clipPosition) { + clipPosition.y *= love_ClipSpaceParams.x; + clipPosition.z = (love_ClipSpaceParams.y * clipPosition.z + love_ClipSpaceParams.z * clipPosition.w) * love_ClipSpaceParams.w; + return clipPosition; +} +)"; static const char vertex_main[] = R"( LOVE_IO_LOCATION(0) attribute vec4 VertexPosition; @@ -262,6 +273,7 @@ void main() { VaryingTexCoord = VertexTexCoord; VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor; love_Position = position(ClipSpaceFromLocal, VertexPosition); + love_Position = love_clipSpaceTransform(love_Position); } )"; @@ -270,6 +282,7 @@ void vertexmain(); void main() { vertexmain(); + love_Position = love_clipSpaceTransform(love_Position); } )"; @@ -586,7 +599,7 @@ static Shader::EntryPoint getComputeEntryPoint(const std::string &src, const std } // glsl -static_assert(sizeof(Shader::BuiltinUniformData) == sizeof(float) * 4 * 13, "Update the array in wrap_GraphicsShader.lua if this changes."); +static_assert(sizeof(Shader::BuiltinUniformData) == sizeof(float) * 4 * 14, "Update the array in wrap_GraphicsShader.lua if this changes."); love::Type Shader::type("Shader", &Object::type); @@ -691,9 +704,48 @@ Shader::Shader(StrongRef _stages[], const CompileOptions &options) , debugName(options.debugName) { std::string err; - if (!validateInternal(_stages, err, validationReflection)) + if (!validateInternal(_stages, err, reflection)) throw love::Exception("%s", err.c_str()); + activeTextures.resize(reflection.textureCount); + activeBuffers.resize(reflection.bufferCount); + + auto gfx = Module::getInstance(Module::M_GRAPHICS); + + // Default bindings for read-only resources. + for (const auto &kvp : reflection.allUniforms) + { + const auto &u = *kvp.second; + + if (u.resourceIndex < 0) + continue; + + if ((u.access & ACCESS_WRITE) != 0) + continue; + + if (u.baseType == UNIFORM_SAMPLER || u.baseType == UNIFORM_STORAGETEXTURE) + { + auto tex = gfx->getDefaultTexture(u.textureType, u.dataBaseType); + for (int i = 0; i < u.count; i++) + { + tex->retain(); + activeTextures[u.resourceIndex + i] = tex; + } + } + else if (u.baseType == UNIFORM_TEXELBUFFER || u.baseType == UNIFORM_STORAGEBUFFER) + { + auto buffer = u.baseType == UNIFORM_TEXELBUFFER + ? gfx->getDefaultTexelBuffer(u.dataBaseType) + : gfx->getDefaultStorageBuffer(); + + for (int i = 0; i < u.count; i++) + { + buffer->retain(); + activeBuffers[u.resourceIndex + i] = buffer; + } + } + } + for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) stages[i] = _stages[i]; } @@ -708,6 +760,18 @@ Shader::~Shader() if (current == this) attachDefault(STANDARD_DEFAULT); + + for (Texture *tex : activeTextures) + { + if (tex) + tex->release(); + } + + for (Buffer *buffer : activeBuffers) + { + if (buffer) + buffer->release(); + } } bool Shader::hasStage(ShaderStageType stage) @@ -740,6 +804,40 @@ bool Shader::isDefaultActive() return false; } +Vector4 Shader::computeClipSpaceParams(uint32 clipSpaceTransformFlags) +{ + // See the love_clipSpaceTransform vertex shader function. + Vector4 params(1.0f, 1.0f, 0.0f, 1.0f); + + if (clipSpaceTransformFlags & CLIP_TRANSFORM_FLIP_Y) + params.x = -1.0f; + + if (clipSpaceTransformFlags & CLIP_TRANSFORM_Z_NEG1_1_TO_0_1) + { + params.z = 1.0f; + params.w = 0.5f; + } + else if (clipSpaceTransformFlags & CLIP_TRANSFORM_Z_0_1_TO_NEG1_1) + { + params.y = 2.0f; + params.z = -1.0f; + } + + return params; +} + +const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const +{ + const auto it = reflection.allUniforms.find(name); + return it != reflection.allUniforms.end() ? it->second : nullptr; +} + +bool Shader::hasUniform(const std::string &name) const +{ + const auto it = reflection.allUniforms.find(name); + return it != reflection.allUniforms.end() && it->second->active; +} + const Shader::UniformInfo *Shader::getMainTextureInfo() const { return getUniformInfo(BUILTIN_TEXTURE_MAIN); @@ -781,9 +879,9 @@ bool Shader::isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b) void Shader::validateDrawState(PrimitiveType primtype, Texture *maintex) const { - if ((primtype == PRIMITIVE_POINTS) != validationReflection.usesPointSize) + if ((primtype == PRIMITIVE_POINTS) != reflection.usesPointSize) { - if (validationReflection.usesPointSize) + if (reflection.usesPointSize) throw love::Exception("The active shader can only be used to draw points."); else throw love::Exception("The gl_PointSize variable must be set in a vertex shader when drawing points."); @@ -825,17 +923,29 @@ void Shader::validateDrawState(PrimitiveType primtype, Texture *maintex) const void Shader::getLocalThreadgroupSize(int *x, int *y, int *z) { - *x = validationReflection.localThreadgroupSize[0]; - *y = validationReflection.localThreadgroupSize[1]; - *z = validationReflection.localThreadgroupSize[2]; + *x = reflection.localThreadgroupSize[0]; + *y = reflection.localThreadgroupSize[1]; + *z = reflection.localThreadgroupSize[2]; } bool Shader::validate(StrongRef stages[], std::string& err) { - ValidationReflection reflection; + Reflection reflection; return validateInternal(stages, err, reflection); } +static DataBaseType getBaseType(glslang::TBasicType basictype) +{ + switch (basictype) + { + case glslang::EbtInt: return DATA_BASETYPE_INT; + case glslang::EbtUint: return DATA_BASETYPE_UINT; + case glslang::EbtFloat: return DATA_BASETYPE_FLOAT; + case glslang::EbtBool: return DATA_BASETYPE_BOOL; + default: return DATA_BASETYPE_FLOAT; + } +} + static PixelFormat getPixelFormat(glslang::TLayoutFormat format) { using namespace glslang; @@ -885,6 +995,30 @@ static PixelFormat getPixelFormat(glslang::TLayoutFormat format) } } +static TextureType getTextureType(const glslang::TSampler &sampler) +{ + if (sampler.is2D()) + return sampler.isArrayed() ? TEXTURE_2D_ARRAY : TEXTURE_2D; + else if (sampler.dim == glslang::EsdCube) + return sampler.isArrayed() ? TEXTURE_MAX_ENUM : TEXTURE_CUBE; + else if (sampler.dim == glslang::Esd3D) + return TEXTURE_VOLUME; + else + return TEXTURE_MAX_ENUM; +} + +static uint32 getStageMask(EShLanguageMask mask) +{ + uint32 m = 0; + if (mask & EShLangVertexMask) + m |= SHADERSTAGEMASK_VERTEX; + if (mask & EShLangFragmentMask) + m |= SHADERSTAGEMASK_PIXEL; + if (mask & EShLangComputeMask) + m |= SHADERSTAGEMASK_COMPUTE; + return m; +} + template static T convertData(const glslang::TConstUnion &data) { @@ -903,7 +1037,7 @@ static T convertData(const glslang::TConstUnion &data) } } -bool Shader::validateInternal(StrongRef stages[], std::string &err, ValidationReflection &reflection) +bool Shader::validateInternal(StrongRef stages[], std::string &err, Reflection &reflection) { glslang::TProgram program; @@ -946,6 +1080,9 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, } } + reflection.textureCount = 0; + reflection.bufferCount = 0; + for (int i = 0; i < program.getNumUniformVariables(); i++) { const glslang::TObjectReflection &info = program.getUniform(i); @@ -955,9 +1092,40 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, const glslang::TQualifier &qualifiers = type->getQualifier(); - if (type->isImage()) + UniformInfo u = {}; + + u.name = canonicaliizeUniformName(info.name); + u.location = -1; + u.access = ACCESS_READ; + u.stageMask = getStageMask(info.stages); + u.components = 1; + u.resourceIndex = -1; + + if (type->isSizedArray()) + u.count = type->getArraySizes()->getCumulativeSize(); + else + u.count = 1; + + const auto &sampler = type->getSampler(); + + if (type->isTexture() && type->getSampler().isCombined() && !sampler.isBuffer()) { - if ((info.stages & EShLangComputeMask) == 0) + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = getBaseType(sampler.getBasicType()); + u.isDepthSampler = sampler.isShadow(); + u.textureType = getTextureType(sampler); + + if (u.textureType == TEXTURE_MAX_ENUM) + continue; + + u.resourceIndex = reflection.textureCount; + reflection.textureCount += u.count; + + reflection.sampledTextures[u.name] = u; + } + else if (type->isImage()) + { + if ((info.stages & (~EShLangComputeMask)) != 0) { err = "Shader validation error:\nStorage Texture uniform variables (image2D, etc) are only allowed in compute shaders."; return false; @@ -965,36 +1133,63 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, if (!qualifiers.hasFormat()) { - err = "Shader validation error:\nStorage Texture '" + info.name + "' must have an explicit format set in its layout declaration."; + err = "Shader validation error:\nStorage Texture '" + u.name + "' must have an explicit format set in its layout declaration."; return false; } - StorageTextureReflection texreflection = {}; + u.baseType = UNIFORM_STORAGETEXTURE; + u.storageTextureFormat = getPixelFormat(qualifiers.getFormat()); + u.dataBaseType = getDataBaseType(u.storageTextureFormat); + u.textureType = getTextureType(sampler); - texreflection.format = getPixelFormat(qualifiers.getFormat()); + if (u.textureType == TEXTURE_MAX_ENUM) + continue; + + u.resourceIndex = reflection.textureCount; + reflection.textureCount += u.count; if (qualifiers.isReadOnly()) - texreflection.access = ACCESS_READ; + u.access = ACCESS_READ; else if (qualifiers.isWriteOnly()) - texreflection.access = ACCESS_WRITE; + u.access = ACCESS_WRITE; else - texreflection.access = (Access)(ACCESS_READ | ACCESS_WRITE); + u.access = (Access)(ACCESS_READ | ACCESS_WRITE); - reflection.storageTextures[info.name] = texreflection; + reflection.storageTextures[u.name] = u; + } + else if (type->getBasicType() == glslang::EbtSampler && sampler.isBuffer()) + { + u.baseType = UNIFORM_TEXELBUFFER; + u.dataBaseType = getBaseType(sampler.getBasicType()); + + u.resourceIndex = reflection.bufferCount; + reflection.bufferCount += u.count; + + reflection.texelBuffers[u.name] = u; } else if (!type->isOpaque()) { - LocalUniform u = {}; - auto &values = u.initializerValues; + std::vector values; const glslang::TConstUnionArray *constarray = info.getConstArray(); + if (type->isMatrix()) + { + u.matrix.rows = type->getMatrixRows(); + u.matrix.columns = type->getMatrixCols(); + } + else + { + u.components = type->getVectorSize(); + } + // Store initializer values for local uniforms. Some love graphics // backends strip these out of the shader so we need to be able to // access them (to re-send them) by getting them here. switch (type->getBasicType()) { case glslang::EbtFloat: - u.dataType = DATA_BASETYPE_FLOAT; + u.baseType = type->isMatrix() ? UNIFORM_MATRIX : UNIFORM_FLOAT; + u.dataBaseType = DATA_BASETYPE_FLOAT; if (constarray != nullptr) { values.resize(constarray->size()); @@ -1003,7 +1198,8 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, } break; case glslang::EbtUint: - u.dataType = DATA_BASETYPE_UINT; + u.baseType = UNIFORM_UINT; + u.dataBaseType = DATA_BASETYPE_UINT; if (constarray != nullptr) { values.resize(constarray->size()); @@ -1012,7 +1208,8 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, } break; case glslang::EbtBool: - u.dataType = DATA_BASETYPE_BOOL; + u.baseType = UNIFORM_BOOL; + u.dataBaseType = DATA_BASETYPE_BOOL; if (constarray != nullptr) { values.resize(constarray->size()); @@ -1022,7 +1219,8 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, break; case glslang::EbtInt: default: - u.dataType = DATA_BASETYPE_INT; + u.baseType = UNIFORM_INT; + u.dataBaseType = DATA_BASETYPE_INT; if (constarray != nullptr) { values.resize(constarray->size()); @@ -1032,7 +1230,8 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, break; } - reflection.localUniforms[info.name] = u; + reflection.localUniforms[u.name] = u; + reflection.localUniformInitializerValues[u.name] = values; } } @@ -1044,7 +1243,7 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, { const glslang::TQualifier &qualifiers = type->getQualifier(); - if ((!qualifiers.isReadOnly() || qualifiers.isWriteOnly()) && (info.stages & EShLangComputeMask) == 0) + if ((!qualifiers.isReadOnly() || qualifiers.isWriteOnly()) && ((info.stages & (~EShLangComputeMask)) != 0)) { err = "Shader validation error:\nStorage Buffer block '" + info.name + "' must be marked as readonly in vertex and pixel shaders."; return false; @@ -1070,18 +1269,32 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, return false; } - BufferReflection bufferReflection = {}; - bufferReflection.stride = (size_t) info.size; - bufferReflection.memberCount = (size_t) info.numMembers; + UniformInfo u = {}; + u.name = canonicaliizeUniformName(info.name); + u.location = -1; + u.stageMask = getStageMask(info.stages); + u.components = 1; + u.baseType = UNIFORM_STORAGEBUFFER; + + if (type->isSizedArray()) + u.count = type->getArraySizes()->getCumulativeSize(); + else + u.count = 1; + + u.bufferStride = (size_t) info.size; + u.bufferMemberCount = (size_t) info.numMembers; + + u.resourceIndex = reflection.bufferCount; + reflection.bufferCount += u.count; if (qualifiers.isReadOnly()) - bufferReflection.access = ACCESS_READ; + u.access = ACCESS_READ; else if (qualifiers.isWriteOnly()) - bufferReflection.access = ACCESS_WRITE; + u.access = ACCESS_WRITE; else - bufferReflection.access = (Access)(ACCESS_READ | ACCESS_WRITE); + u.access = (Access)(ACCESS_READ | ACCESS_WRITE); - reflection.storageBuffers[info.name] = bufferReflection; + reflection.storageBuffers[u.name] = u; } else { @@ -1090,6 +1303,21 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, } } + for (auto &kvp : reflection.texelBuffers) + reflection.allUniforms[kvp.first] = &kvp.second; + + for (auto &kvp : reflection.storageBuffers) + reflection.allUniforms[kvp.first] = &kvp.second; + + for (auto &kvp : reflection.sampledTextures) + reflection.allUniforms[kvp.first] = &kvp.second; + + for (auto &kvp : reflection.storageTextures) + reflection.allUniforms[kvp.first] = &kvp.second; + + for (auto &kvp : reflection.localUniforms) + reflection.allUniforms[kvp.first] = &kvp.second; + return true; } @@ -1141,7 +1369,7 @@ bool Shader::validateTexture(const UniformInfo *info, Texture *tex, bool interna else throw love::Exception("Texture must be created with the computewrite flag set to true in order to be used with a storage texture (image2D etc) shader uniform variable."); } - else if (isstoragetex && info->storageTextureFormat != getLinearPixelFormat(tex->getPixelFormat())) + else if (isstoragetex && info->storageTextureFormat != tex->getPixelFormat()) { if (internalUpdate) return false; @@ -1216,41 +1444,6 @@ bool Shader::validateBuffer(const UniformInfo *info, Buffer *buffer, bool intern return true; } -bool Shader::fillUniformReflectionData(UniformInfo &u) -{ - const auto &r = validationReflection; - - if (u.baseType == UNIFORM_STORAGETEXTURE) - { - const auto reflectionit = r.storageTextures.find(u.name); - if (reflectionit != r.storageTextures.end()) - { - u.storageTextureFormat = reflectionit->second.format; - u.access = reflectionit->second.access; - return true; - } - - // No reflection info - maybe glslang was better at detecting dead code - // than the driver's compiler? - return false; - } - else if (u.baseType == UNIFORM_STORAGEBUFFER) - { - const auto reflectionit = r.storageBuffers.find(u.name); - if (reflectionit != r.storageBuffers.end()) - { - u.bufferStride = reflectionit->second.stride; - u.bufferMemberCount = reflectionit->second.memberCount; - u.access = reflectionit->second.access; - return true; - } - - return false; - } - - return true; -} - std::string Shader::getShaderStageDebugName(ShaderStageType stage) const { std::string name = debugName; @@ -1265,9 +1458,40 @@ std::string Shader::getShaderStageDebugName(ShaderStageType stage) const return name; } +std::string Shader::canonicaliizeUniformName(const std::string &n) +{ + std::string name(n); + + // Some drivers/compilers append "[0]" to the end of array uniform names. + if (name.length() > 3) + { + size_t findpos = name.rfind("[0]"); + if (findpos != std::string::npos && findpos == name.length() - 3) + name.erase(name.length() - 3); + } + + return name; +} + +void Shader::handleUnknownUniformName(const char */*name*/) +{ + // TODO: do something here? +} + bool Shader::initialize() { - return glslang::InitializeProcess(); + bool success = glslang::InitializeProcess(); + if (!success) + return false; + + TBuiltInResource *resources = GetResources(); + *resources = *GetDefaultResources(); + + // This is 32 in the default resource struct, which is too high for Metal. + // TODO: Set this based on what the system actually supports? + resources->maxDrawBuffers = 8; + + return true; } void Shader::deinitialize() diff --git a/src/modules/graphics/Shader.h b/src/modules/graphics/Shader.h index 8e6671c1d..abe57be38 100644 --- a/src/modules/graphics/Shader.h +++ b/src/modules/graphics/Shader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -108,6 +108,14 @@ public: ACCESS_WRITE = (1 << 1), }; + enum ClipSpaceTransformFlags + { + CLIP_TRANSFORM_NONE = 0, + CLIP_TRANSFORM_FLIP_Y = 1 << 0, + CLIP_TRANSFORM_Z_NEG1_1_TO_0_1 = 1 << 1, + CLIP_TRANSFORM_Z_0_1_TO_NEG1_1 = 1 << 2, + }; + struct CompileOptions { std::map defines; @@ -129,6 +137,10 @@ public: struct UniformInfo { + UniformType baseType; + uint32 stageMask; + bool active; + int location; int count; @@ -138,7 +150,6 @@ public: MatrixSize matrix; }; - UniformType baseType; DataBaseType dataBaseType; TextureType textureType; Access access; @@ -148,6 +159,8 @@ public: size_t bufferMemberCount; std::string name; + int resourceIndex; + union { void *data; @@ -157,12 +170,6 @@ public: }; size_t dataSize; - - union - { - Texture **textures; - Buffer **buffers; - }; }; union LocalUniformValue @@ -178,6 +185,7 @@ public: Matrix4 transformMatrix; Matrix4 projectionMatrix; Vector4 normalMatrix[3]; // 3x3 matrix padded to an array of 3 vector4s. + Vector4 clipSpaceParams; Colorf constantColor; // Pixel shader-centric variables past this point. @@ -213,6 +221,18 @@ public: **/ static bool isDefaultActive(); + /** + * Used for transforming standardized post-projection clip space positions + * into the backend's current clip space. + * Right now, the standard is: + * NDC y is [-1, 1] starting at the bottom (y-up). + * NDC z is [-1, 1]. + * Pixel coordinates are y-down. + * Pixel (0, 0) in a texture is the top-left. + * Aside from NDC z, this matches Metal and D3D12. + */ + static Vector4 computeClipSpaceParams(uint32 clipSpaceTransformFlags); + /** * Returns any warnings this Shader may have generated. **/ @@ -222,7 +242,7 @@ public: virtual int getVertexAttributeIndex(const std::string &name) = 0; - virtual const UniformInfo *getUniformInfo(const std::string &name) const = 0; + const UniformInfo *getUniformInfo(const std::string &name) const; virtual const UniformInfo *getUniformInfo(BuiltinUniform builtin) const = 0; virtual void updateUniform(const UniformInfo *info, int count) = 0; @@ -234,7 +254,7 @@ public: * Gets whether a uniform with the specified name exists and is actively * used in the shader. **/ - virtual bool hasUniform(const std::string &name) const = 0; + bool hasUniform(const std::string &name) const; /** * Sets the textures used when rendering a video. For internal use only. @@ -264,39 +284,31 @@ public: protected: - struct BufferReflection + struct Reflection { - size_t stride; - size_t memberCount; - Access access; - }; + std::map texelBuffers; + std::map storageBuffers; + std::map sampledTextures; + std::map storageTextures; + std::map localUniforms; - struct StorageTextureReflection - { - PixelFormat format; - Access access; - }; + std::map allUniforms; - struct LocalUniform - { - DataBaseType dataType; - std::vector initializerValues; - }; + std::map> localUniformInitializerValues; + + int textureCount; + int bufferCount; - struct ValidationReflection - { - std::map storageBuffers; - std::map storageTextures; - std::map localUniforms; int localThreadgroupSize[3]; bool usesPointSize; }; - bool fillUniformReflectionData(UniformInfo &u); - std::string getShaderStageDebugName(ShaderStageType stage) const; - static bool validateInternal(StrongRef stages[], std::string& err, ValidationReflection &reflection); + void handleUnknownUniformName(const char *name); + + static std::string canonicaliizeUniformName(const std::string &name); + static bool validateInternal(StrongRef stages[], std::string& err, Reflection &reflection); static DataBaseType getDataBaseType(PixelFormat format); static bool isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b); @@ -305,7 +317,10 @@ protected: StrongRef stages[SHADERSTAGE_MAX_ENUM]; - ValidationReflection validationReflection; + Reflection reflection; + + std::vector activeTextures; + std::vector activeBuffers; std::string debugName; diff --git a/src/modules/graphics/ShaderStage.cpp b/src/modules/graphics/ShaderStage.cpp index 7c6c60d39..d079cfa96 100644 --- a/src/modules/graphics/ShaderStage.cpp +++ b/src/modules/graphics/ShaderStage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -62,7 +62,7 @@ ShaderStage::ShaderStage(Graphics *gfx, ShaderStageType stage, const std::string bool forwardcompat = supportsGLSL3 && !forcedefault; - if (!glslangShader->parse(GetDefaultResources(), defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings)) + if (!glslangShader->parse(GetResources(), defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings)) { const char *stagename = "unknown"; getConstant(stage, stagename); diff --git a/src/modules/graphics/ShaderStage.h b/src/modules/graphics/ShaderStage.h index 6ad62ee11..fda4e5b9c 100644 --- a/src/modules/graphics/ShaderStage.h +++ b/src/modules/graphics/ShaderStage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -48,6 +48,14 @@ enum ShaderStageType SHADERSTAGE_MAX_ENUM }; +enum ShaderStageMask +{ + SHADERSTAGEMASK_NONE = 0, + SHADERSTAGEMASK_VERTEX = 1 << SHADERSTAGE_VERTEX, + SHADERSTAGEMASK_PIXEL = 1 << SHADERSTAGE_PIXEL, + SHADERSTAGEMASK_COMPUTE = 1 << SHADERSTAGE_COMPUTE, +}; + class ShaderStage : public love::Object { public: diff --git a/src/modules/graphics/SpriteBatch.cpp b/src/modules/graphics/SpriteBatch.cpp index e8f5f9c79..60fadf462 100644 --- a/src/modules/graphics/SpriteBatch.cpp +++ b/src/modules/graphics/SpriteBatch.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/SpriteBatch.h b/src/modules/graphics/SpriteBatch.h index 0ff879c29..dc9c924aa 100644 --- a/src/modules/graphics/SpriteBatch.h +++ b/src/modules/graphics/SpriteBatch.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/StreamBuffer.cpp b/src/modules/graphics/StreamBuffer.cpp index 88718ce9b..489d1a81c 100644 --- a/src/modules/graphics/StreamBuffer.cpp +++ b/src/modules/graphics/StreamBuffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/StreamBuffer.h b/src/modules/graphics/StreamBuffer.h index 3557a5253..ceaa87f94 100644 --- a/src/modules/graphics/StreamBuffer.h +++ b/src/modules/graphics/StreamBuffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -57,6 +57,8 @@ public: BufferUsage getMode() const { return mode; } size_t getUsableSize() const { return bufferSize - frameGPUReadOffset; } + virtual size_t getGPUReadOffset() const = 0; + virtual MapInfo map(size_t minsize) = 0; virtual size_t unmap(size_t usedsize) = 0; virtual void markUsed(size_t usedsize) = 0; diff --git a/src/modules/graphics/TextBatch.cpp b/src/modules/graphics/TextBatch.cpp index 86e62df5b..944d9ccb7 100644 --- a/src/modules/graphics/TextBatch.cpp +++ b/src/modules/graphics/TextBatch.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/TextBatch.h b/src/modules/graphics/TextBatch.h index 82763fc27..f6fc35d9a 100644 --- a/src/modules/graphics/TextBatch.h +++ b/src/modules/graphics/TextBatch.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2006-2023 LOVE Development Team +* Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index a6f3936ee..edae44ff7 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -167,6 +167,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) , renderTarget(settings.renderTarget) , computeWrite(settings.computeWrite) , readable(true) + , viewFormats(settings.viewFormats) , mipmapsMode(settings.mipmaps) , width(settings.width) , height(settings.height) @@ -179,6 +180,8 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) , samplerState() , graphicsMemorySize(0) , debugName(settings.debugName) + , rootView({this, 0, 0}) + , parentView({this, 0, 0}) { const auto &caps = gfx->getCapabilities(); int requestedMipmapCount = settings.mipmapCount; @@ -284,32 +287,30 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) if (isCompressed() && renderTarget) throw love::Exception("Compressed textures cannot be render targets."); - uint32 usage = PIXELFORMATUSAGEFLAGS_NONE; - if (renderTarget) - usage |= PIXELFORMATUSAGEFLAGS_RENDERTARGET; - if (readable) - usage |= PIXELFORMATUSAGEFLAGS_SAMPLE; - if (computeWrite) - usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE; - - if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage)) + for (PixelFormat viewformat : viewFormats) { - const char *fstr = "unknown"; - love::getConstant(format, fstr); + if (getLinearPixelFormat(viewformat) == getLinearPixelFormat(format)) + continue; - const char *readablestr = ""; - if (readable != !isPixelFormatDepthStencil(format)) - readablestr = readable ? " readable" : " non-readable"; + if (isPixelFormatCompressed(format) || isPixelFormatCompressed(viewformat)) + throw love::Exception("Compressed textures cannot use different pixel formats for texture views, aside from sRGB versus linear variants of the same pixel format."); - const char *rtstr = ""; - if (computeWrite) - rtstr = " as a compute shader-writable texture"; - else if (renderTarget) - rtstr = " as a render target"; + if (isPixelFormatColor(viewformat) != isPixelFormatColor(format)) + throw love::Exception("Color-format textures cannot use depth/stencil pixel formats and vice versa, in texture views."); - throw love::Exception("The %s%s pixel format is not supported%s on this system.", fstr, readablestr, rtstr); + // TODO: depth[24|32f]_stencil8 -> stencil8 can work. + if (isPixelFormatDepthStencil(viewformat)) + throw love::Exception("Using different pixel formats for texture views is not currently supported for depth or stencil formats."); + + size_t viewbytes = getPixelFormatBlockSize(viewformat); + size_t basebytes = getPixelFormatBlockSize(format); + + if (viewbytes != basebytes) + throw love::Exception("Texture view pixel formats must have the same bits per pixel as the base texture's pixel format."); } + validatePixelFormat(gfx); + if (!caps.textureTypes[texType]) { const char *textypestr = "unknown"; @@ -330,10 +331,131 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) ++textureCount; } +Texture::Texture(Graphics *gfx, Texture *base, const ViewSettings &viewsettings) + : texType(viewsettings.type.get(base->getTextureType())) + , format(viewsettings.format.get(base->getPixelFormat())) + , renderTarget(base->renderTarget) + , computeWrite(base->computeWrite) + , readable(base->readable) + , viewFormats(base->viewFormats) + , mipmapsMode(base->mipmapsMode) + , width(1) + , height(1) + , depth(1) + , layers(1) + , mipmapCount(1) + , pixelWidth(1) + , pixelHeight(1) + , requestedMSAA(base->requestedMSAA) + , samplerState(base->samplerState) + , quad(base->quad) + , graphicsMemorySize(0) + , debugName(viewsettings.debugName) + , rootView({base->rootView.texture, 0, 0}) + , parentView({base, viewsettings.mipmapStart.get(0), viewsettings.layerStart.get(0)}) +{ + width = base->getWidth(parentView.startMipmap); + height = base->getHeight(parentView.startMipmap); + + if (texType == TEXTURE_VOLUME) + depth = base->getDepth(parentView.startMipmap); + + if (texType == TEXTURE_2D_ARRAY) + { + int baselayers = base->getTextureType() == TEXTURE_CUBE ? 6 : base->getLayerCount(); + layers = viewsettings.layerCount.get(baselayers - parentView.startLayer); + } + + mipmapCount = viewsettings.mipmapCount.get(base->getMipmapCount() - parentView.startMipmap); + + pixelWidth = base->getPixelWidth(parentView.startMipmap); + pixelHeight = base->getPixelHeight(parentView.startMipmap); + + if (parentView.startMipmap < 0) + throw love::Exception("Invalid mipmap start value for texture view (out of range)."); + + if (mipmapCount < 0 || parentView.startMipmap + mipmapCount > base->getMipmapCount()) + throw love::Exception("Invalid mipmap start or count value for texture view (out of range)."); + + if (parentView.startLayer < 0) + throw love::Exception("Invalid layer start value for texture view (out of range)."); + + int baseLayerCount = base->getTextureType() == TEXTURE_CUBE ? 6 : base->getLayerCount(); + if (layers < 0 || parentView.startLayer + layers > baseLayerCount) + throw love::Exception("Invalid layer start or count value for texture view (out of range)."); + + if (texType == TEXTURE_CUBE && parentView.startLayer + 6 > baseLayerCount) + throw love::Exception("Cube texture view cannot fit in the base texture's layers with the given start layer."); + + ViewInfo nextView = { this, 0, 0 }; + while (nextView.texture != rootView.texture) + { + nextView = nextView.texture->parentView; + rootView.startMipmap += nextView.startMipmap; + rootView.startLayer += nextView.startLayer; + } + + const auto &caps = gfx->getCapabilities(); + if (!caps.features[Graphics::FEATURE_GLSL4]) + throw love::Exception("Texture views are not supported on this system (GLSL 4 support is necessary.)"); + + validatePixelFormat(gfx); + + if (!caps.textureTypes[texType]) + { + const char *textypestr = "unknown"; + Texture::getConstant(texType, textypestr); + throw love::Exception("%s textures are not supported on this system.", textypestr); + } + + if (!readable) + throw love::Exception("Texture views are not supported for non-readable textures."); + + if (base->getTextureType() == TEXTURE_2D) + { + if (texType != TEXTURE_2D && texType != TEXTURE_2D_ARRAY) + throw love::Exception("Texture views created from a 2D texture must use the 2d or array texture type."); + } + else if (base->getTextureType() == TEXTURE_2D_ARRAY || base->getTextureType() == TEXTURE_CUBE) + { + if (texType != TEXTURE_2D && texType != TEXTURE_2D_ARRAY && texType != TEXTURE_CUBE) + throw love::Exception("Texture views created from an array or cube texture must use the 2d, array, or cube texture type."); + } + else if (base->getTextureType() == TEXTURE_VOLUME) + { + if (texType != TEXTURE_VOLUME) + throw love::Exception("Texture views created from a volume texture must use the volume texture type."); + } + else + { + throw love::Exception("Unknown texture type."); + } + + if (format != base->getPixelFormat()) + { + if (std::find(viewFormats.begin(), viewFormats.end(), format) == viewFormats.end()) + throw love::Exception("Using a different pixel format in a texture view requires the original texture to be created with a 'viewformats' setting that includes the given format in its list."); + } + + const char *miperr = nullptr; + if (mipmapsMode == MIPMAPS_AUTO && !supportsGenerateMipmaps(miperr)) + mipmapsMode = MIPMAPS_MANUAL; + + rootView.texture->retain(); + parentView.texture->retain(); +} + Texture::~Texture() { - --textureCount; setGraphicsMemorySize(0); + + if (this == rootView.texture) + --textureCount; + + if (rootView.texture != this && rootView.texture != nullptr) + rootView.texture->release(); + if (parentView.texture != this && parentView.texture != nullptr) + parentView.texture->release(); } void Texture::setGraphicsMemorySize(int64 bytes) @@ -352,18 +474,18 @@ void Texture::draw(Graphics *gfx, const Matrix4 &m) void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform) { - if (!readable) - throw love::Exception("Textures with non-readable formats cannot be drawn."); - - if (renderTarget && gfx->isRenderTargetActive(this)) - throw love::Exception("Cannot render a Texture to itself."); - if (texType == TEXTURE_2D_ARRAY) { drawLayer(gfx, q->getLayer(), q, localTransform); return; } + if (!readable) + throw love::Exception("Textures with non-readable formats cannot be drawn."); + + if (renderTarget && gfx->isRenderTargetActive(this)) + throw love::Exception("Cannot render a Texture to itself."); + const Matrix4 &tm = gfx->getTransform(); bool is2D = tm.isAffine2DTransform(); @@ -451,14 +573,8 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m) void Texture::uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y) { - love::image::ImageData *id = dynamic_cast(d); - - love::thread::EmptyLock lock; - if (id != nullptr) - lock.setLock(id->getMutex()); - Rect rect = {x, y, d->getWidth(), d->getHeight()}; - uploadByteData(d->getFormat(), d->getData(), d->getSize(), level, slice, rect); + uploadByteData(d->getData(), d->getSize(), level, slice, rect); } void Texture::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, int x, int y, bool reloadmipmaps) @@ -477,7 +593,9 @@ void Texture::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap if (getHandle() == 0) return; - if (d->getFormat() != getPixelFormat()) + // ImageData format might be linear but intended to be used as sRGB, so we + // don't error if only the sRGBness is different. + if (getLinearPixelFormat(d->getFormat()) != getLinearPixelFormat(getPixelFormat())) throw love::Exception("Pixel formats must match."); if (mipmap < 0 || mipmap >= getMipmapCount()) @@ -533,7 +651,7 @@ void Texture::replacePixels(const void *data, size_t size, int slice, int mipmap Graphics::flushBatchedDrawsGlobal(); - uploadByteData(format, data, size, mipmap, slice, rect); + uploadByteData(data, size, mipmap, slice, rect); if (reloadmipmaps && mipmap == 0 && getMipmapCount() > 1) generateMipmaps(); @@ -586,36 +704,6 @@ void Texture::generateMipmaps() generateMipmapsInternal(); } -TextureType Texture::getTextureType() const -{ - return texType; -} - -PixelFormat Texture::getPixelFormat() const -{ - return format; -} - -Texture::MipmapsMode Texture::getMipmapsMode() const -{ - return mipmapsMode; -} - -bool Texture::isRenderTarget() const -{ - return renderTarget; -} - -bool Texture::isComputeWritable() const -{ - return computeWrite; -} - -bool Texture::isReadable() const -{ - return readable; -} - bool Texture::isCompressed() const { return isPixelFormatCompressed(format); @@ -689,28 +777,39 @@ int Texture::getRequestedMSAA() const return requestedMSAA; } -void Texture::setSamplerState(const SamplerState &s) +const SamplerState &Texture::getSamplerState() const +{ + return samplerState; +} + +SamplerState Texture::validateSamplerState(SamplerState s) const { if (!readable) - return; + return s; if (s.depthSampleMode.hasValue && !isPixelFormatDepth(format)) throw love::Exception("Only depth textures can have a depth sample compare mode."); - Graphics::flushBatchedDrawsGlobal(); - - samplerState = s; - - if (samplerState.mipmapFilter != SamplerState::MIPMAP_FILTER_NONE && getMipmapCount() == 1) - samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE; + if (s.mipmapFilter != SamplerState::MIPMAP_FILTER_NONE && getMipmapCount() == 1) + s.mipmapFilter = SamplerState::MIPMAP_FILTER_NONE; if (texType == TEXTURE_CUBE) - samplerState.wrapU = samplerState.wrapV = samplerState.wrapW = SamplerState::WRAP_CLAMP; -} + s.wrapU = s.wrapV = s.wrapW = SamplerState::WRAP_CLAMP; -const SamplerState &Texture::getSamplerState() const -{ - return samplerState; + if (s.minFilter == SamplerState::FILTER_LINEAR || s.magFilter == SamplerState::FILTER_LINEAR || s.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR) + { + auto gfx = Module::getInstance(Module::M_GRAPHICS); + if (!gfx->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_LINEAR)) + { + s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST; + if (s.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR) + s.mipmapFilter = SamplerState::MIPMAP_FILTER_NEAREST; + } + } + + Graphics::flushBatchedDrawsGlobal(); + + return s; } Quad *Texture::getQuad() const @@ -785,6 +884,35 @@ bool Texture::validateDimensions(bool throwException) const return success; } +void Texture::validatePixelFormat(Graphics *gfx) const +{ + uint32 usage = PIXELFORMATUSAGEFLAGS_NONE; + if (renderTarget) + usage |= PIXELFORMATUSAGEFLAGS_RENDERTARGET; + if (readable) + usage |= PIXELFORMATUSAGEFLAGS_SAMPLE; + if (computeWrite) + usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE; + + if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage)) + { + const char *fstr = "unknown"; + love::getConstant(format, fstr); + + const char *readablestr = ""; + if (readable != !isPixelFormatDepthStencil(format)) + readablestr = readable ? " readable" : " non-readable"; + + const char *rtstr = ""; + if (computeWrite) + rtstr = " as a compute shader-writable texture"; + else if (renderTarget) + rtstr = " as a render target"; + + throw love::Exception("The %s%s pixel format is not supported%s on this system.", fstr, readablestr, rtstr); + } +} + Texture::Slices::Slices(TextureType textype) : textureType(textype) { @@ -975,6 +1103,7 @@ static StringMap::Entry setting { "msaa", Texture::SETTING_MSAA }, { "canvas", Texture::SETTING_RENDER_TARGET }, { "computewrite", Texture::SETTING_COMPUTE_WRITE }, + { "viewformats", Texture::SETTING_VIEW_FORMATS }, { "readable", Texture::SETTING_READABLE }, { "debugname", Texture::SETTING_DEBUGNAME }, }; diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index b9d156c95..0f228848f 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -39,6 +39,7 @@ // C #include +#include namespace love { @@ -174,6 +175,7 @@ public: SETTING_MSAA, SETTING_RENDER_TARGET, SETTING_COMPUTE_WRITE, + SETTING_VIEW_FORMATS, SETTING_READABLE, SETTING_DEBUGNAME, SETTING_MAX_ENUM @@ -194,10 +196,22 @@ public: int msaa = 1; bool renderTarget = false; bool computeWrite = false; + std::vector viewFormats; OptionalBool readable; std::string debugName; }; + struct ViewSettings + { + Optional format; + Optional type; + OptionalInt mipmapStart; + OptionalInt mipmapCount; + OptionalInt layerStart; + OptionalInt layerCount; + std::string debugName; + }; + struct Slices { public: @@ -228,10 +242,14 @@ public: }; // Slices - static int64 totalGraphicsMemory; + struct ViewInfo + { + Texture *texture; + int startMipmap; + int startLayer; + }; - Texture(Graphics *gfx, const Settings &settings, const Slices *slices); - virtual ~Texture(); + static int64 totalGraphicsMemory; // Drawable. void draw(Graphics *gfx, const Matrix4 &m) override; @@ -255,13 +273,15 @@ public: virtual ptrdiff_t getRenderTargetHandle() const = 0; virtual ptrdiff_t getSamplerHandle() const = 0; - TextureType getTextureType() const; - PixelFormat getPixelFormat() const; - MipmapsMode getMipmapsMode() const; + TextureType getTextureType() const { return texType; } + PixelFormat getPixelFormat() const { return format; } + MipmapsMode getMipmapsMode() const { return mipmapsMode; } - bool isRenderTarget() const; - bool isComputeWritable() const; - bool isReadable() const; + bool isRenderTarget() const { return renderTarget; } + bool isComputeWritable() const { return computeWrite; } + bool isReadable() const { return readable; } + + const std::vector &getViewFormats() const { return viewFormats; } bool isCompressed() const; bool isFormatLinear() const; @@ -285,11 +305,14 @@ public: int getRequestedMSAA() const; virtual int getMSAA() const = 0; - virtual void setSamplerState(const SamplerState &s); + virtual void setSamplerState(const SamplerState &s) = 0; const SamplerState &getSamplerState() const; Quad *getQuad() const; + const ViewInfo &getRootViewInfo() const { return rootView; } + const ViewInfo &getParentViewInfo() const { return parentView; } + const std::string &getDebugName() const { return debugName; } static int getTotalMipmapCount(int w, int h); @@ -310,15 +333,22 @@ public: protected: + Texture(Graphics *gfx, const Settings &settings, const Slices *slices); + Texture(Graphics *gfx, Texture *base, const ViewSettings &viewsettings); + virtual ~Texture(); + void setGraphicsMemorySize(int64 size); void uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y); - virtual void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) = 0; + virtual void uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) = 0; bool supportsGenerateMipmaps(const char *&outReason) const; virtual void generateMipmapsInternal() = 0; + SamplerState validateSamplerState(SamplerState s) const; + bool validateDimensions(bool throwException) const; + void validatePixelFormat(Graphics *gfx) const; TextureType texType; @@ -327,6 +357,8 @@ protected: bool computeWrite; bool readable; + std::vector viewFormats; + MipmapsMode mipmapsMode; int width; @@ -349,6 +381,9 @@ protected: std::string debugName; + ViewInfo rootView; + ViewInfo parentView; + }; // Texture } // graphics diff --git a/src/modules/graphics/Video.cpp b/src/modules/graphics/Video.cpp index 7ba5a1098..710942ea0 100644 --- a/src/modules/graphics/Video.cpp +++ b/src/modules/graphics/Video.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Video.h b/src/modules/graphics/Video.h index a814bc83f..dd9568186 100644 --- a/src/modules/graphics/Video.h +++ b/src/modules/graphics/Video.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Volatile.cpp b/src/modules/graphics/Volatile.cpp index 2ee6a7879..fc098c96a 100644 --- a/src/modules/graphics/Volatile.cpp +++ b/src/modules/graphics/Volatile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/Volatile.h b/src/modules/graphics/Volatile.h index 73d6cce15..c72582526 100644 --- a/src/modules/graphics/Volatile.h +++ b/src/modules/graphics/Volatile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/Buffer.h b/src/modules/graphics/metal/Buffer.h index 9e2e4854a..cba716057 100644 --- a/src/modules/graphics/metal/Buffer.h +++ b/src/modules/graphics/metal/Buffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/Buffer.mm b/src/modules/graphics/metal/Buffer.mm index d1b85f601..82d2cbc53 100644 --- a/src/modules/graphics/metal/Buffer.mm +++ b/src/modules/graphics/metal/Buffer.mm @@ -1,5 +1,5 @@ /** -* Copyright (c) 2006-2023 LOVE Development Team +* Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/Graphics.h b/src/modules/graphics/metal/Graphics.h index d0477881c..c23b5b090 100644 --- a/src/modules/graphics/metal/Graphics.h +++ b/src/modules/graphics/metal/Graphics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -60,14 +60,10 @@ public: Graphics(); virtual ~Graphics(); - // Implements Module. - const char *getName() const override { return "love.graphics.metal"; } - love::graphics::Texture *newTexture(const Texture::Settings &settings, const Texture::Slices *data = nullptr) override; + love::graphics::Texture *newTextureView(love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) override; love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) override; - Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override; - void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; void unSetMode() override; @@ -244,6 +240,7 @@ private: StreamBuffer *uniformBuffer; StreamBuffer::MapInfo uniformBufferData; size_t uniformBufferOffset; + size_t uniformBufferGPUStart; Buffer *defaultAttributesBuffer; diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index 518cdbe8f..6fbe01a69 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -263,7 +263,8 @@ struct DefaultVertexAttributes Graphics *Graphics::graphicsInstance = nullptr; Graphics::Graphics() - : device(nil) + : love::graphics::Graphics("love.graphics.metal") + , device(nil) , commandQueue(nil) , commandBuffer(nil) , renderEncoder(nil) @@ -279,6 +280,7 @@ Graphics::Graphics() , attachmentStoreActions() , renderBindings() , uniformBufferOffset(0) + , uniformBufferGPUStart(0) , defaultAttributesBuffer(nullptr) , families() { @autoreleasepool { @@ -340,6 +342,7 @@ Graphics::Graphics() }; Buffer::Settings attribsettings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC); + attribsettings.debugName = "Default Vertex Attributes"; defaultAttributesBuffer = newBuffer(attribsettings, dataformat, &defaults, sizeof(DefaultVertexAttributes), 0); } @@ -432,6 +435,11 @@ love::graphics::Texture *Graphics::newTexture(const Texture::Settings &settings, return new Texture(this, device, settings, data); } +love::graphics::Texture *Graphics::newTextureView(love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) +{ + return new Texture(this, device, base, viewsettings); +} + love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) { return new ShaderStage(this, stage, source, gles, cachekey); @@ -457,12 +465,6 @@ love::graphics::GraphicsReadback *Graphics::newReadbackInternal(ReadbackMethod m return new GraphicsReadback(this, method, texture, slice, mipmap, rect, dest, destx, desty); } -Matrix4 Graphics::computeDeviceProjection(const Matrix4 &projection, bool /*rendertotexture*/) const -{ - uint32 flags = DEVICE_PROJECTION_FLIP_Y; - return calculateDeviceProjection(projection, flags); -} - void Graphics::backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { bool sizechanged = width != this->width || height != this->height @@ -913,8 +915,8 @@ void Graphics::applyRenderState(id encoder, const Verte const auto &rt = state.renderTargets.getFirstTarget(); if (rt.texture.get()) { - rtw = rt.texture->getPixelWidth(); - rth = rt.texture->getPixelHeight(); + rtw = rt.texture->getPixelWidth(rt.mipmap); + rth = rt.texture->getPixelHeight(rt.mipmap); } else { @@ -1028,14 +1030,19 @@ bool Graphics::applyShaderUniforms(id encoder, love::g if (uniformBuffer->getSize() < uniformBufferOffset + size) { size_t newsize = uniformBuffer->getSize() * 2; + if (uniformBufferOffset > 0) + uniformBuffer->nextFrame(); uniformBuffer->release(); - uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_VERTEX, newsize); + uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_UNIFORM, newsize); uniformBufferData = {}; uniformBufferOffset = 0; } if (uniformBufferData.data == nullptr) + { uniformBufferData = uniformBuffer->map(uniformBuffer->getSize()); + uniformBufferGPUStart = uniformBuffer->getGPUReadOffset(); + } memcpy(uniformBufferData.data + uniformBufferOffset, bufferdata, size); @@ -1043,7 +1050,7 @@ bool Graphics::applyShaderUniforms(id encoder, love::g int uniformindex = Shader::getUniformBufferBinding(); auto &bindings = renderBindings; - setBuffer(encoder, bindings, uniformindex, buffer, uniformBufferOffset); + setBuffer(encoder, bindings, uniformindex, buffer, uniformBufferGPUStart + uniformBufferOffset); uniformBufferOffset += alignUp(size, alignment); @@ -1120,12 +1127,15 @@ void Graphics::applyShaderUniforms(id renderEncoder, lo // Same with point size. builtins->normalMatrix[1].w = getPointSize(); + uint32 flags = Shader::CLIP_TRANSFORM_Z_NEG1_1_TO_0_1; + builtins->clipSpaceParams = Shader::computeClipSpaceParams(flags); + builtins->screenSizeParams = Vector4(getPixelWidth(), getPixelHeight(), 1.0f, 0.0f); - auto rt = states.back().renderTargets.getFirstTarget().texture.get(); - if (rt != nullptr) + auto rt = states.back().renderTargets.getFirstTarget(); + if (rt.texture.get()) { - builtins->screenSizeParams.x = rt->getPixelWidth(); - builtins->screenSizeParams.y = rt->getPixelHeight(); + builtins->screenSizeParams.x = rt.texture->getPixelWidth(rt.mipmap); + builtins->screenSizeParams.y = rt.texture->getPixelHeight(rt.mipmap); } builtins->constantColor = getColor(); @@ -1134,14 +1144,19 @@ void Graphics::applyShaderUniforms(id renderEncoder, lo if (uniformBuffer->getSize() < uniformBufferOffset + size) { size_t newsize = uniformBuffer->getSize() * 2; + if (uniformBufferOffset > 0) + uniformBuffer->nextFrame(); uniformBuffer->release(); - uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_VERTEX, newsize); + uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_UNIFORM, newsize); uniformBufferData = {}; uniformBufferOffset = 0; } if (uniformBufferData.data == nullptr) + { uniformBufferData = uniformBuffer->map(uniformBuffer->getSize()); + uniformBufferGPUStart = uniformBuffer->getGPUReadOffset(); + } memcpy(uniformBufferData.data + uniformBufferOffset, bufferdata, size); @@ -1149,8 +1164,8 @@ void Graphics::applyShaderUniforms(id renderEncoder, lo int uniformindex = Shader::getUniformBufferBinding(); auto &bindings = renderBindings; - setBuffer(renderEncoder, bindings, SHADERSTAGE_VERTEX, uniformindex, buffer, uniformBufferOffset); - setBuffer(renderEncoder, bindings, SHADERSTAGE_PIXEL, uniformindex, buffer, uniformBufferOffset); + setBuffer(renderEncoder, bindings, SHADERSTAGE_VERTEX, uniformindex, buffer, uniformBufferGPUStart + uniformBufferOffset); + setBuffer(renderEncoder, bindings, SHADERSTAGE_PIXEL, uniformindex, buffer, uniformBufferGPUStart + uniformBufferOffset); uniformBufferOffset += alignUp(size, alignment); diff --git a/src/modules/graphics/metal/GraphicsReadback.h b/src/modules/graphics/metal/GraphicsReadback.h index 7c9486019..7069a4a31 100644 --- a/src/modules/graphics/metal/GraphicsReadback.h +++ b/src/modules/graphics/metal/GraphicsReadback.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/GraphicsReadback.mm b/src/modules/graphics/metal/GraphicsReadback.mm index d74195d7a..808ca1e74 100644 --- a/src/modules/graphics/metal/GraphicsReadback.mm +++ b/src/modules/graphics/metal/GraphicsReadback.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/Metal.h b/src/modules/graphics/metal/Metal.h index 2283d9d87..aaaaab220 100644 --- a/src/modules/graphics/metal/Metal.h +++ b/src/modules/graphics/metal/Metal.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/Metal.mm b/src/modules/graphics/metal/Metal.mm index 589329b4f..ff27cfb76 100644 --- a/src/modules/graphics/metal/Metal.mm +++ b/src/modules/graphics/metal/Metal.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/Shader.h b/src/modules/graphics/metal/Shader.h index 5ff3a3c20..174902bfc 100644 --- a/src/modules/graphics/metal/Shader.h +++ b/src/modules/graphics/metal/Shader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -107,12 +107,10 @@ public: void attach() override; std::string getWarnings() const override { return ""; } int getVertexAttributeIndex(const std::string &name) override; - const UniformInfo *getUniformInfo(const std::string &name) const override; const UniformInfo *getUniformInfo(BuiltinUniform builtin) const override; void updateUniform(const UniformInfo *info, int count) override; void sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count) override; void sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count) override; - bool hasUniform(const std::string &name) const override; ptrdiff_t getHandle() const override { return 0; } void setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture) override; @@ -140,13 +138,11 @@ private: }; void buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename); - void addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Resource &resource, UniformType baseType); void compileFromGLSLang(id device, const glslang::TProgram &program); id functions[SHADERSTAGE_MAX_ENUM]; UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM]; - std::map uniforms; uint8 *localUniformStagingData; uint8 *localUniformBufferData; diff --git a/src/modules/graphics/metal/Shader.mm b/src/modules/graphics/metal/Shader.mm index c421c2330..316efd6fc 100644 --- a/src/modules/graphics/metal/Shader.mm +++ b/src/modules/graphics/metal/Shader.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -208,7 +208,7 @@ Shader::Shader(id device, StrongRef stag forcedefault = true; #endif - if (!tshader->parse(GetDefaultResources(), defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings)) + if (!tshader->parse(GetResources(), defaultversion, defaultprofile, forcedefault, forwardcompat, EShMsgSuppressWarnings)) { const char *stagename = "unknown"; ShaderStage::getConstant(stage, stagename); @@ -299,134 +299,47 @@ void Shader::buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv continue; } + name = canonicaliizeUniformName(name); + if (offset + membersize > localUniformBufferSize) throw love::Exception("Invalid uniform offset + size for '%s' (offset=%d, size=%d, buffer size=%d)", name.c_str(), (int)offset, (int)membersize, (int)localUniformBufferSize); - UniformInfo u = {}; - u.name = name; + auto uniformit = reflection.allUniforms.find(name); + if (uniformit == reflection.allUniforms.end()) + { + handleUnknownUniformName(name.c_str()); + continue; + } + + UniformInfo &u = *(uniformit->second); + u.active = true; + + if (u.dataSize > 0) + continue; + u.dataSize = membersize; - u.count = membertype.array.empty() ? 1 : membertype.array[0]; - u.components = 1; - u.data = localUniformStagingData + offset; - if (membertype.columns == 1) - { - if (membertype.basetype == SPIRType::Int) - u.baseType = UNIFORM_INT; - else if (membertype.basetype == SPIRType::UInt) - u.baseType = UNIFORM_UINT; - else - u.baseType = UNIFORM_FLOAT; - u.components = membertype.vecsize; - } - else - { - u.baseType = UNIFORM_MATRIX; - u.matrix.rows = membertype.vecsize; - u.matrix.columns = membertype.columns; - } - const auto &reflectionit = validationReflection.localUniforms.find(u.name); - if (reflectionit != validationReflection.localUniforms.end()) + const auto &reflectionit = reflection.localUniformInitializerValues.find(u.name); + if (reflectionit != reflection.localUniformInitializerValues.end()) { - const auto &localuniform = reflectionit->second; - const auto &values = localuniform.initializerValues; + const auto &values = reflectionit->second; if (!values.empty()) memcpy(u.data, values.data(), std::min(u.dataSize, values.size() * sizeof(LocalUniformValue))); } - uniforms[u.name] = u; - BuiltinUniform builtin = BUILTIN_MAX_ENUM; if (getConstant(u.name.c_str(), builtin)) { if (builtin == BUILTIN_UNIFORMS_PER_DRAW) builtinUniformDataOffset = offset; - builtinUniformInfo[builtin] = &uniforms[u.name]; + builtinUniformInfo[builtin] = &u; } updateUniform(&u, u.count); } } -void Shader::addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Resource &resource, UniformType baseType) -{ - using namespace spirv_cross; - - const SPIRType &basetype = msl.get_type(resource.base_type_id); - const SPIRType &type = msl.get_type(resource.type_id); - const SPIRType &imagetype = msl.get_type(basetype.image.type); - - UniformInfo u = {}; - u.baseType = baseType; - u.name = resource.name; - u.count = type.array.empty() ? 1 : type.array[0]; - u.isDepthSampler = type.image.depth; - u.components = 1; - - auto it = uniforms.find(u.name); - if (it != uniforms.end()) - return; - - if (!fillUniformReflectionData(u)) - return; - - switch (imagetype.basetype) - { - case SPIRType::Float: - u.dataBaseType = DATA_BASETYPE_FLOAT; - break; - case SPIRType::Int: - u.dataBaseType = DATA_BASETYPE_INT; - break; - case SPIRType::UInt: - u.dataBaseType = DATA_BASETYPE_UINT; - break; - default: - break; - } - - switch (basetype.image.dim) - { - case spv::Dim2D: - u.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D; - u.textures = new love::graphics::Texture*[u.count]; - memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count); - break; - case spv::Dim3D: - u.textureType = TEXTURE_VOLUME; - u.textures = new love::graphics::Texture*[u.count]; - memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count); - break; - case spv::DimCube: - if (basetype.image.arrayed) - throw love::Exception("Cubemap Arrays are not currently supported."); - u.textureType = TEXTURE_CUBE; - u.textures = new love::graphics::Texture*[u.count]; - memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count); - break; - case spv::DimBuffer: - u.baseType = UNIFORM_TEXELBUFFER; - u.buffers = new love::graphics::Buffer*[u.count]; - memset(u.buffers, 0, sizeof(love::graphics::Buffer *) * u.count); - break; - default: - // TODO: error? continue? - break; - } - - u.dataSize = sizeof(int) * u.count; - u.data = malloc(u.dataSize); - for (int i = 0; i < u.count; i++) - u.ints[i] = -1; // Initialized below, after compiling. - - uniforms[u.name] = u; - - BuiltinUniform builtin; - if (getConstant(resource.name.c_str(), builtin)) - builtinUniformInfo[builtin] = &uniforms[u.name]; -} - void Shader::compileFromGLSLang(id device, const glslang::TProgram &program) { using namespace glslang; @@ -473,21 +386,10 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p auto &msl = *mslpointer; auto interfacevars = msl.get_active_interface_variables(); + ShaderResources resources = msl.get_shader_resources(interfacevars); msl.set_enabled_interface_variables(interfacevars); - ShaderResources resources = msl.get_shader_resources(); - - for (const auto &resource : resources.storage_images) - { - addImage(msl, resource, UNIFORM_STORAGETEXTURE); - } - - for (const auto &resource : resources.sampled_images) - { - addImage(msl, resource, UNIFORM_SAMPLER); - } - for (const auto &resource : resources.uniform_buffers) { MSLResourceBinding binding; @@ -535,33 +437,6 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p binding.desc_set = msl.get_decoration(resource.id, spv::DecorationDescriptorSet); binding.msl_buffer = metalBufferIndices[stageindex]++; msl.add_msl_resource_binding(binding); - - auto it = uniforms.find(resource.name); - if (it != uniforms.end()) - continue; - - const SPIRType &type = msl.get_type(resource.type_id); - - UniformInfo u = {}; - u.baseType = UNIFORM_STORAGEBUFFER; - u.components = 1; - u.name = resource.name; - u.count = type.array.empty() ? 1 : type.array[0]; - - if (!fillUniformReflectionData(u)) - continue; - - u.buffers = new love::graphics::Buffer*[u.count]; - u.dataSize = sizeof(int) * u.count; - u.data = malloc(u.dataSize); - - for (int i = 0; i < u.count; i++) - { - u.ints[i] = -1; // Initialized below, after compiling. - u.buffers[i] = nullptr; - } - - uniforms[u.name] = u; } if (stageindex == SHADERSTAGE_VERTEX) @@ -634,7 +509,8 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p if (library == nil && err != nil) { NSLog(@"errors: %@", err); - throw love::Exception("Error compiling converted Metal shader code"); + NSString *errorstr = err.localizedDescription; + throw love::Exception("Error compiling converted Metal shader code:\n\n%s", errorstr.UTF8String); } functions[stageindex] = [library newFunctionWithName:library.functionNames[0]]; @@ -645,11 +521,15 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p auto setTextureBinding = [this](CompilerMSL &msl, int stageindex, const spirv_cross::Resource &resource) -> void { - auto it = uniforms.find(resource.name); - if (it == uniforms.end()) + std::string name = canonicaliizeUniformName(resource.name); + auto it = reflection.allUniforms.find(name); + if (it == reflection.allUniforms.end()) + { + handleUnknownUniformName(name.c_str()); return; + } - UniformInfo &u = it->second; + UniformInfo &u = *(it->second); uint32 texturebinding = msl.get_automatic_msl_resource_binding(resource.id); uint32 samplerbinding = msl.get_automatic_msl_resource_binding_secondary(resource.id); @@ -657,15 +537,16 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p if (texturebinding == (uint32)-1) { // No valid binding, the uniform was likely optimized out because it's not used. - uniforms.erase(resource.name); return; } - for (int i = 0; i < u.count; i++) + u.active = true; + + if (u.location < 0) { - if (u.ints[i] == -1) + u.location = (int)textureBindings.size(); + for (int i = 0; i < u.count; i++) { - u.ints[i] = (int)textureBindings.size(); TextureBinding b = {}; b.access = u.access; @@ -683,11 +564,18 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p textureBindings.push_back(b); } + } - auto &b = textureBindings[u.ints[i]]; + for (int i = 0; i < u.count; i++) + { + auto &b = textureBindings[u.location + i]; b.textureStages[stageindex] = (uint8) texturebinding; b.samplerStages[stageindex] = (uint8) samplerbinding; } + + BuiltinUniform builtin; + if (getConstant(name.c_str(), builtin)) + builtinUniformInfo[builtin] = &u; }; for (const auto &resource : resources.sampled_images) @@ -702,9 +590,13 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p for (const auto &resource : resources.storage_buffers) { - auto it = uniforms.find(resource.name); - if (it == uniforms.end()) + std::string name = canonicaliizeUniformName(resource.name); + auto it = reflection.storageBuffers.find(name); + if (it == reflection.storageBuffers.end()) + { + handleUnknownUniformName(name.c_str()); continue; + } UniformInfo &u = it->second; @@ -712,15 +604,16 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p if (bufferbinding == (uint32)-1) { // No valid binding, the uniform was likely optimized out because it's not used. - uniforms.erase(resource.name); continue; } - for (int i = 0; i < u.count; i++) + u.active = true; + + if (u.location < 0) { - if (u.ints[i] == -1) + u.location = (int)bufferBindings.size(); + for (int i = 0; i < u.count; i++) { - u.ints[i] = (int)bufferBindings.size(); BufferBinding b = {}; b.access = u.access; @@ -729,25 +622,26 @@ void Shader::compileFromGLSLang(id device, const glslang::TProgram &p bufferBindings.push_back(b); } - - bufferBindings[u.ints[i]].stages[stageindex] = (uint8) bufferbinding; } + + for (int i = 0; i < u.count; i++) + bufferBindings[u.location + i].stages[stageindex] = (uint8) bufferbinding; } } // Initialize default resource bindings. - for (auto &kvp : uniforms) + for (const auto &kvp : reflection.allUniforms) { - UniformInfo &info = kvp.second; - switch (info.baseType) + const UniformInfo *info = kvp.second; + switch (info->baseType) { case UNIFORM_SAMPLER: case UNIFORM_STORAGETEXTURE: - sendTextures(&info, info.textures, info.count); + sendTextures(info, &activeTextures[info->resourceIndex], info->count); break; case UNIFORM_TEXELBUFFER: case UNIFORM_STORAGEBUFFER: - sendBuffers(&info, info.buffers, info.count); + sendBuffers(info, &activeBuffers[info->resourceIndex], info->count); break; default: break; @@ -767,31 +661,6 @@ Shader::~Shader() cachedRenderPipelines.clear(); - for (const auto &it : uniforms) - { - const auto &u = it.second; - if (u.baseType == UNIFORM_SAMPLER || u.baseType == UNIFORM_STORAGETEXTURE) - { - free(u.data); - for (int i = 0; i < u.count; i++) - { - if (u.textures[i] != nullptr) - u.textures[i]->release(); - } - delete[] u.textures; - } - else if (u.baseType == UNIFORM_TEXELBUFFER || u.baseType == UNIFORM_STORAGEBUFFER) - { - free(u.data); - for (int i = 0; i < u.count; i++) - { - if (u.buffers[i] != nullptr) - u.buffers[i]->release(); - } - delete[] u.buffers; - } - } - delete[] localUniformStagingData; delete[] localUniformBufferData; }} @@ -813,12 +682,6 @@ int Shader::getVertexAttributeIndex(const std::string &name) return it != attributes.end() ? it->second : -1; } -const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const -{ - const auto it = uniforms.find(name); - return it != uniforms.end() ? &(it->second) : nullptr; -} - const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const { return builtinUniformInfo[(int)builtin]; @@ -826,6 +689,9 @@ const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const void Shader::updateUniform(const UniformInfo *info, int count) { + if (info->dataSize == 0) + return; + if (current == this) Graphics::flushBatchedDrawsGlobal(); @@ -895,12 +761,21 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex tex->retain(); - if (info->textures[i] != nullptr) - info->textures[i]->release(); + int resourceindex = info->resourceIndex + i; - info->textures[i] = tex; + if (activeTextures[resourceindex] != nullptr) + activeTextures[resourceindex]->release(); - auto &binding = textureBindings[info->ints[i]]; + activeTextures[resourceindex] = tex; + + if (info->location < 0) + continue; + + int bindingindex = info->location + i; + if (bindingindex < 0) + continue; + + auto &binding = textureBindings[bindingindex]; if (isdefault && (binding.access & ACCESS_WRITE) != 0) { binding.texture = nil; @@ -927,7 +802,6 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe count = std::min(count, info->count); - // Bind the textures to the texture units. for (int i = 0; i < count; i++) { love::graphics::Buffer *buffer = buffers[i]; @@ -949,18 +823,24 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe buffer->retain(); - if (info->buffers[i] != nullptr) - info->buffers[i]->release(); + int resourceindex = info->resourceIndex + i; - info->buffers[i] = buffer; + if (activeBuffers[resourceindex] != nullptr) + activeBuffers[resourceindex]->release(); - if (texelbinding) + activeBuffers[resourceindex] = buffer; + + if (info->location < 0) + continue; + + int bindingindex = info->location + i; + if (texelbinding && bindingindex >= 0) { - textureBindings[info->ints[i]].texture = getMTLTexture(buffer); + textureBindings[bindingindex].texture = getMTLTexture(buffer); } - else if (storagebinding) + else if (storagebinding && bindingindex >= 0) { - auto &binding = bufferBindings[info->ints[i]]; + auto &binding = bufferBindings[bindingindex]; if (isdefault && (binding.access & ACCESS_WRITE) != 0) binding.buffer = nil; else @@ -987,11 +867,6 @@ void Shader::setVideoTextures(love::graphics::Texture *ytexture, love::graphics: } } -bool Shader::hasUniform(const std::string &name) const -{ - return uniforms.find(name) != uniforms.end(); -} - id Shader::getCachedRenderPipeline(const RenderPipelineKey &key) { auto it = cachedRenderPipelines.find(key); @@ -1073,7 +948,7 @@ id Shader::getCachedRenderPipeline(const RenderPipelineK const auto &attrib = attributes.attribs[i]; int metalBufferIndex = firstVertexBufferBinding + attrib.bufferIndex; - vertdesc.attributes[i].format = getMTLVertexFormat(attrib.format); + vertdesc.attributes[i].format = getMTLVertexFormat(attrib.getFormat()); vertdesc.attributes[i].offset = attrib.offsetFromVertex; vertdesc.attributes[i].bufferIndex = metalBufferIndex; diff --git a/src/modules/graphics/metal/ShaderStage.h b/src/modules/graphics/metal/ShaderStage.h index 6720aeffc..95bf98431 100644 --- a/src/modules/graphics/metal/ShaderStage.h +++ b/src/modules/graphics/metal/ShaderStage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/ShaderStage.mm b/src/modules/graphics/metal/ShaderStage.mm index b56610c76..ac91169b1 100644 --- a/src/modules/graphics/metal/ShaderStage.mm +++ b/src/modules/graphics/metal/ShaderStage.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/StreamBuffer.h b/src/modules/graphics/metal/StreamBuffer.h index 87b99488a..ce3520bc5 100644 --- a/src/modules/graphics/metal/StreamBuffer.h +++ b/src/modules/graphics/metal/StreamBuffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/metal/StreamBuffer.mm b/src/modules/graphics/metal/StreamBuffer.mm index 7a7fae5a9..00d3e33c9 100644 --- a/src/modules/graphics/metal/StreamBuffer.mm +++ b/src/modules/graphics/metal/StreamBuffer.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -48,6 +48,8 @@ public: if (buffer == nil) throw love::Exception("Out of graphics memory."); + buffer.label = [NSString stringWithFormat:@"StreamBuffer (usage: %d, size: %ld)", usage, size]; + data = (uint8 *) buffer.contents; for (int i = 0; i < BUFFER_FRAMES; i++) @@ -65,6 +67,11 @@ public: } }} + size_t getGPUReadOffset() const override + { + return (frameIndex * bufferSize) + frameGPUReadOffset; + } + MapInfo map(size_t /*minsize*/) override { // Make sure this frame's section of the buffer is done being used. diff --git a/src/modules/graphics/metal/Texture.h b/src/modules/graphics/metal/Texture.h index 89730a1f1..01c6e57ec 100644 --- a/src/modules/graphics/metal/Texture.h +++ b/src/modules/graphics/metal/Texture.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -38,6 +38,7 @@ class Texture final : public love::graphics::Texture public: Texture(love::graphics::Graphics *gfx, id device, const Settings &settings, const Slices *data); + Texture(love::graphics::Graphics *gfx, id device, love::graphics::Texture *base, const Texture::ViewSettings &viewsettings); virtual ~Texture(); void copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) override; @@ -55,14 +56,14 @@ public: private: - void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override; + void uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) override; void generateMipmapsInternal() override; - id texture; - id msaaTexture; - id sampler; + id texture = nil; + id msaaTexture = nil; + id sampler = nil; - int actualMSAASamples; + int actualMSAASamples = 1; }; // Texture diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index ee84998e1..e880495ae 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/src/modules/graphics/metal/Texture.mm @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,10 +43,6 @@ static MTLTextureType getMTLTextureType(TextureType type, int msaa) Texture::Texture(love::graphics::Graphics *gfxbase, id device, const Settings &settings, const Slices *data) : love::graphics::Texture(gfxbase, settings, data) - , texture(nil) - , msaaTexture(nil) - , sampler(nil) - , actualMSAASamples(1) { @autoreleasepool { auto gfx = (Graphics *) gfxbase; @@ -81,6 +77,15 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id device, const if (computeWrite) desc.usage |= MTLTextureUsageShaderWrite; + for (PixelFormat viewformat : viewFormats) + { + if (getLinearPixelFormat(viewformat) != getLinearPixelFormat(format)) + { + desc.usage |= MTLTextureUsagePixelFormatView; + break; + } + } + texture = [device newTextureWithDescriptor:desc]; if (texture == nil) @@ -149,7 +154,7 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id device, const emptydata.resize(getPixelFormatSliceSize(format, w, h)); Rect r = {0, 0, getPixelWidth(mip), getPixelHeight(mip)}; - uploadByteData(format, emptydata.data(), emptydata.size(), mip, slice, r); + uploadByteData(emptydata.data(), emptydata.size(), mip, slice, r); } else if (isRenderTarget()) { @@ -212,6 +217,41 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id device, const setSamplerState(samplerState); }} +Texture::Texture(love::graphics::Graphics *gfx, id device, love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) + : love::graphics::Texture(gfx, base, viewsettings) +{ + id basetex = ((Texture *) base)->texture; + auto formatdesc = Metal::convertPixelFormat(device, format); + int slices = texType == TEXTURE_CUBE ? 6 : getLayerCount(); + + if (formatdesc.swizzled) + { + if (@available(macOS 10.15, iOS 13, *)) + { + texture = [basetex newTextureViewWithPixelFormat:formatdesc.format + textureType:getMTLTextureType(texType, 1) + levels:NSMakeRange(parentView.startMipmap, mipmapCount) + slices:NSMakeRange(parentView.startLayer, slices) + swizzle:formatdesc.swizzle]; + } + } + else + { + texture = [basetex newTextureViewWithPixelFormat:formatdesc.format + textureType:getMTLTextureType(texType, 1) + levels:NSMakeRange(parentView.startMipmap, mipmapCount) + slices:NSMakeRange(parentView.startLayer, slices)]; + } + + if (texture == nil) + throw love::Exception("Could not create Metal texture view."); + + if (!debugName.empty()) + texture.label = @(debugName.c_str()); + + setSamplerState(samplerState); +} + Texture::~Texture() { @autoreleasepool { texture = nil; @@ -219,15 +259,13 @@ Texture::~Texture() sampler = nil; }} -void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) +void Texture::uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) { @autoreleasepool { auto gfx = Graphics::getInstance(); id buffer = [gfx->device newBufferWithBytes:data length:size options:MTLResourceStorageModeShared]; - memcpy(buffer.contents, data, size); - id encoder = gfx->useBlitEncoder(); int z = 0; @@ -239,7 +277,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s MTLBlitOption options = MTLBlitOptionNone; - switch (pixelformat) + switch (format) { case PIXELFORMAT_PVR1_RGB2_UNORM: case PIXELFORMAT_PVR1_RGB4_UNORM: @@ -342,10 +380,8 @@ void Texture::setSamplerState(const SamplerState &s) if (s.depthSampleMode.hasValue && !Graphics::getInstance()->isDepthCompareSamplerSupported()) throw love::Exception("Depth comparison sampling in shaders is not supported on this system."); - // Base class does common validation and assigns samplerState. - love::graphics::Texture::setSamplerState(s); - - sampler = Graphics::getInstance()->getCachedSampler(s); + samplerState = validateSamplerState(s); + sampler = Graphics::getInstance()->getCachedSampler(samplerState); }} } // metal diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index 8dc5b57e8..f37f74f94 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index 15cacab28..ea4846b2e 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/FenceSync.cpp b/src/modules/graphics/opengl/FenceSync.cpp index 09ced0f30..664e2194c 100644 --- a/src/modules/graphics/opengl/FenceSync.cpp +++ b/src/modules/graphics/opengl/FenceSync.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/FenceSync.h b/src/modules/graphics/opengl/FenceSync.h index 90d4a3231..898f7a759 100644 --- a/src/modules/graphics/opengl/FenceSync.h +++ b/src/modules/graphics/opengl/FenceSync.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 9013ee808..f0450dfbf 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -106,7 +106,8 @@ love::graphics::Graphics *createInstance() } Graphics::Graphics() - : windowHasStencil(false) + : love::graphics::Graphics("love.graphics.opengl") + , windowHasStencil(false) , mainVAO(0) , internalBackbufferFBO(0) , requestedBackbufferMSAA(0) @@ -147,11 +148,6 @@ Graphics::~Graphics() delete[] bufferMapMemory; } -const char *Graphics::getName() const -{ - return "love.graphics.opengl"; -} - love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferUsage type, size_t size) { return CreateStreamBuffer(type, size); @@ -162,6 +158,11 @@ love::graphics::Texture *Graphics::newTexture(const Texture::Settings &settings, return new Texture(this, settings, data); } +love::graphics::Texture *Graphics::newTextureView(love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) +{ + return new Texture(this, base, viewsettings); +} + love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) { return new ShaderStage(this, stage, source, gles, cachekey); @@ -187,18 +188,6 @@ love::graphics::GraphicsReadback *Graphics::newReadbackInternal(ReadbackMethod m return new GraphicsReadback(this, method, texture, slice, mipmap, rect, dest, destx, desty); } -Matrix4 Graphics::computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const -{ - uint32 flags = DEVICE_PROJECTION_DEFAULT; - - // The projection matrix is flipped compared to rendering to a texture, due - // to OpenGL considering (0,0) bottom-left instead of top-left. - if (!rendertotexture) - flags |= DEVICE_PROJECTION_FLIP_Y; - - return calculateDeviceProjection(projection, flags); -} - void Graphics::backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { bool changed = width != this->width || height != this->height @@ -707,24 +696,27 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes &attribute static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, const GLvoid* /*usr*/) { + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) + return; + // Human-readable strings for the debug info. const char *sourceStr = OpenGL::debugSourceString(source); const char *typeStr = OpenGL::debugTypeString(type); const char *severityStr = OpenGL::debugSeverityString(severity); - const char *fmt = "OpenGL: %s [source=%s, type=%s, severity=%s, id=%d]\n"; - printf(fmt, msg, sourceStr, typeStr, severityStr, id); + const char *fmt = "OpenGL: [source=%s, type=%s, severity=%s, id=%d]: %s\n"; + printf(fmt, sourceStr, typeStr, severityStr, id, msg); } void Graphics::setDebug(bool enable) { // Make sure debug output is supported. The AMD ext. is a bit different // so we don't make use of it, since AMD drivers now support KHR_debug. - if (!(GLAD_VERSION_4_3 || GLAD_KHR_debug || GLAD_ARB_debug_output)) + if (!(GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_2 || GLAD_KHR_debug || GLAD_ARB_debug_output)) return; // TODO: We don't support GL_KHR_debug in GLES yet. - if (GLAD_ES_VERSION_2_0) + if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_2) return; // Ugly hack to reduce code duplication. @@ -740,7 +732,7 @@ void Graphics::setDebug(bool enable) glDebugMessageCallback(nullptr, nullptr); // We can disable debug output entirely with KHR_debug. - if (GLAD_VERSION_4_3 || GLAD_KHR_debug) + if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_2 || GLAD_KHR_debug) glDisable(GL_DEBUG_OUTPUT); return; @@ -758,7 +750,7 @@ void Graphics::setDebug(bool enable) glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE); glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE); - if (GLAD_VERSION_4_3 || GLAD_KHR_debug) + if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_2 || GLAD_KHR_debug) glEnable(GL_DEBUG_OUTPUT); ::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n"); @@ -1689,6 +1681,17 @@ void Graphics::initCapabilities() pixelFormatUsage[i][0] = computePixelFormatUsage(format, false); pixelFormatUsage[i][1] = computePixelFormatUsage(format, true); } + +#ifdef LOVE_ANDROID + // This can't be done in initContext with the rest of the bug checks because + // isPixelFormatSupported relies on state initialized here / after init. + if (GLAD_ES_VERSION_3_0 && !isPixelFormatSupported(PIXELFORMAT_R8_UNORM, PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET)) + { + gl.bugs.brokenR8PixelFormat = true; + pixelFormatUsage[PIXELFORMAT_R8_UNORM][0] = computePixelFormatUsage(PIXELFORMAT_R8_UNORM, false); + pixelFormatUsage[PIXELFORMAT_R8_UNORM][1] = computePixelFormatUsage(PIXELFORMAT_R8_UNORM, true); + } +#endif } uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index cb39c1e81..351532b39 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -56,14 +56,10 @@ public: Graphics(); virtual ~Graphics(); - // Implements Module. - const char *getName() const override; - love::graphics::Texture *newTexture(const Texture::Settings &settings, const Texture::Slices *data = nullptr) override; + love::graphics::Texture *newTextureView(love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) override; love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) override; - Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override; - void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; void unSetMode() override; diff --git a/src/modules/graphics/opengl/GraphicsReadback.cpp b/src/modules/graphics/opengl/GraphicsReadback.cpp index b5eb13f1f..1c903f8f7 100644 --- a/src/modules/graphics/opengl/GraphicsReadback.cpp +++ b/src/modules/graphics/opengl/GraphicsReadback.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -68,8 +68,6 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod { void *dest = prepareReadbackDest(size); - love::thread::Lock lock(imageData->getMutex()); - // Direct readback without copying avoids the need for a staging buffer, // and lowers the system requirements of immediate RT readback. Texture *t = (Texture *) texture; diff --git a/src/modules/graphics/opengl/GraphicsReadback.h b/src/modules/graphics/opengl/GraphicsReadback.h index dd3272d14..46efa3278 100644 --- a/src/modules/graphics/opengl/GraphicsReadback.h +++ b/src/modules/graphics/opengl/GraphicsReadback.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index ff4220010..ecfccf278 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -324,14 +324,6 @@ void OpenGL::setupContext() setColorWriteMask(state.colorWriteMask); contextInitialized = true; - -#ifdef LOVE_ANDROID - // This can't be done in initContext with the rest of the bug checks because - // isPixelFormatSupported relies on state initialized here / after init. - auto gfx = Module::getInstance(Module::M_GRAPHICS); - if (GLAD_ES_VERSION_3_0 && gfx != nullptr && !gfx->isPixelFormatSupported(PIXELFORMAT_R8_UNORM, PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET)) - bugs.brokenR8PixelFormat = true; -#endif } void OpenGL::deInitContext() @@ -870,7 +862,7 @@ void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const Buffe int components = 0; GLboolean normalized = GL_FALSE; bool intformat = false; - GLenum gltype = getGLVertexDataType(attrib.format, components, normalized, intformat); + GLenum gltype = getGLVertexDataType(attrib.getFormat(), components, normalized, intformat); const void *offsetpointer = reinterpret_cast(bufferinfo.offset + attrib.offsetFromVertex); @@ -1344,7 +1336,17 @@ bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelform glTexParameteri(gltarget, GL_TEXTURE_SWIZZLE_A, fmt.swizzle[3]); } - if (isTexStorageSupported()) + bool usetexstorage = isTexStorageSupported(); + + // The fallback for bugs.brokenR8PixelFormat is GL_LUMINANCE, which doesn't have a sized + // version in ES3 so it can't be used with glTexStorage. + if (pixelformat == PIXELFORMAT_R8_UNORM && bugs.brokenR8PixelFormat && GLAD_ES_VERSION_3_0) + { + usetexstorage = false; + fmt.internalformat = fmt.externalformat; + } + + if (usetexstorage) { if (target == TEXTURE_2D || target == TEXTURE_CUBE) glTexStorage2D(gltarget, levels, fmt.internalformat, width, height); @@ -2162,8 +2164,6 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || ((GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB) && (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB))) flags |= commonrender; - if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_1) - flags |= computewrite; break; case PIXELFORMAT_BGRA8_UNORM: case PIXELFORMAT_BGRA8_sRGB: @@ -2190,7 +2190,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample | commonrender; if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_half_float && GLAD_EXT_texture_rg)) flags |= commonsample; - if (GLAD_EXT_color_buffer_half_float && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg)) + if ((GLAD_EXT_color_buffer_half_float || GLAD_EXT_color_buffer_float) && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg)) flags |= commonrender; if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear)) flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; @@ -2202,7 +2202,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample | commonrender; if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float) flags |= commonsample; - if (GLAD_EXT_color_buffer_half_float) + if (GLAD_EXT_color_buffer_half_float || GLAD_EXT_color_buffer_float) flags |= commonrender; if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear)) flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; @@ -2218,6 +2218,8 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample | commonrender; if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_float && GLAD_EXT_texture_rg)) flags |= commonsample; + if (GLAD_EXT_color_buffer_float) + flags |= commonrender; if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear)) flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; if (GLAD_VERSION_4_3) @@ -2228,6 +2230,8 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= commonsample | commonrender; if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_float) flags |= commonsample; + if (GLAD_EXT_color_buffer_float) + flags |= commonrender; if (!(GLAD_VERSION_1_1 || GLAD_OES_texture_float_linear)) flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_1) @@ -2295,10 +2299,12 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= computewrite; break; case PIXELFORMAT_RG11B10_FLOAT: - if (GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_texture_packed_float) + if (GLAD_ES_VERSION_3_1 || GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_texture_packed_float) flags |= commonsample; if (GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_color_buffer_packed_float) flags |= commonrender; + if (GLAD_EXT_color_buffer_float) + flags |= commonrender; if (GLAD_VERSION_4_3) flags |= computewrite; break; @@ -2506,6 +2512,8 @@ const char *OpenGL::debugSeverityString(GLenum severity) return "medium"; case GL_DEBUG_SEVERITY_LOW: return "low"; + case GL_DEBUG_SEVERITY_NOTIFICATION: + return "notification"; default: return "unknown"; } diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 6aa6a5337..4f5dad811 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index 16b7def3d..3885b7d8a 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -38,11 +38,6 @@ namespace graphics namespace opengl { -static bool isBuffer(Shader::UniformType utype) -{ - return utype == Shader::UNIFORM_TEXELBUFFER || utype == Shader::UNIFORM_STORAGEBUFFER; -} - Shader::Shader(StrongRef stages[SHADERSTAGE_MAX_ENUM], const CompileOptions &options) : love::graphics::Shader(stages, options) , program(0) @@ -58,32 +53,11 @@ Shader::~Shader() { unloadVolatile(); - for (const auto &p : uniforms) + for (const auto &p : reflection.allUniforms) { // Allocated with malloc(). - if (p.second.data != nullptr) - free(p.second.data); - - if (p.second.baseType == UNIFORM_SAMPLER || p.second.baseType == UNIFORM_STORAGETEXTURE) - { - for (int i = 0; i < p.second.count; i++) - { - if (p.second.textures[i] != nullptr) - p.second.textures[i]->release(); - } - - delete[] p.second.textures; - } - else if (isBuffer(p.second.baseType)) - { - for (int i = 0; i < p.second.count; i++) - { - if (p.second.buffers[i] != nullptr) - p.second.buffers[i]->release(); - } - - delete[] p.second.buffers; - } + if (p.second->data != nullptr) + free(p.second->data); } } @@ -96,6 +70,26 @@ void Shader::mapActiveUniforms() builtinUniformInfo[i] = nullptr; } + // Make sure all stored resources have their Volatiles loaded before + // the sendTextures/sendBuffers calls below, since they call getHandle(). + for (love::graphics::Texture *tex : activeTextures) + { + if (tex == nullptr) + continue; + Volatile *v = dynamic_cast(tex); + if (v != nullptr) + v->loadVolatile(); + } + + for (love::graphics::Buffer *buffer : activeBuffers) + { + if (buffer == nullptr) + continue; + Volatile *v = dynamic_cast(buffer); + if (v != nullptr) + v->loadVolatile(); + } + GLint activeprogram = 0; glGetIntegerv(GL_CURRENT_PROGRAM, &activeprogram); @@ -107,43 +101,39 @@ void Shader::mapActiveUniforms() GLchar cname[256]; const GLint bufsize = (GLint) (sizeof(cname) / sizeof(GLchar)); - std::map olduniforms = uniforms; - uniforms.clear(); - - auto gfx = Module::getInstance(Module::M_GRAPHICS); - for (int uindex = 0; uindex < numuniforms; uindex++) { GLsizei namelen = 0; GLenum gltype = 0; - UniformInfo u = {}; + int count = 0; - glGetActiveUniform(program, (GLuint) uindex, bufsize, &namelen, &u.count, &gltype, cname); + glGetActiveUniform(program, (GLuint) uindex, bufsize, &namelen, &count, &gltype, cname); - u.name = std::string(cname, (size_t) namelen); - u.location = glGetUniformLocation(program, u.name.c_str()); - u.access = ACCESS_READ; - computeUniformTypeInfo(gltype, u); + std::string name(cname, (size_t) namelen); + int location = glGetUniformLocation(program, name.c_str()); - // glGetActiveUniform appends "[0]" to the end of array uniform names... - if (u.name.length() > 3) + if (location == -1) + continue; + + name = canonicaliizeUniformName(name); + + const auto &uniformit = reflection.allUniforms.find(name); + if (uniformit == reflection.allUniforms.end()) { - size_t findpos = u.name.find("[0]"); - if (findpos != std::string::npos && findpos == u.name.length() - 3) - u.name.erase(u.name.length() - 3); + handleUnknownUniformName(name.c_str()); + continue; } + UniformInfo &u = *uniformit->second; + + u.active = true; + u.location = location; + // If this is a built-in (LOVE-created) uniform, store the location. BuiltinUniform builtin = BUILTIN_MAX_ENUM; if (getConstant(u.name.c_str(), builtin)) builtinUniforms[int(builtin)] = u.location; - if (u.location == -1) - continue; - - if (!fillUniformReflectionData(u)) - continue; - if ((u.baseType == UNIFORM_SAMPLER && builtin != BUILTIN_TEXTURE_MAIN) || u.baseType == UNIFORM_TEXELBUFFER) { TextureUnit unit; @@ -175,183 +165,51 @@ void Shader::mapActiveUniforms() storageTextureBindings.push_back(binding); } - // Make sure previously set uniform data is preserved, and shader- - // initialized values are retrieved. - auto oldu = olduniforms.find(u.name); - if (oldu != olduniforms.end()) + if (u.dataSize == 0) { - u.data = oldu->second.data; - u.dataSize = oldu->second.dataSize; - u.textures = oldu->second.textures; + if (u.baseType == UNIFORM_MATRIX) + u.dataSize = sizeof(uint32) * u.matrix.rows * u.matrix.columns * u.count; + else + u.dataSize = sizeof(uint32) * u.components * u.count; - updateUniform(&u, u.count, true); + u.data = malloc(u.dataSize); + memset(u.data, 0, u.dataSize); + + const auto &valuesit = reflection.localUniformInitializerValues.find(u.name); + if (valuesit != reflection.localUniformInitializerValues.end()) + { + const auto &values = valuesit->second; + if (!values.empty()) + memcpy(u.data, values.data(), std::min(u.dataSize, sizeof(LocalUniformValue) * values.size())); + } } - else + + if (u.baseType == UNIFORM_SAMPLER || u.baseType == UNIFORM_TEXELBUFFER) { - u.dataSize = 0; + int startunit = (int) textureUnits.size() - u.count; - switch (u.baseType) - { - case UNIFORM_FLOAT: - u.dataSize = sizeof(float) * u.components * u.count; - u.data = malloc(u.dataSize); - break; - case UNIFORM_INT: - case UNIFORM_BOOL: - case UNIFORM_SAMPLER: - case UNIFORM_STORAGETEXTURE: - case UNIFORM_TEXELBUFFER: - u.dataSize = sizeof(int) * u.components * u.count; - u.data = malloc(u.dataSize); - break; - case UNIFORM_UINT: - u.dataSize = sizeof(unsigned int) * u.components * u.count; - u.data = malloc(u.dataSize); - break; - case UNIFORM_MATRIX: - u.dataSize = sizeof(float) * ((size_t)u.matrix.rows * u.matrix.columns) * u.count; - u.data = malloc(u.dataSize); - break; - default: - break; - } + if (builtin == BUILTIN_TEXTURE_MAIN) + startunit = 0; - if (u.dataSize > 0) - { - memset(u.data, 0, u.dataSize); - - if (u.baseType == UNIFORM_SAMPLER || u.baseType == UNIFORM_TEXELBUFFER) - { - int startunit = (int) textureUnits.size() - u.count; - - if (builtin == BUILTIN_TEXTURE_MAIN) - startunit = 0; - - for (int i = 0; i < u.count; i++) - u.ints[i] = startunit + i; - - glUniform1iv(u.location, u.count, u.ints); - - if (u.baseType == UNIFORM_TEXELBUFFER) - { - u.buffers = new love::graphics::Buffer*[u.count]; - memset(u.buffers, 0, sizeof(Buffer *) * u.count); - } - else - { - u.textures = new love::graphics::Texture*[u.count]; - - auto *tex = gfx->getDefaultTexture(u.textureType, u.dataBaseType); - for (int i = 0; i < u.count; i++) - { - tex->retain(); - u.textures[i] = tex; - } - } - } - else if (u.baseType == UNIFORM_STORAGETEXTURE) - { - int startbinding = (int) storageTextureBindings.size() - u.count; - for (int i = 0; i < u.count; i++) - u.ints[i] = startbinding + i; - - glUniform1iv(u.location, u.count, u.ints); - - u.textures = new love::graphics::Texture*[u.count]; - - if ((u.access & ACCESS_WRITE) != 0) - { - memset(u.textures, 0, sizeof(Texture *) * u.count); - } - else - { - auto *tex = gfx->getDefaultTexture(u.textureType, u.dataBaseType); - for (int i = 0; i < u.count; i++) - { - tex->retain(); - u.textures[i] = tex; - } - } - } - } - - size_t offset = 0; - - // Store any shader-initialized values in our own memory. for (int i = 0; i < u.count; i++) - { - GLint location = u.location; - - if (u.count > 1) - { - std::ostringstream ss; - ss << i; - - std::string indexname = u.name + "[" + ss.str() + "]"; - location = glGetUniformLocation(program, indexname.c_str()); - } - - if (location == -1) - continue; - - switch (u.baseType) - { - case UNIFORM_FLOAT: - glGetUniformfv(program, location, &u.floats[offset]); - offset += u.components; - break; - case UNIFORM_INT: - case UNIFORM_BOOL: - glGetUniformiv(program, location, &u.ints[offset]); - offset += u.components; - break; - case UNIFORM_UINT: - glGetUniformuiv(program, location, &u.uints[offset]); - offset += u.components; - break; - case UNIFORM_MATRIX: - glGetUniformfv(program, location, &u.floats[offset]); - offset += (size_t)u.matrix.rows * u.matrix.columns; - break; - default: - break; - } - } + u.ints[i] = startunit + i; + } + else if (u.baseType == UNIFORM_STORAGETEXTURE) + { + int startbinding = (int) storageTextureBindings.size() - u.count; + for (int i = 0; i < u.count; i++) + u.ints[i] = startbinding + i; } - uniforms[u.name] = u; + updateUniform(&u, u.count, true); if (builtin != BUILTIN_MAX_ENUM) - builtinUniformInfo[(int)builtin] = &uniforms[u.name]; + builtinUniformInfo[(int)builtin] = &u; if (u.baseType == UNIFORM_SAMPLER || u.baseType == UNIFORM_STORAGETEXTURE) - { - // Make sure all stored textures have their Volatiles loaded before - // the sendTextures call, since it calls getHandle(). - for (int i = 0; i < u.count; i++) - { - if (u.textures[i] == nullptr) - continue; - Volatile *v = dynamic_cast(u.textures[i]); - if (v != nullptr) - v->loadVolatile(); - } - - sendTextures(&u, u.textures, u.count, true); - } + sendTextures(&u, &activeTextures[u.resourceIndex], u.count, true); else if (u.baseType == UNIFORM_TEXELBUFFER) - { - for (int i = 0; i < u.count; i++) - { - if (u.buffers[i] == nullptr) - continue; - Volatile *v = dynamic_cast(u.buffers[i]); - if (v != nullptr) - v->loadVolatile(); - } - - sendBuffers(&u, u.buffers, u.count, true); - } + sendBuffers(&u, &activeBuffers[u.resourceIndex], u.count, true); } if (gl.isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE)) @@ -364,37 +222,28 @@ void Shader::mapActiveUniforms() for (int sindex = 0; sindex < numstoragebuffers; sindex++) { - UniformInfo u = {}; - u.baseType = UNIFORM_STORAGEBUFFER; - u.access = ACCESS_READ; - GLsizei namelength = 0; glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, sindex, 2048, &namelength, namebuffer); - u.name = std::string(namebuffer, namelength); - u.count = 1; + std::string name = canonicaliizeUniformName(std::string(namebuffer, namelength)); - if (!fillUniformReflectionData(u)) + const auto &uniformit = reflection.storageBuffers.find(name); + if (uniformit == reflection.storageBuffers.end()) + { + handleUnknownUniformName(name.c_str()); continue; - - // Make sure previously set uniform data is preserved, and shader- - // initialized values are retrieved. - auto oldu = olduniforms.find(u.name); - if (oldu != olduniforms.end()) - { - u.data = oldu->second.data; - u.dataSize = oldu->second.dataSize; - u.buffers = oldu->second.buffers; } - else + + UniformInfo &u = uniformit->second; + + u.active = true; + + if (u.dataSize == 0) { - u.dataSize = sizeof(int) * 1; + u.dataSize = sizeof(int) * u.count; u.data = malloc(u.dataSize); - - u.ints[0] = -1; - - u.buffers = new love::graphics::Buffer * [u.count]; - memset(u.buffers, 0, sizeof(Buffer*)* u.count); + for (int i = 0; i < u.count; i++) + u.ints[i] = -1; } // Unlike local uniforms and attributes, OpenGL doesn't auto-assign storage @@ -417,56 +266,13 @@ void Shader::mapActiveUniforms() if (u.access & ACCESS_WRITE) { p.second = (int)activeWritableStorageBuffers.size(); - activeWritableStorageBuffers.push_back(u.buffers[0]); + activeWritableStorageBuffers.push_back(activeBuffers[u.resourceIndex]); } storageBufferBindingIndexToActiveBinding[binding.bindingindex] = p; } - uniforms[u.name] = u; - - for (int i = 0; i < u.count; i++) - { - if (u.buffers[i] == nullptr) - continue; - Volatile* v = dynamic_cast(u.buffers[i]); - if (v != nullptr) - v->loadVolatile(); - } - - sendBuffers(&u, u.buffers, u.count, true); - } - } - - // Make sure uniforms that existed before but don't exist anymore are - // cleaned up. This theoretically shouldn't happen, but... - for (const auto &p : olduniforms) - { - if (uniforms.find(p.first) == uniforms.end()) - { - if (p.second.data != nullptr) - free(p.second.data); - - if (p.second.baseType == UNIFORM_SAMPLER || p.second.baseType == UNIFORM_STORAGETEXTURE) - { - for (int i = 0; i < p.second.count; i++) - { - if (p.second.textures[i] != nullptr) - p.second.textures[i]->release(); - } - - delete[] p.second.textures; - } - else if (isBuffer(p.second.baseType)) - { - for (int i = 0; i < p.second.count; i++) - { - if (p.second.buffers[i] != nullptr) - p.second.buffers[i]->release(); - } - - delete[] p.second.buffers; - } + sendBuffers(&u, &activeBuffers[u.resourceIndex], u.count, true); } } @@ -600,7 +406,7 @@ std::string Shader::getWarnings() const const std::string &stagewarnings = stage->getWarnings(); - if (ShaderStage::getConstant(stage->getStageType(), stagestr)) + if (!stagewarnings.empty() && ShaderStage::getConstant(stage->getStageType(), stagestr)) warnings += std::string(stagestr) + std::string(" shader:\n") + stagewarnings; } @@ -649,16 +455,6 @@ void Shader::attach() } } -const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const -{ - const auto it = uniforms.find(name); - - if (it == uniforms.end()) - return nullptr; - - return &(it->second); -} - const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const { return builtinUniformInfo[(int)builtin]; @@ -802,10 +598,12 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex tex->retain(); - if (info->textures[i] != nullptr) - info->textures[i]->release(); + int resourceindex = info->resourceIndex + i; - info->textures[i] = tex; + if (activeTextures[resourceindex] != nullptr) + activeTextures[resourceindex]->release(); + + activeTextures[resourceindex] = tex; if (isstoragetex) { @@ -885,10 +683,12 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe buffer->retain(); - if (info->buffers[i] != nullptr) - info->buffers[i]->release(); + int resourceindex = info->resourceIndex + i; - info->buffers[i] = buffer; + if (activeBuffers[resourceindex] != nullptr) + activeBuffers[resourceindex]->release(); + + activeBuffers[resourceindex] = buffer; if (texelbinding) { @@ -926,11 +726,6 @@ void Shader::flushBatchedDraws() const Graphics::flushBatchedDrawsGlobal(); } -bool Shader::hasUniform(const std::string &name) const -{ - return uniforms.find(name) != uniforms.end(); -} - ptrdiff_t Shader::getHandle() const { return program; @@ -972,6 +767,8 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, if (current != this) return; + bool rt = gfx->isRenderTargetActive(); + BuiltinUniformData data; data.transformMatrix = gfx->getTransform(); @@ -997,13 +794,26 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, // Same with point size. data.normalMatrix[1].w = gfx->getPointSize(); + // Users expect to work with y-up NDC, y-down pixel coordinates and textures + // (see graphics/Shader.h). + // OpenGL has y-up NDC and y-up pixel coordinates and textures. If we just flip + // NDC y when rendering to a texture, it's enough to make (0, 0) on the texture + // match what we expect when sampling from it - so it's the same as if textures + // are y-down with y-up NDC. + // Windowing systems treat (0, 0) on the backbuffer texture as the bottom left, + // so we don't need to do that there. + uint32 clipflags = 0; + if (rt) + clipflags |= CLIP_TRANSFORM_FLIP_Y; + data.clipSpaceParams = computeClipSpaceParams(clipflags); + data.screenSizeParams.x = viewportW; data.screenSizeParams.y = viewportH; // The shader does pixcoord.y = gl_FragCoord.y * params.z + params.w. // This lets us flip pixcoord.y when needed, to be consistent (drawing // with no RT active makes the pixel coordinates y-flipped.) - if (gfx->isRenderTargetActive()) + if (rt) { // No flipping: pixcoord.y = gl_FragCoord.y * 1.0 + 0.0. data.screenSizeParams.z = 1.0f; @@ -1030,7 +840,7 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, { GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW]; if (location >= 0) - glUniform4fv(location, 12, (const GLfloat *) &data); + glUniform4fv(location, 13, (const GLfloat *) &data); GLint location2 = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW_2]; if (location2 >= 0) glUniform4fv(location2, 1, (const GLfloat *) &data.screenSizeParams); @@ -1039,294 +849,7 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, { GLint location = builtinUniforms[BUILTIN_UNIFORMS_PER_DRAW]; if (location >= 0) - glUniform4fv(location, 13, (const GLfloat *) &data); - } -} - -int Shader::getUniformTypeComponents(GLenum type) const -{ - switch (type) - { - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - case GL_BOOL: - return 1; - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - case GL_FLOAT_VEC2: - case GL_FLOAT_MAT2: - case GL_BOOL_VEC2: - return 2; - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - case GL_FLOAT_VEC3: - case GL_FLOAT_MAT3: - case GL_BOOL_VEC3: - return 3; - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT4: - case GL_BOOL_VEC4: - return 4; - default: - return 1; - } -} - -Shader::MatrixSize Shader::getMatrixSize(GLenum type) const -{ - MatrixSize m; - - switch (type) - { - case GL_FLOAT_MAT2: - m.columns = m.rows = 2; - break; - case GL_FLOAT_MAT3: - m.columns = m.rows = 3; - break; - case GL_FLOAT_MAT4: - m.columns = m.rows = 4; - break; - case GL_FLOAT_MAT2x3: - m.columns = 2; - m.rows = 3; - break; - case GL_FLOAT_MAT2x4: - m.columns = 2; - m.rows = 4; - break; - case GL_FLOAT_MAT3x2: - m.columns = 3; - m.rows = 2; - break; - case GL_FLOAT_MAT3x4: - m.columns = 3; - m.rows = 4; - break; - case GL_FLOAT_MAT4x2: - m.columns = 4; - m.rows = 2; - break; - case GL_FLOAT_MAT4x3: - m.columns = 4; - m.rows = 3; - break; - default: - m.columns = m.rows = 0; - break; - } - - return m; -} - -void Shader::computeUniformTypeInfo(GLenum type, UniformInfo &u) -{ - u.isDepthSampler = false; - u.components = getUniformTypeComponents(type); - u.baseType = UNIFORM_UNKNOWN; - - switch (type) - { - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - u.baseType = UNIFORM_INT; - u.dataBaseType = DATA_BASETYPE_INT; - break; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_VEC2: - case GL_UNSIGNED_INT_VEC3: - case GL_UNSIGNED_INT_VEC4: - u.baseType = UNIFORM_UINT; - u.dataBaseType = DATA_BASETYPE_UINT; - break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - u.baseType = UNIFORM_FLOAT; - u.dataBaseType = DATA_BASETYPE_FLOAT; - break; - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - u.baseType = UNIFORM_MATRIX; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.matrix = getMatrixSize(type); - break; - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - u.baseType = UNIFORM_BOOL; - u.dataBaseType = DATA_BASETYPE_BOOL; - break; - - case GL_SAMPLER_2D: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_2D; - break; - case GL_SAMPLER_2D_SHADOW: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_2D; - u.isDepthSampler = true; - break; - case GL_INT_SAMPLER_2D: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_2D; - break; - case GL_UNSIGNED_INT_SAMPLER_2D: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_2D; - break; - case GL_SAMPLER_2D_ARRAY: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_2D_ARRAY; - break; - case GL_SAMPLER_2D_ARRAY_SHADOW: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_2D_ARRAY; - u.isDepthSampler = true; - break; - case GL_INT_SAMPLER_2D_ARRAY: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_2D_ARRAY; - break; - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_2D_ARRAY; - break; - case GL_SAMPLER_3D: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_VOLUME; - break; - case GL_INT_SAMPLER_3D: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_VOLUME; - break; - case GL_UNSIGNED_INT_SAMPLER_3D: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_VOLUME; - break; - case GL_SAMPLER_CUBE: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_CUBE; - break; - case GL_SAMPLER_CUBE_SHADOW: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_CUBE; - u.isDepthSampler = true; - break; - case GL_INT_SAMPLER_CUBE: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_CUBE; - break; - case GL_UNSIGNED_INT_SAMPLER_CUBE: - u.baseType = UNIFORM_SAMPLER; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_CUBE; - break; - - case GL_SAMPLER_BUFFER: - u.baseType = UNIFORM_TEXELBUFFER; - u.dataBaseType = DATA_BASETYPE_FLOAT; - break; - case GL_INT_SAMPLER_BUFFER: - u.baseType = UNIFORM_TEXELBUFFER; - u.dataBaseType = DATA_BASETYPE_INT; - break; - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - u.baseType = UNIFORM_TEXELBUFFER; - u.dataBaseType = DATA_BASETYPE_UINT; - break; - - case GL_IMAGE_2D: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_2D; - break; - case GL_INT_IMAGE_2D: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_2D; - break; - case GL_UNSIGNED_INT_IMAGE_2D: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_2D; - break; - case GL_IMAGE_2D_ARRAY: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_2D_ARRAY; - break; - case GL_INT_IMAGE_2D_ARRAY: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_2D_ARRAY; - break; - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_2D_ARRAY; - break; - case GL_IMAGE_3D: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_VOLUME; - break; - case GL_INT_IMAGE_3D: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_VOLUME; - break; - case GL_UNSIGNED_INT_IMAGE_3D: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_VOLUME; - break; - case GL_IMAGE_CUBE: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_FLOAT; - u.textureType = TEXTURE_CUBE; - break; - case GL_INT_IMAGE_CUBE: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_INT; - u.textureType = TEXTURE_CUBE; - break; - case GL_UNSIGNED_INT_IMAGE_CUBE: - u.baseType = UNIFORM_STORAGETEXTURE; - u.dataBaseType = DATA_BASETYPE_UINT; - u.textureType = TEXTURE_CUBE; - break; - - default: - break; + glUniform4fv(location, 14, (const GLfloat *) &data); } } diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index 0712ba9bb..134ab97fb 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -63,12 +63,10 @@ public: void attach() override; std::string getWarnings() const override; int getVertexAttributeIndex(const std::string &name) override; - const UniformInfo *getUniformInfo(const std::string &name) const override; const UniformInfo *getUniformInfo(BuiltinUniform builtin) const override; void updateUniform(const UniformInfo *info, int count) override; void sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count) override; void sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count) override; - bool hasUniform(const std::string &name) const override; ptrdiff_t getHandle() const override; void setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture) override; @@ -100,10 +98,6 @@ private: void sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count, bool internalupdate); void sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count, bool internalupdate); - int getUniformTypeComponents(GLenum type) const; - void computeUniformTypeInfo(GLenum type, UniformInfo &u); - MatrixSize getMatrixSize(GLenum type) const; - void flushBatchedDraws() const; // Get any warnings or errors generated only by the shader program object. @@ -120,9 +114,6 @@ private: std::map attributes; - // Uniform location buffer map - std::map uniforms; - // Texture unit pool for setting textures std::vector textureUnits; diff --git a/src/modules/graphics/opengl/ShaderStage.cpp b/src/modules/graphics/opengl/ShaderStage.cpp index babd1b777..4001404e0 100644 --- a/src/modules/graphics/opengl/ShaderStage.cpp +++ b/src/modules/graphics/opengl/ShaderStage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/ShaderStage.h b/src/modules/graphics/opengl/ShaderStage.h index db21b6322..1481fdc39 100644 --- a/src/modules/graphics/opengl/ShaderStage.h +++ b/src/modules/graphics/opengl/ShaderStage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/StreamBuffer.cpp b/src/modules/graphics/opengl/StreamBuffer.cpp index df304b5a9..9317ead3a 100644 --- a/src/modules/graphics/opengl/StreamBuffer.cpp +++ b/src/modules/graphics/opengl/StreamBuffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -63,6 +63,11 @@ public: delete[] data; } + size_t getGPUReadOffset() const override + { + return (size_t) data; + } + MapInfo map(size_t /*minsize*/) override { return MapInfo(data, bufferSize); @@ -111,6 +116,11 @@ public: delete[] data; } + size_t getGPUReadOffset() const override + { + return frameGPUReadOffset; + } + MapInfo map(size_t /*minsize*/) override { if (orphan) @@ -192,6 +202,11 @@ public: virtual ~StreamBufferSync() {} + size_t getGPUReadOffset() const override + { + return (frameIndex * bufferSize) + frameGPUReadOffset; + } + void nextFrame() override { // Insert a GPU fence for this frame's section of the data, we'll wait diff --git a/src/modules/graphics/opengl/StreamBuffer.h b/src/modules/graphics/opengl/StreamBuffer.h index f6c036176..0fa184a09 100644 --- a/src/modules/graphics/opengl/StreamBuffer.h +++ b/src/modules/graphics/opengl/StreamBuffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index afa4e1e01..49f377f03 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -244,6 +244,25 @@ Texture::Texture(love::graphics::Graphics *gfx, const Settings &settings, const slices.clear(); } +Texture::Texture(love::graphics::Graphics *gfx, love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) + : love::graphics::Texture(gfx, base, viewsettings) + , slices(viewsettings.type.get(base->getTextureType())) + , fbo(0) + , texture(0) + , renderbuffer(0) + , framebufferStatus(GL_FRAMEBUFFER_COMPLETE) + , textureGLError(GL_NO_ERROR) + , actualSamples(1) +{ + if (!loadVolatile()) + { + if (framebufferStatus != GL_FRAMEBUFFER_COMPLETE) + throw love::Exception("Cannot create texture view (OpenGL framebuffer error: %s)", OpenGL::framebufferStatusString(framebufferStatus)); + if (textureGLError != GL_NO_ERROR) + throw love::Exception("Cannot create texture view (OpenGL error: %s)", OpenGL::errorString(textureGLError)); + } +} + Texture::~Texture() { unloadVolatile(); @@ -254,11 +273,26 @@ void Texture::createTexture() // The base class handles some validation. For example, if ImageData is // given then it must exist for all mip levels, a render target can't use // a compressed format, etc. - glGenTextures(1, &texture); + GLenum gltype = OpenGL::getGLTextureType(texType); + + if (parentView.texture != this) + { + OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false); + Texture *basetex = (Texture *) parentView.texture; + int layers = texType == TEXTURE_CUBE ? 6 : getLayerCount(); + + glTextureView(texture, gltype, basetex->texture, fmt.internalformat, + parentView.startMipmap, getMipmapCount(), + parentView.startLayer, layers); + + gl.bindTextureToUnit(this, 0, false); + setSamplerState(samplerState); + return; + } + gl.bindTextureToUnit(this, 0, false); - GLenum gltype = OpenGL::getGLTextureType(texType); if (renderTarget && GLAD_ANGLE_texture_usage) glTexParameteri(gltype, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE); @@ -356,7 +390,7 @@ void Texture::createTexture() int slices = texType == TEXTURE_VOLUME ? getDepth(mip) : layers; slices = texType == TEXTURE_CUBE ? 6 : slices; for (int i = 0; i < slices; i++) - uploadByteData(format, emptydata.data(), emptydata.size(), mip, i, r); + uploadByteData(emptydata.data(), emptydata.size(), mip, i, r); } } @@ -371,6 +405,12 @@ bool Texture::loadVolatile() if (texture != 0 || renderbuffer != 0) return true; + if (parentView.texture != this) + { + Texture *basetex = (Texture *) parentView.texture; + basetex->loadVolatile(); + } + OpenGL::TempDebugGroup debuggroup("Texture load"); // NPOT textures don't support mipmapping without full NPOT support. @@ -466,19 +506,19 @@ void Texture::unloadVolatile() setGraphicsMemorySize(0); } -void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) +void Texture::uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) { OpenGL::TempDebugGroup debuggroup("Texture data upload"); gl.bindTextureToUnit(this, 0, false); - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false); GLenum gltarget = OpenGL::getGLTextureType(texType); if (texType == TEXTURE_CUBE) gltarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice; - if (isPixelFormatCompressed(pixelformat)) + if (isPixelFormatCompressed(format)) { if (texType == TEXTURE_2D || texType == TEXTURE_CUBE) { @@ -566,7 +606,7 @@ void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset // glTexSubImage and friends copy from the active pixel_unpack_buffer by // treating the pointer as a byte offset. const uint8 *byteoffset = (const uint8 *)(ptrdiff_t)sourceoffset; - uploadByteData(format, byteoffset, size, mipmap, slice, rect); + uploadByteData(byteoffset, size, mipmap, slice, rect); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); @@ -593,18 +633,7 @@ void Texture::setSamplerState(const SamplerState &s) if (s.depthSampleMode.hasValue && !gl.isDepthCompareSampleSupported()) throw love::Exception("Depth comparison sampling in shaders is not supported on this system."); - // Base class does common validation and assigns samplerState. - love::graphics::Texture::setSamplerState(s); - - auto supportedflags = OpenGL::getPixelFormatUsageFlags(getPixelFormat()); - - if ((supportedflags & PIXELFORMATUSAGEFLAGS_LINEAR) == 0) - { - samplerState.magFilter = samplerState.minFilter = SamplerState::FILTER_NEAREST; - - if (samplerState.mipmapFilter == SamplerState::MIPMAP_FILTER_LINEAR) - samplerState.mipmapFilter = SamplerState::MIPMAP_FILTER_NEAREST; - } + samplerState = validateSamplerState(s); // If we only have limited NPOT support then the wrap mode must be CLAMP. if ((GLAD_ES_VERSION_2_0 && !(GLAD_ES_VERSION_3_0 || GLAD_OES_texture_npot)) diff --git a/src/modules/graphics/opengl/Texture.h b/src/modules/graphics/opengl/Texture.h index 321f7b21c..4e507fb2f 100644 --- a/src/modules/graphics/opengl/Texture.h +++ b/src/modules/graphics/opengl/Texture.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -39,6 +39,7 @@ class Texture final : public love::graphics::Texture, public Volatile public: Texture(love::graphics::Graphics *gfx, const Settings &settings, const Slices *data); + Texture(love::graphics::Graphics *gfx, love::graphics::Texture *base, const Texture::ViewSettings &viewsettings); virtual ~Texture(); @@ -61,9 +62,10 @@ public: void readbackInternal(int slice, int mipmap, const Rect &rect, int destwidth, size_t size, void *dest); private: + void createTexture(); - void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override; + void uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) override; void generateMipmapsInternal() override; diff --git a/src/modules/graphics/renderstate.cpp b/src/modules/graphics/renderstate.cpp index 171103de0..f52afd4f9 100644 --- a/src/modules/graphics/renderstate.cpp +++ b/src/modules/graphics/renderstate.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/renderstate.h b/src/modules/graphics/renderstate.h index 193dc567c..662b5cd11 100644 --- a/src/modules/graphics/renderstate.h +++ b/src/modules/graphics/renderstate.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 64b6dc1eb..b2e5f098e 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -26,6 +26,8 @@ namespace love namespace graphics { +static_assert(sizeof(VertexAttributeInfo) == 4, "Unexpected sizeof(VertexAttributeInfo)"); + static_assert(sizeof(Color32) == 4, "sizeof(Color32) incorrect!"); static_assert(sizeof(STf_RGBAub) == sizeof(float)*2 + sizeof(Color32), "sizeof(STf_RGBAub) incorrect!"); static_assert(sizeof(STPf_RGBAub) == sizeof(float)*3 + sizeof(Color32), "sizeof(STPf_RGBAub) incorrect!"); @@ -336,7 +338,7 @@ bool VertexAttributes::operator == (const VertexAttributes &other) const { const auto &a = attribs[i]; const auto &b = other.attribs[i]; - if (a.bufferIndex != b.bufferIndex || a.format != b.format || a.offsetFromVertex != b.offsetFromVertex) + if (a.bufferIndex != b.bufferIndex || a.packedFormat != b.packedFormat || a.offsetFromVertex != b.offsetFromVertex) return false; if (bufferLayouts[a.bufferIndex].stride != other.bufferLayouts[a.bufferIndex].stride) diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index 044ba2c44..7669c407d 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -298,9 +298,12 @@ struct BufferBindings struct VertexAttributeInfo { - uint8 bufferIndex; - DataFormat format : 8; uint16 offsetFromVertex; + uint8 packedFormat; + uint8 bufferIndex; + + void setFormat(DataFormat format) { packedFormat = (uint8)format; } + DataFormat getFormat() const { return (DataFormat)packedFormat; } }; struct VertexBufferLayout @@ -335,7 +338,7 @@ struct VertexAttributes enableBits |= (1u << index); attribs[index].bufferIndex = bufferindex; - attribs[index].format = format; + attribs[index].setFormat(format); attribs[index].offsetFromVertex = offsetfromvertex; } diff --git a/src/modules/graphics/vulkan/Buffer.cpp b/src/modules/graphics/vulkan/Buffer.cpp index b68ae9c1a..4cf4f45d4 100644 --- a/src/modules/graphics/vulkan/Buffer.cpp +++ b/src/modules/graphics/vulkan/Buffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vulkan/Buffer.h b/src/modules/graphics/vulkan/Buffer.h index 6b393b52b..41d64b6cd 100644 --- a/src/modules/graphics/vulkan/Buffer.h +++ b/src/modules/graphics/vulkan/Buffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 98e64e520..b4d98a0ce 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -21,6 +21,7 @@ #include "common/Exception.h" #include "common/pixelformat.h" #include "common/version.h" +#include "common/memory.h" #include "window/Window.h" #include "Buffer.h" #include "Graphics.h" @@ -60,11 +61,6 @@ static const std::vector deviceExtensions = { constexpr uint32_t USAGES_POLL_INTERVAL = 5000; -const char *Graphics::getName() const -{ - return "love.graphics.vulkan"; -} - VkDevice Graphics::getDevice() const { return device; @@ -95,6 +91,7 @@ static void checkOptionalInstanceExtensions(OptionalInstanceExtensions& ext) } Graphics::Graphics() + : love::graphics::Graphics("love.graphics.vulkan") { if (SDL_Vulkan_LoadLibrary(nullptr)) throw love::Exception("could not find vulkan"); @@ -157,6 +154,7 @@ Graphics::~Graphics() { defaultConstantTexCoord.set(nullptr); defaultConstantColor.set(nullptr); + localUniformBuffer.set(nullptr); Volatile::unloadAll(); cleanup(); @@ -172,6 +170,11 @@ love::graphics::Texture *Graphics::newTexture(const love::graphics::Texture::Set return new Texture(this, settings, data); } +love::graphics::Texture *Graphics::newTextureView(love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) +{ + return new Texture(this, base, viewsettings); +} + love::graphics::Buffer *Graphics::newBuffer(const love::graphics::Buffer::Settings &settings, const std::vector &format, const void *data, size_t size, size_t arraylength) { return new Buffer(this, settings, format, data, size, arraylength); @@ -383,63 +386,50 @@ void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallback if (renderPassState.active) endRenderPass(); + VkBuffer screenshotBuffer = VK_NULL_HANDLE; + VmaAllocation screenshotAllocation = VK_NULL_HANDLE; + VmaAllocationInfo screenshotAllocationInfo = {}; + if (submitMode == SUBMIT_PRESENT) { if (pendingScreenshotCallbacks.empty()) Vulkan::cmdTransitionImageLayout( commandBuffers.at(currentFrame), swapChainImages.at(imageIndex), + swapChainPixelFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); else { + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = 4ll * swapChainExtent.width * swapChainExtent.height; + bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; + + auto result = vmaCreateBuffer( + vmaAllocator, + &bufferInfo, + &allocCreateInfo, + &screenshotBuffer, + &screenshotAllocation, + &screenshotAllocationInfo); + + if (result != VK_SUCCESS) + throw love::Exception("failed to create screenshot readback buffer"); + + // TODO: swap chain images aren't guaranteed to support TRANSFER_SRC_BIT usage flags. Vulkan::cmdTransitionImageLayout( commandBuffers.at(currentFrame), swapChainImages.at(imageIndex), + swapChainPixelFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - Vulkan::cmdTransitionImageLayout( - commandBuffers.at(currentFrame), - screenshotReadbackBuffers.at(currentFrame).image, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkImageBlit blit{}; - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.layerCount = 1; - blit.srcOffsets[1] = { - static_cast(swapChainExtent.width), - static_cast(swapChainExtent.height), - 1 - }; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.layerCount = 1; - blit.dstOffsets[1] = { - static_cast(swapChainExtent.width), - static_cast(swapChainExtent.height), - 1 - }; - - vkCmdBlitImage( - commandBuffers.at(currentFrame), - swapChainImages.at(imageIndex), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - screenshotReadbackBuffers.at(currentFrame).image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &blit, - VK_FILTER_NEAREST); - - Vulkan::cmdTransitionImageLayout( - commandBuffers.at(currentFrame), - swapChainImages.at(imageIndex), - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - Vulkan::cmdTransitionImageLayout( - commandBuffers.at(currentFrame), - screenshotReadbackBuffers.at(currentFrame).image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - VkBufferImageCopy region{}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.layerCount = 1; @@ -451,32 +441,17 @@ void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallback vkCmdCopyImageToBuffer( commandBuffers.at(currentFrame), - screenshotReadbackBuffers.at(currentFrame).image, + swapChainImages.at(imageIndex), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - screenshotReadbackBuffers.at(currentFrame).buffer, + screenshotBuffer, 1, ®ion); - addReadbackCallback([ - w = swapChainExtent.width, - h = swapChainExtent.height, - pendingScreenshotCallbacks = pendingScreenshotCallbacks, - screenShotReadbackBuffer = screenshotReadbackBuffers.at(currentFrame), - screenshotCallbackData = screenshotCallbackData]() { - auto imageModule = Module::getInstance(M_IMAGE); - - for (const auto &info : pendingScreenshotCallbacks) - { - image::ImageData *img = imageModule->newImageData( - w, - h, - PIXELFORMAT_RGBA8_UNORM, - screenShotReadbackBuffer.allocationInfo.pMappedData); - info.callback(&info, img, screenshotCallbackData); - img->release(); - } - }); - - pendingScreenshotCallbacks.clear(); + Vulkan::cmdTransitionImageLayout( + commandBuffers.at(currentFrame), + swapChainImages.at(imageIndex), + swapChainPixelFormat, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); } } @@ -521,7 +496,7 @@ void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallback if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS) throw love::Exception("failed to submit draw command buffer"); - if (submitMode == SUBMIT_NOPRESENT || submitMode == SUBMIT_RESTART) + if (submitMode == SUBMIT_NOPRESENT || submitMode == SUBMIT_RESTART || screenshotBuffer != VK_NULL_HANDLE) { vkQueueWaitIdle(graphicsQueue); @@ -532,6 +507,64 @@ void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallback callbacks.clear(); } + if (screenshotBuffer != VK_NULL_HANDLE) + { + auto imageModule = Module::getInstance(M_IMAGE); + + for (int i = 0; i < (int)pendingScreenshotCallbacks.size(); i++) + { + const auto &info = pendingScreenshotCallbacks[i]; + image::ImageData *img = nullptr; + + try + { + img = imageModule->newImageData( + swapChainExtent.width, + swapChainExtent.height, + PIXELFORMAT_RGBA8_UNORM, + screenshotAllocationInfo.pMappedData); + } + catch (love::Exception &) + { + info.callback(&info, nullptr, nullptr); + for (int j = i + 1; j < (int)pendingScreenshotCallbacks.size(); j++) + { + const auto& ninfo = pendingScreenshotCallbacks[j]; + ninfo.callback(&ninfo, nullptr, nullptr); + } + vmaDestroyBuffer(vmaAllocator, screenshotBuffer, screenshotAllocation); + pendingScreenshotCallbacks.clear(); + throw; + } + + uint8 *screenshot = (uint8*)img->getData(); + + if (swapChainImageFormat == VK_FORMAT_B8G8R8A8_UNORM || swapChainImageFormat == VK_FORMAT_B8G8R8A8_SRGB) + { + // Convert from BGRA to RGBA and replace alpha with full opacity. + for (size_t i = 0; i < img->getSize(); i += 4) + { + uint8 r = screenshot[i + 2]; + screenshot[i + 2] = screenshot[i + 0]; + screenshot[i + 0] = r; + screenshot[i + 3] = 255; + } + } + else + { + // Replace alpha with full opacity. + for (size_t i = 0; i < img->getSize(); i += 4) + screenshot[i + 3] = 255; + } + + info.callback(&info, img, screenshotCallbackData); + img->release(); + } + + vmaDestroyBuffer(vmaAllocator, screenshotBuffer, screenshotAllocation); + pendingScreenshotCallbacks.clear(); + } + if (submitMode == SUBMIT_RESTART) startRecordingGraphicsCommands(); } @@ -637,7 +670,6 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int createSwapChain(); createImageViews(); - createScreenshotCallbackBuffers(); createColorResources(); createDepthResources(); transitionColorDepthLayouts = true; @@ -649,6 +681,9 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int createSyncObjects(); } + if (localUniformBuffer == nullptr) + localUniformBuffer.set(new StreamBuffer(this, BUFFERUSAGE_UNIFORM, 1024 * 512 * 1), Acquire::NORETAIN); + beginFrame(); if (createBaseObjects) @@ -1057,6 +1092,22 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage) { format = getSizedFormat(format); + switch (format) + { + case PIXELFORMAT_PVR1_RGB2_UNORM: + case PIXELFORMAT_PVR1_RGB2_sRGB: + case PIXELFORMAT_PVR1_RGB4_UNORM: + case PIXELFORMAT_PVR1_RGB4_sRGB: + case PIXELFORMAT_PVR1_RGBA2_UNORM: + case PIXELFORMAT_PVR1_RGBA2_sRGB: + case PIXELFORMAT_PVR1_RGBA4_UNORM: + case PIXELFORMAT_PVR1_RGBA4_sRGB: + // Lets not support these in Vulkan - they're deprecated. + return false; + default: + break; + } + auto vulkanFormat = Vulkan::getTextureFormat(format); VkFormatProperties formatProperties; @@ -1188,12 +1239,6 @@ bool Graphics::dispatch(love::graphics::Shader *shader, love::graphics::Buffer * return true; } -Matrix4 Graphics::computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const -{ - uint32 flags = DEVICE_PROJECTION_DEFAULT; - return calculateDeviceProjection(projection, flags); -} - void Graphics::setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) { if (renderPassState.active) @@ -1277,6 +1322,7 @@ void Graphics::beginFrame() Vulkan::cmdTransitionImageLayout( commandBuffers.at(currentFrame), swapChainImages[imageIndex], + swapChainPixelFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -1286,6 +1332,7 @@ void Graphics::beginFrame() Vulkan::cmdTransitionImageLayout( commandBuffers.at(currentFrame), depthImage, + depthStencilPixelFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); @@ -1293,6 +1340,7 @@ void Graphics::beginFrame() Vulkan::cmdTransitionImageLayout( commandBuffers.at(currentFrame), colorImage, + swapChainPixelFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -1301,9 +1349,11 @@ void Graphics::beginFrame() Vulkan::resetShaderSwitches(); - for (const auto shader : usedShadersInFrame) + for (const auto &shader : usedShadersInFrame) shader->newFrame(); usedShadersInFrame.clear(); + + localUniformBuffer->nextFrame(); } void Graphics::startRecordingGraphicsCommands() @@ -1329,11 +1379,6 @@ void Graphics::endRecordingGraphicsCommands() { throw love::Exception("failed to record command buffer"); } -const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const -{ - return minUniformBufferOffsetAlignment; -} - VkCommandBuffer Graphics::getCommandBufferForDataTransfer() { if (renderPassState.active) @@ -1379,8 +1424,22 @@ graphics::Shader::BuiltinUniformData Graphics::getCurrentBuiltinUniformData() // Same with point size. data.normalMatrix[1].w = getPointSize(); - data.screenSizeParams.x = static_cast(swapChainExtent.width); - data.screenSizeParams.y = static_cast(swapChainExtent.height); + // Flip y to convert input y-up [-1, 1] to vulkan's y-down [-1, 1]. + // Convert input z [-1, 1] to vulkan [0, 1]. + uint32 flags = Shader::CLIP_TRANSFORM_FLIP_Y | Shader::CLIP_TRANSFORM_Z_NEG1_1_TO_0_1; + data.clipSpaceParams = Shader::computeClipSpaceParams(flags); + + const auto &rt = states.back().renderTargets.getFirstTarget(); + if (rt.texture != nullptr) + { + data.screenSizeParams.x = rt.texture->getPixelWidth(rt.mipmap); + data.screenSizeParams.y = rt.texture->getPixelHeight(rt.mipmap); + } + else + { + data.screenSizeParams.x = getPixelWidth(); + data.screenSizeParams.y = getPixelHeight(); + } data.screenSizeParams.z = 1.0f; data.screenSizeParams.w = 0.0f; @@ -1459,6 +1518,18 @@ void Graphics::pickPhysicalDevice() deviceApiVersion = properties.apiVersion; depthStencilFormat = findDepthFormat(); + switch (depthStencilFormat) + { + case VK_FORMAT_D32_SFLOAT_S8_UINT: + depthStencilPixelFormat = PIXELFORMAT_DEPTH32_FLOAT_STENCIL8; + break; + case VK_FORMAT_D24_UNORM_S8_UINT: + depthStencilPixelFormat = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; + break; + default: + throw love::Exception("Failed to convert vulkan depth/stencil swapchain pixel format %d to love PixelFormat.", depthStencilFormat); + break; + } } bool Graphics::checkDeviceExtensionSupport(VkPhysicalDevice device) @@ -1848,6 +1919,25 @@ void Graphics::createSwapChain() swapChainImageFormat = surfaceFormat.format; swapChainExtent = extent; preTransform = swapChainSupport.capabilities.currentTransform; + + switch (swapChainImageFormat) + { + case VK_FORMAT_B8G8R8A8_SRGB: + swapChainPixelFormat = PIXELFORMAT_BGRA8_sRGB; + break; + case VK_FORMAT_B8G8R8A8_UNORM: + swapChainPixelFormat = PIXELFORMAT_BGRA8_UNORM; + break; + case VK_FORMAT_R8G8B8A8_SRGB: + swapChainPixelFormat = PIXELFORMAT_RGBA8_sRGB; + break; + case VK_FORMAT_R8G8B8A8_UNORM: + swapChainPixelFormat = PIXELFORMAT_RGBA8_UNORM; + break; + default: + throw love::Exception("Failed to convert vulkan depth/stencil swapchain image format %d to love PixelFormat.", swapChainImageFormat); + break; + } } VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector &availableFormats) @@ -1983,65 +2073,6 @@ void Graphics::createImageViews() } } -void Graphics::createScreenshotCallbackBuffers() -{ - screenshotReadbackBuffers.resize(MAX_FRAMES_IN_FLIGHT); - - for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - { - VkBufferCreateInfo bufferInfo{}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = 4ll * swapChainExtent.width * swapChainExtent.height; - bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VmaAllocationCreateInfo allocCreateInfo{}; - allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; - allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; - - auto result = vmaCreateBuffer( - vmaAllocator, - &bufferInfo, - &allocCreateInfo, - &screenshotReadbackBuffers.at(i).buffer, - &screenshotReadbackBuffers.at(i).allocation, - &screenshotReadbackBuffers.at(i).allocationInfo); - - if (result != VK_SUCCESS) - throw love::Exception("failed to create screenshot readback buffer"); - - VkImageCreateInfo imageInfo{}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB; - imageInfo.extent = { - swapChainExtent.width, - swapChainExtent.height, - 1 - }; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VmaAllocationCreateInfo imageAllocCreateInfo{}; - - result = vmaCreateImage( - vmaAllocator, - &imageInfo, - &imageAllocCreateInfo, - &screenshotReadbackBuffers.at(i).image, - &screenshotReadbackBuffers.at(i).imageAllocation, - nullptr); - - if (result != VK_SUCCESS) - throw love::Exception("failed to create screenshot readback image"); - } -} - VkFramebuffer Graphics::createFramebuffer(FramebufferConfiguration &configuration) { std::vector attachments; @@ -2272,7 +2303,7 @@ void Graphics::createVulkanVertexFormat( attributeDescription.location = i; attributeDescription.binding = bufferBinding; attributeDescription.offset = attrib.offsetFromVertex; - attributeDescription.format = Vulkan::getVulkanVertexFormat(attrib.format); + attributeDescription.format = Vulkan::getVulkanVertexFormat(attrib.getFormat()); attributeDescriptions.push_back(attributeDescription); } @@ -2353,28 +2384,39 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi configuration.dynamicState.cullmode = cullmode; } - std::vector bufferVector; - std::vector offsets; + VkBuffer vkbuffers[VertexAttributes::MAX + 2]; + VkDeviceSize vkoffsets[VertexAttributes::MAX + 2]; + int buffercount = 0; - for (uint32_t i = 0; i < VertexAttributes::MAX; i++) + uint32 allbits = buffers.useBits; + uint32 i = 0; + while (allbits) { - if (buffers.useBits & (1u << i)) + uint32 bit = 1u << i; + + if (buffers.useBits & bit) { - bufferVector.push_back((VkBuffer)buffers.info[i].buffer->getHandle()); - offsets.push_back((VkDeviceSize)buffers.info[i].offset); + vkbuffers[buffercount] = (VkBuffer)buffers.info[i].buffer->getHandle(); + vkoffsets[buffercount] = (VkDeviceSize)buffers.info[i].offset; + buffercount++; } + + i++; + allbits >>= 1; } if (!(attributes.enableBits & (1u << ATTRIB_TEXCOORD))) { - bufferVector.push_back((VkBuffer)defaultConstantTexCoord->getHandle()); - offsets.push_back((VkDeviceSize)0); + vkbuffers[buffercount] = (VkBuffer)defaultConstantTexCoord->getHandle(); + vkoffsets[buffercount] = (VkDeviceSize)0; + buffercount++; } if (!(attributes.enableBits & (1u << ATTRIB_COLOR))) { - bufferVector.push_back((VkBuffer)defaultConstantColor->getHandle()); - offsets.push_back((VkDeviceSize)0); + vkbuffers[buffercount] = (VkBuffer)defaultConstantColor->getHandle(); + vkoffsets[buffercount] = (VkDeviceSize)0; + buffercount++; } configuration.shader->setMainTex(texture); @@ -2382,7 +2424,9 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi ensureGraphicsPipelineConfiguration(configuration); configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS); - vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), 0, static_cast(bufferVector.size()), bufferVector.data(), offsets.data()); + + if (buffercount > 0) + vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), 0, static_cast(buffercount), vkbuffers, vkoffsets); } void Graphics::setDefaultRenderPass() @@ -2455,12 +2499,12 @@ void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, b FramebufferConfiguration configuration{}; - std::vector transitionImages; + std::vector> transitionImages; for (const auto &color : rts.colors) { configuration.colorViews.push_back(dynamic_cast(color.texture)->getRenderTargetView(color.mipmap, color.slice)); - transitionImages.push_back((VkImage) color.texture->getHandle()); + transitionImages.push_back({ (VkImage)color.texture->getHandle(), color.texture->getPixelFormat() }); } if (rts.depthStencil.texture != nullptr) configuration.staticData.depthView = dynamic_cast(rts.depthStencil.texture)->getRenderTargetView(rts.depthStencil.mipmap, rts.depthStencil.slice); @@ -2513,8 +2557,8 @@ void Graphics::startRenderPass() renderPassState.framebufferConfiguration.staticData.renderPass = renderPassState.beginInfo.renderPass; renderPassState.beginInfo.framebuffer = getFramebuffer(renderPassState.framebufferConfiguration); - for (const auto &image : renderPassState.transitionImages) - Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + for (const auto &[image, format] : renderPassState.transitionImages) + Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), image, format, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); vkCmdBeginRenderPass(commandBuffers.at(currentFrame), &renderPassState.beginInfo, VK_SUBPASS_CONTENTS_INLINE); } @@ -2525,8 +2569,8 @@ void Graphics::endRenderPass() vkCmdEndRenderPass(commandBuffers.at(currentFrame)); - for (const auto &image : renderPassState.transitionImages) - Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + for (const auto &[image, format] : renderPassState.transitionImages) + Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), image, format, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); for (auto &colorAttachment : renderPassState.renderPassConfiguration.colorAttachments) colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; @@ -2855,6 +2899,23 @@ int Graphics::getVsync() const return vsync; } +void Graphics::mapLocalUniformData(void *data, size_t size, VkDescriptorBufferInfo &bufferInfo) +{ + size_t alignedSize = alignUp(size, minUniformBufferOffsetAlignment); + + if (localUniformBuffer->getUsableSize() < alignedSize) + localUniformBuffer.set(new StreamBuffer(this, BUFFERUSAGE_UNIFORM, localUniformBuffer->getSize() * 2), Acquire::NORETAIN); + + auto mapInfo = localUniformBuffer->map(size); + memcpy(mapInfo.data, data, size); + + bufferInfo.buffer = (VkBuffer)localUniformBuffer->getHandle(); + bufferInfo.offset = localUniformBuffer->unmap(size); + bufferInfo.range = size; + + localUniformBuffer->markUsed(alignedSize); +} + void Graphics::createColorResources() { if (msaaSamples & VK_SAMPLE_COUNT_1_BIT) @@ -3073,11 +3134,6 @@ void Graphics::cleanup() void Graphics::cleanupSwapChain() { - for (const auto &readbackBuffer : screenshotReadbackBuffers) - { - vmaDestroyBuffer(vmaAllocator, readbackBuffer.buffer, readbackBuffer.allocation); - vmaDestroyImage(vmaAllocator, readbackBuffer.image, readbackBuffer.imageAllocation); - } if (colorImage) { vkDestroyImageView(device, colorImageView, nullptr); @@ -3104,7 +3160,6 @@ void Graphics::recreateSwapChain() createSwapChain(); createImageViews(); - createScreenshotCallbackBuffers(); createColorResources(); createDepthResources(); diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index fc51d69ce..ffaff9399 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -37,7 +37,7 @@ #include #include #include - +#include namespace love { @@ -236,7 +236,7 @@ struct RenderpassState RenderPassConfiguration renderPassConfiguration{}; FramebufferConfiguration framebufferConfiguration{}; VkPipeline pipeline = VK_NULL_HANDLE; - std::vector transitionImages; + std::vector> transitionImages; uint32_t numColorAttachments = 0; float width = 0.0f; float height = 0.0f; @@ -249,16 +249,6 @@ struct RenderpassState OptionalInt mainWindowClearStencilValue; }; -struct ScreenshotReadbackBuffer -{ - VkBuffer buffer; - VmaAllocation allocation; - VmaAllocationInfo allocationInfo; - - VkImage image; - VmaAllocation imageAllocation; -}; - enum SubmitMode { SUBMIT_PRESENT, @@ -274,14 +264,13 @@ public: ~Graphics(); // implementation for virtual functions - const char *getName() const override; love::graphics::Texture *newTexture(const love::graphics::Texture::Settings &settings, const love::graphics::Texture::Slices *data) override; + love::graphics::Texture *newTextureView(love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) override; love::graphics::Buffer *newBuffer(const love::graphics::Buffer::Settings &settings, const std::vector& format, const void *data, size_t size, size_t arraylength) override; graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) override; graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty) override; void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override; void clear(const std::vector &colors, OptionalInt stencil, OptionalDouble depth) override; - Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override; void discard(const std::vector& colorbuffers, bool depthstencil) override; void present(void *screenshotCallbackdata) override; void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; @@ -316,7 +305,6 @@ public: void queueCleanUp(std::function cleanUp); void addReadbackCallback(std::function callback); void submitGpuCommands(SubmitMode, void *screenshotCallbackData = nullptr); - const VkDeviceSize getMinUniformBufferOffsetAlignment() const; VkSampler getCachedSampler(const SamplerState &sampler); void setComputeShader(Shader *computeShader); graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData(); @@ -325,6 +313,9 @@ public: VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const; void setVsync(int vsync); int getVsync() const; + void mapLocalUniformData(void *data, size_t size, VkDescriptorBufferInfo &bufferInfo); + + uint32 getDeviceApiVersion() const { return deviceApiVersion; } protected: graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override; @@ -353,7 +344,6 @@ private: VkCompositeAlphaFlagBitsKHR chooseCompositeAlpha(const VkSurfaceCapabilitiesKHR &capabilities); void createSwapChain(); void createImageViews(); - void createScreenshotCallbackBuffers(); VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration); VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration); void createDefaultShaders(); @@ -406,7 +396,9 @@ private: Matrix4 displayRotation; std::vector swapChainImages; VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED; + PixelFormat swapChainPixelFormat = PIXELFORMAT_UNKNOWN; VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED; + PixelFormat depthStencilPixelFormat = PIXELFORMAT_UNKNOWN; VkExtent2D swapChainExtent = VkExtent2D(); std::vector swapChainImageViews; VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT; @@ -442,12 +434,12 @@ private: VmaAllocator vmaAllocator = VK_NULL_HANDLE; StrongRef defaultConstantColor; StrongRef defaultConstantTexCoord; + StrongRef localUniformBuffer; // functions that need to be called to cleanup objects that were needed for rendering a frame. // We need a vector for each frame in flight. std::vector>> cleanUpFunctions; std::vector>> readbackCallbacks; - std::vector screenshotReadbackBuffers; - std::set usedShadersInFrame; + std::set> usedShadersInFrame; RenderpassState renderPassState; }; diff --git a/src/modules/graphics/vulkan/GraphicsReadback.cpp b/src/modules/graphics/vulkan/GraphicsReadback.cpp index 257a3b219..8a9af2628 100644 --- a/src/modules/graphics/vulkan/GraphicsReadback.cpp +++ b/src/modules/graphics/vulkan/GraphicsReadback.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vulkan/GraphicsReadback.h b/src/modules/graphics/vulkan/GraphicsReadback.h index c502927ba..12069fd6b 100644 --- a/src/modules/graphics/vulkan/GraphicsReadback.h +++ b/src/modules/graphics/vulkan/GraphicsReadback.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 364ab6f0b..8f606e9fa 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -21,6 +21,7 @@ #include "graphics/vertex.h" #include "Shader.h" #include "Graphics.h" +#include "common/Range.h" #include "libraries/glslang/glslang/Public/ShaderLang.h" #include "libraries/glslang/glslang/Public/ResourceLimits.h" @@ -35,65 +36,65 @@ namespace graphics namespace vulkan { -static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16; static const uint32_t DESCRIPTOR_POOL_SIZE = 1000; class BindingMapper { public: - uint32_t operator()(spirv_cross::CompilerGLSL &comp, std::vector &spirv, const std::string &name, const spirv_cross::ID &id) + uint32_t operator()(spirv_cross::CompilerGLSL &comp, std::vector &spirv, const std::string &name, int count, const spirv_cross::ID &id) { auto it = bindingMappings.find(name); if (it == bindingMappings.end()) { auto binding = comp.get_decoration(id, spv::DecorationBinding); - if (isFreeBinding(binding)) + if (isFreeBinding(binding, count)) { - bindingMappings[name] = binding; + bindingMappings[name] = Range(binding, count); return binding; } else { - uint32_t freeBinding = getFreeBinding(); + uint32_t freeBinding = getFreeBinding(count); uint32_t binaryBindingOffset; if (!comp.get_binary_offset_for_decoration(id, spv::DecorationBinding, binaryBindingOffset)) - throw love::Exception("could not get binary offset for binding"); + throw love::Exception("could not get binary offset for uniform %s binding", name.c_str()); spirv[binaryBindingOffset] = freeBinding; - bindingMappings[name] = freeBinding; + bindingMappings[name] = Range(freeBinding, count); return freeBinding; } } else - return it->second; + return (uint32_t)it->second.getOffset(); }; private: - uint32_t getFreeBinding() + uint32_t getFreeBinding(int count) { for (uint32_t i = 0;; i++) { - if (isFreeBinding(i)) + if (isFreeBinding(i, count)) return i; } } - bool isFreeBinding(uint32_t binding) + bool isFreeBinding(uint32_t binding, int count) { + Range r(binding, count); for (const auto &entry : bindingMappings) { - if (entry.second == binding) + if (entry.second.intersects(r)) return false; } return true; } - std::map bindingMappings; + std::map bindingMappings; }; @@ -155,14 +156,11 @@ bool Shader::loadVolatile() builtinUniformInfo[i] = nullptr; compileShaders(); - calculateUniformBufferSizeAligned(); createDescriptorSetLayout(); createPipelineLayout(); createDescriptorPoolSizes(); - createStreamBuffers(); descriptorPools.resize(MAX_FRAMES_IN_FLIGHT); currentFrame = 0; - currentUsedUniformStreamBuffersCount = 0; newFrame(); return true; @@ -173,31 +171,6 @@ void Shader::unloadVolatile() if (shaderModules.empty()) return; - for (const auto &uniform : uniformInfos) - { - switch (uniform.second.baseType) - { - case UNIFORM_SAMPLER: - case UNIFORM_STORAGETEXTURE: - for (int i = 0; i < uniform.second.count; i++) - { - if (uniform.second.textures[i] != nullptr) - uniform.second.textures[i]->release(); - } - delete[] uniform.second.textures; - break; - case UNIFORM_TEXELBUFFER: - case UNIFORM_STORAGEBUFFER: - for (int i = 0; i < uniform.second.count; i++) - { - if (uniform.second.buffers[i] != nullptr) - uniform.second.buffers[i]->release(); - } - delete[] uniform.second.buffers; - break; - } - } - vgfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){ for (const auto &pools : descriptorPools) { @@ -212,12 +185,8 @@ void Shader::unloadVolatile() vkDestroyPipeline(device, computePipeline, nullptr); }); - for (const auto streamBuffer : streamBuffers) - streamBuffer->release(); - shaderModules.clear(); shaderStages.clear(); - streamBuffers.clear(); descriptorPools.clear(); } @@ -240,51 +209,20 @@ void Shader::newFrame() { currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - currentUsedUniformStreamBuffersCount = 0; currentDescriptorPool = 0; - if (streamBuffers.size() > 1) - { - size_t newSize = 0; - for (auto streamBuffer : streamBuffers) - { - newSize += streamBuffer->getSize(); - streamBuffer->release(); - } - streamBuffers.clear(); - streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, newSize)); - } - else - streamBuffers.at(0)->nextFrame(); - for (VkDescriptorPool pool : descriptorPools[currentFrame]) vkResetDescriptorPool(device, pool, 0); } void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint) { - VkDescriptorSet currentDescriptorSet = allocateDescriptorSet(); - - std::vector bufferInfos; - bufferInfos.reserve(numBuffers); - - std::vector imageInfos; - imageInfos.reserve(numTextures); - - std::vector bufferViews; - bufferViews.reserve(numBufferViews); - - std::vector descriptorWrites; + int imageIndex = 0; + int bufferIndex = 0; + int bufferViewIndex = 0; if (!localUniformData.empty()) { - auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; - if (usedStreamBufferMemory >= streamBuffers.back()->getSize()) - { - streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); - currentUsedUniformStreamBuffersCount = 0; - } - if (builtinUniformDataOffset.hasValue) { auto builtinData = vgfx->getCurrentBuiltinUniformData(); @@ -292,127 +230,93 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind memcpy(dst, &builtinData, sizeof(builtinData)); } - auto currentStreamBuffer = streamBuffers.back(); - - auto mapInfo = currentStreamBuffer->map(uniformBufferSizeAligned); - memcpy(mapInfo.data, localUniformData.data(), localUniformData.size()); - auto offset = currentStreamBuffer->unmap(uniformBufferSizeAligned); - currentStreamBuffer->markUsed(uniformBufferSizeAligned); - - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = (VkBuffer)currentStreamBuffer->getHandle(); - bufferInfo.offset = offset; - bufferInfo.range = localUniformData.size(); - - bufferInfos.push_back(bufferInfo); - - VkWriteDescriptorSet uniformWrite{}; - uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - uniformWrite.dstSet = currentDescriptorSet; - uniformWrite.dstBinding = localUniformLocation; - uniformWrite.dstArrayElement = 0; - uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniformWrite.descriptorCount = 1; - uniformWrite.pBufferInfo = &bufferInfos[bufferInfos.size() - 1]; - - descriptorWrites.push_back(uniformWrite); - - currentUsedUniformStreamBuffersCount++; + vgfx->mapLocalUniformData(localUniformData.data(), localUniformData.size(), descriptorBuffers[bufferIndex++]); } - for (const auto &u : uniformInfos) + // TODO: iteration order must match the order at the end of compileShaders right now. + // TODO: We can store data via setTextures and setBuffers instead of iterating over + // everything here. + for (const auto &u : reflection.sampledTextures) { - auto &info = u.second; - - if (usesLocalUniformData(&info)) + const auto &info = u.second; + if (!info.active) continue; - if (info.baseType == UNIFORM_SAMPLER || info.baseType == UNIFORM_STORAGETEXTURE) + for (int i = 0; i < info.count; i++) { - bool isSampler = info.baseType == UNIFORM_SAMPLER; + auto vkTexture = dynamic_cast(activeTextures[info.resourceIndex + i]); - for (int i = 0; i < info.count; i++) - { - auto vkTexture = dynamic_cast(info.textures[i]); + if (vkTexture == nullptr) + throw love::Exception("uniform variable %s is not set.", info.name.c_str()); - if (vkTexture == nullptr) - throw love::Exception("uniform variable %s is not set.", info.name.c_str()); + VkDescriptorImageInfo &imageInfo = descriptorImages[imageIndex++]; - VkDescriptorImageInfo imageInfo{}; - - imageInfo.imageLayout = vkTexture->getImageLayout(); - imageInfo.imageView = (VkImageView)vkTexture->getRenderTargetHandle(); - if (isSampler) - imageInfo.sampler = (VkSampler)vkTexture->getSamplerHandle(); - - imageInfos.push_back(imageInfo); - } - - VkWriteDescriptorSet write{}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.dstSet = currentDescriptorSet; - write.dstBinding = info.location; - write.dstArrayElement = 0; - if (isSampler) - write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - else - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - write.descriptorCount = static_cast(info.count); - write.pImageInfo = &imageInfos[imageInfos.size() - info.count]; - - descriptorWrites.push_back(write); - } - if (info.baseType == UNIFORM_STORAGEBUFFER) - { - VkWriteDescriptorSet write{}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.dstSet = currentDescriptorSet; - write.dstBinding = info.location; - write.dstArrayElement = 0; - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - write.descriptorCount = info.count; - - for (int i = 0; i < info.count; i++) - { - if (info.buffers[i] == nullptr) - throw love::Exception("uniform variable %s is not set.", info.name.c_str()); - - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = (VkBuffer)info.buffers[i]->getHandle();; - bufferInfo.offset = 0; - bufferInfo.range = info.buffers[i]->getSize(); - - bufferInfos.push_back(bufferInfo); - } - - write.pBufferInfo = &bufferInfos[bufferInfos.size() - info.count]; - - descriptorWrites.push_back(write); - } - if (info.baseType == UNIFORM_TEXELBUFFER) - { - VkWriteDescriptorSet write{}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.dstSet = currentDescriptorSet; - write.dstBinding = info.location; - write.dstArrayElement = 0; - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - write.descriptorCount = info.count; - - for (int i = 0; i < info.count; i++) - { - if (info.buffers[i] == nullptr) - throw love::Exception("uniform variable %s is not set.", info.name.c_str()); - - bufferViews.push_back((VkBufferView)info.buffers[i]->getTexelBufferHandle()); - } - - write.pTexelBufferView = &bufferViews[bufferViews.size() - info.count]; - - descriptorWrites.push_back(write); + imageInfo.imageLayout = vkTexture->getImageLayout(); + imageInfo.imageView = (VkImageView)vkTexture->getRenderTargetHandle(); + imageInfo.sampler = (VkSampler)vkTexture->getSamplerHandle(); } } + for (const auto &u : reflection.storageTextures) + { + const auto &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + { + auto vkTexture = dynamic_cast(activeTextures[info.resourceIndex + i]); + + if (vkTexture == nullptr) + throw love::Exception("uniform variable %s is not set.", info.name.c_str()); + + VkDescriptorImageInfo &imageInfo = descriptorImages[imageIndex++]; + + imageInfo.imageLayout = vkTexture->getImageLayout(); + imageInfo.imageView = (VkImageView)vkTexture->getRenderTargetHandle(); + } + } + + for (const auto &u : reflection.texelBuffers) + { + const auto &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + { + auto b = activeBuffers[info.resourceIndex + i]; + if (b == nullptr) + throw love::Exception("uniform variable %s is not set.", info.name.c_str()); + + descriptorBufferViews[bufferViewIndex++] = (VkBufferView)b->getTexelBufferHandle(); + } + } + + for (const auto &u : reflection.storageBuffers) + { + const auto &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + { + auto b = activeBuffers[info.resourceIndex + i]; + if (b == nullptr) + throw love::Exception("uniform variable %s is not set.", info.name.c_str()); + + VkDescriptorBufferInfo &bufferInfo = descriptorBuffers[bufferIndex++]; + bufferInfo.buffer = (VkBuffer)b->getHandle(); + bufferInfo.offset = 0; + bufferInfo.range = b->getSize(); + } + } + + VkDescriptorSet currentDescriptorSet = allocateDescriptorSet(); + + for (auto &write : descriptorWrites) + write.dstSet = currentDescriptorSet; + vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr); @@ -444,12 +348,6 @@ int Shader::getVertexAttributeIndex(const std::string &name) return it == attributes.end() ? -1 : it->second; } -const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const -{ - const auto it = uniformInfos.find(name); - return it != uniformInfos.end() ? &(it->second) : nullptr; -} - const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const { return builtinUniformInfo[builtin]; @@ -466,11 +364,15 @@ void Shader::updateUniform(const UniformInfo *info, int count) void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count) { + if (current == this) + Graphics::flushBatchedDrawsGlobal(); + for (int i = 0; i < count; i++) { - auto oldTexture = info->textures[i]; - info->textures[i] = textures[i]; - info->textures[i]->retain(); + int resourceindex = info->resourceIndex + i; + auto oldTexture = activeTextures[resourceindex]; + activeTextures[resourceindex] = textures[i]; + activeTextures[resourceindex]->retain(); if (oldTexture) oldTexture->release(); } @@ -478,24 +380,20 @@ void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count) { + if (current == this) + Graphics::flushBatchedDrawsGlobal(); + for (int i = 0; i < count; i++) { - auto oldBuffer = info->buffers[i]; - info->buffers[i] = buffers[i]; - info->buffers[i]->retain(); + int resourceindex = info->resourceIndex + i; + auto oldBuffer = activeBuffers[resourceindex]; + activeBuffers[resourceindex] = buffers[i]; + activeBuffers[resourceindex]->retain(); if (oldBuffer) oldBuffer->release(); } } -void Shader::calculateUniformBufferSizeAligned() -{ - auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment(); - size_t size = localUniformStagingData.size(); - auto factor = static_cast(std::ceil(static_cast(size) / static_cast(minAlignment))); - uniformBufferSizeAligned = factor * minAlignment; -} - void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename) { using namespace spirv_cross; @@ -524,38 +422,25 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: continue; } - UniformInfo u{}; - u.name = name; + name = canonicaliizeUniformName(name); + + auto uniformit = reflection.allUniforms.find(name); + if (uniformit == reflection.allUniforms.end()) + { + handleUnknownUniformName(name.c_str()); + continue; + } + + UniformInfo &u = *(uniformit->second); + + u.active = true; u.dataSize = memberSize; - u.count = memberType.array.empty() ? 1 : memberType.array[0]; - u.components = 1; u.data = localUniformStagingData.data() + offset; - if (memberType.columns == 1) + const auto &valuesit = reflection.localUniformInitializerValues.find(name); + if (valuesit != reflection.localUniformInitializerValues.end()) { - if (memberType.basetype == SPIRType::Int) - u.baseType = UNIFORM_INT; - else if (memberType.basetype == SPIRType::UInt) - u.baseType = UNIFORM_UINT; - else - u.baseType = UNIFORM_FLOAT; - u.components = memberType.vecsize; - } - else - { - u.baseType = UNIFORM_MATRIX; - u.matrix.rows = memberType.vecsize; - u.matrix.columns = memberType.columns; - } - - const auto &reflectionIt = validationReflection.localUniforms.find(u.name); - if (reflectionIt != validationReflection.localUniforms.end()) - { - const auto &localUniform = reflectionIt->second; - if (localUniform.dataType == DATA_BASETYPE_BOOL) - u.baseType = UNIFORM_BOOL; - - const auto &values = localUniform.initializerValues; + const auto &values = valuesit->second; if (!values.empty()) memcpy( u.data, @@ -563,14 +448,12 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: std::min(u.dataSize, values.size() * sizeof(LocalUniformValue))); } - uniformInfos[u.name] = u; - BuiltinUniform builtin = BUILTIN_MAX_ENUM; if (getConstant(u.name.c_str(), builtin)) { if (builtin == BUILTIN_UNIFORMS_PER_DRAW) builtinUniformDataOffset = offset; - builtinUniformInfo[builtin] = &uniformInfos[u.name]; + builtinUniformInfo[builtin] = &u; } } } @@ -621,7 +504,7 @@ void Shader::compileShaders() bool forceDefault = false; bool forwardCompat = true; - if (!tshader->parse(GetDefaultResources(), defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings)) + if (!tshader->parse(GetResources(), defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings)) { const char *stageName = "unknown"; ShaderStage::getConstant(stage, stageName); @@ -643,8 +526,6 @@ void Shader::compileShaders() if (!program->mapIO()) throw love::Exception("mapIO failed"); - uniformInfos.clear(); - BindingMapper bindingMapper; for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) @@ -679,7 +560,7 @@ void Shader::compileShaders() localUniformStagingData.resize(defaultUniformBlockSize); localUniformData.resize(defaultUniformBlockSize); - localUniformLocation = bindingMapper(comp, spirv, resource.name, resource.id); + localUniformLocation = bindingMapper(comp, spirv, resource.name, 1, resource.id); memset(localUniformStagingData.data(), 0, defaultUniformBlockSize); memset(localUniformData.data(), 0, defaultUniformBlockSize); @@ -695,119 +576,51 @@ void Shader::compileShaders() for (const auto &r : shaderResources.sampled_images) { - const SPIRType &basetype = comp.get_type(r.base_type_id); - const SPIRType &type = comp.get_type(r.type_id); - const SPIRType &imagetype = comp.get_type(basetype.image.type); - - graphics::Shader::UniformInfo info; - info.location = bindingMapper(comp, spirv, r.name, r.id); - info.baseType = UNIFORM_SAMPLER; - info.name = r.name; - info.count = type.array.empty() ? 1 : type.array[0]; - info.isDepthSampler = type.image.depth; - info.components = 1; - - switch (imagetype.basetype) + std::string name = canonicaliizeUniformName(r.name); + auto uniformit = reflection.allUniforms.find(name); + if (uniformit == reflection.allUniforms.end()) { - case SPIRType::Float: - info.dataBaseType = DATA_BASETYPE_FLOAT; - break; - case SPIRType::Int: - info.dataBaseType = DATA_BASETYPE_INT; - break; - case SPIRType::UInt: - info.dataBaseType = DATA_BASETYPE_UINT; - break; - default: - break; + handleUnknownUniformName(name.c_str()); + continue; } - switch (basetype.image.dim) - { - case spv::Dim2D: - info.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D; - info.textures = new love::graphics::Texture *[info.count]; - break; - case spv::Dim3D: - info.textureType = TEXTURE_VOLUME; - info.textures = new love::graphics::Texture *[info.count]; - break; - case spv::DimCube: - if (basetype.image.arrayed) { - throw love::Exception("cubemap arrays are not currently supported"); - } - info.textureType = TEXTURE_CUBE; - info.textures = new love::graphics::Texture *[info.count]; - break; - case spv::DimBuffer: - info.baseType = UNIFORM_TEXELBUFFER; - info.buffers = new love::graphics::Buffer *[info.count]; - break; - default: - throw love::Exception("unknown dim"); - } + UniformInfo &u = *(uniformit->second); + u.active = true; + u.location = bindingMapper(comp, spirv, name, u.count, r.id); - if (info.baseType == UNIFORM_TEXELBUFFER) - { - for (int i = 0; i < info.count; i++) - info.buffers[i] = nullptr; - } - else - { - for (int i = 0; i < info.count; i++) - { - info.textures[i] = nullptr; - } - } - - uniformInfos[r.name] = info; BuiltinUniform builtin; - if (getConstant(r.name.c_str(), builtin)) - builtinUniformInfo[builtin] = &uniformInfos[info.name]; + if (getConstant(name.c_str(), builtin)) + builtinUniformInfo[builtin] = &u; } for (const auto &r : shaderResources.storage_buffers) { - const auto &type = comp.get_type(r.type_id); - - UniformInfo u{}; - u.baseType = UNIFORM_STORAGEBUFFER; - u.components = 1; - u.name = r.name; - u.count = type.array.empty() ? 1 : type.array[0]; - - if (!fillUniformReflectionData(u)) + std::string name = canonicaliizeUniformName(r.name); + const auto &uniformit = reflection.storageBuffers.find(name); + if (uniformit == reflection.storageBuffers.end()) + { + handleUnknownUniformName(name.c_str()); continue; + } - u.location = bindingMapper(comp, spirv, r.name, r.id); - u.buffers = new love::graphics::Buffer *[u.count]; - - for (int i = 0; i < u.count; i++) - u.buffers[i] = nullptr; - - uniformInfos[u.name] = u; + UniformInfo &u = uniformit->second; + u.active = true; + u.location = bindingMapper(comp, spirv, name, u.count, r.id); } for (const auto &r : shaderResources.storage_images) { - const auto &type = comp.get_type(r.type_id); - - UniformInfo u{}; - u.baseType = UNIFORM_STORAGETEXTURE; - u.components = 1; - u.name = r.name; - u.count = type.array.empty() ? 1 : type.array[0]; - - if (!fillUniformReflectionData(u)) + std::string name = canonicaliizeUniformName(r.name); + const auto &uniformit = reflection.storageTextures.find(name); + if (uniformit == reflection.storageTextures.end()) + { + handleUnknownUniformName(name.c_str()); continue; + } - u.textures = new love::graphics::Texture *[u.count]; - u.location = bindingMapper(comp, spirv, r.name, r.id); - - for (int i = 0; i < u.count; i++) - u.textures[i] = nullptr; - - uniformInfos[u.name] = u; + UniformInfo &u = uniformit->second; + u.active = true; + u.location = bindingMapper(comp, spirv, name, u.count, r.id); } if (shaderStage == SHADERSTAGE_VERTEX) @@ -826,7 +639,7 @@ void Shader::compileShaders() uint32_t locationOffset; if (!comp.get_binary_offset_for_decoration(r.id, spv::DecorationLocation, locationOffset)) - throw love::Exception("could not get binary offset for location"); + throw love::Exception("could not get binary offset for vertex attribute %s location", r.name.c_str()); spirv[locationOffset] = (uint32_t)index; @@ -868,31 +681,151 @@ void Shader::compileShaders() shaderStages.push_back(shaderStageInfo); } - numBuffers = 0; - numTextures = 0; - numBufferViews = 0; + int numBuffers = 0; + int numTextures = 0; + int numBufferViews = 0; if (localUniformData.size() > 0) numBuffers++; - for (const auto &u : uniformInfos) + for (const auto kvp : reflection.allUniforms) { - switch (u.second.baseType) + if (!kvp.second->active) + continue; + + switch (kvp.second->baseType) { case UNIFORM_SAMPLER: case UNIFORM_STORAGETEXTURE: - numTextures++; + numTextures += kvp.second->count; break; case UNIFORM_STORAGEBUFFER: - numBuffers++; + numBuffers += kvp.second->count; break; case UNIFORM_TEXELBUFFER: - numBufferViews++; + numBufferViews += kvp.second->count; break; default: continue; } } + + descriptorWrites.clear(); + + descriptorBuffers.clear(); + descriptorBuffers.reserve(numBuffers); + + descriptorImages.clear(); + descriptorImages.reserve(numTextures); + + descriptorBufferViews.clear(); + descriptorBufferViews.reserve(numBufferViews); + + if (localUniformData.size() > 0) + { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.range = localUniformData.size(); + + descriptorBuffers.push_back(bufferInfo); + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstBinding = localUniformLocation; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write.descriptorCount = 1; + write.pBufferInfo = &descriptorBuffers.back(); + descriptorWrites.push_back(write); + } + + for (const auto &u : reflection.sampledTextures) + { + const UniformInfo &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + { + VkDescriptorImageInfo imageInfo{}; + descriptorImages.push_back(imageInfo); + } + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstBinding = info.location; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write.descriptorCount = static_cast(info.count); + write.pImageInfo = &descriptorImages[descriptorImages.size() - info.count]; + + descriptorWrites.push_back(write); + } + + for (const auto &u : reflection.storageTextures) + { + const UniformInfo &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + { + VkDescriptorImageInfo imageInfo{}; + descriptorImages.push_back(imageInfo); + } + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstBinding = info.location; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + write.descriptorCount = static_cast(info.count); + write.pImageInfo = &descriptorImages[descriptorImages.size() - info.count]; + + descriptorWrites.push_back(write); + } + + for (const auto &u : reflection.texelBuffers) + { + const UniformInfo &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + descriptorBufferViews.push_back(VK_NULL_HANDLE); + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstBinding = info.location; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + write.descriptorCount = info.count; + write.pTexelBufferView = &descriptorBufferViews[descriptorBufferViews.size() - info.count]; + + descriptorWrites.push_back(write); + } + + for (const auto &u : reflection.storageBuffers) + { + const UniformInfo &info = u.second; + if (!info.active) + continue; + + for (int i = 0; i < info.count; i++) + { + VkDescriptorBufferInfo bufferInfo{}; + descriptorBuffers.push_back(bufferInfo); + } + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstBinding = info.location; + write.dstArrayElement = 0; + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + write.descriptorCount = info.count; + write.pBufferInfo = &descriptorBuffers[descriptorBuffers.size() - info.count]; + + descriptorWrites.push_back(write); + } } void Shader::createDescriptorSetLayout() @@ -905,16 +838,19 @@ void Shader::createDescriptorSetLayout() else stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - for (auto const &entry : uniformInfos) + for (auto const &entry : reflection.allUniforms) { - auto type = Vulkan::getDescriptorType(entry.second.baseType); + if (!entry.second->active) + continue; + + auto type = Vulkan::getDescriptorType(entry.second->baseType); if (type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) { VkDescriptorSetLayoutBinding layoutBinding{}; - layoutBinding.binding = entry.second.location; + layoutBinding.binding = entry.second->location; layoutBinding.descriptorType = type; - layoutBinding.descriptorCount = entry.second.count; + layoutBinding.descriptorCount = entry.second->count; layoutBinding.stageFlags = stageFlags; bindings.push_back(layoutBinding); @@ -976,10 +912,13 @@ void Shader::createDescriptorPoolSizes() descriptorPoolSizes.push_back(size); } - for (const auto &entry : uniformInfos) + for (const auto &entry : reflection.allUniforms) { + if (entry.second->location < 0) + continue; + VkDescriptorPoolSize size{}; - auto type = Vulkan::getDescriptorType(entry.second.baseType); + auto type = Vulkan::getDescriptorType(entry.second->baseType); if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) continue; @@ -989,13 +928,6 @@ void Shader::createDescriptorPoolSizes() } } -void Shader::createStreamBuffers() -{ - size_t size = STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned; - if (size > 0) - streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, size)); -} - void Shader::setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture) { std::array textures = { @@ -1012,29 +944,26 @@ void Shader::setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cb for (size_t i = 0; i < textures.size(); i++) { - if (builtinUniformInfo[builtIns[i]] != nullptr) + const UniformInfo *u = builtinUniformInfo[builtIns[i]]; + if (u != nullptr) { textures[i]->retain(); - if (builtinUniformInfo[builtIns[i]]->textures[0]) - builtinUniformInfo[builtIns[i]]->textures[0]->release(); - builtinUniformInfo[builtIns[i]]->textures[0] = textures[i]; + if (activeTextures[u->resourceIndex]) + activeTextures[u->resourceIndex]->release(); + activeTextures[u->resourceIndex] = textures[i]; } } } -bool Shader::hasUniform(const std::string &name) const -{ - return uniformInfos.find(name) != uniformInfos.end(); -} - void Shader::setMainTex(graphics::Texture *texture) { - if (builtinUniformInfo[BUILTIN_TEXTURE_MAIN] != nullptr) + const UniformInfo *u = builtinUniformInfo[BUILTIN_TEXTURE_MAIN]; + if (u != nullptr) { texture->retain(); - if (builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0]) - builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0]->release(); - builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0] = texture; + if (activeTextures[u->resourceIndex]) + activeTextures[u->resourceIndex]->release(); + activeTextures[u->resourceIndex] = texture; } } diff --git a/src/modules/graphics/vulkan/Shader.h b/src/modules/graphics/vulkan/Shader.h index 40ef6f778..cbca89218 100644 --- a/src/modules/graphics/vulkan/Shader.h +++ b/src/modules/graphics/vulkan/Shader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -76,7 +76,6 @@ public: int getVertexAttributeIndex(const std::string &name) override; - const UniformInfo *getUniformInfo(const std::string &name) const override; const UniformInfo *getUniformInfo(BuiltinUniform builtin) const override; void updateUniform(const UniformInfo *info, int count) override; @@ -84,40 +83,32 @@ public: void sendTextures(const UniformInfo *info, graphics::Texture **textures, int count) override; void sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count) override; - bool hasUniform(const std::string &name) const override; - void setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture) override; void setMainTex(graphics::Texture *texture); private: - void calculateUniformBufferSizeAligned(); void compileShaders(); void createDescriptorSetLayout(); void createPipelineLayout(); void createDescriptorPoolSizes(); - void createStreamBuffers(); void buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename); void createDescriptorPool(); VkDescriptorSet allocateDescriptorSet(); - VkDeviceSize uniformBufferSizeAligned; - VkPipeline computePipeline; - uint32_t numTextures; - uint32_t numBuffers; - uint32_t numBufferViews; - VkDescriptorSetLayout descriptorSetLayout; VkPipelineLayout pipelineLayout; std::vector descriptorPoolSizes; - // we don't know how much memory we need per frame for the uniform buffer descriptors - // we keep a vector of stream buffers that gets dynamically increased if more memory is needed - std::vector streamBuffers; std::vector> descriptorPools; + std::vector descriptorBuffers; + std::vector descriptorImages; + std::vector descriptorBufferViews; + std::vector descriptorWrites; + std::vector shaderStages; std::vector shaderModules; @@ -126,7 +117,6 @@ private: bool isCompute = false; - std::unordered_map uniformInfos; UniformInfo *builtinUniformInfo[BUILTIN_MAX_ENUM]; std::unique_ptr uniformBufferObjectBuffer; @@ -138,7 +128,6 @@ private: std::unordered_map attributes; uint32_t currentFrame; - uint32_t currentUsedUniformStreamBuffersCount; uint32_t currentDescriptorPool; }; diff --git a/src/modules/graphics/vulkan/ShaderStage.cpp b/src/modules/graphics/vulkan/ShaderStage.cpp index 2e3b70c5d..e7657affd 100644 --- a/src/modules/graphics/vulkan/ShaderStage.cpp +++ b/src/modules/graphics/vulkan/ShaderStage.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vulkan/ShaderStage.h b/src/modules/graphics/vulkan/ShaderStage.h index f3c015f15..a084e2b81 100644 --- a/src/modules/graphics/vulkan/ShaderStage.h +++ b/src/modules/graphics/vulkan/ShaderStage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/vulkan/StreamBuffer.cpp b/src/modules/graphics/vulkan/StreamBuffer.cpp index eba9e9681..517a69eaa 100644 --- a/src/modules/graphics/vulkan/StreamBuffer.cpp +++ b/src/modules/graphics/vulkan/StreamBuffer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -96,6 +96,11 @@ ptrdiff_t StreamBuffer::getHandle() const return (ptrdiff_t) buffer; } +size_t StreamBuffer::getGPUReadOffset() const +{ + return (frameIndex * bufferSize) + frameGPUReadOffset; +} + love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t /*minsize*/) { // TODO: do we also need to wait until a fence is complete, here? diff --git a/src/modules/graphics/vulkan/StreamBuffer.h b/src/modules/graphics/vulkan/StreamBuffer.h index 98cc86b14..c32533d13 100644 --- a/src/modules/graphics/vulkan/StreamBuffer.h +++ b/src/modules/graphics/vulkan/StreamBuffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -47,6 +47,7 @@ public: virtual void unloadVolatile() override; + size_t getGPUReadOffset() const override; MapInfo map(size_t minsize) override; size_t unmap(size_t usedSize) override; void markUsed(size_t usedSize) override; diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 7a02b0224..7400a1464 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -47,11 +47,22 @@ Texture::Texture(love::graphics::Graphics *gfx, const Settings &settings, const slices.clear(); } +Texture::Texture(love::graphics::Graphics *gfx, love::graphics::Texture *base, const Texture::ViewSettings &viewsettings) + : love::graphics::Texture(gfx, base, viewsettings) + , vgfx(dynamic_cast(gfx)) + , slices(viewsettings.type.get(base->getTextureType())) + , imageAspect(0) +{ + loadVolatile(); +} + bool Texture::loadVolatile() { allocator = vgfx->getVmaAllocator(); device = vgfx->getDevice(); + bool root = rootView.texture == this; + if (isPixelFormatDepth(format)) imageAspect |= VK_IMAGE_ASPECT_DEPTH_BIT; if (isPixelFormatStencil(format)) @@ -79,82 +90,115 @@ bool Texture::loadVolatile() usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } - VkImageCreateFlags createFlags = 0; - layerCount = 1; if (texType == TEXTURE_2D_ARRAY) layerCount = getLayerCount(); else if (texType == TEXTURE_CUBE) - { layerCount = 6; - createFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - } - msaaSamples = vgfx->getMsaaCount(requestedMSAA); - - VkImageCreateInfo imageInfo{}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.flags = createFlags; - imageInfo.imageType = Vulkan::getImageType(getTextureType()); - imageInfo.extent.width = static_cast(pixelWidth); - imageInfo.extent.height = static_cast(pixelHeight); - imageInfo.extent.depth = static_cast(depth); - imageInfo.arrayLayers = static_cast(layerCount); - imageInfo.mipLevels = static_cast(mipmapCount); - imageInfo.format = vulkanFormat.internalFormat; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageInfo.usage = usageFlags; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.samples = msaaSamples; - - VmaAllocationCreateInfo imageAllocationCreateInfo{}; - - if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS) - throw love::Exception("failed to create image"); - - auto commandBuffer = vgfx->getCommandBufferForDataTransfer(); - - if (isPixelFormatDepthStencil(format)) - imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - else if (computeWrite) - imageLayout = VK_IMAGE_LAYOUT_GENERAL; - else - imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, - VK_IMAGE_LAYOUT_UNDEFINED, imageLayout, - 0, VK_REMAINING_MIP_LEVELS, - 0, VK_REMAINING_ARRAY_LAYERS); - - bool hasdata = slices.get(0, 0) != nullptr; - - if (hasdata) + if (root) { - for (int mip = 0; mip < getMipmapCount(); mip++) - { - int sliceCount; - if (texType == TEXTURE_CUBE) - sliceCount = 6; - else - sliceCount = slices.getSliceCount(); + VkImageCreateFlags createFlags = 0; + std::vector vkviewformats; - for (int slice = 0; slice < sliceCount; slice++) + for (PixelFormat viewformat : viewFormats) + { + if (viewformat != format) { - auto id = slices.get(slice, mip); - if (id != nullptr) - uploadImageData(id, mip, slice, 0, 0); + createFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + TextureFormat f = Vulkan::getTextureFormat(viewformat); + vkviewformats.push_back(f.internalFormat); } } + + if (texType == TEXTURE_CUBE || (texType == TEXTURE_2D_ARRAY && layerCount >= 6)) + createFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + + msaaSamples = vgfx->getMsaaCount(requestedMSAA); + + VkImageCreateInfo imageInfo{}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.flags = createFlags; + imageInfo.imageType = Vulkan::getImageType(getTextureType()); + imageInfo.extent.width = static_cast(pixelWidth); + imageInfo.extent.height = static_cast(pixelHeight); + imageInfo.extent.depth = static_cast(depth); + imageInfo.arrayLayers = static_cast(layerCount); + imageInfo.mipLevels = static_cast(mipmapCount); + imageInfo.format = vulkanFormat.internalFormat; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.usage = usageFlags; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageInfo.samples = msaaSamples; + + VkImageFormatListCreateInfo viewFormatsInfo{}; + viewFormatsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO; + + if (!vkviewformats.empty() && vgfx->getDeviceApiVersion() >= VK_API_VERSION_1_2) + { + viewFormatsInfo.viewFormatCount = (uint32)vkviewformats.size(); + viewFormatsInfo.pViewFormats = vkviewformats.data(); + + imageInfo.pNext = &viewFormatsInfo; + } + + VmaAllocationCreateInfo imageAllocationCreateInfo{}; + + if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS) + throw love::Exception("failed to create image"); + + auto commandBuffer = vgfx->getCommandBufferForDataTransfer(); + + if (isPixelFormatDepthStencil(format)) + imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + else if (computeWrite) + imageLayout = VK_IMAGE_LAYOUT_GENERAL; + else + imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, + VK_IMAGE_LAYOUT_UNDEFINED, imageLayout, + 0, VK_REMAINING_MIP_LEVELS, + 0, VK_REMAINING_ARRAY_LAYERS); + + bool hasdata = slices.get(0, 0) != nullptr; + + if (hasdata) + { + for (int mip = 0; mip < getMipmapCount(); mip++) + { + int sliceCount; + if (texType == TEXTURE_CUBE) + sliceCount = 6; + else + sliceCount = slices.getSliceCount(); + + for (int slice = 0; slice < sliceCount; slice++) + { + auto id = slices.get(slice, mip); + if (id != nullptr) + uploadImageData(id, mip, slice, 0, 0); + } + } + } + else + clear(); } else - clear(); + { + Texture *roottex = (Texture *) rootView.texture; + textureImage = roottex->textureImage; + textureImageAllocation = VK_NULL_HANDLE; + imageLayout = roottex->imageLayout; + msaaSamples = roottex->msaaSamples; + } createTextureImageView(); - textureSampler = vgfx->getCachedSampler(samplerState); + setSamplerState(samplerState); - if (!isPixelFormatDepthStencil(format) && slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE) + if (root && !isPixelFormatDepthStencil(format) && slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE) generateMipmaps(); if (renderTarget) @@ -172,9 +216,9 @@ bool Texture::loadVolatile() viewInfo.viewType = Vulkan::getImageViewType(getTextureType()); viewInfo.format = vulkanFormat.internalFormat; viewInfo.subresourceRange.aspectMask = imageAspect; - viewInfo.subresourceRange.baseMipLevel = mip; + viewInfo.subresourceRange.baseMipLevel = mip + rootView.startMipmap; viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = slice; + viewInfo.subresourceRange.baseArrayLayer = slice + rootView.startLayer; viewInfo.subresourceRange.layerCount = 1; viewInfo.components.r = vulkanFormat.swizzleR; viewInfo.components.g = vulkanFormat.swizzleG; @@ -189,15 +233,18 @@ bool Texture::loadVolatile() int64 memsize = 0; - for (int mip = 0; mip < getMipmapCount(); mip++) + if (root) { - int w = getPixelWidth(mip); - int h = getPixelHeight(mip); - int slices = getDepth(mip) * layerCount; - memsize += getPixelFormatSliceSize(format, w, h) * slices; - } + for (int mip = 0; mip < getMipmapCount(); mip++) + { + int w = getPixelWidth(mip); + int h = getPixelHeight(mip); + int slices = getDepth(mip) * layerCount; + memsize += getPixelFormatSliceSize(format, w, h) * slices; + } - memsize *= static_cast(msaaSamples); + memsize *= static_cast(msaaSamples); + } setGraphicsMemorySize(memsize); @@ -207,8 +254,16 @@ bool Texture::loadVolatile() { VkDebugUtilsObjectNameInfoEXT nameInfo{}; nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; - nameInfo.objectType = VK_OBJECT_TYPE_IMAGE; - nameInfo.objectHandle = (uint64_t)textureImage; + if (root) + { + nameInfo.objectType = VK_OBJECT_TYPE_IMAGE; + nameInfo.objectHandle = (uint64_t)textureImage; + } + else + { + nameInfo.objectType = VK_OBJECT_TYPE_IMAGE_VIEW; + nameInfo.objectHandle = (uint64_t)textureImageView; + } nameInfo.pObjectName = debugName.c_str(); vkSetDebugUtilsObjectNameEXT(device, &nameInfo); } @@ -230,13 +285,15 @@ void Texture::unloadVolatile() textureImageAllocation = textureImageAllocation, textureImageViews = std::move(renderTargetImageViews)] () { vkDestroyImageView(device, textureImageView, nullptr); - vmaDestroyImage(allocator, textureImage, textureImageAllocation); + if (textureImageAllocation) + vmaDestroyImage(allocator, textureImage, textureImageAllocation); for (const auto &views : textureImageViews) for (const auto &view : views) vkDestroyImageView(device, view, nullptr); }); textureImage = VK_NULL_HANDLE; + textureImageAllocation = VK_NULL_HANDLE; setGraphicsMemorySize(0); } @@ -278,8 +335,7 @@ ptrdiff_t Texture::getHandle() const void Texture::setSamplerState(const SamplerState &s) { - love::graphics::Texture::setSamplerState(s); - + samplerState = validateSamplerState(s); textureSampler = vgfx->getCachedSampler(samplerState); } @@ -291,16 +347,15 @@ VkImageLayout Texture::getImageLayout() const void Texture::createTextureImageView() { auto vulkanFormat = Vulkan::getTextureFormat(format); - VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = textureImage; viewInfo.viewType = Vulkan::getImageViewType(getTextureType()); viewInfo.format = vulkanFormat.internalFormat; viewInfo.subresourceRange.aspectMask = imageAspect; - viewInfo.subresourceRange.baseMipLevel = 0; + viewInfo.subresourceRange.baseMipLevel = rootView.startMipmap; viewInfo.subresourceRange.levelCount = getMipmapCount(); - viewInfo.subresourceRange.baseArrayLayer = 0; + viewInfo.subresourceRange.baseArrayLayer = rootView.startLayer; viewInfo.subresourceRange.layerCount = layerCount; viewInfo.components.r = vulkanFormat.swizzleR; viewInfo.components.g = vulkanFormat.swizzleG; @@ -324,7 +379,7 @@ void Texture::clear() if (imageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS); @@ -332,7 +387,7 @@ void Texture::clear() vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range); - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS); } @@ -344,7 +399,7 @@ void Texture::clear() } else { - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS); @@ -354,7 +409,7 @@ void Texture::clear() vkCmdClearDepthStencilImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencilColor, 1, &range); - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS); } @@ -394,7 +449,7 @@ void Texture::generateMipmapsInternal() auto commandBuffer = vgfx->getCommandBufferForDataTransfer(); if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, static_cast(getMipmapCount()), 0, static_cast(layerCount)); @@ -404,16 +459,16 @@ void Texture::generateMipmapsInternal() barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.baseArrayLayer = rootView.startLayer; barrier.subresourceRange.layerCount = static_cast(layerCount); - barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.baseMipLevel = rootView.startMipmap; barrier.subresourceRange.levelCount = 1u; uint32_t mipLevels = static_cast(getMipmapCount()); for (uint32_t i = 1; i < mipLevels; i++) { - barrier.subresourceRange.baseMipLevel = i - 1; + barrier.subresourceRange.baseMipLevel = rootView.startMipmap + i - 1; barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -429,15 +484,15 @@ void Texture::generateMipmapsInternal() blit.srcOffsets[0] = { 0, 0, 0 }; blit.srcOffsets[1] = { getPixelWidth(i - 1), getPixelHeight(i - 1), 1 }; blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.mipLevel = i - 1; - blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.mipLevel = rootView.startMipmap + i - 1; + blit.srcSubresource.baseArrayLayer = rootView.startLayer; blit.srcSubresource.layerCount = static_cast(layerCount); blit.dstOffsets[0] = { 0, 0, 0 }; blit.dstOffsets[1] = { getPixelWidth(i), getPixelHeight(i), 1 }; blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.mipLevel = i; - blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.mipLevel = rootView.startMipmap + i; + blit.dstSubresource.baseArrayLayer = rootView.startLayer; blit.dstSubresource.layerCount = static_cast(layerCount); vkCmdBlitImage(commandBuffer, @@ -458,7 +513,7 @@ void Texture::generateMipmapsInternal() 1, &barrier); } - barrier.subresourceRange.baseMipLevel = mipLevels - 1; + barrier.subresourceRange.baseMipLevel = rootView.startMipmap + mipLevels - 1; barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -472,7 +527,7 @@ void Texture::generateMipmapsInternal() 1, &barrier); } -void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) +void Texture::uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) { VkBuffer stagingBuffer; VmaAllocation vmaAllocation; @@ -496,11 +551,11 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s region.bufferRowLength = 0; region.bufferImageHeight = 0; - uint32_t baseLayer; - if (getTextureType() == TEXTURE_VOLUME) - baseLayer = 0; - else - baseLayer = slice; + uint32_t baseLayer = rootView.startLayer; + if (getTextureType() != TEXTURE_VOLUME) + baseLayer += slice; + + level += rootView.startMipmap; region.imageSubresource.aspectMask = imageAspect; region.imageSubresource.mipLevel = level; @@ -520,7 +575,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, level, 1, baseLayer, 1); @@ -533,7 +588,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s ®ion ); - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout, level, 1, baseLayer, 1); } @@ -558,8 +613,8 @@ void Texture::copyFromBuffer(graphics::Buffer *source, size_t sourceoffset, int VkImageSubresourceLayers layers{}; layers.aspectMask = imageAspect; - layers.mipLevel = mipmap; - layers.baseArrayLayer = slice; + layers.mipLevel = mipmap + rootView.startMipmap; + layers.baseArrayLayer = slice + rootView.startLayer; layers.layerCount = 1; VkBufferImageCopy region{}; @@ -572,11 +627,11 @@ void Texture::copyFromBuffer(graphics::Buffer *source, size_t sourceoffset, int if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } else vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); @@ -588,8 +643,8 @@ void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const VkImageSubresourceLayers layers{}; layers.aspectMask = imageAspect; - layers.mipLevel = mipmap; - layers.baseArrayLayer = slice; + layers.mipLevel = mipmap + rootView.startMipmap; + layers.baseArrayLayer = slice + rootView.startLayer; layers.layerCount = 1; VkBufferImageCopy region{}; @@ -603,11 +658,11 @@ void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, (VkBuffer) dest->getHandle(), 1, ®ion); - Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageLayout); + Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, format, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageLayout); } else vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, (VkBuffer)dest->getHandle(), 1, ®ion); diff --git a/src/modules/graphics/vulkan/Texture.h b/src/modules/graphics/vulkan/Texture.h index 571621a05..9ad198378 100644 --- a/src/modules/graphics/vulkan/Texture.h +++ b/src/modules/graphics/vulkan/Texture.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -40,11 +40,13 @@ class Texture final , public Volatile { public: - Texture(love::graphics::Graphics *gfx, const Settings &settings, const Slices *data); - ~Texture(); - virtual bool loadVolatile() override; - virtual void unloadVolatile() override; + Texture(love::graphics::Graphics *gfx, const Settings &settings, const Slices *data); + Texture(love::graphics::Graphics *gfx, love::graphics::Texture *base, const Texture::ViewSettings &viewsettings); + virtual ~Texture(); + + bool loadVolatile() override; + void unloadVolatile() override; void setSamplerState(const SamplerState &s) override; @@ -59,9 +61,9 @@ public: VkImageView getRenderTargetView(int mip, int layer); VkSampleCountFlagBits getMsaaSamples() const; - void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override; + void uploadByteData(const void *data, size_t size, int level, int slice, const Rect &r) override; - void generateMipmapsInternal() override; + void generateMipmapsInternal() override; int getMSAA() const override; ptrdiff_t getHandle() const override; diff --git a/src/modules/graphics/vulkan/Vulkan.cpp b/src/modules/graphics/vulkan/Vulkan.cpp index afd991fcd..f73f1f5cc 100644 --- a/src/modules/graphics/vulkan/Vulkan.cpp +++ b/src/modules/graphics/vulkan/Vulkan.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -291,6 +291,9 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format) textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_DEPTH24_UNORM: + textureFormat.internalFormat = VK_FORMAT_X8_D24_UNORM_PACK32; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; + break; case PIXELFORMAT_DEPTH24_UNORM_STENCIL8: textureFormat.internalFormat = VK_FORMAT_D24_UNORM_S8_UINT; textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; @@ -816,7 +819,7 @@ VkIndexType Vulkan::getVulkanIndexBufferType(IndexDataType type) } } -static void setImageLayoutTransitionOptions(bool previous, VkImageLayout layout, VkAccessFlags &accessMask, VkPipelineStageFlags &stageFlags, bool &depthStencil) +static void setImageLayoutTransitionOptions(bool previous, VkImageLayout layout, VkAccessFlags &accessMask, VkPipelineStageFlags &stageFlags) { switch (layout) { @@ -838,7 +841,6 @@ static void setImageLayoutTransitionOptions(bool previous, VkImageLayout layout, stageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - depthStencil = true; accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; stageFlags = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; @@ -863,7 +865,7 @@ static void setImageLayoutTransitionOptions(bool previous, VkImageLayout layout, } } -void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t baseLevel, uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount) +void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, PixelFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t baseLevel, uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount) { VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -877,17 +879,19 @@ void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage ima barrier.subresourceRange.baseArrayLayer = baseLayer; barrier.subresourceRange.layerCount = layerCount; - bool depthStencil = false; VkPipelineStageFlags sourceStage; VkPipelineStageFlags destinationStage; - setImageLayoutTransitionOptions(true, oldLayout, barrier.srcAccessMask, sourceStage, depthStencil); - setImageLayoutTransitionOptions(false, newLayout, barrier.dstAccessMask, destinationStage, depthStencil); + setImageLayoutTransitionOptions(true, oldLayout, barrier.srcAccessMask, sourceStage); + setImageLayoutTransitionOptions(false, newLayout, barrier.dstAccessMask, destinationStage); - if (depthStencil) - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - else - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + const PixelFormatInfo &info = getPixelFormatInfo(format); + if (info.color) + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT; + if (info.depth) + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (info.stencil) + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; vkCmdPipelineBarrier( commandBuffer, diff --git a/src/modules/graphics/vulkan/Vulkan.h b/src/modules/graphics/vulkan/Vulkan.h index 46d27519f..7e4db7c70 100644 --- a/src/modules/graphics/vulkan/Vulkan.h +++ b/src/modules/graphics/vulkan/Vulkan.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -81,7 +81,7 @@ public: static VkIndexType getVulkanIndexBufferType(IndexDataType type); static void cmdTransitionImageLayout( - VkCommandBuffer, VkImage, VkImageLayout oldLayout, VkImageLayout newLayout, + VkCommandBuffer, VkImage, PixelFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t baseLevel = 0, uint32_t levelCount = VK_REMAINING_MIP_LEVELS, uint32_t baseLayer = 0, uint32_t layerCount = VK_REMAINING_ARRAY_LAYERS); }; diff --git a/src/modules/graphics/vulkan/VulkanWrapper.h b/src/modules/graphics/vulkan/VulkanWrapper.h index c09617163..6ac7c6da5 100644 --- a/src/modules/graphics/vulkan/VulkanWrapper.h +++ b/src/modules/graphics/vulkan/VulkanWrapper.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Buffer.cpp b/src/modules/graphics/wrap_Buffer.cpp index 9917358f8..3f6d4960a 100644 --- a/src/modules/graphics/wrap_Buffer.cpp +++ b/src/modules/graphics/wrap_Buffer.cpp @@ -1,5 +1,5 @@ /** -* Copyright (c) 2006-2023 LOVE Development Team +* Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Buffer.h b/src/modules/graphics/wrap_Buffer.h index 35a5742a7..9676b99bb 100644 --- a/src/modules/graphics/wrap_Buffer.h +++ b/src/modules/graphics/wrap_Buffer.h @@ -1,5 +1,5 @@ /** -* Copyright (c) 2006-2023 LOVE Development Team +* Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Font.cpp b/src/modules/graphics/wrap_Font.cpp index 807feefbd..1982daa84 100644 --- a/src/modules/graphics/wrap_Font.cpp +++ b/src/modules/graphics/wrap_Font.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Font.h b/src/modules/graphics/wrap_Font.h index 69ff068d6..404b215af 100644 --- a/src/modules/graphics/wrap_Font.h +++ b/src/modules/graphics/wrap_Font.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 6ff392c71..b4f46fdb9 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -799,6 +799,13 @@ static void luax_checktexturesettings(lua_State *L, int idx, bool opt, bool chec if (s.type == TEXTURE_2D_ARRAY || s.type == TEXTURE_VOLUME) s.layers = luax_checkintflag(L, idx, Texture::getConstant(Texture::SETTING_LAYERS)); } + else + { + s.width = luax_intflag(L, idx, Texture::getConstant(Texture::SETTING_WIDTH), s.width); + s.height = luax_intflag(L, idx, Texture::getConstant(Texture::SETTING_HEIGHT), s.height); + if (s.type == TEXTURE_2D_ARRAY || s.type == TEXTURE_VOLUME) + s.layers = luax_intflag(L, idx, Texture::getConstant(Texture::SETTING_LAYERS), s.layers); + } lua_getfield(L, idx, Texture::getConstant(Texture::SETTING_MIPMAPS)); if (!lua_isnoneornil(L, -1)) @@ -824,6 +831,25 @@ static void luax_checktexturesettings(lua_State *L, int idx, bool opt, bool chec s.computeWrite = luax_boolflag(L, idx, Texture::getConstant(Texture::SETTING_COMPUTE_WRITE), s.computeWrite); + lua_getfield(L, idx, Texture::getConstant(Texture::SETTING_VIEW_FORMATS)); + if (!lua_isnoneornil(L, -1)) + { + if (lua_type(L, -1) != LUA_TTABLE) + luaL_argerror(L, idx, "expected field 'viewformats' to be a table type"); + + for (int i = 1; i <= luax_objlen(L, -1); i++) + { + lua_rawgeti(L, -1, i); + const char *str = luaL_checkstring(L, -1); + PixelFormat viewformat = PIXELFORMAT_UNKNOWN; + if (!getConstant(str, viewformat)) + luax_enumerror(L, "pixel format", str); + s.viewFormats.push_back(viewformat); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, idx, Texture::getConstant(Texture::SETTING_READABLE)); if (!lua_isnoneornil(L, -1)) s.readable.set(luax_checkboolean(L, -1)); @@ -1240,6 +1266,66 @@ int w_newVolumeImage(lua_State *L) return w_newVolumeTexture(L); } +int w_newTextureView(lua_State *L) +{ + Texture *base = luax_checktexture(L, 1); + luaL_checktype(L, 2, LUA_TTABLE); + + Texture::ViewSettings settings; + + lua_getfield(L, 2, "format"); + if (!lua_isnoneornil(L, -1)) + { + const char *str = luaL_checkstring(L, -1); + if (!getConstant(str, settings.format.value)) + luax_enumerror(L, "pixel format", str); + settings.format.hasValue = true; + } + lua_pop(L, 1); + + lua_getfield(L, 2, "type"); + if (!lua_isnoneornil(L, -1)) + { + const char *str = luaL_checkstring(L, -1); + if (!Texture::getConstant(str, settings.type.value)) + luax_enumerror(L, "texture type", Texture::getConstants(settings.type.value), str); + settings.type.hasValue = true; + } + lua_pop(L, 1); + + lua_getfield(L, 2, "mipmapstart"); + if (!lua_isnoneornil(L, -1)) + settings.mipmapStart.set(luaL_checkint(L, -1) - 1); + lua_pop(L, 1); + + lua_getfield(L, 2, "mipmapcount"); + if (!lua_isnoneornil(L, -1)) + settings.mipmapCount.set(luaL_checkint(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, 2, "layerstart"); + if (!lua_isnoneornil(L, -1)) + settings.layerStart.set(luaL_checkint(L, -1) - 1); + lua_pop(L, 1); + + lua_getfield(L, 2, "layers"); + if (!lua_isnoneornil(L, -1)) + settings.layerCount.set(luaL_checkint(L, -1)); + lua_pop(L, 1); + + lua_getfield(L, 2, "debugname"); + if (!lua_isnoneornil(L, -1)) + settings.debugName = luaL_checkstring(L, -1); + lua_pop(L, 1); + + Texture *t = nullptr; + luax_catchexcept(L, [&]() { t = instance()->newTextureView(base, settings); }); + + luax_pushtype(L, t); + t->release(); + return 1; +} + int w_newQuad(lua_State *L) { luax_checkgraphicscreated(L); @@ -3052,13 +3138,12 @@ int w_draw(lua_State *L) { Drawable *drawable = nullptr; Texture *texture = nullptr; - Quad *quad = nullptr; + Quad *quad = luax_totype(L, 2); int startidx = 2; - if (luax_istype(L, 2, Quad::type)) + if (quad != nullptr) { texture = luax_checktexture(L, 1); - quad = luax_totype(L, 2); startidx = 3; } else if (lua_isnil(L, 2) && !lua_isnoneornil(L, 3)) @@ -3088,14 +3173,14 @@ int w_draw(lua_State *L) int w_drawLayer(lua_State *L) { Texture *texture = luax_checktexture(L, 1); - Quad *quad = nullptr; int layer = (int) luaL_checkinteger(L, 2) - 1; - int startidx = 3; - if (luax_istype(L, startidx, Quad::type)) + int startidx = 3; + Quad *quad = luax_totype(L, startidx); + + if (quad != nullptr) { texture = luax_checktexture(L, 1); - quad = luax_totype(L, startidx); startidx++; } else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1)) @@ -3815,25 +3900,31 @@ int w_inverseTransformPoint(lua_State *L) return 2; } -int w_setOrthoProjection(lua_State *L) +int w_setCustomProjection(lua_State *L) { - float w = (float) luaL_checknumber(L, 1); - float h = (float) luaL_checknumber(L, 2); - float near = (float) luaL_optnumber(L, 3, -10.0); - float far = (float) luaL_optnumber(L, 4, 10.0); + math::Transform *transform = luax_totype(L, 1); + if (transform != nullptr) + { + instance()->setCustomProjection(transform->getMatrix()); + return 0; + } - luax_catchexcept(L, [&]() { instance()->setOrthoProjection(w, h, near, far); }); - return 0; -} + math::Transform::MatrixLayout layout = math::Transform::MATRIX_ROW_MAJOR; -int w_setPerspectiveProjection(lua_State *L) -{ - float verticalfov = (float) luaL_checknumber(L, 1); - float aspect = (float) luaL_checknumber(L, 2); - float near = (float) luaL_checknumber(L, 3); - float far = (float) luaL_checknumber(L, 4); + int idx = 1; + if (lua_type(L, idx) == LUA_TSTRING) + { + const char* layoutstr = lua_tostring(L, idx); + if (!math::Transform::getConstant(layoutstr, layout)) + return luax_enumerror(L, "matrix layout", math::Transform::getConstants(layout), layoutstr); - luax_catchexcept(L, [&]() { instance()->setPerspectiveProjection(verticalfov, aspect, near, far); }); + idx++; + } + + float elements[16]; + love::math::luax_checkmatrix(L, idx, layout, elements); + + instance()->setCustomProjection(Matrix4(elements)); return 0; } @@ -3857,6 +3948,7 @@ static const luaL_Reg functions[] = { "newCubeTexture", w_newCubeTexture }, { "newArrayTexture", w_newArrayTexture }, { "newVolumeTexture", w_newVolumeTexture }, + { "newTextureView", w_newTextureView }, { "newQuad", w_newQuad }, { "newFont", w_newFont }, { "newImageFont", w_newImageFont }, @@ -3988,8 +4080,7 @@ static const luaL_Reg functions[] = { "transformPoint", w_transformPoint }, { "inverseTransformPoint", w_inverseTransformPoint }, - { "setOrthoProjection", w_setOrthoProjection }, - { "setPerspectiveProjection", w_setPerspectiveProjection }, + { "setCustomProjection", w_setCustomProjection }, { "resetProjection", w_resetProjection }, // Deprecated diff --git a/src/modules/graphics/wrap_Graphics.h b/src/modules/graphics/wrap_Graphics.h index b1a1c2f00..9946f161f 100644 --- a/src/modules/graphics/wrap_Graphics.h +++ b/src/modules/graphics/wrap_Graphics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Graphics.lua b/src/modules/graphics/wrap_Graphics.lua index 3d6a3b259..3f1b3879c 100644 --- a/src/modules/graphics/wrap_Graphics.lua +++ b/src/modules/graphics/wrap_Graphics.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_GraphicsReadback.cpp b/src/modules/graphics/wrap_GraphicsReadback.cpp index 262e3faa1..18e1ecc1b 100644 --- a/src/modules/graphics/wrap_GraphicsReadback.cpp +++ b/src/modules/graphics/wrap_GraphicsReadback.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_GraphicsReadback.h b/src/modules/graphics/wrap_GraphicsReadback.h index 9b9197199..c4e2ba2e2 100644 --- a/src/modules/graphics/wrap_GraphicsReadback.h +++ b/src/modules/graphics/wrap_GraphicsReadback.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Mesh.cpp b/src/modules/graphics/wrap_Mesh.cpp index 7c4072ef5..38df1d58d 100644 --- a/src/modules/graphics/wrap_Mesh.cpp +++ b/src/modules/graphics/wrap_Mesh.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Mesh.h b/src/modules/graphics/wrap_Mesh.h index 3d00c58de..fdd65739b 100644 --- a/src/modules/graphics/wrap_Mesh.h +++ b/src/modules/graphics/wrap_Mesh.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_ParticleSystem.cpp b/src/modules/graphics/wrap_ParticleSystem.cpp index c6fc1b878..57b2d0634 100644 --- a/src/modules/graphics/wrap_ParticleSystem.cpp +++ b/src/modules/graphics/wrap_ParticleSystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_ParticleSystem.h b/src/modules/graphics/wrap_ParticleSystem.h index dff5c5024..c828e9e0d 100644 --- a/src/modules/graphics/wrap_ParticleSystem.h +++ b/src/modules/graphics/wrap_ParticleSystem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Quad.cpp b/src/modules/graphics/wrap_Quad.cpp index 6d65f247a..9328123b4 100644 --- a/src/modules/graphics/wrap_Quad.cpp +++ b/src/modules/graphics/wrap_Quad.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Quad.h b/src/modules/graphics/wrap_Quad.h index bf8e401e1..02cf333fa 100644 --- a/src/modules/graphics/wrap_Quad.h +++ b/src/modules/graphics/wrap_Quad.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Shader.cpp b/src/modules/graphics/wrap_Shader.cpp index 8024022ad..51de56b8c 100644 --- a/src/modules/graphics/wrap_Shader.cpp +++ b/src/modules/graphics/wrap_Shader.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -446,7 +446,7 @@ int w_Shader_send(lua_State *L) const char *name = luaL_checkstring(L, 2); const Shader::UniformInfo *info = shader->getUniformInfo(name); - if (info == nullptr) + if (info == nullptr || !info->active) return luaL_error(L, "Shader uniform '%s' does not exist.\nA common error is to define but not use the variable.", name); if (luax_istype(L, 3, Data::type) || (info->baseType == Shader::UNIFORM_MATRIX && luax_istype(L, 4, Data::type))) @@ -461,14 +461,11 @@ int w_Shader_sendColors(lua_State *L) const char *name = luaL_checkstring(L, 2); const Shader::UniformInfo *info = shader->getUniformInfo(name); - if (info == nullptr) - { - luax_pushboolean(L, false); - return 1; - } + if (info == nullptr || !info->active) + return luaL_error(L, "Shader uniform '%s' does not exist.\nA common error is to define but not use the variable.", name); if (info->baseType != Shader::UNIFORM_FLOAT || info->components < 3) - return luaL_error(L, "sendColor can only be used on vec3 or vec4 uniforms."); + return luaL_error(L, "Shader:sendColor can only be used with vec3 or vec4 uniforms."); if (luax_istype(L, 3, Data::type)) w_Shader_sendData(L, 3, shader, info, true); diff --git a/src/modules/graphics/wrap_Shader.h b/src/modules/graphics/wrap_Shader.h index d71ad141f..ca6d2f2e5 100644 --- a/src/modules/graphics/wrap_Shader.h +++ b/src/modules/graphics/wrap_Shader.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_SpriteBatch.cpp b/src/modules/graphics/wrap_SpriteBatch.cpp index 1ef99e259..47168093b 100644 --- a/src/modules/graphics/wrap_SpriteBatch.cpp +++ b/src/modules/graphics/wrap_SpriteBatch.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -35,13 +35,10 @@ SpriteBatch *luax_checkspritebatch(lua_State *L, int idx) static inline int w_SpriteBatch_add_or_set(lua_State *L, SpriteBatch *t, int startidx, int index) { - Quad *quad = nullptr; + Quad *quad = luax_totype(L, startidx); - if (luax_istype(L, startidx, Quad::type)) - { - quad = luax_totype(L, startidx); + if (quad != nullptr) startidx++; - } else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1)) return luax_typerror(L, startidx, "Quad"); @@ -61,15 +58,13 @@ static inline int w_SpriteBatch_add_or_set(lua_State *L, SpriteBatch *t, int sta static int w_SpriteBatch_addLayer_or_setLayer(lua_State *L, SpriteBatch *t, int startidx, int index) { - Quad *quad = nullptr; int layer = (int) luaL_checkinteger(L, startidx) - 1; startidx++; - if (luax_istype(L, startidx, Quad::type)) - { - quad = luax_totype(L, startidx); + Quad *quad = luax_totype(L, startidx); + + if (quad != nullptr) startidx++; - } else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1)) return luax_typerror(L, startidx, "Quad"); diff --git a/src/modules/graphics/wrap_SpriteBatch.h b/src/modules/graphics/wrap_SpriteBatch.h index d7f0c09a2..1e0894831 100644 --- a/src/modules/graphics/wrap_SpriteBatch.h +++ b/src/modules/graphics/wrap_SpriteBatch.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -32,22 +32,33 @@ namespace graphics template static void luax_checkstandardtransform(lua_State *L, int idx, const T &func) { - if (luax_istype(L, idx, math::Transform::type)) + math::Transform *tf = luax_totype(L, idx); + if (tf != nullptr) { - math::Transform *tf = luax_totype(L, idx); func(tf->getMatrix()); } else { + int nargs = lua_gettop(L); float x = (float) luaL_optnumber(L, idx + 0, 0.0); float y = (float) luaL_optnumber(L, idx + 1, 0.0); float a = (float) luaL_optnumber(L, idx + 2, 0.0); float sx = (float) luaL_optnumber(L, idx + 3, 1.0); float sy = (float) luaL_optnumber(L, idx + 4, sx); - float ox = (float) luaL_optnumber(L, idx + 5, 0.0); - float oy = (float) luaL_optnumber(L, idx + 6, 0.0); - float kx = (float) luaL_optnumber(L, idx + 7, 0.0); - float ky = (float) luaL_optnumber(L, idx + 8, 0.0); + float ox = 0.0f; + float oy = 0.0f; + if (nargs >= idx + 5) + { + ox = (float) luaL_optnumber(L, idx + 5, 0.0); + oy = (float) luaL_optnumber(L, idx + 6, 0.0); + } + float kx = 0.0f; + float ky = 0.0f; + if (nargs >= idx + 7) + { + kx = (float) luaL_optnumber(L, idx + 7, 0.0); + ky = (float) luaL_optnumber(L, idx + 8, 0.0); + } func(Matrix4(x, y, a, sx, sy, ox, oy, kx, ky)); } } diff --git a/src/modules/graphics/wrap_TextBatch.cpp b/src/modules/graphics/wrap_TextBatch.cpp index 6a21da769..ffe0867f1 100644 --- a/src/modules/graphics/wrap_TextBatch.cpp +++ b/src/modules/graphics/wrap_TextBatch.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_TextBatch.h b/src/modules/graphics/wrap_TextBatch.h index 933626d28..272f1364d 100644 --- a/src/modules/graphics/wrap_TextBatch.h +++ b/src/modules/graphics/wrap_TextBatch.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Texture.cpp b/src/modules/graphics/wrap_Texture.cpp index 8198d9a57..b667c48b3 100644 --- a/src/modules/graphics/wrap_Texture.cpp +++ b/src/modules/graphics/wrap_Texture.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -300,6 +300,24 @@ int w_Texture_isReadable(lua_State *L) return 1; } +int w_Texture_getViewFormats(lua_State *L) +{ + Texture *t = luax_checktexture(L, 1); + const std::vector &viewformats = t->getViewFormats(); + + lua_createtable(L, (int) viewformats.size(), 0); + for (int i = 0; i < (int) viewformats.size(); i++) + { + const char *str = nullptr; + if (!getConstant(viewformats[i], str)) + return luaL_error(L, "Unknown pixel format."); + lua_pushstring(L, str); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + int w_Texture_setDepthSampleMode(lua_State *L) { Texture *t = luax_checktexture(L, 1); @@ -511,6 +529,7 @@ const luaL_Reg w_Texture_functions[] = { "isCanvas", w_Texture_isCanvas }, { "isComputeWritable", w_Texture_isComputeWritable }, { "isReadable", w_Texture_isReadable }, + { "getViewFormats", w_Texture_getViewFormats }, { "getMipmapMode", w_Texture_getMipmapMode }, { "getDepthSampleMode", w_Texture_getDepthSampleMode }, { "setDepthSampleMode", w_Texture_setDepthSampleMode }, diff --git a/src/modules/graphics/wrap_Texture.h b/src/modules/graphics/wrap_Texture.h index 94c62dfb0..aae3f97dd 100644 --- a/src/modules/graphics/wrap_Texture.h +++ b/src/modules/graphics/wrap_Texture.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Video.cpp b/src/modules/graphics/wrap_Video.cpp index 4004c61d8..1463d0899 100644 --- a/src/modules/graphics/wrap_Video.cpp +++ b/src/modules/graphics/wrap_Video.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Video.h b/src/modules/graphics/wrap_Video.h index 39f6e5e45..700a4bba1 100644 --- a/src/modules/graphics/wrap_Video.h +++ b/src/modules/graphics/wrap_Video.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/graphics/wrap_Video.lua b/src/modules/graphics/wrap_Video.lua index ae8097b95..eaf7a0631 100644 --- a/src/modules/graphics/wrap_Video.lua +++ b/src/modules/graphics/wrap_Video.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/CompressedImageData.cpp b/src/modules/image/CompressedImageData.cpp index 724367a12..6ec15b927 100644 --- a/src/modules/image/CompressedImageData.cpp +++ b/src/modules/image/CompressedImageData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/CompressedImageData.h b/src/modules/image/CompressedImageData.h index 70e55cc19..743d3bd0d 100644 --- a/src/modules/image/CompressedImageData.h +++ b/src/modules/image/CompressedImageData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/CompressedSlice.cpp b/src/modules/image/CompressedSlice.cpp index f2116a1d9..34d79621c 100644 --- a/src/modules/image/CompressedSlice.cpp +++ b/src/modules/image/CompressedSlice.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/CompressedSlice.h b/src/modules/image/CompressedSlice.h index 09d009adc..cffdf57f1 100644 --- a/src/modules/image/CompressedSlice.h +++ b/src/modules/image/CompressedSlice.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/FormatHandler.cpp b/src/modules/image/FormatHandler.cpp index 692d38e70..f1a1edff3 100644 --- a/src/modules/image/FormatHandler.cpp +++ b/src/modules/image/FormatHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/FormatHandler.h b/src/modules/image/FormatHandler.h index 762905f82..aa5f8db4b 100644 --- a/src/modules/image/FormatHandler.h +++ b/src/modules/image/FormatHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/Image.cpp b/src/modules/image/Image.cpp index d5f58e997..8bf46a619 100644 --- a/src/modules/image/Image.cpp +++ b/src/modules/image/Image.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -40,6 +40,7 @@ namespace image love::Type Image::type("image", &Module::type); Image::Image() + : Module(M_IMAGE, "love.image.magpie") { using namespace magpie; @@ -65,11 +66,6 @@ Image::~Image() handler->release(); } -const char *Image::getName() const -{ - return "love.image.magpie"; -} - love::image::ImageData *Image::newImageData(Data *data) { return new ImageData(data); diff --git a/src/modules/image/Image.h b/src/modules/image/Image.h index 9ac76ee6c..cac95f5d1 100644 --- a/src/modules/image/Image.h +++ b/src/modules/image/Image.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -52,10 +52,6 @@ public: Image(); virtual ~Image(); - // Implements Module. - ModuleType getModuleType() const override { return M_IMAGE; } - const char *getName() const override; - /** * Creates new ImageData from FileData. * @param data The FileData containing the encoded image data. diff --git a/src/modules/image/ImageData.cpp b/src/modules/image/ImageData.cpp index 377569cc3..7c2c5205c 100644 --- a/src/modules/image/ImageData.cpp +++ b/src/modules/image/ImageData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -194,10 +194,7 @@ love::filesystem::FileData *ImageData::encode(FormatHandler::EncodedFormat encod } if (encoder != nullptr) - { - thread::Lock lock(mutex); encodedimage = encoder->encode(rawimage, encodedFormat); - } if (encoder == nullptr || encodedimage.data == nullptr) throw love::Exception("No suitable image encoder for the %s pixel format.", getPixelFormatName(format)); @@ -537,8 +534,6 @@ void ImageData::setPixel(int x, int y, const Colorf &c) if (pixelSetFunction == nullptr) throw love::Exception("ImageData:setPixel does not currently support the %s pixel format.", getPixelFormatName(format)); - Lock lock(mutex); - pixelSetFunction(c, p); } @@ -553,8 +548,6 @@ void ImageData::getPixel(int x, int y, Colorf &c) const if (pixelGetFunction == nullptr) throw love::Exception("ImageData:getPixel does not currently support the %s pixel format.", getPixelFormatName(format)); - Lock lock(mutex); - pixelGetFunction(p, c); } @@ -701,9 +694,6 @@ void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, in if (sy + sh > srcH) sh = srcH - sy; - Lock lock2(src->mutex); - Lock lock1(mutex); - uint8 *s = (uint8 *) src->getData(); uint8 *d = (uint8 *) getData(); @@ -774,11 +764,6 @@ void ImageData::paste(ImageData *src, int dx, int dy, int sx, int sy, int sw, in } } -love::thread::Mutex *ImageData::getMutex() const -{ - return mutex; -} - size_t ImageData::getPixelSize() const { return getPixelFormatBlockSize(format); diff --git a/src/modules/image/ImageData.h b/src/modules/image/ImageData.h index c0fad8dba..5eb800f4d 100644 --- a/src/modules/image/ImageData.h +++ b/src/modules/image/ImageData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -110,8 +110,6 @@ public: **/ love::filesystem::FileData *encode(FormatHandler::EncodedFormat format, const char *filename, bool writefile) const; - love::thread::Mutex *getMutex() const; - // Implements ImageDataBase. ImageData *clone() const override; void *getData() const override; @@ -142,8 +140,6 @@ private: // The actual data. unsigned char *data = nullptr; - love::thread::MutexRef mutex; - // The format handler that was used to decode the ImageData. We need to know // this so we can properly delete memory allocated by the decoder. StrongRef decodeHandler; diff --git a/src/modules/image/ImageDataBase.cpp b/src/modules/image/ImageDataBase.cpp index 56b698757..27ac610f1 100644 --- a/src/modules/image/ImageDataBase.cpp +++ b/src/modules/image/ImageDataBase.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/ImageDataBase.h b/src/modules/image/ImageDataBase.h index 237f9872f..d57010109 100644 --- a/src/modules/image/ImageDataBase.h +++ b/src/modules/image/ImageDataBase.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/ASTCHandler.cpp b/src/modules/image/magpie/ASTCHandler.cpp index 1f56d6d3f..e0917d336 100644 --- a/src/modules/image/magpie/ASTCHandler.cpp +++ b/src/modules/image/magpie/ASTCHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/ASTCHandler.h b/src/modules/image/magpie/ASTCHandler.h index ac2b1d6b9..946374558 100644 --- a/src/modules/image/magpie/ASTCHandler.h +++ b/src/modules/image/magpie/ASTCHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/EXRHandler.cpp b/src/modules/image/magpie/EXRHandler.cpp index f986e4e38..e35df2336 100644 --- a/src/modules/image/magpie/EXRHandler.cpp +++ b/src/modules/image/magpie/EXRHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/EXRHandler.h b/src/modules/image/magpie/EXRHandler.h index 7aabdc236..c6a2a7b53 100644 --- a/src/modules/image/magpie/EXRHandler.h +++ b/src/modules/image/magpie/EXRHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/KTXHandler.cpp b/src/modules/image/magpie/KTXHandler.cpp index 37313735c..39af852ca 100644 --- a/src/modules/image/magpie/KTXHandler.cpp +++ b/src/modules/image/magpie/KTXHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/KTXHandler.h b/src/modules/image/magpie/KTXHandler.h index 3533416da..7af5ed7ea 100644 --- a/src/modules/image/magpie/KTXHandler.h +++ b/src/modules/image/magpie/KTXHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/PKMHandler.cpp b/src/modules/image/magpie/PKMHandler.cpp index 746265aa3..8b316fbd5 100644 --- a/src/modules/image/magpie/PKMHandler.cpp +++ b/src/modules/image/magpie/PKMHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/PKMHandler.h b/src/modules/image/magpie/PKMHandler.h index b1f26644e..ad8e0e1f1 100644 --- a/src/modules/image/magpie/PKMHandler.h +++ b/src/modules/image/magpie/PKMHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/PNGHandler.cpp b/src/modules/image/magpie/PNGHandler.cpp index 69dd3fb50..7c8b0c978 100644 --- a/src/modules/image/magpie/PNGHandler.cpp +++ b/src/modules/image/magpie/PNGHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/PNGHandler.h b/src/modules/image/magpie/PNGHandler.h index 13a0c7f4e..49d5c4848 100644 --- a/src/modules/image/magpie/PNGHandler.h +++ b/src/modules/image/magpie/PNGHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/PVRHandler.cpp b/src/modules/image/magpie/PVRHandler.cpp index ef074f0f8..c66be4606 100644 --- a/src/modules/image/magpie/PVRHandler.cpp +++ b/src/modules/image/magpie/PVRHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/PVRHandler.h b/src/modules/image/magpie/PVRHandler.h index 67978772e..414cd9d95 100644 --- a/src/modules/image/magpie/PVRHandler.h +++ b/src/modules/image/magpie/PVRHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/STBHandler.cpp b/src/modules/image/magpie/STBHandler.cpp index 24119faf2..768ed6dc5 100644 --- a/src/modules/image/magpie/STBHandler.cpp +++ b/src/modules/image/magpie/STBHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/STBHandler.h b/src/modules/image/magpie/STBHandler.h index 476563315..fd636f588 100644 --- a/src/modules/image/magpie/STBHandler.h +++ b/src/modules/image/magpie/STBHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/ddsHandler.cpp b/src/modules/image/magpie/ddsHandler.cpp index cfe903b1d..416c96cd9 100644 --- a/src/modules/image/magpie/ddsHandler.cpp +++ b/src/modules/image/magpie/ddsHandler.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/magpie/ddsHandler.h b/src/modules/image/magpie/ddsHandler.h index 008297aaf..dd70d9690 100644 --- a/src/modules/image/magpie/ddsHandler.h +++ b/src/modules/image/magpie/ddsHandler.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/wrap_CompressedImageData.cpp b/src/modules/image/wrap_CompressedImageData.cpp index ee8655326..aa8fd0cce 100644 --- a/src/modules/image/wrap_CompressedImageData.cpp +++ b/src/modules/image/wrap_CompressedImageData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/wrap_CompressedImageData.h b/src/modules/image/wrap_CompressedImageData.h index 041511a71..473e99eb1 100644 --- a/src/modules/image/wrap_CompressedImageData.h +++ b/src/modules/image/wrap_CompressedImageData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/wrap_Image.cpp b/src/modules/image/wrap_Image.cpp index 2af0d7b20..7fbcba3fc 100644 --- a/src/modules/image/wrap_Image.cpp +++ b/src/modules/image/wrap_Image.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/wrap_Image.h b/src/modules/image/wrap_Image.h index 86daafd79..cd60f6741 100644 --- a/src/modules/image/wrap_Image.h +++ b/src/modules/image/wrap_Image.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/wrap_ImageData.cpp b/src/modules/image/wrap_ImageData.cpp index e717a0fb3..7b04e7c1d 100644 --- a/src/modules/image/wrap_ImageData.cpp +++ b/src/modules/image/wrap_ImageData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -158,18 +158,15 @@ int w_ImageData_setPixel(lua_State *L) return 0; } -// ImageData:mapPixel. Not thread-safe! See wrap_ImageData.lua for the thread- -// safe wrapper function. -int w_ImageData__mapPixelUnsafe(lua_State *L) +int w_ImageData_mapPixel(lua_State *L) { ImageData *t = luax_checkimagedata(L, 1); luaL_checktype(L, 2, LUA_TFUNCTION); - // No optints because we assume they're done in the wrapper function. - int sx = (int) lua_tonumber(L, 3); - int sy = (int) lua_tonumber(L, 4); - int w = (int) lua_tonumber(L, 5); - int h = (int) lua_tonumber(L, 6); + int sx = luaL_optint(L, 3, 0); + int sy = luaL_optint(L, 4, 0); + int w = luaL_optint(L, 5, t->getWidth()); + int h = luaL_optint(L, 6, t->getHeight()); if (!(t->inside(sx, sy) && t->inside(sx+w-1, sy+h-1))) return luaL_error(L, "Invalid rectangle dimensions."); @@ -264,32 +261,9 @@ int w_ImageData_encode(lua_State *L) return 1; } -int w_ImageData__performAtomic(lua_State *L) -{ - ImageData *t = luax_checkimagedata(L, 1); - int err = 0; - - { - love::thread::Lock lock(t->getMutex()); - // call the function, passing any user-specified arguments. - err = lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 0); - } - - // Unfortunately, this eats the stack trace, too bad. - if (err != 0) - return lua_error(L); - - // The function and everything after it in the stack are eaten by the pcall, - // leaving only the ImageData object. Everything else is a return value. - return lua_gettop(L) - 1; -} - // C functions in a struct, necessary for the FFI versions of ImageData methods. struct FFI_ImageData { - void (*lockMutex)(Proxy *p); - void (*unlockMutex)(Proxy *p); - float (*float16to32)(float16 f); float16 (*float32to16)(float f); @@ -302,20 +276,6 @@ struct FFI_ImageData static FFI_ImageData ffifuncs = { - [](Proxy *p) // lockMutex - { - // We don't do any type-checking for the Proxy here since these functions - // are always called from code which has already done type checking. - ImageData *i = (ImageData *) p->object; - i->getMutex()->lock(); - }, - - [](Proxy *p) // unlockMutex - { - ImageData *i = (ImageData *) p->object; - i->getMutex()->unlock(); - }, - float16to32, float32to16, float11to32, @@ -336,12 +296,8 @@ static const luaL_Reg w_ImageData_functions[] = { "getPixel", w_ImageData_getPixel }, { "setPixel", w_ImageData_setPixel }, { "paste", w_ImageData_paste }, + { "mapPixel", w_ImageData_mapPixel }, { "encode", w_ImageData_encode }, - - // Used in the Lua wrapper code. - { "_mapPixelUnsafe", w_ImageData__mapPixelUnsafe }, - { "_performAtomic", w_ImageData__performAtomic }, - { 0, 0 } }; diff --git a/src/modules/image/wrap_ImageData.h b/src/modules/image/wrap_ImageData.h index 6d797068b..bd5e1beba 100644 --- a/src/modules/image/wrap_ImageData.h +++ b/src/modules/image/wrap_ImageData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/image/wrap_ImageData.lua b/src/modules/image/wrap_ImageData.lua index 308272da6..c3bfed49e 100644 --- a/src/modules/image/wrap_ImageData.lua +++ b/src/modules/image/wrap_ImageData.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -38,29 +38,6 @@ local function clamp01(x) return min(max(x, 0), 1) end --- Implement thread-safe ImageData:mapPixel regardless of whether the FFI is --- used or not. -function ImageData:mapPixel(func, ix, iy, iw, ih) - local idw, idh = self:getDimensions() - - ix = ix or 0 - iy = iy or 0 - iw = iw or idw - ih = ih or idh - - if type(ix) ~= "number" then error("bad argument #2 to ImageData:mapPixel (expected number)", 2) end - if type(iy) ~= "number" then error("bad argument #3 to ImageData:mapPixel (expected number)", 2) end - if type(iw) ~= "number" then error("bad argument #4 to ImageData:mapPixel (expected number)", 2) end - if type(ih) ~= "number" then error("bad argument #5 to ImageData:mapPixel (expected number)", 2) end - - if type(func) ~= "function" then error("bad argument #1 to ImageData:mapPixel (expected function)", 2) end - if not (inside(ix, iy, idw, idh) and inside(ix+iw-1, iy+ih-1, idw, idh)) then error("Invalid rectangle dimensions", 2) end - - -- performAtomic and mapPixelUnsafe have Lua-C API and FFI versions. - self:_performAtomic(self._mapPixelUnsafe, self, func, ix, iy, iw, ih) -end - - -- Everything below this point is efficient FFI replacements for existing -- ImageData functionality. @@ -84,9 +61,6 @@ typedef uint16_t float10; typedef struct FFI_ImageData { - void (*lockMutex)(Proxy *p); - void (*unlockMutex)(Proxy *p); - float (*float16to32)(float16 f); float16 (*float32to16)(float f); @@ -381,20 +355,23 @@ local objectcache = setmetatable({}, { -- Overwrite existing functions with new FFI versions. -function ImageData:_performAtomic(...) - ffifuncs.lockMutex(self) - local success, err = pcall(...) - ffifuncs.unlockMutex(self) - - if not success then - error(err, 3) - end -end - -function ImageData:_mapPixelUnsafe(func, ix, iy, iw, ih) +function ImageData:mapPixel(func, ix, iy, iw, ih) local p = objectcache[self] local idw, idh = p.width, p.height + ix = ix or 0 + iy = iy or 0 + iw = iw or idw + ih = ih or idh + + if type(ix) ~= "number" then error("bad argument #2 to ImageData:mapPixel (expected number)", 2) end + if type(iy) ~= "number" then error("bad argument #3 to ImageData:mapPixel (expected number)", 2) end + if type(iw) ~= "number" then error("bad argument #4 to ImageData:mapPixel (expected number)", 2) end + if type(ih) ~= "number" then error("bad argument #5 to ImageData:mapPixel (expected number)", 2) end + + if type(func) ~= "function" then error("bad argument #1 to ImageData:mapPixel (expected function)", 2) end + if not (inside(ix, iy, idw, idh) and inside(ix+iw-1, iy+ih-1, idw, idh)) then error("Invalid rectangle dimensions", 2) end + if p.pointer == nil then error("ImageData:mapPixel does not currently support the "..p.format.." pixel format.", 2) end ix = floor(ix) @@ -427,12 +404,8 @@ function ImageData:getPixel(x, y) if p.pointer == nil then error("ImageData:getPixel does not currently support the "..p.format.." pixel format.", 2) end - ffifuncs.lockMutex(self) local pixel = p.pointer[y * p.width + x] - local r, g, b, a = p.tolua(pixel) - ffifuncs.unlockMutex(self) - - return r, g, b, a + return p.tolua(pixel) end function ImageData:setPixel(x, y, r, g, b, a) @@ -457,9 +430,7 @@ function ImageData:setPixel(x, y, r, g, b, a) if p.pointer == nil then error("ImageData:setPixel does not currently support the "..p.format.." pixel format.", 2) end - ffifuncs.lockMutex(self) p.fromlua(p.pointer[y * p.width + x], r, g, b, a) - ffifuncs.unlockMutex(self) end function ImageData:getWidth() diff --git a/src/modules/joystick/Joystick.cpp b/src/modules/joystick/Joystick.cpp index 34b2a29f3..5f955e18e 100644 --- a/src/modules/joystick/Joystick.cpp +++ b/src/modules/joystick/Joystick.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index db5de2d7e..50c922c76 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/JoystickModule.h b/src/modules/joystick/JoystickModule.h index ef0f5f6db..26b208bc6 100644 --- a/src/modules/joystick/JoystickModule.h +++ b/src/modules/joystick/JoystickModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -36,9 +36,6 @@ public: virtual ~JoystickModule() {} - // Implements Module. - ModuleType getModuleType() const override { return M_JOYSTICK; } - /** * Adds a connected Joystick device and opens it for use. * Returns NULL if the Joystick could not be added. @@ -101,6 +98,12 @@ public: **/ virtual std::string getGamepadMappingString(const std::string &guid) const = 0; +protected: + + JoystickModule(const char *name) + : Module(M_JOYSTICK, name) + {} + }; // JoystickModule } // joystick diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index 826930444..1ebe6f545 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/sdl/Joystick.h b/src/modules/joystick/sdl/Joystick.h index d01dc50f1..75763712f 100644 --- a/src/modules/joystick/sdl/Joystick.h +++ b/src/modules/joystick/sdl/Joystick.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/sdl/JoystickModule.cpp b/src/modules/joystick/sdl/JoystickModule.cpp index 9c319a822..9e4510ecd 100644 --- a/src/modules/joystick/sdl/JoystickModule.cpp +++ b/src/modules/joystick/sdl/JoystickModule.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -41,6 +41,7 @@ namespace sdl { JoystickModule::JoystickModule() + : love::joystick::JoystickModule("love.joystick.sdl") { #if SDL_VERSION_ATLEAST(3, 0, 0) if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) @@ -91,11 +92,6 @@ JoystickModule::~JoystickModule() #endif } -const char *JoystickModule::getName() const -{ - return "love.joystick.sdl"; -} - love::joystick::Joystick *JoystickModule::getJoystick(int joyindex) { if (joyindex < 0 || (size_t) joyindex >= activeSticks.size()) diff --git a/src/modules/joystick/sdl/JoystickModule.h b/src/modules/joystick/sdl/JoystickModule.h index d543d44fb..5afdc133a 100644 --- a/src/modules/joystick/sdl/JoystickModule.h +++ b/src/modules/joystick/sdl/JoystickModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -44,9 +44,6 @@ public: JoystickModule(); virtual ~JoystickModule(); - // Implements Module. - const char *getName() const override; - // Implements JoystickModule. love::joystick::Joystick *addJoystick(int64 deviceid) override; void removeJoystick(love::joystick::Joystick *joystick) override; diff --git a/src/modules/joystick/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp index 73386f1b1..4e08826a1 100644 --- a/src/modules/joystick/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/wrap_Joystick.h b/src/modules/joystick/wrap_Joystick.h index b80dcd71a..2f3bdc96a 100644 --- a/src/modules/joystick/wrap_Joystick.h +++ b/src/modules/joystick/wrap_Joystick.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/wrap_JoystickModule.cpp b/src/modules/joystick/wrap_JoystickModule.cpp index 5a98f6d0a..b0c6e8289 100644 --- a/src/modules/joystick/wrap_JoystickModule.cpp +++ b/src/modules/joystick/wrap_JoystickModule.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/joystick/wrap_JoystickModule.h b/src/modules/joystick/wrap_JoystickModule.h index c84d05915..1344fb0a5 100644 --- a/src/modules/joystick/wrap_JoystickModule.h +++ b/src/modules/joystick/wrap_JoystickModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/keyboard/Keyboard.cpp b/src/modules/keyboard/Keyboard.cpp index 666957a2b..e7c66a6e1 100644 --- a/src/modules/keyboard/Keyboard.cpp +++ b/src/modules/keyboard/Keyboard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -27,6 +27,11 @@ namespace love namespace keyboard { +Keyboard::Keyboard(const char *name) + : Module(M_KEYBOARD, name) +{ +} + bool Keyboard::getConstant(const char *in, Key &out) { return keys.find(in, out); diff --git a/src/modules/keyboard/Keyboard.h b/src/modules/keyboard/Keyboard.h index 65c6e465b..29d071911 100644 --- a/src/modules/keyboard/Keyboard.h +++ b/src/modules/keyboard/Keyboard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -533,9 +533,6 @@ public: virtual ~Keyboard() {} - // Implements Module. - virtual ModuleType getModuleType() const { return M_KEYBOARD; } - /** * Sets whether repeat keypress events should be sent if a key is held down. * Does not affect text input events. @@ -614,6 +611,10 @@ public: static bool getConstant(const char *in, ModifierKey &out); static bool getConstant(ModifierKey in, const char *&out); +protected: + + Keyboard(const char *name); + private: static StringMap::Entry keyEntries[]; diff --git a/src/modules/keyboard/sdl/Keyboard.cpp b/src/modules/keyboard/sdl/Keyboard.cpp index d7a7977c0..0f54a221e 100644 --- a/src/modules/keyboard/sdl/Keyboard.cpp +++ b/src/modules/keyboard/sdl/Keyboard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -36,15 +36,11 @@ namespace sdl { Keyboard::Keyboard() - : key_repeat(false) + : love::keyboard::Keyboard("love.keyboard.sdl") + , key_repeat(false) { } -const char *Keyboard::getName() const -{ - return "love.keyboard.sdl"; -} - void Keyboard::setKeyRepeat(bool enable) { key_repeat = enable; diff --git a/src/modules/keyboard/sdl/Keyboard.h b/src/modules/keyboard/sdl/Keyboard.h index a2dff098d..939e430a0 100644 --- a/src/modules/keyboard/sdl/Keyboard.h +++ b/src/modules/keyboard/sdl/Keyboard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -41,9 +41,6 @@ public: Keyboard(); - // Implements Module. - const char *getName() const; - void setKeyRepeat(bool enable); bool hasKeyRepeat() const; bool isDown(const std::vector &keylist) const; diff --git a/src/modules/keyboard/wrap_Keyboard.cpp b/src/modules/keyboard/wrap_Keyboard.cpp index f221709df..78cc7a1ff 100644 --- a/src/modules/keyboard/wrap_Keyboard.cpp +++ b/src/modules/keyboard/wrap_Keyboard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/keyboard/wrap_Keyboard.h b/src/modules/keyboard/wrap_Keyboard.h index 8983393ef..462d3fa74 100644 --- a/src/modules/keyboard/wrap_Keyboard.h +++ b/src/modules/keyboard/wrap_Keyboard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/love/arg.lua b/src/modules/love/arg.lua index 934a217c7..41d339de2 100644 --- a/src/modules/love/arg.lua +++ b/src/modules/love/arg.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/love/boot.lua b/src/modules/love/boot.lua index 03610f31a..5ff38a13c 100644 --- a/src/modules/love/boot.lua +++ b/src/modules/love/boot.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -136,11 +136,11 @@ function love.boot() if not can_has_game then -- when editing this message, change it at love.cpp too - print([[LÖVE is an *awesome* framework you can use to make 2D games in Lua + print([[LOVE is an *awesome* framework you can use to make 2D games in Lua https://love2d.org usage: - love --version prints LÖVE version and quits + love --version prints LOVE version and quits love --help prints this message and quits love path/to/gamedir runs the game from the given directory which contains a main.lua file love path/to/packagedgame.love runs the packaged game from the provided .love file diff --git a/src/modules/love/callbacks.lua b/src/modules/love/callbacks.lua index a7560e678..98d7afad5 100644 --- a/src/modules/love/callbacks.lua +++ b/src/modules/love/callbacks.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/love/jitsetup.lua b/src/modules/love/jitsetup.lua index 296ba6c22..0049cc8dc 100644 --- a/src/modules/love/jitsetup.lua +++ b/src/modules/love/jitsetup.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/love/love.cpp b/src/modules/love/love.cpp index defe5541c..81503e955 100644 --- a/src/modules/love/love.cpp +++ b/src/modules/love/love.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/love/love.h b/src/modules/love/love.h index be63092c0..1ee3f6b0f 100644 --- a/src/modules/love/love.h +++ b/src/modules/love/love.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/BezierCurve.cpp b/src/modules/math/BezierCurve.cpp index 56d2eb5e3..2fc46865f 100644 --- a/src/modules/math/BezierCurve.cpp +++ b/src/modules/math/BezierCurve.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/BezierCurve.h b/src/modules/math/BezierCurve.h index 0235f105a..4e0420cb7 100644 --- a/src/modules/math/BezierCurve.h +++ b/src/modules/math/BezierCurve.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/MathModule.cpp b/src/modules/math/MathModule.cpp index 02a41477f..122c35163 100644 --- a/src/modules/math/MathModule.cpp +++ b/src/modules/math/MathModule.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -200,11 +200,13 @@ float linearToGamma(float c) } Math::Math() - : rng() + : Module(M_MATH, "love.math") { RandomGenerator::Seed seed; seed.b64 = (uint64) time(nullptr); - rng.setSeed(seed); + + rng.set(new RandomGenerator(), Acquire::NORETAIN); + rng->setSeed(seed); } Math::~Math() diff --git a/src/modules/math/MathModule.h b/src/modules/math/MathModule.h index 67b11249d..645df8aae 100644 --- a/src/modules/math/MathModule.h +++ b/src/modules/math/MathModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -102,7 +102,7 @@ public: RandomGenerator *getRandomGenerator() { - return &rng; + return rng.get(); } /** @@ -118,20 +118,11 @@ public: Transform *newTransform(); Transform *newTransform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky); - // Implements Module. - virtual ModuleType getModuleType() const - { - return M_MATH; - } - - virtual const char *getName() const - { - return "love.math"; - } - private: - RandomGenerator rng; + // All love objects accessible in Lua should be heap-allocated, + // to guarantee a minimum pointer alignment. + StrongRef rng; }; // Math diff --git a/src/modules/math/RandomGenerator.cpp b/src/modules/math/RandomGenerator.cpp index 29359b58b..3c7439a64 100644 --- a/src/modules/math/RandomGenerator.cpp +++ b/src/modules/math/RandomGenerator.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/RandomGenerator.h b/src/modules/math/RandomGenerator.h index 58e1990fd..749dc097a 100644 --- a/src/modules/math/RandomGenerator.h +++ b/src/modules/math/RandomGenerator.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/Transform.cpp b/src/modules/math/Transform.cpp index a53d71d73..00bb74e20 100644 --- a/src/modules/math/Transform.cpp +++ b/src/modules/math/Transform.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/Transform.h b/src/modules/math/Transform.h index 40068b77a..e340b0bb2 100644 --- a/src/modules/math/Transform.h +++ b/src/modules/math/Transform.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp index 53167c1a1..c1be7a4b6 100644 --- a/src/modules/math/wrap_BezierCurve.cpp +++ b/src/modules/math/wrap_BezierCurve.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_BezierCurve.h b/src/modules/math/wrap_BezierCurve.h index d748b8253..9ed9ac59f 100644 --- a/src/modules/math/wrap_BezierCurve.h +++ b/src/modules/math/wrap_BezierCurve.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_Math.cpp b/src/modules/math/wrap_Math.cpp index 26701d749..1e91e3675 100644 --- a/src/modules/math/wrap_Math.cpp +++ b/src/modules/math/wrap_Math.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_Math.h b/src/modules/math/wrap_Math.h index 8d5bbe2b4..ca40caba1 100644 --- a/src/modules/math/wrap_Math.h +++ b/src/modules/math/wrap_Math.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_Math.lua b/src/modules/math/wrap_Math.lua index f6e145ed2..c89012c7d 100644 --- a/src/modules/math/wrap_Math.lua +++ b/src/modules/math/wrap_Math.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_RandomGenerator.cpp b/src/modules/math/wrap_RandomGenerator.cpp index ebe7fdffc..007cad60c 100644 --- a/src/modules/math/wrap_RandomGenerator.cpp +++ b/src/modules/math/wrap_RandomGenerator.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_RandomGenerator.h b/src/modules/math/wrap_RandomGenerator.h index a1459da9c..9bbe807e6 100644 --- a/src/modules/math/wrap_RandomGenerator.h +++ b/src/modules/math/wrap_RandomGenerator.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_RandomGenerator.lua b/src/modules/math/wrap_RandomGenerator.lua index 4e96f5f61..e394833ec 100644 --- a/src/modules/math/wrap_RandomGenerator.lua +++ b/src/modules/math/wrap_RandomGenerator.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/math/wrap_Transform.cpp b/src/modules/math/wrap_Transform.cpp index 3ac5b2f78..24e2aa45a 100644 --- a/src/modules/math/wrap_Transform.cpp +++ b/src/modules/math/wrap_Transform.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -30,6 +30,99 @@ Transform *luax_checktransform(lua_State *L, int idx) return luax_checktype(L, idx, Transform::type); } +void luax_checkmatrix(lua_State *L, int idx, Transform::MatrixLayout layout, float elements[16]) +{ + bool columnmajor = layout == Transform::MATRIX_COLUMN_MAJOR; + + if (lua_istable(L, idx)) + { + lua_rawgeti(L, idx, 1); + bool tableoftables = lua_istable(L, -1); + lua_pop(L, 1); + + if (tableoftables) + { + if (columnmajor) + { + for (int column = 0; column < 4; column++) + { + lua_rawgeti(L, idx, column + 1); + + for (int row = 0; row < 4; row++) + { + lua_rawgeti(L, -(row + 1), row + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + + lua_pop(L, 4 + 1); + } + } + else + { + for (int row = 0; row < 4; row++) + { + lua_rawgeti(L, idx, row + 1); + + for (int column = 0; column < 4; column++) + { + // The table has the matrix elements laid out in row-major + // order, but we need to store them column-major in memory. + lua_rawgeti(L, -(column + 1), column + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + + lua_pop(L, 4 + 1); + } + } + } + else + { + if (columnmajor) + { + for (int column = 0; column < 4; column++) + { + for (int row = 0; row < 4; row++) + { + lua_rawgeti(L, idx, column * 4 + row + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + } + } + else + { + for (int column = 0; column < 4; column++) + { + for (int row = 0; row < 4; row++) + { + // The table has the matrix elements laid out in row-major + // order, but we need to store them column-major in memory. + lua_rawgeti(L, idx, row * 4 + column + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + } + } + + lua_pop(L, 16); + } + } + else + { + if (columnmajor) + { + for (int i = 0; i < 16; i++) + elements[i] = (float) luaL_checknumber(L, idx + i); + } + else + { + for (int column = 0; column < 4; column++) + { + for (int row = 0; row < 4; row++) + elements[column * 4 + row] = (float) luaL_checknumber(L, row * 4 + column + idx); + } + } + } +} + int w_Transform_clone(lua_State *L) { Transform *t = luax_checktransform(L, 1); @@ -131,110 +224,20 @@ int w_Transform_setTransformation(lua_State *L) int w_Transform_setMatrix(lua_State *L) { Transform *t = luax_checktransform(L, 1); - - bool columnmajor = false; + Transform::MatrixLayout layout = Transform::MATRIX_ROW_MAJOR; int idx = 2; if (lua_type(L, idx) == LUA_TSTRING) { const char *layoutstr = lua_tostring(L, idx); - Transform::MatrixLayout layout; if (!Transform::getConstant(layoutstr, layout)) return luax_enumerror(L, "matrix layout", Transform::getConstants(layout), layoutstr); - columnmajor = (layout == Transform::MATRIX_COLUMN_MAJOR); idx++; } float elements[16]; - - if (lua_istable(L, idx)) - { - lua_rawgeti(L, idx, 1); - bool tableoftables = lua_istable(L, -1); - lua_pop(L, 1); - - if (tableoftables) - { - if (columnmajor) - { - for (int column = 0; column < 4; column++) - { - lua_rawgeti(L, idx, column + 1); - - for (int row = 0; row < 4; row++) - { - lua_rawgeti(L, -(row + 1), row + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - - lua_pop(L, 4 + 1); - } - } - else - { - for (int row = 0; row < 4; row++) - { - lua_rawgeti(L, idx, row + 1); - - for (int column = 0; column < 4; column++) - { - // The table has the matrix elements laid out in row-major - // order, but we need to store them column-major in memory. - lua_rawgeti(L, -(column + 1), column + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - - lua_pop(L, 4 + 1); - } - } - } - else - { - if (columnmajor) - { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - { - lua_rawgeti(L, idx, column * 4 + row + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - } - } - else - { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - { - // The table has the matrix elements laid out in row-major - // order, but we need to store them column-major in memory. - lua_rawgeti(L, idx, row * 4 + column + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - } - } - - lua_pop(L, 16); - } - } - else - { - if (columnmajor) - { - for (int i = 0; i < 16; i++) - elements[i] = (float) luaL_checknumber(L, idx + i); - } - else - { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - elements[column * 4 + row] = (float) luaL_checknumber(L, row * 4 + column + idx); - } - } - } + luax_checkmatrix(L, idx, layout, elements); t->setMatrix(Matrix4(elements)); lua_pushvalue(L, 1); diff --git a/src/modules/math/wrap_Transform.h b/src/modules/math/wrap_Transform.h index 830794807..53feb3b7a 100644 --- a/src/modules/math/wrap_Transform.h +++ b/src/modules/math/wrap_Transform.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -30,6 +30,7 @@ namespace math { Transform *luax_checktransform(lua_State *L, int idx); +void luax_checkmatrix(lua_State *L, int idx, Transform::MatrixLayout layout, float elements[16]); extern "C" int luaopen_transform(lua_State *L); } // math diff --git a/src/modules/mouse/Cursor.cpp b/src/modules/mouse/Cursor.cpp index 6f537de91..dada2b616 100644 --- a/src/modules/mouse/Cursor.cpp +++ b/src/modules/mouse/Cursor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/Cursor.h b/src/modules/mouse/Cursor.h index 69e220f9a..352c6b392 100644 --- a/src/modules/mouse/Cursor.h +++ b/src/modules/mouse/Cursor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/Mouse.h b/src/modules/mouse/Mouse.h index 9b37b7f2f..4ad70dc56 100644 --- a/src/modules/mouse/Mouse.h +++ b/src/modules/mouse/Mouse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -64,6 +64,12 @@ public: virtual bool setRelativeMode(bool relative) = 0; virtual bool getRelativeMode() const = 0; +protected: + + Mouse(const char *name) + : Module(M_MOUSE, name) + {} + }; // Mouse } // mouse diff --git a/src/modules/mouse/sdl/Cursor.cpp b/src/modules/mouse/sdl/Cursor.cpp index a3c388099..bc059bea6 100644 --- a/src/modules/mouse/sdl/Cursor.cpp +++ b/src/modules/mouse/sdl/Cursor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/sdl/Cursor.h b/src/modules/mouse/sdl/Cursor.h index 9f6b37a0f..b72d46131 100644 --- a/src/modules/mouse/sdl/Cursor.h +++ b/src/modules/mouse/sdl/Cursor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/sdl/Mouse.cpp b/src/modules/mouse/sdl/Mouse.cpp index 6bcae186e..934b2b911 100644 --- a/src/modules/mouse/sdl/Mouse.cpp +++ b/src/modules/mouse/sdl/Mouse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -57,13 +57,9 @@ static void clampToWindow(double *x, double *y) window->clampPositionInWindow(x, y); } -const char *Mouse::getName() const -{ - return "love.mouse.sdl"; -} - Mouse::Mouse() - : curCursor(nullptr) + : love::mouse::Mouse("love.mouse.sdl") + , curCursor(nullptr) { // SDL may need the video subsystem in order to clean up the cursor when // quitting. Subsystems are reference-counted. diff --git a/src/modules/mouse/sdl/Mouse.h b/src/modules/mouse/sdl/Mouse.h index b859c4c52..a74dd334d 100644 --- a/src/modules/mouse/sdl/Mouse.h +++ b/src/modules/mouse/sdl/Mouse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -39,9 +39,6 @@ class Mouse : public love::mouse::Mouse { public: - // Implements Module. - const char *getName() const override; - Mouse(); virtual ~Mouse(); diff --git a/src/modules/mouse/wrap_Cursor.cpp b/src/modules/mouse/wrap_Cursor.cpp index fc3bed46e..dc4a871cf 100644 --- a/src/modules/mouse/wrap_Cursor.cpp +++ b/src/modules/mouse/wrap_Cursor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/wrap_Cursor.h b/src/modules/mouse/wrap_Cursor.h index 963bb8802..14304c489 100644 --- a/src/modules/mouse/wrap_Cursor.h +++ b/src/modules/mouse/wrap_Cursor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/wrap_Mouse.cpp b/src/modules/mouse/wrap_Mouse.cpp index 2dd8233a7..f54a69803 100644 --- a/src/modules/mouse/wrap_Mouse.cpp +++ b/src/modules/mouse/wrap_Mouse.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/mouse/wrap_Mouse.h b/src/modules/mouse/wrap_Mouse.h index 9cc285ee5..f39564eb6 100644 --- a/src/modules/mouse/wrap_Mouse.h +++ b/src/modules/mouse/wrap_Mouse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/Body.cpp b/src/modules/physics/Body.cpp index fc93a401e..ec7214594 100644 --- a/src/modules/physics/Body.cpp +++ b/src/modules/physics/Body.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/Body.h b/src/modules/physics/Body.h index 97b578e63..eca01fd3f 100644 --- a/src/modules/physics/Body.h +++ b/src/modules/physics/Body.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/Joint.cpp b/src/modules/physics/Joint.cpp index 8b12e78a5..83cb91789 100644 --- a/src/modules/physics/Joint.cpp +++ b/src/modules/physics/Joint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/Joint.h b/src/modules/physics/Joint.h index 89b3fb2d4..d30c4aec7 100644 --- a/src/modules/physics/Joint.h +++ b/src/modules/physics/Joint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/Shape.cpp b/src/modules/physics/Shape.cpp index fe184b829..712b10830 100644 --- a/src/modules/physics/Shape.cpp +++ b/src/modules/physics/Shape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/Shape.h b/src/modules/physics/Shape.h index ca5a5f7a9..49ae39229 100644 --- a/src/modules/physics/Shape.h +++ b/src/modules/physics/Shape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index a939de73b..d4a569d08 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index 1c5ae8a37..f69511d48 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/ChainShape.cpp b/src/modules/physics/box2d/ChainShape.cpp index 7a2390ab0..76ed1952f 100644 --- a/src/modules/physics/box2d/ChainShape.cpp +++ b/src/modules/physics/box2d/ChainShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/ChainShape.h b/src/modules/physics/box2d/ChainShape.h index 2b2ee14e1..e73fa0f4a 100644 --- a/src/modules/physics/box2d/ChainShape.h +++ b/src/modules/physics/box2d/ChainShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/CircleShape.cpp b/src/modules/physics/box2d/CircleShape.cpp index 628b96bb0..29fc6ba88 100644 --- a/src/modules/physics/box2d/CircleShape.cpp +++ b/src/modules/physics/box2d/CircleShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/CircleShape.h b/src/modules/physics/box2d/CircleShape.h index 20e5e3bac..1f314f43c 100644 --- a/src/modules/physics/box2d/CircleShape.h +++ b/src/modules/physics/box2d/CircleShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Contact.cpp b/src/modules/physics/box2d/Contact.cpp index 63b51ef04..a25e7f921 100644 --- a/src/modules/physics/box2d/Contact.cpp +++ b/src/modules/physics/box2d/Contact.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Contact.h b/src/modules/physics/box2d/Contact.h index 1287ca285..9407f32ab 100644 --- a/src/modules/physics/box2d/Contact.h +++ b/src/modules/physics/box2d/Contact.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/DistanceJoint.cpp b/src/modules/physics/box2d/DistanceJoint.cpp index ca4bc4fc9..a3f77f33a 100644 --- a/src/modules/physics/box2d/DistanceJoint.cpp +++ b/src/modules/physics/box2d/DistanceJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/DistanceJoint.h b/src/modules/physics/box2d/DistanceJoint.h index f98a197c2..5b59d9905 100644 --- a/src/modules/physics/box2d/DistanceJoint.h +++ b/src/modules/physics/box2d/DistanceJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/EdgeShape.cpp b/src/modules/physics/box2d/EdgeShape.cpp index f49925783..f394664e0 100644 --- a/src/modules/physics/box2d/EdgeShape.cpp +++ b/src/modules/physics/box2d/EdgeShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/EdgeShape.h b/src/modules/physics/box2d/EdgeShape.h index 9445e5b62..8e57b6704 100644 --- a/src/modules/physics/box2d/EdgeShape.h +++ b/src/modules/physics/box2d/EdgeShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/FrictionJoint.cpp b/src/modules/physics/box2d/FrictionJoint.cpp index af0066e30..80ec092df 100644 --- a/src/modules/physics/box2d/FrictionJoint.cpp +++ b/src/modules/physics/box2d/FrictionJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/FrictionJoint.h b/src/modules/physics/box2d/FrictionJoint.h index 145bbf78d..d8d7391be 100644 --- a/src/modules/physics/box2d/FrictionJoint.h +++ b/src/modules/physics/box2d/FrictionJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/GearJoint.cpp b/src/modules/physics/box2d/GearJoint.cpp index 474e19448..691bc5c12 100644 --- a/src/modules/physics/box2d/GearJoint.cpp +++ b/src/modules/physics/box2d/GearJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/GearJoint.h b/src/modules/physics/box2d/GearJoint.h index f6199de0b..2c434ea1a 100644 --- a/src/modules/physics/box2d/GearJoint.h +++ b/src/modules/physics/box2d/GearJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Joint.cpp b/src/modules/physics/box2d/Joint.cpp index d387b7ae2..635f42401 100644 --- a/src/modules/physics/box2d/Joint.cpp +++ b/src/modules/physics/box2d/Joint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Joint.h b/src/modules/physics/box2d/Joint.h index 140842df4..f8f120e60 100644 --- a/src/modules/physics/box2d/Joint.h +++ b/src/modules/physics/box2d/Joint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/MotorJoint.cpp b/src/modules/physics/box2d/MotorJoint.cpp index bff22662c..9ee884634 100644 --- a/src/modules/physics/box2d/MotorJoint.cpp +++ b/src/modules/physics/box2d/MotorJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/MotorJoint.h b/src/modules/physics/box2d/MotorJoint.h index ef0faf0c0..a3a875c42 100644 --- a/src/modules/physics/box2d/MotorJoint.h +++ b/src/modules/physics/box2d/MotorJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/MouseJoint.cpp b/src/modules/physics/box2d/MouseJoint.cpp index 81f8831ea..a47b367e5 100644 --- a/src/modules/physics/box2d/MouseJoint.cpp +++ b/src/modules/physics/box2d/MouseJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/MouseJoint.h b/src/modules/physics/box2d/MouseJoint.h index 1588b2024..032c58b4d 100644 --- a/src/modules/physics/box2d/MouseJoint.h +++ b/src/modules/physics/box2d/MouseJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Physics.cpp b/src/modules/physics/box2d/Physics.cpp index 6fb860b18..c3b3d5189 100644 --- a/src/modules/physics/box2d/Physics.cpp +++ b/src/modules/physics/box2d/Physics.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -35,7 +35,8 @@ namespace box2d float Physics::meter = Physics::DEFAULT_METER; Physics::Physics() - : blockAllocator() + : Module(M_PHYSICS, "love.physics.box2d") + , blockAllocator() { meter = DEFAULT_METER; } @@ -44,11 +45,6 @@ Physics::~Physics() { } -const char *Physics::getName() const -{ - return "love.physics.box2d"; -} - World *Physics::newWorld(float gx, float gy, bool sleep) { return new World(b2Vec2(gx, gy), sleep); diff --git a/src/modules/physics/box2d/Physics.h b/src/modules/physics/box2d/Physics.h index c198a7b78..41da7d0fd 100644 --- a/src/modules/physics/box2d/Physics.h +++ b/src/modules/physics/box2d/Physics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -65,10 +65,6 @@ public: Physics(); virtual ~Physics(); - // Implements Module. - const char *getName() const; - virtual ModuleType getModuleType() const { return M_PHYSICS; } - /** * Creates a new World. * @param gx Gravity along x-axis. diff --git a/src/modules/physics/box2d/PolygonShape.cpp b/src/modules/physics/box2d/PolygonShape.cpp index 12b314f02..a3d209b6f 100644 --- a/src/modules/physics/box2d/PolygonShape.cpp +++ b/src/modules/physics/box2d/PolygonShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/PolygonShape.h b/src/modules/physics/box2d/PolygonShape.h index 5d400553f..3ff0d8e0c 100644 --- a/src/modules/physics/box2d/PolygonShape.h +++ b/src/modules/physics/box2d/PolygonShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/PrismaticJoint.cpp b/src/modules/physics/box2d/PrismaticJoint.cpp index dba52f8e2..ecaad09d1 100644 --- a/src/modules/physics/box2d/PrismaticJoint.cpp +++ b/src/modules/physics/box2d/PrismaticJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/PrismaticJoint.h b/src/modules/physics/box2d/PrismaticJoint.h index 0c774367b..939caa0b3 100644 --- a/src/modules/physics/box2d/PrismaticJoint.h +++ b/src/modules/physics/box2d/PrismaticJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/PulleyJoint.cpp b/src/modules/physics/box2d/PulleyJoint.cpp index afc1c0d88..b4c73f782 100644 --- a/src/modules/physics/box2d/PulleyJoint.cpp +++ b/src/modules/physics/box2d/PulleyJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/PulleyJoint.h b/src/modules/physics/box2d/PulleyJoint.h index 61be4cfef..6c3ad5aea 100644 --- a/src/modules/physics/box2d/PulleyJoint.h +++ b/src/modules/physics/box2d/PulleyJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/RevoluteJoint.cpp b/src/modules/physics/box2d/RevoluteJoint.cpp index cead503ee..2144386e9 100644 --- a/src/modules/physics/box2d/RevoluteJoint.cpp +++ b/src/modules/physics/box2d/RevoluteJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/RevoluteJoint.h b/src/modules/physics/box2d/RevoluteJoint.h index 5d6feab95..c4980731e 100644 --- a/src/modules/physics/box2d/RevoluteJoint.h +++ b/src/modules/physics/box2d/RevoluteJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/RopeJoint.cpp b/src/modules/physics/box2d/RopeJoint.cpp index 426697910..f42dce6e8 100644 --- a/src/modules/physics/box2d/RopeJoint.cpp +++ b/src/modules/physics/box2d/RopeJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/RopeJoint.h b/src/modules/physics/box2d/RopeJoint.h index 927cca30b..393e23a13 100644 --- a/src/modules/physics/box2d/RopeJoint.h +++ b/src/modules/physics/box2d/RopeJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Shape.cpp b/src/modules/physics/box2d/Shape.cpp index b7c0ddece..cec11f5c3 100644 --- a/src/modules/physics/box2d/Shape.cpp +++ b/src/modules/physics/box2d/Shape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/Shape.h b/src/modules/physics/box2d/Shape.h index 6eb4e0586..43f754598 100644 --- a/src/modules/physics/box2d/Shape.h +++ b/src/modules/physics/box2d/Shape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/WeldJoint.cpp b/src/modules/physics/box2d/WeldJoint.cpp index ff5aeed2e..e84036ac0 100644 --- a/src/modules/physics/box2d/WeldJoint.cpp +++ b/src/modules/physics/box2d/WeldJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/WeldJoint.h b/src/modules/physics/box2d/WeldJoint.h index 73f74a4f6..e277fe0a7 100644 --- a/src/modules/physics/box2d/WeldJoint.h +++ b/src/modules/physics/box2d/WeldJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/WheelJoint.cpp b/src/modules/physics/box2d/WheelJoint.cpp index cc42e4224..867ae4383 100644 --- a/src/modules/physics/box2d/WheelJoint.cpp +++ b/src/modules/physics/box2d/WheelJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/WheelJoint.h b/src/modules/physics/box2d/WheelJoint.h index 83182a1bf..9f98c83d2 100644 --- a/src/modules/physics/box2d/WheelJoint.h +++ b/src/modules/physics/box2d/WheelJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 1ec53926e..5bb68a159 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 9b8af3b89..ce7d7bd97 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index 44bda7c0e..9f83d7a4f 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Body.h b/src/modules/physics/box2d/wrap_Body.h index bf2398d0b..66e657b31 100644 --- a/src/modules/physics/box2d/wrap_Body.h +++ b/src/modules/physics/box2d/wrap_Body.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_ChainShape.cpp b/src/modules/physics/box2d/wrap_ChainShape.cpp index d0597e778..f39021a0c 100644 --- a/src/modules/physics/box2d/wrap_ChainShape.cpp +++ b/src/modules/physics/box2d/wrap_ChainShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_ChainShape.h b/src/modules/physics/box2d/wrap_ChainShape.h index ce283df01..ce40c0de8 100644 --- a/src/modules/physics/box2d/wrap_ChainShape.h +++ b/src/modules/physics/box2d/wrap_ChainShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_CircleShape.cpp b/src/modules/physics/box2d/wrap_CircleShape.cpp index 99bc524d6..d0fe71509 100644 --- a/src/modules/physics/box2d/wrap_CircleShape.cpp +++ b/src/modules/physics/box2d/wrap_CircleShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_CircleShape.h b/src/modules/physics/box2d/wrap_CircleShape.h index 9e9ef36fc..7e0ccacbd 100644 --- a/src/modules/physics/box2d/wrap_CircleShape.h +++ b/src/modules/physics/box2d/wrap_CircleShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Contact.cpp b/src/modules/physics/box2d/wrap_Contact.cpp index a61c6a72b..4b965bd92 100644 --- a/src/modules/physics/box2d/wrap_Contact.cpp +++ b/src/modules/physics/box2d/wrap_Contact.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Contact.h b/src/modules/physics/box2d/wrap_Contact.h index 3dd811344..40f8d4235 100644 --- a/src/modules/physics/box2d/wrap_Contact.h +++ b/src/modules/physics/box2d/wrap_Contact.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_DistanceJoint.cpp b/src/modules/physics/box2d/wrap_DistanceJoint.cpp index 96aa5c286..ca691b730 100644 --- a/src/modules/physics/box2d/wrap_DistanceJoint.cpp +++ b/src/modules/physics/box2d/wrap_DistanceJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_DistanceJoint.h b/src/modules/physics/box2d/wrap_DistanceJoint.h index 583e60a01..86a5f1b85 100644 --- a/src/modules/physics/box2d/wrap_DistanceJoint.h +++ b/src/modules/physics/box2d/wrap_DistanceJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_EdgeShape.cpp b/src/modules/physics/box2d/wrap_EdgeShape.cpp index a97b115a5..2ffca1f79 100644 --- a/src/modules/physics/box2d/wrap_EdgeShape.cpp +++ b/src/modules/physics/box2d/wrap_EdgeShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_EdgeShape.h b/src/modules/physics/box2d/wrap_EdgeShape.h index 35f07cd34..c92e92c3f 100644 --- a/src/modules/physics/box2d/wrap_EdgeShape.h +++ b/src/modules/physics/box2d/wrap_EdgeShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_FrictionJoint.cpp b/src/modules/physics/box2d/wrap_FrictionJoint.cpp index 14caa958b..fcb3230a8 100644 --- a/src/modules/physics/box2d/wrap_FrictionJoint.cpp +++ b/src/modules/physics/box2d/wrap_FrictionJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_FrictionJoint.h b/src/modules/physics/box2d/wrap_FrictionJoint.h index 16561bfa7..490e819e3 100644 --- a/src/modules/physics/box2d/wrap_FrictionJoint.h +++ b/src/modules/physics/box2d/wrap_FrictionJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_GearJoint.cpp b/src/modules/physics/box2d/wrap_GearJoint.cpp index 905a619f6..b7d0966cc 100644 --- a/src/modules/physics/box2d/wrap_GearJoint.cpp +++ b/src/modules/physics/box2d/wrap_GearJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_GearJoint.h b/src/modules/physics/box2d/wrap_GearJoint.h index 9469750b2..eb58da935 100644 --- a/src/modules/physics/box2d/wrap_GearJoint.h +++ b/src/modules/physics/box2d/wrap_GearJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Joint.cpp b/src/modules/physics/box2d/wrap_Joint.cpp index 71ed39225..8139ff39a 100644 --- a/src/modules/physics/box2d/wrap_Joint.cpp +++ b/src/modules/physics/box2d/wrap_Joint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Joint.h b/src/modules/physics/box2d/wrap_Joint.h index 47e976daa..e9794525b 100644 --- a/src/modules/physics/box2d/wrap_Joint.h +++ b/src/modules/physics/box2d/wrap_Joint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_MotorJoint.cpp b/src/modules/physics/box2d/wrap_MotorJoint.cpp index 62513b120..3001d4df3 100644 --- a/src/modules/physics/box2d/wrap_MotorJoint.cpp +++ b/src/modules/physics/box2d/wrap_MotorJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_MotorJoint.h b/src/modules/physics/box2d/wrap_MotorJoint.h index 3d684041d..464b2b09b 100644 --- a/src/modules/physics/box2d/wrap_MotorJoint.h +++ b/src/modules/physics/box2d/wrap_MotorJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_MouseJoint.cpp b/src/modules/physics/box2d/wrap_MouseJoint.cpp index 570962b26..084f37653 100644 --- a/src/modules/physics/box2d/wrap_MouseJoint.cpp +++ b/src/modules/physics/box2d/wrap_MouseJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_MouseJoint.h b/src/modules/physics/box2d/wrap_MouseJoint.h index c36a8f241..a45f79167 100644 --- a/src/modules/physics/box2d/wrap_MouseJoint.h +++ b/src/modules/physics/box2d/wrap_MouseJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index 34dfb81ff..680973d36 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Physics.h b/src/modules/physics/box2d/wrap_Physics.h index 0d8b93b5f..0b56b17bd 100644 --- a/src/modules/physics/box2d/wrap_Physics.h +++ b/src/modules/physics/box2d/wrap_Physics.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_PolygonShape.cpp b/src/modules/physics/box2d/wrap_PolygonShape.cpp index e558f000e..b416d8ee6 100644 --- a/src/modules/physics/box2d/wrap_PolygonShape.cpp +++ b/src/modules/physics/box2d/wrap_PolygonShape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_PolygonShape.h b/src/modules/physics/box2d/wrap_PolygonShape.h index 0eda5f054..c281dfe13 100644 --- a/src/modules/physics/box2d/wrap_PolygonShape.h +++ b/src/modules/physics/box2d/wrap_PolygonShape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_PrismaticJoint.cpp b/src/modules/physics/box2d/wrap_PrismaticJoint.cpp index 11cdce0ed..359ec4d89 100644 --- a/src/modules/physics/box2d/wrap_PrismaticJoint.cpp +++ b/src/modules/physics/box2d/wrap_PrismaticJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_PrismaticJoint.h b/src/modules/physics/box2d/wrap_PrismaticJoint.h index b66651652..307a1d1df 100644 --- a/src/modules/physics/box2d/wrap_PrismaticJoint.h +++ b/src/modules/physics/box2d/wrap_PrismaticJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_PulleyJoint.cpp b/src/modules/physics/box2d/wrap_PulleyJoint.cpp index d41e64031..7e376f4b8 100644 --- a/src/modules/physics/box2d/wrap_PulleyJoint.cpp +++ b/src/modules/physics/box2d/wrap_PulleyJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_PulleyJoint.h b/src/modules/physics/box2d/wrap_PulleyJoint.h index e365478fb..2cec64fbe 100644 --- a/src/modules/physics/box2d/wrap_PulleyJoint.h +++ b/src/modules/physics/box2d/wrap_PulleyJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_RevoluteJoint.cpp b/src/modules/physics/box2d/wrap_RevoluteJoint.cpp index 4b3efa370..ff7a61df1 100644 --- a/src/modules/physics/box2d/wrap_RevoluteJoint.cpp +++ b/src/modules/physics/box2d/wrap_RevoluteJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_RevoluteJoint.h b/src/modules/physics/box2d/wrap_RevoluteJoint.h index 9347606fd..66e4b3386 100644 --- a/src/modules/physics/box2d/wrap_RevoluteJoint.h +++ b/src/modules/physics/box2d/wrap_RevoluteJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_RopeJoint.cpp b/src/modules/physics/box2d/wrap_RopeJoint.cpp index d91445288..c3fef9faf 100644 --- a/src/modules/physics/box2d/wrap_RopeJoint.cpp +++ b/src/modules/physics/box2d/wrap_RopeJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_RopeJoint.h b/src/modules/physics/box2d/wrap_RopeJoint.h index c264c710c..2b0fd7414 100644 --- a/src/modules/physics/box2d/wrap_RopeJoint.h +++ b/src/modules/physics/box2d/wrap_RopeJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Shape.cpp b/src/modules/physics/box2d/wrap_Shape.cpp index b1f0b55b5..05c73169a 100644 --- a/src/modules/physics/box2d/wrap_Shape.cpp +++ b/src/modules/physics/box2d/wrap_Shape.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_Shape.h b/src/modules/physics/box2d/wrap_Shape.h index 960945c1c..25ddba824 100644 --- a/src/modules/physics/box2d/wrap_Shape.h +++ b/src/modules/physics/box2d/wrap_Shape.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_WeldJoint.cpp b/src/modules/physics/box2d/wrap_WeldJoint.cpp index f03d99405..ad51f9e29 100644 --- a/src/modules/physics/box2d/wrap_WeldJoint.cpp +++ b/src/modules/physics/box2d/wrap_WeldJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_WeldJoint.h b/src/modules/physics/box2d/wrap_WeldJoint.h index 234c7350c..f9a3e1132 100644 --- a/src/modules/physics/box2d/wrap_WeldJoint.h +++ b/src/modules/physics/box2d/wrap_WeldJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_WheelJoint.cpp b/src/modules/physics/box2d/wrap_WheelJoint.cpp index fa116833e..56b34e9f3 100644 --- a/src/modules/physics/box2d/wrap_WheelJoint.cpp +++ b/src/modules/physics/box2d/wrap_WheelJoint.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_WheelJoint.h b/src/modules/physics/box2d/wrap_WheelJoint.h index 827863d02..5bfdd48af 100644 --- a/src/modules/physics/box2d/wrap_WheelJoint.h +++ b/src/modules/physics/box2d/wrap_WheelJoint.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index 1659374df..016e5b4db 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/physics/box2d/wrap_World.h b/src/modules/physics/box2d/wrap_World.h index cf0660299..e65f83b7b 100644 --- a/src/modules/physics/box2d/wrap_World.h +++ b/src/modules/physics/box2d/wrap_World.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sensor/Sensor.cpp b/src/modules/sensor/Sensor.cpp index c1235967e..7e991baa1 100644 --- a/src/modules/sensor/Sensor.cpp +++ b/src/modules/sensor/Sensor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -26,6 +26,11 @@ namespace love namespace sensor { +Sensor::Sensor(const char *name) + : Module(M_SENSOR, name) +{ +} + STRINGMAP_CLASS_BEGIN(Sensor, Sensor::SensorType, Sensor::SENSOR_MAX_ENUM, sensorType) { { "accelerometer", Sensor::SENSOR_ACCELEROMETER }, diff --git a/src/modules/sensor/Sensor.h b/src/modules/sensor/Sensor.h index 1fd51dc7f..bf79d1d87 100644 --- a/src/modules/sensor/Sensor.h +++ b/src/modules/sensor/Sensor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,9 +43,6 @@ public: virtual ~Sensor() {} - // Implements Module. - ModuleType getModuleType() const override { return M_SENSOR; } - /** * Check the availability of the sensor. **/ @@ -75,6 +72,10 @@ public: STRINGMAP_CLASS_DECLARE(SensorType); +protected: + + Sensor(const char *name); + }; // Sensor } // sensor diff --git a/src/modules/sensor/sdl/Sensor.cpp b/src/modules/sensor/sdl/Sensor.cpp index caf4a5701..0337ade3a 100644 --- a/src/modules/sensor/sdl/Sensor.cpp +++ b/src/modules/sensor/sdl/Sensor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -33,7 +33,8 @@ namespace sdl { Sensor::Sensor() -: sensors() + : love::sensor::Sensor("love.sensor.sdl") + , sensors() { if (SDL_InitSubSystem(SDL_INIT_SENSOR) < 0) throw love::Exception("Could not initialize SDL sensor subsystem (%s)", SDL_GetError()); @@ -44,11 +45,6 @@ Sensor::~Sensor() SDL_QuitSubSystem(SDL_INIT_SENSOR); } -const char *Sensor::getName() const -{ - return "love.sensor.sdl"; -} - bool Sensor::hasSensor(SensorType type) { #if SDL_VERSION_ATLEAST(3, 0, 0) diff --git a/src/modules/sensor/sdl/Sensor.h b/src/modules/sensor/sdl/Sensor.h index afd28a701..02491add7 100644 --- a/src/modules/sensor/sdl/Sensor.h +++ b/src/modules/sensor/sdl/Sensor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,9 +43,6 @@ public: Sensor(); ~Sensor() override; - // Implements Module. - const char *getName() const override; - bool hasSensor(SensorType type) override; bool isEnabled(SensorType type) override; void setEnabled(SensorType type, bool enable) override; diff --git a/src/modules/sensor/wrap_Sensor.cpp b/src/modules/sensor/wrap_Sensor.cpp index 98c13cc8a..f5dde10a4 100644 --- a/src/modules/sensor/wrap_Sensor.cpp +++ b/src/modules/sensor/wrap_Sensor.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sensor/wrap_Sensor.h b/src/modules/sensor/wrap_Sensor.h index e4628deca..eaf5c76e1 100644 --- a/src/modules/sensor/wrap_Sensor.h +++ b/src/modules/sensor/wrap_Sensor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/Decoder.cpp b/src/modules/sound/Decoder.cpp index a7562f1b4..326e8097a 100644 --- a/src/modules/sound/Decoder.cpp +++ b/src/modules/sound/Decoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/Decoder.h b/src/modules/sound/Decoder.h index 1fbd9dbb4..2925338b8 100644 --- a/src/modules/sound/Decoder.h +++ b/src/modules/sound/Decoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/Sound.cpp b/src/modules/sound/Sound.cpp index 99ff80992..f4f3da271 100644 --- a/src/modules/sound/Sound.cpp +++ b/src/modules/sound/Sound.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -27,6 +27,11 @@ namespace sound love::Type Sound::type("Sound", &Module::type); +Sound::Sound(const char *name) + : Module(M_SOUND, name) +{ +} + Sound::~Sound() { } diff --git a/src/modules/sound/Sound.h b/src/modules/sound/Sound.h index 7ccc1be6c..3b0685b08 100644 --- a/src/modules/sound/Sound.h +++ b/src/modules/sound/Sound.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -46,9 +46,6 @@ public: virtual ~Sound(); - // Implements Module. - virtual ModuleType getModuleType() const { return M_SOUND; } - /** * Creates new SoundData from a decoder. Fully expands the * encoded sound data into raw sound data. Not recommended @@ -89,6 +86,10 @@ public: **/ virtual Decoder *newDecoder(Stream *stream, int bufferSize) = 0; +protected: + + Sound(const char *name); + }; // Sound } // sound diff --git a/src/modules/sound/SoundData.cpp b/src/modules/sound/SoundData.cpp index 39ed8ee78..ac441f04d 100644 --- a/src/modules/sound/SoundData.cpp +++ b/src/modules/sound/SoundData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/SoundData.h b/src/modules/sound/SoundData.h index e08fef043..7b7864328 100644 --- a/src/modules/sound/SoundData.h +++ b/src/modules/sound/SoundData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/CoreAudioDecoder.cpp b/src/modules/sound/lullaby/CoreAudioDecoder.cpp index ff3c44450..421cdf7a2 100644 --- a/src/modules/sound/lullaby/CoreAudioDecoder.cpp +++ b/src/modules/sound/lullaby/CoreAudioDecoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/CoreAudioDecoder.h b/src/modules/sound/lullaby/CoreAudioDecoder.h index 3f9582685..8e461e1f4 100644 --- a/src/modules/sound/lullaby/CoreAudioDecoder.h +++ b/src/modules/sound/lullaby/CoreAudioDecoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/FLACDecoder.cpp b/src/modules/sound/lullaby/FLACDecoder.cpp index b39206abb..1a4662716 100644 --- a/src/modules/sound/lullaby/FLACDecoder.cpp +++ b/src/modules/sound/lullaby/FLACDecoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/FLACDecoder.h b/src/modules/sound/lullaby/FLACDecoder.h index 9795e5785..109399295 100644 --- a/src/modules/sound/lullaby/FLACDecoder.h +++ b/src/modules/sound/lullaby/FLACDecoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/MP3Decoder.cpp b/src/modules/sound/lullaby/MP3Decoder.cpp index cd50f44a9..c5b55b152 100644 --- a/src/modules/sound/lullaby/MP3Decoder.cpp +++ b/src/modules/sound/lullaby/MP3Decoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/MP3Decoder.h b/src/modules/sound/lullaby/MP3Decoder.h index aa3349feb..ea08183ea 100644 --- a/src/modules/sound/lullaby/MP3Decoder.h +++ b/src/modules/sound/lullaby/MP3Decoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/ModPlugDecoder.cpp b/src/modules/sound/lullaby/ModPlugDecoder.cpp index e03706912..7f297fd39 100644 --- a/src/modules/sound/lullaby/ModPlugDecoder.cpp +++ b/src/modules/sound/lullaby/ModPlugDecoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/ModPlugDecoder.h b/src/modules/sound/lullaby/ModPlugDecoder.h index f36f58b17..8e0d38f86 100644 --- a/src/modules/sound/lullaby/ModPlugDecoder.h +++ b/src/modules/sound/lullaby/ModPlugDecoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/Sound.cpp b/src/modules/sound/lullaby/Sound.cpp index fbb6a36be..a5fe66411 100644 --- a/src/modules/sound/lullaby/Sound.cpp +++ b/src/modules/sound/lullaby/Sound.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -59,6 +59,7 @@ namespace lullaby { Sound::Sound() + : love::sound::Sound("love.sound.lullaby") { } @@ -66,11 +67,6 @@ Sound::~Sound() { } -const char *Sound::getName() const -{ - return "love.sound.lullaby"; -} - sound::Decoder *Sound::newDecoder(Stream *stream, int bufferSize) { std::vector possibleDecoders = { diff --git a/src/modules/sound/lullaby/Sound.h b/src/modules/sound/lullaby/Sound.h index 03bfd49e5..13e5e1fa3 100644 --- a/src/modules/sound/lullaby/Sound.h +++ b/src/modules/sound/lullaby/Sound.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -48,9 +48,6 @@ public: Sound(); virtual ~Sound(); - /// @copydoc love::Module::getName - const char *getName() const override; - /// @copydoc love::sound::Sound::newDecoder sound::Decoder *newDecoder(Stream *stream, int bufferSize) override; diff --git a/src/modules/sound/lullaby/VorbisDecoder.cpp b/src/modules/sound/lullaby/VorbisDecoder.cpp index 2d2ac5af6..829825112 100644 --- a/src/modules/sound/lullaby/VorbisDecoder.cpp +++ b/src/modules/sound/lullaby/VorbisDecoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/VorbisDecoder.h b/src/modules/sound/lullaby/VorbisDecoder.h index 7d453b7b5..cf7a58bca 100644 --- a/src/modules/sound/lullaby/VorbisDecoder.h +++ b/src/modules/sound/lullaby/VorbisDecoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/WaveDecoder.cpp b/src/modules/sound/lullaby/WaveDecoder.cpp index 8a9cd608c..fdefd4df9 100644 --- a/src/modules/sound/lullaby/WaveDecoder.cpp +++ b/src/modules/sound/lullaby/WaveDecoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/lullaby/WaveDecoder.h b/src/modules/sound/lullaby/WaveDecoder.h index 4abfb6cd5..525a9b052 100644 --- a/src/modules/sound/lullaby/WaveDecoder.h +++ b/src/modules/sound/lullaby/WaveDecoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_Decoder.cpp b/src/modules/sound/wrap_Decoder.cpp index 8054111bd..ff2193bf3 100644 --- a/src/modules/sound/wrap_Decoder.cpp +++ b/src/modules/sound/wrap_Decoder.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_Decoder.h b/src/modules/sound/wrap_Decoder.h index 974ec5306..55533f2c3 100644 --- a/src/modules/sound/wrap_Decoder.h +++ b/src/modules/sound/wrap_Decoder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_Sound.cpp b/src/modules/sound/wrap_Sound.cpp index b5190e5e0..1a1395393 100644 --- a/src/modules/sound/wrap_Sound.cpp +++ b/src/modules/sound/wrap_Sound.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_Sound.h b/src/modules/sound/wrap_Sound.h index 995b626c0..c2fc31c41 100644 --- a/src/modules/sound/wrap_Sound.h +++ b/src/modules/sound/wrap_Sound.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_SoundData.cpp b/src/modules/sound/wrap_SoundData.cpp index 79ce4d11e..67554bca4 100644 --- a/src/modules/sound/wrap_SoundData.cpp +++ b/src/modules/sound/wrap_SoundData.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_SoundData.h b/src/modules/sound/wrap_SoundData.h index 218fbefea..84fac0145 100644 --- a/src/modules/sound/wrap_SoundData.h +++ b/src/modules/sound/wrap_SoundData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/sound/wrap_SoundData.lua b/src/modules/sound/wrap_SoundData.lua index 4e074101e..ebc2c8879 100644 --- a/src/modules/sound/wrap_SoundData.lua +++ b/src/modules/sound/wrap_SoundData.lua @@ -3,7 +3,7 @@ R"luastring"--( -- There is a matching delimiter at the bottom of the file. --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index 4864bc0d8..cee7674c9 100644 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -58,7 +58,8 @@ namespace love namespace system { -System::System() +System::System(const char *name) + : Module(M_SYSTEM, name) { } diff --git a/src/modules/system/System.h b/src/modules/system/System.h index 6abef3cd3..7a7ed764e 100644 --- a/src/modules/system/System.h +++ b/src/modules/system/System.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -48,12 +48,9 @@ public: POWER_MAX_ENUM }; - System(); + System(const char *name); virtual ~System() {} - // Implements Module. - virtual ModuleType getModuleType() const { return M_SYSTEM; } - /** * Gets the current operating system. **/ diff --git a/src/modules/system/sdl/System.cpp b/src/modules/system/sdl/System.cpp index 1bae95e73..b25f6334f 100644 --- a/src/modules/system/sdl/System.cpp +++ b/src/modules/system/sdl/System.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -39,14 +39,10 @@ namespace sdl { System::System() + : love::system::System("love.system.sdl") { } -const char *System::getName() const -{ - return "love.system.sdl"; -} - int System::getProcessorCount() const { return SDL_GetCPUCount(); diff --git a/src/modules/system/sdl/System.h b/src/modules/system/sdl/System.h index 7c1da5aef..39787e9d4 100644 --- a/src/modules/system/sdl/System.h +++ b/src/modules/system/sdl/System.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -42,9 +42,6 @@ public: System(); virtual ~System() {} - // Implements Module. - const char *getName() const override; - int getProcessorCount() const override; void setClipboardText(const std::string &text) const override; diff --git a/src/modules/system/wrap_System.cpp b/src/modules/system/wrap_System.cpp index feac514c5..bfe461366 100644 --- a/src/modules/system/wrap_System.cpp +++ b/src/modules/system/wrap_System.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/system/wrap_System.h b/src/modules/system/wrap_System.h index b89e3b111..94e0d1a81 100644 --- a/src/modules/system/wrap_System.h +++ b/src/modules/system/wrap_System.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/Channel.cpp b/src/modules/thread/Channel.cpp index 7c20158e2..0b352d9c1 100644 --- a/src/modules/thread/Channel.cpp +++ b/src/modules/thread/Channel.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/Channel.h b/src/modules/thread/Channel.h index 1409488a4..121f2321b 100644 --- a/src/modules/thread/Channel.h +++ b/src/modules/thread/Channel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/LuaThread.cpp b/src/modules/thread/LuaThread.cpp index 50046c3bc..948ecfe7c 100644 --- a/src/modules/thread/LuaThread.cpp +++ b/src/modules/thread/LuaThread.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/LuaThread.h b/src/modules/thread/LuaThread.h index 4e7cc8c8d..5142751fe 100644 --- a/src/modules/thread/LuaThread.h +++ b/src/modules/thread/LuaThread.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/Thread.h b/src/modules/thread/Thread.h index b761190bd..19c8cd5da 100644 --- a/src/modules/thread/Thread.h +++ b/src/modules/thread/Thread.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/ThreadModule.cpp b/src/modules/thread/ThreadModule.cpp index f48af26ea..3d94bae53 100644 --- a/src/modules/thread/ThreadModule.cpp +++ b/src/modules/thread/ThreadModule.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -25,6 +25,11 @@ namespace love namespace thread { +ThreadModule::ThreadModule() + : love::Module(M_THREAD, "love.thread.sdl") +{ +} + LuaThread *ThreadModule::newThread(const std::string &name, love::Data *data) { return new LuaThread(name, data); @@ -48,10 +53,5 @@ Channel *ThreadModule::getChannel(const std::string &name) return c; } -const char *ThreadModule::getName() const -{ - return "love.thread.sdl"; -} - } // thread } // love diff --git a/src/modules/thread/ThreadModule.h b/src/modules/thread/ThreadModule.h index 819b05557..516c23392 100644 --- a/src/modules/thread/ThreadModule.h +++ b/src/modules/thread/ThreadModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,15 +43,12 @@ class ThreadModule : public love::Module { public: + ThreadModule(); virtual ~ThreadModule() {} virtual LuaThread *newThread(const std::string &name, love::Data *data); virtual Channel *newChannel(); virtual Channel *getChannel(const std::string &name); - // Implements Module. - virtual const char *getName() const; - virtual ModuleType getModuleType() const { return M_THREAD; } - private: std::map> namedChannels; diff --git a/src/modules/thread/sdl/Thread.cpp b/src/modules/thread/sdl/Thread.cpp index aa69b9276..f9f59e932 100644 --- a/src/modules/thread/sdl/Thread.cpp +++ b/src/modules/thread/sdl/Thread.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/sdl/Thread.h b/src/modules/thread/sdl/Thread.h index 3545e1b16..a01926b63 100644 --- a/src/modules/thread/sdl/Thread.h +++ b/src/modules/thread/sdl/Thread.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/sdl/threads.cpp b/src/modules/thread/sdl/threads.cpp index 9805a7f83..67fd9652f 100644 --- a/src/modules/thread/sdl/threads.cpp +++ b/src/modules/thread/sdl/threads.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/sdl/threads.h b/src/modules/thread/sdl/threads.h index 374585e0e..4a7bbde6e 100644 --- a/src/modules/thread/sdl/threads.h +++ b/src/modules/thread/sdl/threads.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/threads.cpp b/src/modules/thread/threads.cpp index cf76dcbf9..2e76865dc 100644 --- a/src/modules/thread/threads.cpp +++ b/src/modules/thread/threads.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/threads.h b/src/modules/thread/threads.h index e5d8bd059..d20c7e4ec 100644 --- a/src/modules/thread/threads.h +++ b/src/modules/thread/threads.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/wrap_Channel.h b/src/modules/thread/wrap_Channel.h index 01097e474..5842fb569 100644 --- a/src/modules/thread/wrap_Channel.h +++ b/src/modules/thread/wrap_Channel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/wrap_LuaThread.h b/src/modules/thread/wrap_LuaThread.h index 554b01b07..942134e4d 100644 --- a/src/modules/thread/wrap_LuaThread.h +++ b/src/modules/thread/wrap_LuaThread.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/thread/wrap_ThreadModule.h b/src/modules/thread/wrap_ThreadModule.h index a31eafda2..8c14455f3 100644 --- a/src/modules/thread/wrap_ThreadModule.h +++ b/src/modules/thread/wrap_ThreadModule.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/timer/Timer.cpp b/src/modules/timer/Timer.cpp index 09aeb3d24..c9c602f3d 100644 --- a/src/modules/timer/Timer.cpp +++ b/src/modules/timer/Timer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,7 +43,8 @@ namespace timer { Timer::Timer() - : currTime(0) + : Module(M_TIMER, "love.timer") + , currTime(0) , prevFpsUpdate(0) , fps(0) , averageDelta(0) diff --git a/src/modules/timer/Timer.h b/src/modules/timer/Timer.h index c3a7f43bb..883a6230b 100644 --- a/src/modules/timer/Timer.h +++ b/src/modules/timer/Timer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -36,10 +36,6 @@ public: Timer(); virtual ~Timer() {} - // Implements Module. - ModuleType getModuleType() const override { return M_TIMER; } - const char *getName() const override { return "love.timer"; } - /** * Measures the time between this call and the previous call, * and updates internal values accordingly. diff --git a/src/modules/timer/wrap_Timer.cpp b/src/modules/timer/wrap_Timer.cpp index 8f9c18a20..9896c4902 100644 --- a/src/modules/timer/wrap_Timer.cpp +++ b/src/modules/timer/wrap_Timer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/timer/wrap_Timer.h b/src/modules/timer/wrap_Timer.h index 7f9897396..0f2daaa41 100644 --- a/src/modules/timer/wrap_Timer.h +++ b/src/modules/timer/wrap_Timer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/touch/Touch.h b/src/modules/touch/Touch.h index 2fdf8d6cd..08b9de60a 100644 --- a/src/modules/touch/Touch.h +++ b/src/modules/touch/Touch.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -51,9 +51,6 @@ public: virtual ~Touch() {} - // Implements Module. - virtual ModuleType getModuleType() const { return M_TOUCH; } - /** * Gets all currently active touches. **/ @@ -64,6 +61,12 @@ public: **/ virtual const TouchInfo &getTouch(int64 id) const = 0; +protected: + + Touch(const char *name) + : Module(M_TOUCH, name) + {} + }; // Touch } // touch diff --git a/src/modules/touch/sdl/Touch.cpp b/src/modules/touch/sdl/Touch.cpp index cd65c0173..a004ff85c 100644 --- a/src/modules/touch/sdl/Touch.cpp +++ b/src/modules/touch/sdl/Touch.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -35,6 +35,11 @@ namespace touch namespace sdl { +Touch::Touch() + : love::touch::Touch("love.touch.sdl") +{ +} + const std::vector &Touch::getTouches() const { return touches; @@ -51,11 +56,6 @@ const Touch::TouchInfo &Touch::getTouch(int64 id) const throw love::Exception("Invalid active touch ID: %d", id); } -const char *Touch::getName() const -{ - return "love.touch.sdl"; -} - void Touch::onEvent(Uint32 eventtype, const TouchInfo &info) { auto compare = [&](const TouchInfo &touch) -> bool diff --git a/src/modules/touch/sdl/Touch.h b/src/modules/touch/sdl/Touch.h index f0465f8a8..8bd5c918d 100644 --- a/src/modules/touch/sdl/Touch.h +++ b/src/modules/touch/sdl/Touch.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -38,14 +38,12 @@ class Touch : public love::touch::Touch { public: + Touch(); virtual ~Touch() {} const std::vector &getTouches() const override; const TouchInfo &getTouch(int64 id) const override; - // Implements Module. - const char *getName() const override; - // SDL has functions to query the state of touch presses, but unfortunately // they are updated on a different thread in some backends, which causes // issues especially if the user is iterating through the current touches diff --git a/src/modules/touch/wrap_Touch.cpp b/src/modules/touch/wrap_Touch.cpp index e9df11861..69b72cae3 100644 --- a/src/modules/touch/wrap_Touch.cpp +++ b/src/modules/touch/wrap_Touch.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/touch/wrap_Touch.h b/src/modules/touch/wrap_Touch.h index 0e9097a34..5cb4dbab3 100644 --- a/src/modules/touch/wrap_Touch.h +++ b/src/modules/touch/wrap_Touch.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/Video.h b/src/modules/video/Video.h index 90767f11d..9cfc16298 100644 --- a/src/modules/video/Video.h +++ b/src/modules/video/Video.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -35,15 +35,20 @@ namespace video class Video : public Module { public: - virtual ~Video() {} - // Implements Module - virtual ModuleType getModuleType() const { return M_VIDEO; } + virtual ~Video() {} /** * Create a VideoStream representing video frames **/ virtual VideoStream *newVideoStream(love::filesystem::File *file) = 0; + +protected: + + Video(const char *name) + : Module(M_VIDEO, name) + {} + }; // Video } // video diff --git a/src/modules/video/VideoStream.cpp b/src/modules/video/VideoStream.cpp index 1b7528b94..9a16a5c12 100644 --- a/src/modules/video/VideoStream.cpp +++ b/src/modules/video/VideoStream.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/VideoStream.h b/src/modules/video/VideoStream.h index abe61c115..f9a0a0d19 100644 --- a/src/modules/video/VideoStream.h +++ b/src/modules/video/VideoStream.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/theora/OggDemuxer.cpp b/src/modules/video/theora/OggDemuxer.cpp index 30455afa9..390dadf35 100644 --- a/src/modules/video/theora/OggDemuxer.cpp +++ b/src/modules/video/theora/OggDemuxer.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/theora/OggDemuxer.h b/src/modules/video/theora/OggDemuxer.h index 2cb31259c..65edff46f 100644 --- a/src/modules/video/theora/OggDemuxer.h +++ b/src/modules/video/theora/OggDemuxer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/theora/TheoraVideoStream.cpp b/src/modules/video/theora/TheoraVideoStream.cpp index a54ccb42d..3711466f9 100644 --- a/src/modules/video/theora/TheoraVideoStream.cpp +++ b/src/modules/video/theora/TheoraVideoStream.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/theora/TheoraVideoStream.h b/src/modules/video/theora/TheoraVideoStream.h index 79b6c30db..ae45ab517 100644 --- a/src/modules/video/theora/TheoraVideoStream.h +++ b/src/modules/video/theora/TheoraVideoStream.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/theora/Video.cpp b/src/modules/video/theora/Video.cpp index 73a8dd714..f3fd0db2c 100644 --- a/src/modules/video/theora/Video.cpp +++ b/src/modules/video/theora/Video.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -34,6 +34,7 @@ namespace theora { Video::Video() + : love::video::Video("love.video.theora") { workerThread = new Worker(); workerThread->start(); @@ -51,11 +52,6 @@ VideoStream *Video::newVideoStream(love::filesystem::File *file) return stream; } -const char *Video::getName() const -{ - return "love.video.theora"; -} - Worker::Worker() : stopping(false) { diff --git a/src/modules/video/theora/Video.h b/src/modules/video/theora/Video.h index 0bd5265f1..744822d73 100644 --- a/src/modules/video/theora/Video.h +++ b/src/modules/video/theora/Video.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -46,9 +46,6 @@ public: Video(); virtual ~Video(); - // Implements Module - virtual const char *getName() const; - VideoStream *newVideoStream(love::filesystem::File* file); private: diff --git a/src/modules/video/wrap_Video.cpp b/src/modules/video/wrap_Video.cpp index 8329c9aa6..32b59c45e 100644 --- a/src/modules/video/wrap_Video.cpp +++ b/src/modules/video/wrap_Video.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/wrap_Video.h b/src/modules/video/wrap_Video.h index 16eaa4542..5c12ac558 100644 --- a/src/modules/video/wrap_Video.h +++ b/src/modules/video/wrap_Video.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/wrap_VideoStream.cpp b/src/modules/video/wrap_VideoStream.cpp index 34f1ae3c2..bbf75e822 100644 --- a/src/modules/video/wrap_VideoStream.cpp +++ b/src/modules/video/wrap_VideoStream.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/video/wrap_VideoStream.h b/src/modules/video/wrap_VideoStream.h index 39c03c125..4fa5fd4d5 100644 --- a/src/modules/video/wrap_VideoStream.h +++ b/src/modules/video/wrap_VideoStream.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/modules/window/Window.cpp b/src/modules/window/Window.cpp index 57dc62172..6b6b282da 100644 --- a/src/modules/window/Window.cpp +++ b/src/modules/window/Window.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -43,6 +43,11 @@ bool isHighDPIAllowed() return highDPIAllowed; } +Window::Window(const char *name) + : Module(M_WINDOW, name) +{ +} + Window::~Window() { } diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index 3a53cba79..cae80beab 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -131,9 +131,6 @@ public: virtual ~Window(); - // Implements Module. - virtual ModuleType getModuleType() const { return M_WINDOW; } - virtual void setGraphics(graphics::Graphics *graphics) = 0; virtual bool setWindow(int width = 800, int height = 600, WindowSettings *settings = nullptr) = 0; @@ -239,6 +236,10 @@ public: static bool getConstant(DisplayOrientation in, const char *&out); static std::vector getConstants(DisplayOrientation); +protected: + + Window(const char *name); + private: static StringMap::Entry settingEntries[]; diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index dc43c2d65..31f0db984 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -90,7 +90,8 @@ namespace sdl { Window::Window() - : open(false) + : love::window::Window("love.window.sdl") + , open(false) , mouseGrabbed(false) , window(nullptr) , glcontext(nullptr) @@ -1271,17 +1272,11 @@ bool Window::setIcon(love::image::ImageData *imgd) int bytesperpixel = (int) getPixelFormatBlockSize(imgd->getFormat()); int pitch = w * bytesperpixel; - SDL_Surface *sdlicon = nullptr; - - { - // We don't want another thread modifying the ImageData mid-copy. - love::thread::Lock lock(imgd->getMutex()); #if SDL_VERSION_ATLEAST(3, 0, 0) - sdlicon = SDL_CreateSurfaceFrom(imgd->getData(), w, h, pitch, SDL_PIXELFORMAT_RGBA8888); + SDL_Surface *sdlicon = SDL_CreateSurfaceFrom(imgd->getData(), w, h, pitch, SDL_PIXELFORMAT_RGBA8888); #else - sdlicon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, bytesperpixel * 8, pitch, rmask, gmask, bmask, amask); + SDL_Surface *sdlicon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, bytesperpixel * 8, pitch, rmask, gmask, bmask, amask); #endif - } if (!sdlicon) return false; @@ -1749,11 +1744,6 @@ void Window::requestAttention(bool continuous) // TODO: Linux? } -const char *Window::getName() const -{ - return "love.window.sdl"; -} - } // sdl } // window } // love diff --git a/src/modules/window/sdl/Window.h b/src/modules/window/sdl/Window.h index fd006958a..ca71bc37f 100644 --- a/src/modules/window/sdl/Window.h +++ b/src/modules/window/sdl/Window.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -130,8 +130,6 @@ public: void requestAttention(bool continuous) override; - const char *getName() const override; - private: struct ContextAttribs diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index cc1bd3bd1..19efd9991 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -348,6 +348,7 @@ int w_isOpen(lua_State *L) int w_close(lua_State *L) { + luax_markdeprecated(L, 1, "love.window.close", API_FUNCTION, DEPRECATED_NO_REPLACEMENT, nullptr); luax_catchexcept(L, [&]() { instance()->close(); }); return 0; } diff --git a/src/modules/window/wrap_Window.h b/src/modules/window/wrap_Window.h index 382ce7c65..6c1069ebf 100644 --- a/src/modules/window/wrap_Window.h +++ b/src/modules/window/wrap_Window.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/scripts/auto.lua b/src/scripts/auto.lua index f9fa450ea..8f70ee667 100644 --- a/src/scripts/auto.lua +++ b/src/scripts/auto.lua @@ -7,7 +7,7 @@ local max_width = 18 local pattern = [[ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages diff --git a/src/scripts/nogame.lua b/src/scripts/nogame.lua index 39e473140..3fe8c67df 100644 --- a/src/scripts/nogame.lua +++ b/src/scripts/nogame.lua @@ -1,5 +1,5 @@ --[[ -Copyright (c) 2006-2023 LOVE Development Team +Copyright (c) 2006-2024 LOVE Development Team This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/scripts/nogame.lua.h b/src/scripts/nogame.lua.h index b467c5eff..83feae732 100644 --- a/src/scripts/nogame.lua.h +++ b/src/scripts/nogame.lua.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2006-2023 LOVE Development Team + * Copyright (c) 2006-2024 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -27,7 +27,7 @@ const unsigned char nogame_lua[] = 0x2d, 0x2d, 0x5b, 0x5b, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, - 0x2d, 0x32, 0x30, 0x32, 0x33, 0x20, 0x4c, 0x4f, 0x56, 0x45, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x2d, 0x32, 0x30, 0x32, 0x34, 0x20, 0x4c, 0x4f, 0x56, 0x45, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index f4f8688d6..405b9275b 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -64,7 +64,7 @@ TestMethod = { table.insert(self.asserts, { key = 'assert ' .. tostring(self.count), passed = expected == actual, - message = 'expected \'' .. tostring(expected) .. '\' got \'' .. + message = 'expected \'' .. tostring(expected) .. '\' got \'' .. tostring(actual) .. '\'', test = label or 'no label given' }) @@ -81,7 +81,7 @@ TestMethod = { table.insert(self.asserts, { key = 'assert ' .. tostring(self.count), passed = value == true, - message = 'expected \'true\' got \'' .. + message = 'expected \'true\' got \'' .. tostring(value) .. '\'', test = label or 'no label given' }) @@ -98,7 +98,7 @@ TestMethod = { table.insert(self.asserts, { key = 'assert ' .. tostring(self.count), passed = value == false, - message = 'expected \'false\' got \'' .. + message = 'expected \'false\' got \'' .. tostring(value) .. '\'', test = label or 'no label given' }) @@ -123,38 +123,6 @@ TestMethod = { end, - -- @method - TestMethod:assertPixels() - -- @desc - checks a list of coloured pixels agaisnt given imgdata - -- @param {ImageData} imgdata - image data to check - -- @param {table} pixelchecks - map of colors to list of pixel coords, i.e. - -- { blue = { {1, 1}, {2, 2}, {3, 4} } } - -- @return {nil} - assertPixels = function(self, imgdata, pixelchecks, label) - for i, v in pairs(pixelchecks) do - local col = self.colors[i] - local pixels = v - for p=1,#pixels do - local coord = pixels[p] - local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2]) - local compare_id = tostring(coord[1]) .. ',' .. tostring(coord[2]) - -- prevent us getting stuff like 0.501960785 for 0.5 red - tr = math.floor((tr*10)+0.5)/10 - tg = math.floor((tg*10)+0.5)/10 - tb = math.floor((tb*10)+0.5)/10 - ta = math.floor((ta*10)+0.5)/10 - col[1] = math.floor((col[1]*10)+0.5)/10 - col[2] = math.floor((col[2]*10)+0.5)/10 - col[3] = math.floor((col[3]*10)+0.5)/10 - col[4] = math.floor((col[4]*10)+0.5)/10 - self:assertEquals(col[1], tr, 'check pixel r for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') - self:assertEquals(col[2], tg, 'check pixel g for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') - self:assertEquals(col[3], tb, 'check pixel b for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') - self:assertEquals(col[4], ta, 'check pixel a for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') - end - end - end, - - -- @method - TestMethod:assertRange() -- @desc - used to check a value is within an expected range -- @param {number} actual - actual value of the test @@ -197,7 +165,7 @@ TestMethod = { -- @method - TestMethod:assertGreaterEqual() - -- @desc - used to check a value is >= than a certain target value + -- @desc - used to check a value is >= than a certain target value -- @param {any} target - value to check the test agaisnt -- @param {any} actual - actual value of the test -- @param {string} label - label for this test to use in exports @@ -219,7 +187,7 @@ TestMethod = { -- @method - TestMethod:assertLessEqual() - -- @desc - used to check a value is <= than a certain target value + -- @desc - used to check a value is <= than a certain target value -- @param {any} target - value to check the test agaisnt -- @param {any} actual - actual value of the test -- @param {string} label - label for this test to use in exports @@ -241,7 +209,7 @@ TestMethod = { -- @method - TestMethod:assertObject() - -- @desc - used to check a table is a love object, this runs 3 seperate + -- @desc - used to check a table is a love object, this runs 3 seperate -- tests to check table has the basic properties of an object -- @note - actual object functionality tests have their own methods -- @param {table} obj - table to check is a valid love object @@ -270,7 +238,7 @@ TestMethod = { table.insert(self.asserts, { key = 'assert ' .. tostring(self.count), passed = passing, - message = 'expected \'' .. tostring(expected[1]) .. 'x,' .. + message = 'expected \'' .. tostring(expected[1]) .. 'x,' .. tostring(expected[2]) .. 'y\' got \'' .. tostring(actual[1]) .. 'x,' .. tostring(actual[2]) .. 'y\'', test = label or 'no label given' @@ -279,7 +247,7 @@ TestMethod = { -- @method - TestMethod:assertNotNil() - -- @desc - quick assert for value not nil + -- @desc - quick assert for value not nil -- @param {any} value - value to check not nil -- @return {nil} assertNotNil = function (self, value, err) @@ -296,34 +264,39 @@ TestMethod = { -- @method - TestMethod:compareImg() - -- @desc - compares a given image to the 'expected' version, with a tolerance of - -- 1px in any direction, and then saves it as the 'actual' version for + -- @desc - compares a given image to the 'expected' version, with a tolerance of + -- 1px in any direction, and then saves it as the 'actual' version for -- report viewing -- @param {table} imgdata - imgdata to save as a png -- @return {nil} compareImg = function(self, imgdata) - local expected = love.image.newImageData( - 'tempoutput/expected/love.test.graphics.' .. self.method .. '-' .. - tostring(self.imgs) .. '.png' - ) - local iw = imgdata:getWidth()-2 - local ih = imgdata:getHeight()-2 + local expected_path = 'tempoutput/expected/love.test.graphics.' .. + self.method .. '-' .. tostring(self.imgs) .. '.png' + local ok, chunk, _ = pcall(love.image.newImageData, expected_path) + if ok == false then return self:assertEquals(true, false, chunk) end + local expected = chunk + local iw = imgdata:getWidth()-1 + local ih = imgdata:getHeight()-1 + local differences = {} local rgba_tolerance = self.rgba_tolerance * (1/255) - for ix=2,iw do - for iy=2,ih do + + -- for each pixel, compare the expected vs the actual pixel data + -- by default rgba_tolerance is 0 + for ix=0,iw do + for iy=0,ih do local ir, ig, ib, ia = imgdata:getPixel(ix, iy) local points = { {expected:getPixel(ix, iy)} } if self.pixel_tolerance > 0 then - table.insert(points, {expected:getPixel(ix-1, iy+1)}) - table.insert(points, {expected:getPixel(ix-1, iy)}) - table.insert(points, {expected:getPixel(ix-1, iy-1)}) - table.insert(points, {expected:getPixel(ix, iy+1)}) - table.insert(points, {expected:getPixel(ix, iy-1)}) - table.insert(points, {expected:getPixel(ix+1, iy+1)}) - table.insert(points, {expected:getPixel(ix+1, iy)}) - table.insert(points, {expected:getPixel(ix+1, iy-1)}) + if ix > 0 and iy < ih-1 then table.insert(points, {expected:getPixel(ix-1, iy+1)}) end + if ix > 0 then table.insert(points, {expected:getPixel(ix-1, iy)}) end + if ix > 0 and iy > 0 then table.insert(points, {expected:getPixel(ix-1, iy-1)}) end + if iy < ih-1 then table.insert(points, {expected:getPixel(ix, iy+1)}) end + if iy > 0 then table.insert(points, {expected:getPixel(ix, iy-1)}) end + if ix < iw-1 and iy < ih-1 then table.insert(points, {expected:getPixel(ix+1, iy+1)}) end + if ix < iw-1 then table.insert(points, {expected:getPixel(ix+1, iy)}) end + if ix < iw-1 and iy > 0 then table.insert(points, {expected:getPixel(ix+1, iy-1)}) end end local has_match_r = false local has_match_g = false @@ -348,15 +321,57 @@ TestMethod = { tostring(ix) .. ',' .. tostring(iy) .. ', matching = ' .. ymatch .. ', not matching = ' .. nmatch .. ' (' .. self.method .. '-' .. tostring(self.imgs) .. ')' ) + -- add difference co-ord for rendering later + if matching ~= true then + table.insert(differences, ix+1) + table.insert(differences, iy+1) + end end end - local path = 'tempoutput/actual/love.test.graphics.' .. + local path = 'tempoutput/actual/love.test.graphics.' .. self.method .. '-' .. tostring(self.imgs) .. '.png' imgdata:encode('png', path) + + -- if we have differences draw them to a new canvas to display in HTML report + local dpath = 'tempoutput/difference/love.test.graphics.' .. + self.method .. '-' .. tostring(self.imgs) .. '.png' + if #differences > 0 then + local difference = love.graphics.newCanvas(iw+1, ih+1) + love.graphics.setCanvas(difference) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(1, 0, 1, 1) + love.graphics.points(differences) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setCanvas() + love.graphics.readbackTexture(difference):encode('png', dpath) + + -- otherwise clear the old difference file (if any) to stop it coming up + -- in future reports when there's no longer a difference + elseif love.filesystem.openFile(dpath, 'r') then + love.filesystem.remove(dpath) + end + self.imgs = self.imgs + 1 end, + -- @method - TestMethod:exportImg() + -- @desc - exports the given imgdata to the 'output/expected/' folder, to use when + -- writing new graphics tests to set the expected image output + -- @NOTE - you should not leave this method in when you are finished this is + -- for test writing only + -- @param {table} imgdata - imgdata to save as a png + -- @param {integer} imgdata - index of the png, graphic tests are run sequentially + -- and each test image is numbered in order that its + -- compared to, so set the number here to match + -- @return {nil} + exportImg = function(self, imgdata, index) + local path = 'tempoutput/expected/love.test.graphics.' .. + self.method .. '-' .. tostring(index) .. '.png' + imgdata:encode('png', path) + end, + + -- @method - TestMethod:skipTest() -- @desc - used to mark this test as skipped for a specific reason -- @param {string} reason - reason why method is being skipped @@ -367,11 +382,19 @@ TestMethod = { end, + -- @method - TestMethod:waitFrames() + -- @desc - yields the method for x amount of frames + -- @param {number} frames - no. frames to wait + -- @return {nil} waitFrames = function(self, frames) - for i=1,frames do coroutine.yield() end + for _=1,frames do coroutine.yield() end end, + -- @method - TestMethod:waitSeconds() + -- @desc - yields the method for x amount of seconds + -- @param {number} seconds - no. seconds to wait + -- @return {nil} waitSeconds = function(self, seconds) local start = love.timer.getTime() while love.timer.getTime() < start + seconds do @@ -380,73 +403,117 @@ TestMethod = { end, + -- @method - TestMethod:isOS() + -- @desc - checks for a specific OS (or list of OSs) + -- @param {string/s} - each arg passed will be checked as a valid OS, as long + -- as one passed the function will return true + -- @return {boolean} - returns true if one of the OSs given matches actual OS + isOS = function(self, ...) + for os=1,select("#", ...) do + if select(os, ...) == love.test.current_os then return true end + end + return false + end, + + -- @method - TestMethod:isLuaVersion() + -- @desc - checks for a specific Lua version (or list of versions) + -- @param {number} - the minimum Lua version to check against + -- @return {boolean} - returns true if the current Lua version is at least the given version + isAtLeastLuaVersion = function(self, version) + return love.test.lua_version >= version + end, + + -- @method - TestMethod:isLuaJITEnabled() + -- @desc - checks if LuaJIT is enabled + -- @return {boolean} - returns true if LuaJIT is enabled + isLuaJITEnabled = function(self) + return love.test.has_lua_jit + end, + -- @method - TestMethod:evaluateTest() -- @desc - evaluates the results of all assertions for a final restult -- @return {nil} evaluateTest = function(self) local failure = '' local failures = 0 + + -- check all asserts for failures, additional failures are also printed + local assert_failures = {} for a=1,#self.asserts do - -- @TODO show all failed assertion methods? - -- currently just shows the first assert that failed if not self.asserts[a].passed and not self.skipped then if failure == '' then failure = self.asserts[a] end + table.insert(assert_failures, self.asserts[a]) failures = failures + 1 end end if self.fatal ~= '' then failure = self.fatal end local passed = tostring(#self.asserts - failures) local total = '(' .. passed .. '/' .. tostring(#self.asserts) .. ')' + + -- skipped tests have a special log if self.skipped then self.testmodule.skipped = self.testmodule.skipped + 1 love.test.totals[3] = love.test.totals[3] + 1 - self.result = { - total = '', - result = "SKIP", - passed = false, - message = '(0/0) - method skipped [' .. self.skipreason .. ']' + self.result = { + total = '', + result = "SKIP", + passed = false, + message = '(0/0) - method skipped [' .. self.skipreason .. ']', + failures = {} } else + + -- if no failure but has asserts, then passed if failure == '' and #self.asserts > 0 then self.passed = true self.testmodule.passed = self.testmodule.passed + 1 love.test.totals[1] = love.test.totals[1] + 1 - self.result = { - total = total, - result = 'PASS', - passed = true, - message = nil + self.result = { + total = total, + result = 'PASS', + passed = true, + message = nil, + failures = {} } + + -- otherwise it failed else self.passed = false self.testmodule.failed = self.testmodule.failed + 1 love.test.totals[2] = love.test.totals[2] + 1 + + -- no asserts means invalid test if #self.asserts == 0 then local msg = 'no asserts defined' if self.fatal ~= '' then msg = self.fatal end - self.result = { - total = total, - result = 'FAIL', - passed = false, - key = 'test', - message = msg + self.result = { + total = total, + result = 'FAIL', + passed = false, + key = 'test', + message = msg, + failures = {} } + + -- otherwise we had failures, log the first and supply the list of + -- additional failures if any for printResult() else local key = failure['key'] if failure['test'] ~= nil then key = key .. ' [' .. failure['test'] .. ']' end local msg = failure['message'] - if self.fatal ~= '' then + if self.fatal ~= '' then key = 'code' msg = self.fatal end - self.result = { - total = total, - result = 'FAIL', - passed = false, + self.result = { + total = total, + result = 'FAIL', + passed = false, key = key, - message = msg + message = msg, + failures = assert_failures } end end @@ -494,25 +561,25 @@ TestMethod = { local preview = '' if self.testmodule.module == 'graphics' then local filename = 'love.test.graphics.' .. self.method - if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-1.png', 'r') then - preview = '
' .. '

Expected

' .. - '
' .. '

Actual

' - end - if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-2.png', 'r') then - preview = preview .. '
' .. '

Expected

' .. - '
' .. '

Actual

' - end - if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-3.png', 'r') then - preview = preview .. '
' .. '

Expected

' .. - '
' .. '

Actual

' + for f=1,5 do + local fstr = tostring(f) + if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-' .. fstr .. '.png', 'r') then + preview = preview .. '
' + preview = preview .. '
' .. '

Expected

' .. + '
' .. '

Actual

' + if love.filesystem.openFile('tempoutput/difference/' .. filename .. '-' .. fstr .. '.png', 'r') then + preview = preview .. '
' .. '

Difference

' + end + preview = preview .. '
' + end end end - -- append HTML for the test class result - local status = '🔴' + -- append HTML for the test class result + local status = '' local cls = 'red' - if self.passed then status = '🟢'; cls = '' end - if self.skipped then status = '🟡'; cls = '' end + if self.passed then status = '
'; cls = 'green' end + if self.skipped then status = ''; cls = 'yellow' end self.testmodule.html = self.testmodule.html .. '' .. '' .. status .. '' .. @@ -541,6 +608,21 @@ TestMethod = { ' ==> ' .. self.result.result .. ' - ' .. endtime .. 's ' .. self.result.total .. msg ) + + -- if we failed on multiple asserts, list them here - makes it easier for + -- debugging new methods added that are failing multiple asserts + if #self.result.failures > 1 then + for f=2,#self.result.failures do + local addf = self.result.failures[f] + self.testmodule:log( + self.testmodule.colors[self.result.result], + ' ' .. tested .. matching, + ' ==> ' .. + addf['key'] .. ' [' .. addf['test'] .. '] failed - ' .. addf['message'] + ) + end + end + end diff --git a/testing/classes/TestModule.lua b/testing/classes/TestModule.lua index f66d247ed..e4a446116 100644 --- a/testing/classes/TestModule.lua +++ b/testing/classes/TestModule.lua @@ -82,8 +82,8 @@ TestModule = { -- @return {nil} printResult = function(self) local finaltime = UtilTimeFormat(self.time) - local status = '🔴' - if self.failed == 0 then status = '🟢' end + local status = '
' + if self.failed == 0 then status = '
' end -- add md row to main output love.test.mdrows = love.test.mdrows .. '| ' .. status .. ' ' .. self.module .. @@ -98,13 +98,23 @@ TestModule = { '" skipped="' .. tostring(self.skipped) .. '" time="' .. finaltime .. '">\n' .. self.xml .. '\t\n' -- add html to main output - love.test.html = love.test.html .. '

' .. status .. ' love.' .. self.module .. '

    ' .. - '
  • 🟢 ' .. tostring(self.passed) .. ' Tests
  • ' .. - '
  • 🔴 ' .. tostring(self.failed) .. ' Failures
  • ' .. - '
  • 🟡 ' .. tostring(self.skipped) .. ' Skipped
  • ' .. - '
  • ' .. finaltime .. 's
  • ' .. '


      ' .. + local module_cls = 'toggle close' + local module_txt = '▶' + local wrap_cls = '' + if self.failed > 0 then + module_cls = 'toggle open' + module_txt = '▼' + wrap_cls = 'fail' + end + love.test.html = love.test.html .. '
      ' .. + '
      ' .. module_txt .. '
      ' .. + '

      ' .. status .. ' love.' .. self.module .. '

        ' .. + '
      • ' .. tostring(self.passed) .. ' Passed
      • ' .. + '
      • ' .. tostring(self.failed) .. ' Failed
      • ' .. + '
      • ' .. tostring(self.skipped) .. ' Skipped
      • ' .. + '
      • ' .. finaltime .. 's
      • ' .. '


      ' .. '' .. - self.html .. '
      MethodTimeDetails
      ' + self.html .. '
      ' -- print module results to console self:log('yellow', 'love.' .. self.module .. '.testmodule.end') local failedcol = '\27[31m' diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 8a2e76dee..8a4d7c777 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -23,6 +23,9 @@ TestSuite = { delayed = nil, fakequit = false, windowmode = true, + current_os = love._os, + lua_version = tonumber(_VERSION:match("%d%.%d")), + has_lua_jit = type(jit) == 'table', -- love modules to test audio = {}, @@ -76,7 +79,10 @@ TestSuite = { TextRun = 'love.' .. self.module.module .. '.' .. method self.test.co = coroutine.create(function() - local ok, chunk, err = pcall(love.test[love.test.module.module][method], love.test.test) + local ok, chunk, err = pcall( + love.test[love.test.module.module][method], + love.test.test + ) if ok == false then love.test.test['passed'] = false love.test.test['fatal'] = tostring(chunk) .. tostring(err) @@ -94,7 +100,7 @@ TestSuite = { -- when wait finished (or no yields) if coroutine.status(self.test.co) == 'dead' then - -- now we're all done evaluate the test + -- now we're all done evaluate the test local ok, chunk, err = pcall(self.test.evaluateTest, self.test) if ok == false then self.test.passed = false @@ -125,7 +131,7 @@ TestSuite = { self:printResult() love.event.quit(0) end - + end end end @@ -140,8 +146,15 @@ TestSuite = { printResult = function(self) local finaltime = UtilTimeFormat(self.time) - local name, version, vendor, device = love.graphics.getRendererInfo() - + -- in case we dont have love.graphics loaded, for future module specific disabling + local name = 'NONE' + local version = 'NONE' + local vendor = 'NONE' + local device = 'NONE' + if love.graphics then + name, version, vendor, device = love.graphics.getRendererInfo() + end + local md = ' + ### Info -**344** tests were completed in **14.817s** with **335** passed, **0** failed, and **9** skipped +**355** tests were completed in **14.567s** with **343** passed, **2** failed, and **10** skipped Renderer: OpenGL | 4.1 Metal - 76.3 | Apple | Apple M1 Max ### Report | Module | Pass | Fail | Skip | Time | | --------------------- | ------ | ------ | ------- | ------ | -| 🟢 audio | 28 | 0 | 0 | 0.886s | -| 🟢 data | 12 | 0 | 0 | 0.212s | -| 🟢 event | 4 | 0 | 2 | 0.103s | -| 🟢 filesystem | 29 | 0 | 2 | 0.555s | -| 🟢 font | 7 | 0 | 0 | 0.124s | -| 🟢 graphics | 104 | 0 | 1 | 3.006s | -| 🟢 image | 5 | 0 | 0 | 0.085s | -| 🟢 joystick | 6 | 0 | 0 | 0.106s | -| 🟢 keyboard | 9 | 0 | 0 | 0.150s | -| 🟢 love | 6 | 0 | 0 | 0.098s | -| 🟢 math | 20 | 0 | 0 | 0.337s | -| 🟢 mouse | 18 | 0 | 0 | 0.302s | -| 🟢 physics | 26 | 0 | 0 | 0.434s | -| 🟢 sensor | 1 | 0 | 0 | 0.016s | -| 🟢 sound | 4 | 0 | 0 | 0.072s | -| 🟢 system | 6 | 0 | 2 | 0.135s | -| 🟢 thread | 5 | 0 | 0 | 0.363s | -| 🟢 timer | 6 | 0 | 0 | 2.074s | -| 🟢 touch | 3 | 0 | 0 | 0.023s | -| 🟢 video | 2 | 0 | 0 | 0.039s | -| 🟢 window | 34 | 0 | 2 | 5.696s | +| 🟢 audio | 31 | 0 | 0 | 1.328s | +| 🟢 data | 12 | 0 | 0 | 0.197s | +| 🟢 event | 4 | 0 | 2 | 0.100s | +| 🟢 filesystem | 33 | 0 | 2 | 0.601s | +| 🟢 font | 7 | 0 | 0 | 0.116s | +| 🔴 graphics | 104 | 1 | 2 | 3.463s | +| 🟢 image | 5 | 0 | 0 | 0.093s | +| 🟢 joystick | 6 | 0 | 0 | 0.116s | +| 🟢 keyboard | 10 | 0 | 0 | 0.170s | +| 🟢 love | 6 | 0 | 0 | 0.100s | +| 🟢 math | 20 | 0 | 0 | 0.334s | +| 🔴 mouse | 17 | 1 | 0 | 0.301s | +| 🟢 physics | 26 | 0 | 0 | 0.435s | +| 🟢 sensor | 1 | 0 | 0 | 0.017s | +| 🟢 sound | 4 | 0 | 0 | 0.075s | +| 🟢 system | 7 | 0 | 2 | 0.150s | +| 🟢 thread | 5 | 0 | 0 | 0.306s | +| 🟢 timer | 6 | 0 | 0 | 0.298s | +| 🟢 touch | 3 | 0 | 0 | 0.051s | +| 🟢 video | 2 | 0 | 0 | 0.038s | +| 🟢 window | 34 | 0 | 2 | 6.275s | ### Failures +> 🔴 Shader +> assert 4 [check shader valid] expected '' got 'vertex shader: +pixel shader: +' + +> 🔴 setGrabbed +> assert 2 [check now grabbed] expected 'true' got 'false' + diff --git a/testing/examples/lovetest_runAllTests.xml b/testing/examples/lovetest_runAllTests.xml index f6bf47390..888feca6c 100644 --- a/testing/examples/lovetest_runAllTests.xml +++ b/testing/examples/lovetest_runAllTests.xml @@ -1,137 +1,145 @@ - - - + + + - + - + - + - + - + - + - + - + - + - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + @@ -139,187 +147,203 @@ - + - + - + - + - + + + + + - + - + - + - + - + - + + + - - + + - + - + - + - + - - + + - + - + + + - + - + - + + assert 4 [check shader valid] expected '' got 'vertex shader: +pixel shader: +' - + + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -327,345 +351,352 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + + + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + + assert 2 [check now grabbed] expected 'true' got 'false' - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - - + + - + - + + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + + + - + @@ -675,67 +706,65 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + \ No newline at end of file diff --git a/testing/main.lua b/testing/main.lua index 6c7b26165..f3a78ea99 100644 --- a/testing/main.lua +++ b/testing/main.lua @@ -41,6 +41,8 @@ love.load = function(args) resizable = true, centered = true }) + + -- set up some graphics to draw if enabled if love.graphics ~= nil then love.graphics.setDefaultFilter("nearest", "nearest") love.graphics.setLineStyle('rough') @@ -54,6 +56,7 @@ love.load = function(args) TextCommand = 'Loading...' TextRun = '' end + end -- mount for output later @@ -71,7 +74,7 @@ love.load = function(args) end -- convert args to the cmd to run, modules, method (if any) and disabled - local testcmd = '--runAllTests' + local testcmd = '--all' local module = '' local method = '' local cmderr = 'Invalid flag used' @@ -82,7 +85,7 @@ love.load = function(args) } GITHUB_RUNNER = false for a=1,#arglist do - if testcmd == '--runSpecificMethod' then + if testcmd == '--method' then if module == '' and (arglist[a] == 'love' or love[ arglist[a] ] ~= nil) then module = arglist[a] table.insert(modules, module) @@ -90,16 +93,16 @@ love.load = function(args) if love.test[module][arglist[a]] ~= nil then method = arglist[a] end end end - if testcmd == '--runSpecificModules' then + if testcmd == '--modules' then if (arglist[a] == 'love' or love[ arglist[a] ] ~= nil) and arglist[a] ~= '--isRunner' then table.insert(modules, arglist[a]) end end - if arglist[a] == '--runSpecificMethod' then + if arglist[a] == '--method' then testcmd = arglist[a] modules = {} end - if arglist[a] == '--runSpecificModules' then + if arglist[a] == '--modules' then testcmd = arglist[a] modules = {} end @@ -108,22 +111,22 @@ love.load = function(args) end end - -- runSpecificMethod uses the module + method given - if testcmd == '--runSpecificMethod' then + -- method uses the module + method given + if testcmd == '--method' then local testmodule = TestModule:new(module, method) table.insert(love.test.modules, testmodule) if module ~= '' and method ~= '' then love.test.module = testmodule - love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"') - love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method + love.test.module:log('grey', '--method "' .. module .. '" "' .. method .. '"') + love.test.output = 'lovetest_method_' .. module .. '_' .. method else if method == '' then cmderr = 'No valid method specified' end if module == '' then cmderr = 'No valid module specified' end end end - -- runSpecificModules runs all methods for all the modules given - if testcmd == '--runSpecificModules' then + -- modules runs all methods for all the modules given + if testcmd == '--modules' then local modulelist = {} for m=1,#modules do local testmodule = TestModule:new(modules[m]) @@ -132,22 +135,22 @@ love.load = function(args) end if #modulelist > 0 then love.test.module = love.test.modules[1] - love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"') - love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_') + love.test.module:log('grey', '--modules "' .. table.concat(modulelist, '" "') .. '"') + love.test.output = 'lovetest_modules_' .. table.concat(modulelist, '_') else cmderr = 'No modules specified' end end -- otherwise default runs all methods for all modules - if arglist[1] == nil or arglist[1] == '' or arglist[1] == '--runAllTests' then + if arglist[1] == nil or arglist[1] == '' or arglist[1] == '--all' then for m=1,#modules do local testmodule = TestModule:new(modules[m]) table.insert(love.test.modules, testmodule) end love.test.module = love.test.modules[1] - love.test.module:log('grey', '--runAllTests') - love.test.output = 'lovetest_runAllTests' + love.test.module:log('grey', '--all') + love.test.output = 'lovetest_all' end if GITHUB_RUNNER then diff --git a/testing/output/difference/notes.txt b/testing/output/difference/notes.txt new file mode 100644 index 000000000..ac3589e55 --- /dev/null +++ b/testing/output/difference/notes.txt @@ -0,0 +1,3 @@ +# Graphic Differences +If a graphics test fails then a "difference" image will be created to highlight +the differences between the actual + expected image, for use in the HTML report \ No newline at end of file diff --git a/testing/output/expected/love.test.graphics.Canvas-3.png b/testing/output/expected/love.test.graphics.Canvas-3.png new file mode 100644 index 000000000..15a5cf8e3 Binary files /dev/null and b/testing/output/expected/love.test.graphics.Canvas-3.png differ diff --git a/testing/output/expected/love.test.graphics.Canvas-4.png b/testing/output/expected/love.test.graphics.Canvas-4.png new file mode 100644 index 000000000..9dbe75c20 Binary files /dev/null and b/testing/output/expected/love.test.graphics.Canvas-4.png differ diff --git a/testing/output/expected/love.test.graphics.captureScreenshot-1.png b/testing/output/expected/love.test.graphics.captureScreenshot-1.png new file mode 100644 index 000000000..f26a3a081 Binary files /dev/null and b/testing/output/expected/love.test.graphics.captureScreenshot-1.png differ diff --git a/testing/output/expected/love.test.graphics.scale-1.png b/testing/output/expected/love.test.graphics.scale-1.png new file mode 100644 index 000000000..a97348e50 Binary files /dev/null and b/testing/output/expected/love.test.graphics.scale-1.png differ diff --git a/testing/output/expected/love.test.graphics.setFrontFaceWinding-1.png b/testing/output/expected/love.test.graphics.setFrontFaceWinding-1.png new file mode 100644 index 000000000..acc6f6932 Binary files /dev/null and b/testing/output/expected/love.test.graphics.setFrontFaceWinding-1.png differ diff --git a/testing/readme.md b/testing/readme.md index 9cd0cc254..1e322d2ca 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -25,15 +25,15 @@ This is the status of all module tests. See the **Todo** section for outstanding tasks if you want to contribute! | Module | Done | Skip | Modules | Done | Skip | | ----------------- | ---- | ---- | ---------------- | ---- | ---- | -| 🟢 audio | 28 | 0 | 🟢 mouse | 18 | 0 | +| 🟢 audio | 31 | 0 | 🟢 mouse | 18 | 0 | | 🟢 data | 12 | 0 | 🟢 physics | 26 | 0 | | 🟢 event | 4 | 2 | 🟢 sensor | 1 | 0 | -| 🟢 filesystem | 29 | 2 | 🟢 sound | 4 | 0 | -| 🟢 font | 7 | 0 | 🟢 system | 6 | 2 | -| 🟢 graphics | 104 | 1 | 🟢 thread | 5 | 0 | +| 🟢 filesystem | 33 | 2 | 🟢 sound | 4 | 0 | +| 🟢 font | 7 | 0 | 🟢 system | 7 | 2 | +| 🟢 graphics | 105 | 1 | 🟢 thread | 5 | 0 | | 🟢 image | 5 | 0 | 🟢 timer | 6 | 0 | | 🟢 joystick | 6 | 0 | 🟢 touch | 3 | 0 | -| 🟢 keyboard | 9 | 0 | 🟢 video | 2 | 0 | +| 🟢 keyboard | 10 | 0 | 🟢 video | 2 | 0 | | 🟢 love | 6 | 0 | 🟢 window | 34 | 2 | | 🟢 math | 20 | 0 | @@ -52,9 +52,9 @@ LINUX: `./love.AppImage PATH_TO_TESTING_FOLDER/main.lua` By default all tests will be run for all modules. If you want to specify a module/s you can use: -`--runSpecificModules filesystem,audio` +`--modules filesystem,audio` If you want to specify only 1 specific method only you can use: -`--runSpecificMethod filesystem write` +`--method filesystem write` All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level. @@ -82,7 +82,6 @@ Each module has a TestModule object created, and each test method has a TestMeth - **assertGreaterEqual**(expected, actual, label) - **assertLessEqual**(expected, actual, label) - **assertObject**(table) -- **assertPixels**(imgdata, pixeltable, label) - **assertCoords**(expected, actual, label) Example test method: @@ -103,7 +102,7 @@ love.test.filesystem.read = function(test) end ``` -Each test is run inside it's own coroutine - you can use `test:waitFrames(frames)` to pause the test for a small period if you need to check things that won't happen for a few seconds. +Each test is run inside it's own coroutine - you can use `test:waitFrames(frames)` or `test:waitSeconds(seconds)` to pause the test for a small period if you need to check things that won't happen for a few frames/seconds. After each test method is ran, the assertions are totalled up, printed, and we move onto the next method! Once all methods in the suite are run a total pass/fail/skip is given for that module and we move onto the next module (if any) @@ -114,14 +113,7 @@ For sanity-checking, if it's currently not covered or it's not possible to test ## Todo If you would like to contribute to the test suite please raise a PR with the main [love-test](https://github.com/ellraiser/love-test) repo. -The following items are all the things still outstanding, expanding on any existing tests is also very welcome! -- [ ] check for any 12.0 methods in the changelog not yet covered in the test suite -- [ ] add BMfont alt. tests for font class tests (Rasterizer + GlyphData) -- [ ] graphics.isCompressed() should have an example of all compressed files -- [ ] graphics.Mesh should have some graphical tests ideally to check vertex settings w/ shaders -- [ ] ability to test loading different combinations of modules if needed -- [ ] more scenario based tests similar to some of the obj class tests -- [ ] performance tests? need to discuss what + how +There is a list of outstanding methods that require test coverage in `todo.md`, expanding on any existing tests is also very welcome! --- @@ -141,10 +133,9 @@ The automated tests through Github work for the most part however there are a fe These exceptions are either skipped, or handled by using a 1px or 1/255rgba tolerance - when run locally on real hardware, these tests pass fine at the default 0 tolerance. You can specify the test suite is being run on a runner by adding the `--isRunner` flag in your workflow file, i.e.: -`& 'c:\Program Files\LOVE\love.exe' PATH_TO_TESTING_FOLDER/main.lua --console --runAllTests --isRunner` +`& 'c:\Program Files\LOVE\love.exe' PATH_TO_TESTING_FOLDER/main.lua --console --all --isRunner` | Test | OS | Exception | Reason | | -------------------------- | --------- | ------------------- | ------ | -| love.graphics.points | MacOS | 1px tolerance | Points are offset by 1,1 when drawn | | love.graphics.setWireframe | MacOS | 1px tolerance | Wireframes are offset by 1,1 when drawn | | love.graphica.arc | MacOS | Skipped | Arc curves are drawn slightly off at really low scale | | love.graphics.setLineStyle | Linux | 1rgba tolerance | 'Rough' lines blend differently with the background rgba | diff --git a/testing/resources/pop.ogg b/testing/resources/pop.ogg new file mode 100644 index 000000000..fb0a82a7b Binary files /dev/null and b/testing/resources/pop.ogg differ diff --git a/testing/resources/tone.ogg b/testing/resources/tone.ogg new file mode 100644 index 000000000..1e7156e47 Binary files /dev/null and b/testing/resources/tone.ogg differ diff --git a/testing/tests/audio.lua b/testing/tests/audio.lua index 39133ab91..d1b36c24f 100644 --- a/testing/tests/audio.lua +++ b/testing/tests/audio.lua @@ -299,6 +299,20 @@ love.test.audio.getOrientation = function(test) end +-- love.audio.getPlaybackDevice +love.test.audio.getPlaybackDevice = function(test) + test:assertNotNil(love.audio.getPlaybackDevice) + test:assertNotNil(love.audio.getPlaybackDevice()) +end + + +-- love.audio.getPlaybackDevices +love.test.audio.getPlaybackDevices = function(test) + test:assertNotNil(love.audio.getPlaybackDevices) + test:assertGreaterEqual(0, #love.audio.getPlaybackDevices(), 'check table') +end + + -- love.audio.getPosition -- @NOTE is there an expected default listener pos? love.test.audio.getPosition = function(test) @@ -442,6 +456,52 @@ love.test.audio.setOrientation = function(test) end +-- love.audio.setPlaybackDevice +love.test.audio.setPlaybackDevice = function(test) + -- check method + test:assertNotNil(love.audio.setPlaybackDevice) + -- check blank string name + local success1, msg1 = love.audio.setPlaybackDevice('') + -- check invalid name + local success2, msg2 = love.audio.setPlaybackDevice('loveFM') + -- check setting already set + local success3, msg3 = love.audio.setPlaybackDevice(love.audio.getPlaybackDevice()) -- current name + -- rn on macos all 3 return false + -- whereas linux/windows return true for blank/current, which is expected + -- as openalsoft treats blank as current + if test:isOS('OS X') then + test:assertFalse(success1, 'check blank device fails') + test:assertFalse(success2, 'check invalid device fails') + test:assertFalse(success3, 'check existing device fails') + else + test:assertTrue(success1, 'check blank device is fine') + test:assertFalse(success2, 'check invalid device fails') + test:assertTrue(success3, 'check existing device is fine') + end + -- if other devices to play with lets set a different one + local devices = love.audio.getPlaybackDevices() + if #devices > 1 then + local another = '' + local current = love.audio.getPlaybackDevice() + for a=1,#devices do + if devices[a] ~= current then + another = devices[a] + break + end + end + if another ~= '' then + -- check setting new device + local success4, msg4 = love.audio.setPlaybackDevice(another) + test:assertTrue(success4, 'check setting different device') + -- check resetting to default + local success5, msg5 = love.audio.setPlaybackDevice() + test:assertTrue(success5, 'check resetting') + test:assertEquals(current, love.audio.getPlaybackDevice()) + end + end +end + + -- love.audio.setPosition love.test.audio.setPosition = function(test) -- check setting position vals are returned diff --git a/testing/tests/data.lua b/testing/tests/data.lua index 0e21a7713..073ca63fa 100644 --- a/testing/tests/data.lua +++ b/testing/tests/data.lua @@ -33,6 +33,10 @@ love.test.data.ByteData = function(test) test:assertEquals('o', byte5) end + -- check overwriting the byte data string + data:setString('love!', 5) + test:assertEquals('hellolove!', data:getString(), 'check change string') + end @@ -79,6 +83,10 @@ love.test.data.compress = function(test) { love.data.compress('string', 'gzip', 'helloworld', -1), 'string'}, { love.data.compress('string', 'gzip', 'helloworld', 0), 'string'}, { love.data.compress('string', 'gzip', 'helloworld', 9), 'string'}, + { love.data.compress('string', 'deflate', 'aaaaaa', 1), 'string'}, + { love.data.compress('string', 'deflate', 'heloworld', -1), 'string'}, + { love.data.compress('string', 'deflate', 'heloworld', 0), 'string'}, + { love.data.compress('string', 'deflate', 'heloworld', 9), 'string'}, { love.data.compress('data', 'lz4', 'helloworld', -1), 'userdata'}, { love.data.compress('data', 'lz4', 'helloworld', 0), 'userdata'}, { love.data.compress('data', 'lz4', 'helloworld', 9), 'userdata'}, @@ -87,7 +95,10 @@ love.test.data.compress = function(test) { love.data.compress('data', 'zlib', 'helloworld', 9), 'userdata'}, { love.data.compress('data', 'gzip', 'helloworld', -1), 'userdata'}, { love.data.compress('data', 'gzip', 'helloworld', 0), 'userdata'}, - { love.data.compress('data', 'gzip', 'helloworld', 9), 'userdata'} + { love.data.compress('data', 'gzip', 'helloworld', 9), 'userdata'}, + { love.data.compress('data', 'deflate', 'heloworld', -1), 'userdata'}, + { love.data.compress('data', 'deflate', 'heloworld', 0), 'userdata'}, + { love.data.compress('data', 'deflate', 'heloworld', 9), 'userdata'}, } for c=1,#compressions do test:assertNotNil(compressions[c][1]) @@ -196,19 +207,33 @@ end -- love.data.hash love.test.data.hash = function(test) -- setup all the different hashing types - local str1 = love.data.hash('md5', 'helloworld') - local str2 = love.data.hash('sha1', 'helloworld') - local str3 = love.data.hash('sha224', 'helloworld') - local str4 = love.data.hash('sha256', 'helloworld') - local str5 = love.data.hash('sha384', 'helloworld') - local str6 = love.data.hash('sha512', 'helloworld') + local str1 = love.data.hash('string', 'md5', 'helloworld') + local str2 = love.data.hash('string', 'sha1', 'helloworld') + local str3 = love.data.hash('string', 'sha224', 'helloworld') + local str4 = love.data.hash('string', 'sha256', 'helloworld') + local str5 = love.data.hash('string', 'sha384', 'helloworld') + local str6 = love.data.hash('string', 'sha512', 'helloworld') + local data1 = love.data.hash('data', 'md5', 'helloworld') + local data2 = love.data.hash('data', 'sha1', 'helloworld') + local data3 = love.data.hash('data', 'sha224', 'helloworld') + local data4 = love.data.hash('data', 'sha256', 'helloworld') + local data5 = love.data.hash('data', 'sha384', 'helloworld') + local data6 = love.data.hash('data', 'sha512', 'helloworld') -- check encoded hash value matches what's expected for that algo - test:assertEquals('fc5e038d38a57032085441e7fe7010b0', love.data.encode("string", "hex", str1), 'check md5 encode') - test:assertEquals('6adfb183a4a2c94a2f92dab5ade762a47889a5a1', love.data.encode("string", "hex", str2), 'check sha1 encode') - test:assertEquals('b033d770602994efa135c5248af300d81567ad5b59cec4bccbf15bcc', love.data.encode("string", "hex", str3), 'check sha224 encode') - test:assertEquals('936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af', love.data.encode("string", "hex", str4), 'check sha256 encode') - test:assertEquals('97982a5b1414b9078103a1c008c4e3526c27b41cdbcf80790560a40f2a9bf2ed4427ab1428789915ed4b3dc07c454bd9', love.data.encode("string", "hex", str5), 'check sha384 encode') - test:assertEquals('1594244d52f2d8c12b142bb61f47bc2eaf503d6d9ca8480cae9fcf112f66e4967dc5e8fa98285e36db8af1b8ffa8b84cb15e0fbcf836c3deb803c13f37659a60', love.data.encode("string", "hex", str6), 'check sha512 encode') + -- test container string + test:assertEquals('fc5e038d38a57032085441e7fe7010b0', love.data.encode("string", "hex", str1), 'check string md5 encode') + test:assertEquals('6adfb183a4a2c94a2f92dab5ade762a47889a5a1', love.data.encode("string", "hex", str2), 'check string sha1 encode') + test:assertEquals('b033d770602994efa135c5248af300d81567ad5b59cec4bccbf15bcc', love.data.encode("string", "hex", str3), 'check string sha224 encode') + test:assertEquals('936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af', love.data.encode("string", "hex", str4), 'check string sha256 encode') + test:assertEquals('97982a5b1414b9078103a1c008c4e3526c27b41cdbcf80790560a40f2a9bf2ed4427ab1428789915ed4b3dc07c454bd9', love.data.encode("string", "hex", str5), 'check string sha384 encode') + test:assertEquals('1594244d52f2d8c12b142bb61f47bc2eaf503d6d9ca8480cae9fcf112f66e4967dc5e8fa98285e36db8af1b8ffa8b84cb15e0fbcf836c3deb803c13f37659a60', love.data.encode("string", "hex", str6), 'check string sha512 encode') + -- test container data + test:assertEquals('fc5e038d38a57032085441e7fe7010b0', love.data.encode("string", "hex", data1), 'check data md5 encode') + test:assertEquals('6adfb183a4a2c94a2f92dab5ade762a47889a5a1', love.data.encode("string", "hex", data2), 'check data sha1 encode') + test:assertEquals('b033d770602994efa135c5248af300d81567ad5b59cec4bccbf15bcc', love.data.encode("string", "hex", data3), 'check data sha224 encode') + test:assertEquals('936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af', love.data.encode("string", "hex", data4), 'check data sha256 encode') + test:assertEquals('97982a5b1414b9078103a1c008c4e3526c27b41cdbcf80790560a40f2a9bf2ed4427ab1428789915ed4b3dc07c454bd9', love.data.encode("string", "hex", data5), 'check data sha384 encode') + test:assertEquals('1594244d52f2d8c12b142bb61f47bc2eaf503d6d9ca8480cae9fcf112f66e4967dc5e8fa98285e36db8af1b8ffa8b84cb15e0fbcf836c3deb803c13f37659a60', love.data.encode("string", "hex", data6), 'check data sha512 encode') end diff --git a/testing/tests/filesystem.lua b/testing/tests/filesystem.lua index 55e112553..1b8948a27 100644 --- a/testing/tests/filesystem.lua +++ b/testing/tests/filesystem.lua @@ -137,7 +137,7 @@ end -- love.filesystem.createDirectory love.test.filesystem.createDirectory = function(test) - -- try creating a dir + subdir and check both exist + -- try creating a dir + subdir and check both exist local success = love.filesystem.createDirectory('foo/bar') test:assertNotEquals(false, success, 'check success') test:assertNotEquals(nil, love.filesystem.getInfo('foo', 'directory'), 'check directory created') @@ -187,6 +187,27 @@ love.test.filesystem.getDirectoryItems = function(test) end +-- love.filesystem.getFullCommonPath +love.test.filesystem.getFullCommonPath = function(test) + -- check standard paths + local appsavedir = love.filesystem.getFullCommonPath('appsavedir') + local appdocuments = love.filesystem.getFullCommonPath('appdocuments') + local userhome = love.filesystem.getFullCommonPath('userhome') + local userappdata = love.filesystem.getFullCommonPath('userappdata') + local userdesktop = love.filesystem.getFullCommonPath('userdesktop') + local userdocuments = love.filesystem.getFullCommonPath('userdocuments') + test:assertNotNil(appsavedir) + test:assertNotNil(appdocuments) + test:assertNotNil(userhome) + test:assertNotNil(userappdata) + test:assertNotNil(userdesktop) + test:assertNotNil(userdocuments) + -- check invalid path + local ok = pcall(love.filesystem.getFullCommonPath, 'fakepath') + test:assertFalse(ok, 'check invalid common path') +end + + -- love.filesystem.getIdentity love.test.filesystem.getIdentity = function(test) -- check setting identity matches @@ -204,7 +225,7 @@ love.test.filesystem.getRealDirectory = function(test) love.filesystem.createDirectory('foo') love.filesystem.write('foo/test.txt', 'test') -- check save dir matches the real dir we just wrote to - test:assertEquals(love.filesystem.getSaveDirectory(), + test:assertEquals(love.filesystem.getSaveDirectory(), love.filesystem.getRealDirectory('foo/test.txt'), 'check directory matches') -- cleanup love.filesystem.remove('foo/test.txt') @@ -263,6 +284,7 @@ love.test.filesystem.getInfo = function(test) test:assertEquals(nil, love.filesystem.getInfo('foo/bar/file2.txt', 'directory'), 'check not directory') test:assertNotEquals(nil, love.filesystem.getInfo('foo/bar/file2.txt'), 'check info not nil') test:assertEquals(love.filesystem.getInfo('foo/bar/file2.txt').size, 5, 'check info size match') + test:assertFalse(love.filesystem.getInfo('foo/bar/file2.txt').readonly, 'check readonly') -- @TODO test modified timestamp from info.modtime? -- cleanup love.filesystem.remove('foo/bar/file2.txt') @@ -299,13 +321,28 @@ love.test.filesystem.load = function(test) -- setup some fake lua files love.filesystem.write('test1.lua', 'function test()\nreturn 1\nend\nreturn test()') love.filesystem.write('test2.lua', 'function test()\nreturn 1') - -- check file that doesn't exist - local chunk, errormsg = love.filesystem.load('faker.lua') - test:assertEquals(nil, chunk, 'check file doesnt exist') - -- check valid lua file - chunk, errormsg = love.filesystem.load('test1.lua') - test:assertEquals(nil, errormsg, 'check no error message') - test:assertEquals(1, chunk(), 'check lua file runs') + + if test:isAtLeastLuaVersion(5.2) or test:isLuaJITEnabled() then + -- check file that doesn't exist + local chunk1, errormsg1 = love.filesystem.load('faker.lua', 'b') + test:assertEquals(nil, chunk1, 'check file doesnt exist') + -- check valid lua file (text load) + local chunk2, errormsg2 = love.filesystem.load('test1.lua', 't') + test:assertEquals(nil, errormsg2, 'check no error message') + test:assertEquals(1, chunk2(), 'check lua file runs') + else + local _, errormsg3 = love.filesystem.load('test1.lua', 'b') + test:assertNotEquals(nil, errormsg3, 'check for an error message') + + local _, errormsg4 = love.filesystem.load('test1.lua', 't') + test:assertNotEquals(nil, errormsg4, 'check for an error message') + end + + -- check valid lua file (any load) + local chunk5, errormsg5 = love.filesystem.load('test1.lua', 'bt') + test:assertEquals(nil, errormsg5, 'check no error message') + test:assertEquals(1, chunk5(), 'check lua file runs') + -- check invalid lua file local ok, chunk, err = pcall(love.filesystem.load, 'test2.lua') test:assertFalse(ok, 'check invalid lua file') @@ -334,6 +371,88 @@ love.test.filesystem.mount = function(test) end +-- love.filesystem.mountFullPath +love.test.filesystem.mountFullPath = function(test) + -- mount something in the working directory + local mount = love.filesystem.mountFullPath(love.filesystem.getSource() .. '/tests', 'tests', 'read') + test:assertTrue(mount, 'check can mount') + -- check reading file through mounted path label + local contents, _ = love.filesystem.read('tests/audio.lua') + test:assertNotEquals(nil, contents) + local unmount = love.filesystem.unmountFullPath(love.filesystem.getSource() .. '/tests') + test:assertTrue(unmount, 'reset mount') +end + + +-- love.filesystem.unmountFullPath +love.test.filesystem.unmountFullPath = function(test) + -- try unmounting something we never mounted + local unmount1 = love.filesystem.unmountFullPath(love.filesystem.getSource() .. '/faker') + test:assertFalse(unmount1, 'check not mounted to start with') + -- mount something to unmount after + love.filesystem.mountFullPath(love.filesystem.getSource() .. '/tests', 'tests', 'read') + local unmount2 = love.filesystem.unmountFullPath(love.filesystem.getSource() .. '/tests') + test:assertTrue(unmount2, 'check unmounted') +end + + +-- love.filesystem.mountCommonPath +love.test.filesystem.mountCommonPath = function(test) + -- check if we can mount all the expected paths + local mount1 = love.filesystem.mountCommonPath('appsavedir', 'appsavedir', 'readwrite') + local mount2 = love.filesystem.mountCommonPath('appdocuments', 'appdocuments', 'readwrite') + local mount3 = love.filesystem.mountCommonPath('userhome', 'userhome', 'readwrite') + local mount4 = love.filesystem.mountCommonPath('userappdata', 'userappdata', 'readwrite') + -- userdesktop isnt valid on linux + if not test:isOS('Linux') then + local mount5 = love.filesystem.mountCommonPath('userdesktop', 'userdesktop', 'readwrite') + test:assertTrue(mount5, 'check mount userdesktop') + end + local mount6 = love.filesystem.mountCommonPath('userdocuments', 'userdocuments', 'readwrite') + local ok = pcall(love.filesystem.mountCommonPath, 'fakepath', 'fake', 'readwrite') + test:assertTrue(mount1, 'check mount appsavedir') + test:assertTrue(mount2, 'check mount appdocuments') + test:assertTrue(mount3, 'check mount userhome') + test:assertTrue(mount4, 'check mount userappdata') + test:assertTrue(mount6, 'check mount userdocuments') + test:assertFalse(ok, 'check mount invalid common path fails') +end + + +-- love.filesystem.unmountCommonPath +--love.test.filesystem.unmountCommonPath = function(test) +-- -- check unmounting invalid +-- local ok = pcall(love.filesystem.unmountCommonPath, 'fakepath') +-- test:assertFalse(ok, 'check unmount invalid common path') +-- -- check mounting valid paths +-- love.filesystem.mountCommonPath('appsavedir', 'appsavedir', 'read') +-- love.filesystem.mountCommonPath('appdocuments', 'appdocuments', 'read') +-- love.filesystem.mountCommonPath('userhome', 'userhome', 'read') +-- love.filesystem.mountCommonPath('userappdata', 'userappdata', 'read') +-- love.filesystem.mountCommonPath('userdesktop', 'userdesktop', 'read') +-- love.filesystem.mountCommonPath('userdocuments', 'userdocuments', 'read') +-- local unmount1 = love.filesystem.unmountCommonPath('appsavedir') +-- local unmount2 = love.filesystem.unmountCommonPath('appdocuments') +-- local unmount3 = love.filesystem.unmountCommonPath('userhome') +-- local unmount4 = love.filesystem.unmountCommonPath('userappdata') +-- local unmount5 = love.filesystem.unmountCommonPath('userdesktop') +-- local unmount6 = love.filesystem.unmountCommonPath('userdocuments') +-- test:assertTrue(unmount1, 'check unmount appsavedir') +-- test:assertTrue(unmount2, 'check unmount appdocuments') +-- test:assertTrue(unmount3, 'check unmount userhome') +-- test:assertTrue(unmount4, 'check unmount userappdata') +-- test:assertTrue(unmount5, 'check unmount userdesktop') +-- test:assertTrue(unmount6, 'check unmount userdocuments') +-- -- remount or future tests fail +-- love.filesystem.mountCommonPath('appsavedir', 'appsavedir', 'readwrite') +-- love.filesystem.mountCommonPath('appdocuments', 'appdocuments', 'readwrite') +-- love.filesystem.mountCommonPath('userhome', 'userhome', 'readwrite') +-- love.filesystem.mountCommonPath('userappdata', 'userappdata', 'readwrite') +-- love.filesystem.mountCommonPath('userdesktop', 'userdesktop', 'readwrite') +-- love.filesystem.mountCommonPath('userdocuments', 'userdocuments', 'readwrite') +--end + + -- love.filesystem.openFile -- @NOTE this is just basic nil checking, objs have their own test method love.test.filesystem.openFile = function(test) diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua index ec20edb01..1993b0bab 100644 --- a/testing/tests/graphics.lua +++ b/testing/tests/graphics.lua @@ -10,56 +10,53 @@ -- GraphicsBuffer (love.graphics.newBuffer) love.test.graphics.Buffer = function(test) + + -- setup vertex data and create some buffers local vertexformat = { {name="VertexPosition", format="floatvec2"}, {name="VertexTexCoord", format="floatvec2"}, {name="VertexColor", format="unorm8vec4"}, } - local vertexdata = { {0, 0, 0, 0, 1, 0, 1, 1}, {10, 0, 1, 0, 0, 1, 1, 1}, {10, 10, 1, 1, 0, 0, 1, 1}, {0, 10, 0, 1, 1, 0, 0, 1}, } - local flatvertexdata = {} for i, vert in ipairs(vertexdata) do for j, v in ipairs(vert) do table.insert(flatvertexdata, v) end end - local vertexbuffer1 = love.graphics.newBuffer(vertexformat, 4, {vertex=true, debugname='testvertexbuffer'}) local vertexbuffer2 = love.graphics.newBuffer(vertexformat, vertexdata, {vertex=true}) - test:assertObject(vertexbuffer1) test:assertObject(vertexbuffer2) + -- check buffer properties test:assertEquals(4, vertexbuffer1:getElementCount(), 'check vertex count 1') test:assertEquals(4, vertexbuffer2:getElementCount(), 'check vertex count 2') - -- vertex buffers have their elements tightly packed. test:assertEquals(20, vertexbuffer1:getElementStride(), 'check vertex array stride') - test:assertEquals(20 * 4, vertexbuffer1:getSize(), 'check vertex buffer size') - vertexbuffer1:setArrayData(vertexdata) vertexbuffer1:setArrayData(flatvertexdata) - vertexbuffer1:clear(8, 8) -- partial clear (the first texcoord) + -- check buffer types test:assertTrue(vertexbuffer1:isBufferType('vertex'), 'check is vertex buffer') test:assertFalse(vertexbuffer1:isBufferType('index'), 'check is not index buffer') test:assertFalse(vertexbuffer1:isBufferType('texel'), 'check is not texel buffer') test:assertFalse(vertexbuffer1:isBufferType('shaderstorage'), 'check is not shader storage buffer') + -- check debug name test:assertEquals('testvertexbuffer', vertexbuffer1:getDebugName(), 'check buffer debug name') + -- check buffer format and format properties local format = vertexbuffer1:getFormat() test:assertEquals('table', type(format), 'check buffer format is table') test:assertEquals(#vertexformat, #format, 'check buffer format length') - for i, v in ipairs(vertexformat) do test:assertEquals(v.name, format[i].name, string.format('check buffer format %d name', i)) test:assertEquals(v.format, format[i].format, string.format('check buffer format %d format', i)) @@ -67,8 +64,10 @@ love.test.graphics.Buffer = function(test) test:assertNotNil(format[i].offset) end + -- check index buffer local indexbuffer = love.graphics.newBuffer('uint16', 128, {index=true}) test:assertTrue(indexbuffer:isBufferType('index'), 'check is index buffer') + end @@ -80,22 +79,22 @@ love.test.graphics.ShaderStorageBuffer = function(test) return end + -- setup buffer local format = { { name="1", format="float" }, { name="2", format="floatmat4x4" }, { name="3", format="floatvec2" } } - local buffer = love.graphics.newBuffer(format, 1, {shaderstorage = true}) - test:assertEquals(96, buffer:getElementStride(), 'check shader storage buffer element stride') + -- set new data local data = {} for i = 1, 19 do data[i] = 0 end - buffer:setArrayData(data) + end @@ -113,6 +112,8 @@ love.test.graphics.Canvas = function(test) debugname = 'testcanvas' }) test:assertObject(canvas) + test:assertTrue(canvas:isCanvas(), 'check is canvas') + test:assertFalse(canvas:isComputeWritable(), 'check not compute writable') -- check dpi test:assertEquals(love.graphics.getDPIScale(), canvas:getDPIScale(), 'check dpi scale') @@ -190,9 +191,6 @@ love.test.graphics.Canvas = function(test) love.graphics.setColor(1, 1, 1, 1) end) local imgdata1 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata1, { - red = {{0, 0},{0,99},{99,0},{99,99}}, - }, 'font draw check') test:compareImg(imgdata1) -- check using canvas in love.graphics.draw() @@ -201,11 +199,42 @@ love.test.graphics.Canvas = function(test) love.graphics.draw(canvas, 0, 0) love.graphics.setCanvas() local imgdata2 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata2, { - red = {{0, 0},{0,99},{99,0},{99,99}}, - }, 'font draw check') test:compareImg(imgdata2) + -- check y-down + local shader1 = love.graphics.newShader[[ + vec4 effect(vec4 c, Image tex, vec2 tc, vec2 pc) { + return tc.y > 0.5 ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 1.0, 0.0, 1.0); + } + ]] + local shader2 = love.graphics.newShader[[ + vec4 effect(vec4 c, Image tex, vec2 tc, vec2 pc) { + // rounding during quantization from float to unorm8 doesn't seem to be + // totally consistent across devices, lets do it ourselves. + highp vec2 value = pc / love_ScreenSize.xy; + highp vec2 quantized = (floor(255.0 * value + 0.5) + 0.1) / 255.0; + return vec4(quantized, 0.0, 1.0); + } + ]] + local img = love.graphics.newImage(love.image.newImageData(1, 1)) + + love.graphics.push("all") + love.graphics.setCanvas(canvas) + love.graphics.setShader(shader1) + love.graphics.draw(img, 0, 0, 0, canvas:getDimensions()) + love.graphics.pop() + local imgdata3 = love.graphics.readbackTexture(canvas) + test:compareImg(imgdata3) + + love.graphics.push("all") + love.graphics.setCanvas(canvas) + love.graphics.setShader(shader2) + love.graphics.draw(img, 0, 0, 0, canvas:getDimensions()) + love.graphics.pop() + local imgdata4 = love.graphics.readbackTexture(canvas) + test:compareImg(imgdata4) + + -- check depth samples local dcanvas = love.graphics.newCanvas(100, 100, { type = '2d', @@ -216,6 +245,16 @@ love.test.graphics.Canvas = function(test) dcanvas:setDepthSampleMode('equal') test:assertEquals('equal', dcanvas:getDepthSampleMode(), 'check depth sample mode set') + -- check compute writeable (wont work on opengl mac) + if love.graphics.getSupported().glsl4 then + local ccanvas = love.graphics.newCanvas(100, 100, { + type = '2d', + format = 'rgba8', + computewrite = true + }) + test:assertTrue(ccanvas:isComputeWritable()) + end + end @@ -269,9 +308,6 @@ love.test.graphics.Font = function(test) love.graphics.print('Aa', 0, 5) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - white = {{0,3},{4,3},{7,4},{9,4},{10,5},{0,8},{4,8},{10,8}}, - }, 'font draw check') test:compareImg(imgdata) -- check font substitution @@ -285,10 +321,6 @@ love.test.graphics.Font = function(test) love.graphics.print('CD', 0, 9) -- should come from fontcd love.graphics.setCanvas() local imgdata2 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata2, { - green = {{1,8},{6,8},{2,10},{5,10},{9,10}}, - black = {{9,9},{14,8},{14,10},{14,1},{1,10}} - }, 'font draw check') test:compareImg(imgdata2) end @@ -303,6 +335,8 @@ love.test.graphics.Image = function(test) mipmaps = true }) test:assertObject(image) + test:assertFalse(image:isCanvas(), 'check not canvas') + test:assertFalse(image:isComputeWritable(), 'check not compute writable') -- check dpi test:assertEquals(love.graphics.getDPIScale(), image:getDPIScale(), 'check dpi scale') @@ -775,11 +809,6 @@ love.test.graphics.Quad = function(test) love.graphics.draw(texture, quad, 32, 32) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - white = {{17,31},{31,31},{31,24},{32,32},{46,32},{32,46}}, - lovepink = {{2,31},{31,2}}, - loveblue = {{32,61},{61,32}} - }, 'check quad drawing') test:compareImg(imgdata) end @@ -790,7 +819,7 @@ love.test.graphics.Shader = function(test) -- check valid shader local pixelcode1 = [[ - extern Image tex2; + uniform Image tex2; vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex2, texture_coords); return texturecolor * color; @@ -803,14 +832,14 @@ love.test.graphics.Shader = function(test) ]] local shader1 = love.graphics.newShader(pixelcode1, vertexcode1, {debugname = 'testshader'}) test:assertObject(shader1) - test:assertEquals('vertex shader:\npixel shader:\n', shader1:getWarnings(), 'check shader valid') + test:assertEquals('', shader1:getWarnings(), 'check shader valid') test:assertFalse(shader1:hasUniform('tex1'), 'check invalid uniform') test:assertTrue(shader1:hasUniform('tex2'), 'check valid uniform') test:assertEquals('testshader', shader1:getDebugName()) -- check invalid shader local pixelcode2 = [[ - extern float ww; + uniform float ww; vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex, texture_coords); float unused = ww * 3 * color; @@ -823,8 +852,8 @@ love.test.graphics.Shader = function(test) -- check using a shader to draw + sending uniforms -- shader will return a given color if overwrite set to 1, otherwise def. draw local pixelcode3 = [[ - extern vec4 col; - extern float overwrite; + uniform vec4 col; + uniform float overwrite; vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texcol = Texel(tex, texture_coords); if (overwrite == 1.0) { @@ -836,7 +865,8 @@ love.test.graphics.Shader = function(test) ]] local shader3 = love.graphics.newShader(pixelcode3, vertexcode1) local canvas = love.graphics.newCanvas(16, 16) - love.graphics.setCanvas(canvas) + love.graphics.push("all") + love.graphics.setCanvas(canvas) -- set color to yellow love.graphics.setColor(1, 1, 0, 1) -- turn shader 'on' and use red to draw @@ -849,16 +879,52 @@ love.test.graphics.Shader = function(test) shader3:send('overwrite', 0) love.graphics.setShader(shader3) love.graphics.rectangle('fill', 8, 8, 8, 8) - love.graphics.setShader() - love.graphics.setColor(1, 1, 1, 1) - love.graphics.setCanvas() + love.graphics.pop() + local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{1,1},{1,7},{7,7},{7,1}}, - yellow = {{8,8},{8,15},{15,15},{15,8}} - }, 'shader draw check') test:compareImg(imgdata) + -- test some uncommon paths for shader uniforms + local shader4 = love.graphics.newShader[[ + uniform bool booleans[5]; + vec4 effect(vec4 vcolor, Image tex, vec2 tc, vec2 pc) { + return booleans[3] ? vec4(0, 1, 0, 0) : vec4(1, 0, 0, 0); + } + ]] + + shader4:send("booleans", false, true, true) + + local shader5 = love.graphics.newShader[[ + uniform sampler2D textures[5]; + vec4 effect(vec4 vcolor, Image tex, vec2 tc, vec2 pc) { + return Texel(textures[2], tc) + Texel(textures[3], tc); + } + ]] + + local canvas2 = love.graphics.newCanvas(1, 1) + love.graphics.setCanvas(canvas2) + love.graphics.clear(0, 0.5, 0, 1) + love.graphics.setCanvas() + + shader5:send("textures", canvas2, canvas2, canvas2, canvas2, canvas2) + + local shader6 = love.graphics.newShader[[ + struct Data { + bool boolValue; + float floatValue; + sampler2D tex; + }; + + uniform Data data[3]; + + vec4 effect(vec4 vcolor, Image tex, vec2 tc, vec2 pc) { + return data[1].boolValue ? Texel(data[0].tex, tc) : vec4(0.0, 0.0, 0.0, 0.0); + } + ]] + + shader6:send("data[1].boolValue", true) + shader6:send("data[0].tex", canvas2) + end @@ -931,9 +997,6 @@ love.test.graphics.SpriteBatch = function(test) love.graphics.draw(sbatch, 0, 0) love.graphics.setCanvas() local imgdata1 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata1, { - lovepink = {{0,0},{63,2},{0,32},{63,32},{63,0},{63,2}} - }, 'sbatch draw normal') test:compareImg(imgdata1) -- use set to change some sprites @@ -945,11 +1008,6 @@ love.test.graphics.SpriteBatch = function(test) love.graphics.draw(sbatch, 0, 0) love.graphics.setCanvas() local imgdata2 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata2, { - lovepink = {{0,32},{63,32}}, - black = {{0,0},{63,0}}, - white = {{0,1},{63,1},{0,31},{63,31}} - }, 'sbatch draw set') test:compareImg(imgdata2) -- set drawRange and redraw @@ -959,11 +1017,6 @@ love.test.graphics.SpriteBatch = function(test) love.graphics.draw(sbatch, 0, 0) love.graphics.setCanvas() local imgdata3 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata3, { - lovepink = {{0,32},{63,32}}, - black = {{0,0},{63,0},{0,48},{63,48}}, - white = {{0,17},{63,17},{0,31},{63,31}} - }, 'sbatch draw drawrange') test:compareImg(imgdata3) -- clear and redraw @@ -973,9 +1026,6 @@ love.test.graphics.SpriteBatch = function(test) love.graphics.draw(sbatch, 0, 0) love.graphics.setCanvas() local imgdata4 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata4, { - black = {{0,0},{63,0},{0,32},{63,32},{0,63},{63,63}}, - }, 'sbatch draw clear') test:compareImg(imgdata4) -- array texture sbatch @@ -999,11 +1049,6 @@ love.test.graphics.SpriteBatch = function(test) love.graphics.draw(asbatch, 0, 0) love.graphics.setCanvas() local imgdata5 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata5, { - loveblue = {{31,2},{63,2},{3,30},{3,33},{16,47},{63,47}}, - lovepink = {{17,48},{63,48},{31,61},{63,61}}, - black = {{0,0},{63,0},{63,63},{63,0},{30,2},{30,61}}, - }, 'sbatch draw layers') test:compareImg(imgdata5) end @@ -1045,10 +1090,6 @@ love.test.graphics.Text = function(test) love.graphics.draw(colortext, 0, 10) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - yellow = {{1,9},{8,13},{16,11},{22,10},{25,7},{29,9},{32,13},{34,15}}, - white = {{17,13},{30,12},{38,9},{44,13},{58,13},{8,29},{58,29},{57,37},{5,39},{57,45},{1,55}} - }, 'text draw check') test:compareImg(imgdata) end @@ -1110,10 +1151,6 @@ love.test.graphics.Video = function(test) love.graphics.draw(video, 0, 0) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - black = {{0,0},{495,0},{495,499},{0,499}}, - red = {{499,0},{499,499}} - }, 'video draw') test:compareImg(imgdata) end @@ -1166,7 +1203,7 @@ love.test.graphics.arc = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata3 = love.graphics.readbackTexture(canvas) - if GITHUB_RUNNER and love.system.getOS() == 'OS X' then + if GITHUB_RUNNER and test:isOS('OS X') then -- on macosx runners, the arcs are not drawn as accurately at low res -- there's a couple pixels different in the curve of the arc but as we -- are at such a low resolution I think that can be expected @@ -1197,19 +1234,6 @@ love.test.graphics.circle = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - white = {{13,8},{18,8},{23,13},{23,18}}, - green = { - {15,12},{16,12},{13,13},{18,13},{12,15},{12,16},{13,18},{18,18}, - {15,19},{16,19},{19,15},{19,16} - }, - black = {{10,0},{21,0},{0,10},{0,21},{31,10},{31,21},{10,31},{21,31}}, - yellow = { - {11,10},{10,11},{8,14},{8,17},{10,20},{11,21},{14,23},{17,23},{20,21}, - {21,20},{23,17},{23,14},{20,10},{21,11},{17,8},{14,8} - }, - red = {{11,0},{20,0},{11,31},{20,31},{0,11},{0,20},{31,20},{31,11}} - }, 'circle') test:compareImg(imgdata) end @@ -1223,9 +1247,6 @@ love.test.graphics.clear = function(test) love.graphics.clear(1, 1, 0, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - yellow = {{0,0},{15,0},{0,15},{15,15},{8,8}} - }, 'clear') test:compareImg(imgdata) end @@ -1258,12 +1279,6 @@ love.test.graphics.draw = function(test) love.graphics.draw(canvas1, transform) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas2) - test:assertPixels(imgdata, { - lovepink = {{23,3},{23,19},{7,19},{0,0},{16,0},{0,16},{16,16}}, - loveblue = {{0,31},{15,17},{15,31},{16,31},{31,17},{31,31},{16,15},{31,15}}, - white = {{6,19},{8,19},{22,19},{24,19},{22,3},{24,3}}, - red = {{0,1},{1,0},{15,0},{15,7},{0,15},{7,15}} - }, 'drawing') test:compareImg(imgdata) end @@ -1284,12 +1299,6 @@ love.test.graphics.drawInstanced = function(test) love.graphics.drawInstanced(mesh, 1000, 0, 0, 0, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,0}}, - green = {{63,0}}, - blue = {{63,63}}, - yellow = {{0,63}} - }, 'draw instances') -- need 1 tolerance here just cos of the amount of colors test.rgba_tolerance = 1 test:compareImg(imgdata) @@ -1311,12 +1320,6 @@ love.test.graphics.drawLayer = function(test) love.graphics.drawLayer(image, 3, 32, 32, 0, 2, 2, 16, 16) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - lovepink = {{30,2},{33,2},{2,30},{2,33},{4,60},{4,63},{60,4},{63,4},{31,23},{32,23}}, - loveblue = {{14,33},{17,33},{46,1},{49,1},{1,46},{1,49},{33,14},{33,17}}, - black = {{0,0},{63,0},{0,63},{39,6},{40,6},{6,39},{6,40},{6,55},{55,6}}, - white = {{46,11},{48,11},{14,43},{16,43},{30,23},{33,23},{34,54},{53,40},{63,63}} - }, 'draw layer') test:compareImg(imgdata) end @@ -1335,11 +1338,6 @@ love.test.graphics.ellipse = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,14},{0,17},{7,9},{7,22},{14,15},{14,16}}, - pink = {{15,15},{16,15},{8,0},{8,4},{23,0},{23,4},{13,14},{18,14}}, - yellow = {{24,0},{25,0},{14,17},{14,30},{15,31},{31,8}} - }, 'ellipses') test:compareImg(imgdata) end @@ -1372,10 +1370,6 @@ love.test.graphics.line = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - yellow = {{0,0},{15,0},{0,15},{15,15},{7,7},{8,7},{8,7},{8,8}}, - red = {{1,0},{14,0},{0,1},{0,14},{15,1},{15,14},{1,15},{14,15}} - }, 'lines') test:compareImg(imgdata) end @@ -1383,19 +1377,16 @@ end -- love.graphics.points love.test.graphics.points = function(test) local canvas = love.graphics.newCanvas(16, 16) - love.graphics.setCanvas(canvas) + love.graphics.push("all") + love.graphics.setCanvas(canvas) love.graphics.clear(0, 0, 0, 1) + love.graphics.translate(0.5, 0.5) -- draw points at the center of pixels love.graphics.setColor(1, 0, 0, 1) - love.graphics.points(1,1,16,1,16,16,1,16,1,1) + love.graphics.points(0,0,15,0,15,15,0,15,0,0) love.graphics.setColor(1, 1, 0, 1) - love.graphics.points({2,2,8,8,15,2,8,9,15,15,9,9,2,15,9,8}) - love.graphics.setColor(1, 1, 1, 1) - love.graphics.setCanvas() + love.graphics.points({1,1,7,7,14,1,7,8,14,14,8,8,1,14,8,7}) + love.graphics.pop() local imgdata = love.graphics.readbackTexture(canvas) - -- on macOS runners points are drawn 1px off from the target - if GITHUB_RUNNER and love.system.getOS() == 'OS X' then - test.pixel_tolerance = 1 - end test:compareImg(imgdata) end @@ -1412,10 +1403,6 @@ love.test.graphics.polygon = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - yellow = {{1,0},{1,1},{5,9},{7,14},{8,14},{12,3}}, - red = {{2,1},{1,2},{1,7},{5,15},{14,15},{8,8},{14,2},{7,1}} - }, 'polygon') test:compareImg(imgdata) end @@ -1435,17 +1422,6 @@ love.test.graphics.print = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,0},{1,0},{1,1},{2,6},{4,4},{7,6},{10,2},{11,5},{14,3},{14,4}}, - green = { - {2,1},{2,2},{0,3},{1,3},{1,8},{2,9},{7,10},{8,8},{9,4},{13,3},{14,2}, - {13,8},{14,9} - }, - blue = { - {4,15},{10,15},{4,12},{6,12},{8,12},{5,9},{7,9},{4,3},{10,3},{8,6},{7,7}, - {4,7},{7,13},{8,12} - } - }, 'print') test:compareImg(imgdata) end @@ -1465,17 +1441,6 @@ love.test.graphics.printf = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = { - {1,0},{1,1},{0,3},{2,3},{2,7},{0,9},{3,11},{4,10},{0,15},{4,15},{2,19}, - {0,24},{1,23},{3,23},{4,24},{0,26},{1,27},{2,27},{3,27} - }, - green = { - {1,2},{0,8},{1,8},{2,8},{4,7},{5,8},{7,8},{8,7},{10,4},{14,4},{11,7}, - {12,8},{10,13},{11,12},{13,12},{14,13},{10,15},{11,16} - }, - blue = {{6,4},{6,10},{9,7},{10,6},{16,9},{18,9},{21,8},{25,8}} - }, 'printf') test:compareImg(imgdata) end @@ -1493,11 +1458,7 @@ love.test.graphics.rectangle = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata1 = love.graphics.readbackTexture(canvas) - -- test, check red bg and blue central square - test:assertPixels(imgdata1, { - red = {{0,0},{15,0},{15,15},{0,15}}, - blue = {{6,6},{9,6},{9,9},{6,9}} - }, 'fill') + test:compareImg(imgdata1) -- clear canvas to do some line testing love.graphics.setCanvas(canvas) love.graphics.clear(0, 0, 0, 1) @@ -1510,17 +1471,6 @@ love.test.graphics.rectangle = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata2 = love.graphics.readbackTexture(canvas) - -- -- check corners and inner corners - test:assertPixels(imgdata2, { - red = {{3,0},{9,0},{3,15,9,15}}, - blue = {{0,0},{2,0},{0,15},{2,15}}, - green = {{10,0},{15,0},{10,15},{15,15}}, - black = { - {1,1},{1,14},{3,1},{9,1},{3,14}, - {9,14},{11,1},{14,1},{11,14},{14,14} - } - }, 'line') - test:compareImg(imgdata1) test:compareImg(imgdata2) end @@ -1535,10 +1485,29 @@ end -- love.graphics.captureScreenshot love.test.graphics.captureScreenshot = function(test) love.graphics.captureScreenshot('example-screenshot.png') - test:waitFrames(10) + test:waitFrames(1) -- need to wait until end of the frame for the screenshot - test:assertNotNil(love.filesystem.openFile('example-screenshot.png', 'r')) + test:assertTrue(love.filesystem.exists('example-screenshot.png')) love.filesystem.remove('example-screenshot.png') + -- test callback version + local cbdata = nil + local prevtextcommand = TextCommand + TextCommand = "Capturing screenshot" + love.graphics.captureScreenshot(function (idata) + test:assertNotEquals(nil, idata, 'check we have image data') + cbdata = idata + end) + test:waitFrames(1) + TextCommand = prevtextcommand + test:assertNotNil(cbdata) + + if test:isOS('iOS', 'Android') then + -- Mobile operating systems don't let us control the window resolution, + -- so we can't compare the reference image properly. + test:assertTrue(true, 'skip test') + else + test:compareImg(cbdata) + end end @@ -1650,7 +1619,7 @@ love.test.graphics.newSpriteBatch = function(test) end --- love.graphics.newText +-- love.graphics.newTextBatch -- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newTextBatch = function(test) local font = love.graphics.newFont('resources/font.ttf') @@ -1658,6 +1627,14 @@ love.test.graphics.newTextBatch = function(test) end +-- love.graphics.newTexture +-- @NOTE this is just basic nil checking, objs have their own test method +love.test.graphics.newTexture = function(test) + local imgdata = love.image.newImageData('resources/love.png') + test:assertObject(love.graphics.newTexture(imgdata)) +end + + -- love.graphics.newVideo -- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newVideo = function(test) @@ -1962,22 +1939,13 @@ love.test.graphics.intersectScissor = function(test) love.graphics.setScissor() love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,0},{3,3}}, - black ={{4,0},{0,4},{4,4}} - }, 'intersect scissor') test:compareImg(imgdata) end -- love.graphics.isActive love.test.graphics.isActive = function(test) - local name, version, vendor, device = love.graphics.getRendererInfo() - if string.find(name, 'Vulkan') ~= nil then - test:skipTest('love.graphics.isActive() crashes on Vulkan') - else - test:assertTrue(love.graphics.isActive(), 'check graphics is active') -- i mean if you got this far - end + test:assertTrue(love.graphics.isActive(), 'check graphics is active') -- i mean if you got this far end @@ -2058,13 +2026,6 @@ love.test.graphics.setBlendMode = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - -- check the 4 corners - test:assertPixels(imgdata, { - redpale = {{0,0}}, - black = {{15,0}}, - greenhalf = {{15,15}}, - bluefade = {{0,15}} - }, 'blend mode') love.graphics.setBlendMode('alpha', 'alphamultiply') -- reset -- need 1rgba tolerance here on some machines test.rgba_tolerance = 1 @@ -2087,10 +2048,6 @@ love.test.graphics.setCanvas = function(test) love.graphics.setCanvas() test:assertEquals(nil, love.graphics.getCanvas(), 'check no canvas set') local imgdata = love.graphics.readbackTexture(canvas2) - -- check 2nd canvas is red - test:assertPixels(imgdata, { - red = {{0,0},{15,0},{15,15},{0,15}} - }, 'set canvas') test:compareImg(imgdata) end @@ -2118,12 +2075,6 @@ love.test.graphics.setColor = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,0},{5,0},{10,0},{15,0}}, - yellow = {{0,1},{5,1},{10,1},{15,1}}, - greenhalf = {{0,2},{5,2},{10,2},{15,2}}, - blue = {{0,3},{5,3},{10,3},{15,3}} - }, 'set color') test:compareImg(imgdata) end @@ -2147,9 +2098,6 @@ love.test.graphics.setColorMask = function(test) love.graphics.setColorMask(true, true, true, true) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - yellow = {{0,0},{0,15},{15,15},{15,0}} - }, 'set color mask') test:compareImg(imgdata) end @@ -2195,13 +2143,6 @@ love.test.graphics.setFont = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = { - {0,0},{0,6},{2,6},{6,2}, - {4,4},{8,4},{6,6},{10,2}, - {14,2},{12,6} - } - }, 'set font for print') test:compareImg(imgdata) end @@ -2216,6 +2157,23 @@ love.test.graphics.setFrontFaceWinding = function(test) test:assertEquals('ccw', love.graphics.getFrontFaceWinding(), 'check ffw ccw set') love.graphics.setFrontFaceWinding(original) -- @TODO better graphics drawing specific test + + local shader = love.graphics.newShader[[ +vec4 effect(vec4 c, Image tex, vec2 tc, vec2 pc) { + return gl_FrontFacing ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0); +} + ]] + local dummyimg = love.graphics.newImage(love.image.newImageData(1, 1)) + + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.push("all") + love.graphics.setCanvas(canvas) + love.graphics.setShader(shader) + love.graphics.draw(dummyimg, 0, 0, 0, 16, 16) + love.graphics.pop() + + local imgdata = love.graphics.readbackTexture(canvas) + test:compareImg(imgdata) end @@ -2244,12 +2202,6 @@ love.test.graphics.setLineJoin = function(test) love.graphics.origin() love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - black = {{8,0}}, - red = {{8,4}}, - yellow = {{8,7}}, - blue = {{8,8}} - }, 'set line join') test:compareImg(imgdata) end @@ -2272,12 +2224,8 @@ love.test.graphics.setLineStyle = function(test) love.graphics.origin() love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,0},{7,0},{15,0}}, - red07 = {{0,4},{7,4},{15,4}} - }, 'set line style') -- linux runner needs a 1/255 tolerance for the blend between a rough line + bg - if GITHUB_RUNNER and love.system.getOS() == 'Linux' then + if GITHUB_RUNNER and test:isOS('Linux') then test.rgba_tolerance = 1 end test:compareImg(imgdata) @@ -2307,12 +2255,6 @@ love.test.graphics.setLineWidth = function(test) love.graphics.origin() love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - black = {{0,2},{6,2},{0,6},{5,6},{0,11},{5,11}}, - red = {{0,0},{0,1},{7,2},{8,2}}, - yellow = {{0,3},{0,5},{6,6},{8,6}}, - blue = {{0,7},{0,10},{6,15},{9,15}} - }, 'set line width') test:compareImg(imgdata) end @@ -2346,10 +2288,6 @@ love.test.graphics.setScissor = function(test) love.graphics.setScissor() love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{0,0},{7,0},{0,15},{7,15}}, - black ={{8,0},{8,15},{15,0},{15,15}} - }, 'set scissor') test:compareImg(imgdata) end @@ -2380,9 +2318,6 @@ love.test.graphics.setShader = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - yellow = {{0,0},{15,0},{0,15},{15,15}}, - }, 'check shader set to yellow') test:compareImg(imgdata) end @@ -2401,9 +2336,6 @@ love.test.graphics.setStencilState = function(test) love.graphics.setStencilState() love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { - red = {{6,2},{9,2},{2,6},{2,9},{13,6},{9,6},{6,13},{9,13}} - }, 'check stencil test') test:compareImg(imgdata) end @@ -2426,7 +2358,7 @@ love.test.graphics.setWireframe = function(test) love.graphics.setWireframe(false) local imgdata = love.graphics.readbackTexture(canvas) -- on macOS runners wireframes are drawn 1px off from the target - if GITHUB_RUNNER and love.system.getOS() == 'OS X' then + if GITHUB_RUNNER and test:isOS('OS X') then test.pixel_tolerance = 1 end test:compareImg(imgdata) @@ -2455,7 +2387,6 @@ love.test.graphics.applyTransform = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{10, 0}} }, 'apply transform 10') test:compareImg(imgdata) end @@ -2492,7 +2423,6 @@ love.test.graphics.origin = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{0, 0}} }, 'origin check') test:compareImg(imgdata) end @@ -2514,7 +2444,6 @@ love.test.graphics.pop = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{0, 0}} }, 'pop 1') test:compareImg(imgdata) end @@ -2537,7 +2466,6 @@ love.test.graphics.push = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{1, 1}} }, 'push 1') test:compareImg(imgdata) end @@ -2559,7 +2487,6 @@ love.test.graphics.replaceTransform = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{10, 0}} }, 'replace transform 10') test:compareImg(imgdata) end @@ -2578,7 +2505,6 @@ love.test.graphics.rotate = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{0,0},{3,0},{3,3},{0,3}} }, 'rotate 90') test:compareImg(imgdata) end @@ -2596,7 +2522,7 @@ love.test.graphics.scale = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{1,1},{1,15},{15,1},{15,15}} }, 'scale 4x') + test:compareImg(imgdata) end @@ -2614,7 +2540,7 @@ love.test.graphics.shear = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata1 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata1, { red = {{1,0},{4,0},{7,3},{10,3}} }, 'shear x') + test:compareImg(imgdata1) -- same again at 0,0, we shear by 2y and then draw -- we can then check the drawn rectangle has moved down love.graphics.setCanvas(canvas) @@ -2626,8 +2552,6 @@ love.test.graphics.shear = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata2 = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata2, { red = { {0,1},{0,4},{3,7},{3,10}} }, 'shear y') - test:compareImg(imgdata1) test:compareImg(imgdata2) end @@ -2665,7 +2589,6 @@ love.test.graphics.translate = function(test) love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas) - test:assertPixels(imgdata, { red = {{5,0},{0,5},{5,5},{0,0}} }, 'translate 4x') test:compareImg(imgdata) end @@ -2802,8 +2725,8 @@ love.test.graphics.getSupported = function(test) 'clampzero', 'lighten', 'glsl3', 'instancing', 'fullnpot', 'pixelshaderhighp', 'shaderderivatives', 'indirectdraw', 'mipmaprange', 'copyrendertargettobuffer', 'copytexturetobuffer', 'copybuffer', - 'indexbuffer32bit', 'multirendertargetformats', 'clampone', 'blendminmax', - 'glsl4' + 'copybuffertotexture', 'indexbuffer32bit', 'multirendertargetformats', + 'clampone', 'blendminmax', 'glsl4' } local features = love.graphics.getSupported() for g=1,#gfs do diff --git a/testing/tests/image.lua b/testing/tests/image.lua index fa9f4cbd2..db98882d4 100644 --- a/testing/tests/image.lua +++ b/testing/tests/image.lua @@ -32,6 +32,11 @@ love.test.image.CompressedImageData = function(test) -- check mipmap count test:assertEquals(7, idata:getMipmapCount(), 'check mipmap count') + -- check linear + test:assertFalse(idata:isLinear(), 'check not linear') + idata:setLinear(true) + test:assertTrue(idata:isLinear(), 'check now linear') + end @@ -78,12 +83,24 @@ love.test.image.ImageData = function(test) local r2, g2, b2 = idata:getPixel(25, 25) test:assertEquals(1, r2+g2+b2, 'check set to red') - -- check encoding to an image + -- check encoding to an image (png) idata:encode('png', 'test-encode.png') - local read = love.filesystem.openFile('test-encode.png', 'r') - test:assertNotNil(read) + local read1 = love.filesystem.openFile('test-encode.png', 'r') + test:assertNotNil(read1) love.filesystem.remove('test-encode.png') + -- check encoding to an image (exr) + local edata = love.image.newImageData(100, 100, 'r16f') + edata:encode('exr', 'test-encode.exr') + local read2 = love.filesystem.openFile('test-encode.exr', 'r') + test:assertNotNil(read2) + love.filesystem.remove('test-encode.exr') + + -- check linear + test:assertFalse(idata:isLinear(), 'check not linear') + idata:setLinear(true) + test:assertTrue(idata:isLinear(), 'check now linear') + end diff --git a/testing/tests/keyboard.lua b/testing/tests/keyboard.lua index e7a4f5630..c8f9748c9 100644 --- a/testing/tests/keyboard.lua +++ b/testing/tests/keyboard.lua @@ -64,6 +64,19 @@ love.test.keyboard.setKeyRepeat = function(test) end +-- love.keyboard.isModifierActive +love.test.keyboard.isModifierActive = function(test) + local active1 = love.keyboard.isModifierActive('numlock') + local active2 = love.keyboard.isModifierActive('capslock') + local active3 = love.keyboard.isModifierActive('scrolllock') + local active4 = love.keyboard.isModifierActive('mode') + test:assertNotNil(active1) + test:assertNotNil(active2) + test:assertNotNil(active3) + test:assertNotNil(active4) +end + + -- love.keyboard.setTextInput love.test.keyboard.setTextInput = function(test) love.keyboard.setTextInput(false) diff --git a/testing/tests/physics.lua b/testing/tests/physics.lua index 974c89a84..5e4662526 100644 --- a/testing/tests/physics.lua +++ b/testing/tests/physics.lua @@ -19,6 +19,12 @@ love.test.physics.Body = function(test) love.physics.newRectangleShape(body2, 5, 5, 10, 10) test:assertObject(body1) + -- check shapes + test:assertEquals(1, #body1:getShapes(), 'check shapes total 1') + test:assertEquals(1, #body2:getShapes(), 'check shapes total 2') + test:assertNotEquals(nil, body1:getShape(), 'check shape 1') + test:assertNotEquals(nil, body2:getShape(), 'check shape 2') + -- check body active test:assertTrue(body1:isActive(), 'check active by def') @@ -135,6 +141,7 @@ love.test.physics.Body = function(test) test:assertRange(y5, 5, 6, 'check mass data reset y') test:assertRange(mass5, 0.1, 0.2, 'check mass data reset mass') test:assertRange(inertia5, 5, 6, 'check mass data reset inertia') + test:assertFalse(body1:hasCustomMassData()) -- check position local x6, y6 = body1:getPosition() @@ -515,6 +522,10 @@ love.test.physics.World = function(test) test:assertRange(world:getBodies()[1]:getY(), 9, 11, 'check body prop change y') test:assertEquals(1, world:getBodyCount(), 'check 1 body count') + -- check shapes in world + test:assertEquals(1, #world:getShapesInArea(0, 0, 10, 10), 'check shapes in area #1') + test:assertEquals(0, #world:getShapesInArea(20, 20, 30, 30), 'check shapes in area #1') + -- check world status test:assertFalse(world:isLocked(), 'check not updating') test:assertFalse(world:isSleepingAllowed(), 'check no sleep (till brooklyn)') @@ -571,6 +582,8 @@ love.test.physics.World = function(test) return 1 end) test:assertEquals(3, shapes, 'check shapes in raycast') + test:assertEquals(world:rayCastClosest(0, 0, 200, 200), rectangle1, 'check closest raycast') + test:assertNotEquals(nil, world:rayCastAny(0, 0, 200, 200), 'check any raycast') -- change collision logic test:assertEquals(nil, world:getContactFilter(), 'check def filter') diff --git a/testing/tests/sensor.lua b/testing/tests/sensor.lua index fcf3379dc..56c5da7b5 100644 --- a/testing/tests/sensor.lua +++ b/testing/tests/sensor.lua @@ -2,6 +2,47 @@ -- @NOTE we can't test this module fully as it's hardware dependent -- however we can test methods do what is expected and can handle certain params +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------HELPERS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +local function testIsEnabled(test, sensorType) + love.sensor.setEnabled(sensorType, true) + test:assertTrue(love.sensor.isEnabled(sensorType), 'check ' .. sensorType .. ' enabled') + love.sensor.setEnabled(sensorType, false) + test:assertFalse(love.sensor.isEnabled(sensorType), 'check ' .. sensorType .. ' disabled') +end + + +local function testGetName(test, sensorType) + love.sensor.setEnabled(sensorType, true) + local ok, name = pcall(love.sensor.getName, sensorType) + test:assertTrue(ok, 'check sensor.getName("' .. sensorType .. '") success') + test:assertEquals(type(name), 'string', 'check sensor.getName("' .. sensorType .. '") return value type') + + love.sensor.setEnabled(sensorType, false) + ok, name = pcall(love.sensor.getName, sensorType) + test:assertFalse(ok, 'check sensor.getName("' .. sensorType .. '") errors when disabled') +end + + +local function testGetData(test, sensorType) + love.sensor.setEnabled(sensorType, true) + local ok, x, y, z = pcall(love.sensor.getData, sensorType) + test:assertTrue(ok, 'check sensor.getData("' .. sensorType .. '") success') + if ok then + test:assertNotNil(x) + test:assertNotNil(y) + test:assertNotNil(z) + end + + love.sensor.setEnabled(sensorType, false) + ok, x, y, z = pcall(love.sensor.getData, sensorType) + test:assertFalse(ok, 'check sensor.getData("' .. sensorType .. '") errors when disabled') +end + -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ------------------------------------METHODS------------------------------------- @@ -17,3 +58,45 @@ love.test.sensor.hasSensor = function(test) test:assertNotNil(accelerometer) test:assertNotNil(gyroscope) end + + +-- love.sensor.isEnabled and love.sensor.setEnabled +love.test.sensor.isEnabled = function(test) + local accelerometer = love.sensor.hasSensor('accelerometer') + local gyroscope = love.sensor.hasSensor('gyroscope') + + if accelerometer or gyroscope then + if accelerometer then testIsEnabled(test, 'accelerometer') end + if gyroscope then testIsEnabled(test, 'gyroscope') end + else + test:skipTest('neither accelerometer nor gyroscope are supported in this system') + end +end + + +-- love.sensor.getName +love.test.sensor.getName = function(test) + local accelerometer = love.sensor.hasSensor('accelerometer') + local gyroscope = love.sensor.hasSensor('gyroscope') + + if accelerometer or gyroscope then + if accelerometer then testGetName(test, 'accelerometer') end + if gyroscope then testGetName(test, 'gyroscope') end + else + test:skipTest('neither accelerometer nor gyroscope are supported in this system') + end +end + + +-- love.sensor.getData +love.test.sensor.getData = function(test) + local accelerometer = love.sensor.hasSensor('accelerometer') + local gyroscope = love.sensor.hasSensor('gyroscope') + + if accelerometer or gyroscope then + if accelerometer then testGetData(test, 'accelerometer') end + if gyroscope then testGetData(test, 'gyroscope') end + else + test:skipTest('neither accelerometer nor gyroscope are supported in this system') + end +end diff --git a/testing/tests/sound.lua b/testing/tests/sound.lua index 0304d0562..d5032cb30 100644 --- a/testing/tests/sound.lua +++ b/testing/tests/sound.lua @@ -80,6 +80,18 @@ love.test.sound.SoundData = function(test) sdata:setSample(0.002, 1) test:assertEquals(1, sdata:getSample(0.002), 'check setting sample manually') + -- check copying from another sound + local copy1 = love.sound.newSoundData('resources/tone.ogg') + local copy2 = love.sound.newSoundData('resources/pop.ogg') + local before = copy2:getSample(0.02) + copy2:copyFrom(copy1, 0.01, 1, 0.02) + test:assertNotEquals(before, copy2:getSample(0.02), 'check changed') + + -- check slicing + local count = math.floor(copy1:getSampleCount()/2) + local slice = copy1:slice(0, count) + test:assertEquals(count, slice:getSampleCount(), 'check slice length') + end diff --git a/testing/tests/system.lua b/testing/tests/system.lua index e8ef4229c..88912d525 100644 --- a/testing/tests/system.lua +++ b/testing/tests/system.lua @@ -29,6 +29,14 @@ love.test.system.getOS = function(test) end +-- love.system.getPreferredLocales +love.test.system.getPreferredLocales = function(test) + local locale = love.system.getPreferredLocales() + test:assertNotNil(locale) + test:assertEquals('table', type(locale), 'check returns table') +end + + -- love.system.getPowerInfo love.test.system.getPowerInfo = function(test) -- check battery state is one of the documented states diff --git a/testing/tests/window.lua b/testing/tests/window.lua index b1c993776..98cfc2f43 100644 --- a/testing/tests/window.lua +++ b/testing/tests/window.lua @@ -8,6 +8,13 @@ -------------------------------------------------------------------------------- +-- love.window.focus +love.test.window.focus = function(test) + -- cant test as doesnt return anything + test:assertEquals('function', type(love.window.focus), 'check method exists') +end + + -- love.window.fromPixels love.test.window.fromPixels = function(test) -- check dpi/pixel ratio as expected @@ -352,18 +359,3 @@ love.test.window.updateMode = function(test) resizable = true }) end - --- love.window.close --- calling love.window.close() last as it will stop the main test image drawing -love.test.window.z_close = function(test) - -- closing window should cause graphics to not be active - love.window.close() - local active = love.graphics.isActive() - test:assertFalse(active, 'check window not active') - -- should also mark the window as not open and not visible - test:assertFalse(love.window.isOpen(), 'check window closed') - test:assertFalse(love.window.isVisible(), 'check window not visible') - love.window.updateMode(360, 240) -- reset - active = love.graphics.isActive() - test:assertTrue(active, 'check window active again') -end diff --git a/testing/todo.md b/testing/todo.md new file mode 100644 index 000000000..ba589fb75 --- /dev/null +++ b/testing/todo.md @@ -0,0 +1,28 @@ +# TODO +These are all the outstanding methods that require test coverage, along with a few bits that still need doing / discussion. + +## General +- ability to test loading different combinations of modules if needed? +- check expected behaviour of mount + unmount with common path + try uncommenting love.filesystem.unmountCommonPath and you'll see the issues +- revisit love.audio.setPlaybackDevice when we update openal soft for MacOS + +## Graphics +- love.graphics.copyBuffer() +- love.graphics.copyBufferToTexture() +- love.graphics.copyTextureToBuffer() +- love.graphics.readbackTexture() +- love.graphics.readbackTextureAsync() +- love.graphics.readbackBuffer() +- love.graphics.readbackBufferAsync() +- love.graphics.newComputeShader() +- love.graphics.dispatchThreadgroups() +- love.graphics.dispatchIndirect() +- love.graphics.drawFromShader() +- love.graphics.drawFromShaderIndirect() +- love.graphics.drawIndirect() +- love.graphics.getQuadIndexBuffer() +- love.graphics.setBlendState() +- love.graphics.resetProjection() +- love.graphics.Mesh:getAttachedAttributes() +- love.graphics.Shader:hasStage()