diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a2d3a03a3..5ae3ad28b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -58,10 +58,15 @@ jobs: shell: cmd run: cmake --build build --config Release --target install -j2 - name: Artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: love-windows-${{ matrix.platform }} path: install + - name: Artifact JIT Modules + uses: actions/upload-artifact@v2 + with: + name: love-windows-jitmodules-${{ matrix.platform }} + path: build/libs/LuaJIT/src/jit/*.lua macOS: runs-on: macos-latest steps: @@ -71,7 +76,7 @@ jobs: uses: actions/checkout@v2 with: path: apple-dependencies - repository: slime73/love-apple-dependencies + repository: love2d/love-apple-dependencies ref: main - name: Move Dependencies run: @@ -99,11 +104,10 @@ jobs: uses: actions/checkout@v2 with: path: apple-dependencies - repository: slime73/love-apple-dependencies + repository: love2d/love-apple-dependencies ref: main - name: Move Dependencies run: | - mv apple-dependencies/iOS/include platform/xcode/ios mv apple-dependencies/iOS/libraries platform/xcode/ios - name: Build run: diff --git a/changes.txt b/changes.txt index 7630b1cea..ec8c9d417 100644 --- a/changes.txt +++ b/changes.txt @@ -3,17 +3,33 @@ LOVE 12.0 [N/A] Released: N/A +* Added love.parsedGameArguments and love.rawGameArguments tables, in the main thread. +* Added love.markDeprecated. * Added love.event.restart(optionalvalue). A new love.restart field will contain the value after restarting. +* Added love.filesystem.mountFullPath and love.filesystem.unmountFullPath, including opt-in mount-for-write support. +* Added love.filesystem.mountCommonPath, unmountCommonPath, and getFullCommonPath. +* Added 'readonly' field to love.filesystem.getInfo's returned table. * Added SoundData:copyFrom. * Added SoundData:slice. +* Added Joystick:setPlayerIndex and Joystick:getPlayerIndex. +* Added Joystick:getGamepadType. +* Added new Gamepad API buttons: "misc1", "paddle1", "paddle2", "paddle3", "paddle4". and "touchpad". * Added t.highdpi startup flag in love.conf, replacing t.window.highdpi and the highdpi flag of love.window.setMode. * Added per-shader opt in support for the GLSL 4.30 (desktop) and GLSL ES 3.10 (mobile) shading languages, via #pragma language glsl4. * Added love.graphics.newTexture. newImage and newCanvas still exist as convenience constructor functions. * Added love.graphics.getTextureFormats, which replaces getImageFormats and getCanvasFormats. -* Added Graphics Buffer objects, including vertex, index, and texel buffers. +* Added integer texture formats. +* Added Graphics Buffer objects, including vertex, index, texel, and shader storage buffers. +* Added love.graphics.copyBuffer, copyBufferToTexture, and copyTextureToBuffer. * Added APIs for interacting with the Buffer objects owned by Meshes. * Added Mesh:getAttachedAttributes. * Added integer buffer data formats. +* Added 'staging' buffer data usage enum, useful for Buffers used in intermediate copy steps. +* Added new lower level 'vertexmain' and 'pixelmain' shader entry points. +* Added Compute Shader support via new 'computemain' shader entry point. +* Added love.graphics.dispatchThreadgroups for running compute shaders. +* Added Shader:hasStage. +* Added ability to set point size within a vertex shader by setting the 'love_PointSize' variable. * Added love.graphics.setBlendState, which gives lower level control over blend operations than setBlendMode. * Added new 'clampone' wrap mode. * Added a variant of Font:getWidth which takes a codepoint number argument. @@ -22,6 +38,9 @@ Released: N/A * Changed the Texture class and implementation to no longer have separate Canvas and Image subclasses. * Changed Images to no longer hold onto a CPU copy of their pixel data after creation. * Changed love.window.setMode to no longer clear the contents of Canvases or otherwise recreate OpenGL resources. +* Changed love.graphics.points to require 'love_PointSize' to be set in the vertex shader, if a custom shader is used. +* Changed RevoluteJoint:getMotorTorque to take 'dt' as a parameter instead of 'inverse_dt'. +* Changed love.math.noise to use higher precision numbers for its internal calculations. * Updated Box2D from 2.3 to 2.4.1. @@ -39,21 +58,26 @@ LOVE 11.4 [Mysterious Mysteries] Released: N/A * Added native arm64 support on macOS. +* Added a variant of love.filesystem.newFileData which accepts a Data object. * Added Body:getLocalPoints. * Added Font:getKerning. * Added support for r16, rg16, and rgba16 pixel formats in Canvases. * Added Shader:send(name, matrixlayout, data, ...) variant, whose argument order is more consistent than Shader:send(name, data, matrixlayout, ...). +* Changed all builds and platforms where LOVE provides LuaJIT to use LuaJIT 2.1 instead of 2.0. * Changed love.timer.getTime to start at 0 when the module is first loaded. * Changed certain out-of-Lua-memory situations to show a message box instead of instantly crashing. +* Changed the naming scheme of LOVE's embedded Lua files for improved integration with Lua chunkname APIs. * Fixed build-time compatibility with Lua 5.4. * Fixed code compatibility with math.mod and string.gfind when LuaJIT 2.1 is used. * Fixed errors on some systems related to > 53 bit pointer addresses, when recent versions of LuaJIT 2.1 are used. +* Fixed the default error handler showing a blank screen on some mobile devices. * Fixed drag-and-drop to open a love game on macOS causing love.event.quit("restart") to fail. * Fixed fused macOS apps opening other love games when drag-and-drop is used (if the fused app hasn't already removed .love files from recognized document types). * Fixed File:isEOF when called on a dropped file. * Fixed support for > 2GB dropped files on desktops. +* Fixed ByteData and DataView missing Data:clone implementations. * Fixed love.physics meter scale value persisting after love.event.quit("restart"). * Fixed audio to resume properly after interruption on iOS. * Fixed love.graphics.newVideo to error instead of crash when an invalid video file is given. @@ -76,6 +100,7 @@ Released: N/A * Fixed rare issues where textures were not sent to shaders correctly. * Fixed Shader:send(name, data, matrixlayout, ...). * Fixed quad offsets in ParticleSystems when ParticleSystem:setOffset is not used. +* Fixed a performance issue with setting a small subrange of data in non-stream Meshes and SpriteBatches. * Fixed rounded rectangles breaking if the rx or ry parameters are negative. * Fixed rounded rectangle automatic points calculation when rx or ry are more than half the rectangle's size. * Fixed source code compilation on Xcode 12+. diff --git a/platform/xcode/ios/luajit-iOS.sh b/platform/xcode/ios/luajit-iOS.sh index b8b3e1720..0533b4138 100755 --- a/platform/xcode/ios/luajit-iOS.sh +++ b/platform/xcode/ios/luajit-iOS.sh @@ -1,25 +1,25 @@ mkdir -p include/luajit mkdir -p libraries/luajit -git clone https://github.com/LuaJIT/LuaJIT.git luajit-git +if [ ! -d luajit-git ]; then + git clone https://github.com/LuaJIT/LuaJIT.git luajit-git +fi cd luajit-git -git pull +git pull --no-rebase git checkout v2.1 +export MACOSX_DEPLOYMENT_TARGET=10.7 + # iOS device binaries +# LuaJIT does not support building for armv7 on modern macOS versions. ISDKP=$(xcrun --sdk iphoneos --show-sdk-path) ICC=$(xcrun --sdk iphoneos --find clang) -ISDKF="-arch armv7 -isysroot $ISDKP -mios-version-min=8.0" -make clean -make -j8 HOST_CC="clang -m32 -arch i386" CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS -cp src/libluajit.a ../libraries/luajit/libluajit_arm7.a - ISDKF="-arch arm64 -isysroot $ISDKP -mios-version-min=8.0" -make clean -make -j8 CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS -cp src/libluajit.a ../libraries/luajit/libluajit_arm64.a +make clean TARGET_SYS=iOS +make -j8 CC="clang" CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS +cp src/libluajit.a ../libraries/luajit/libluajit_arm64_device.a # iOS simulator binaries @@ -27,15 +27,15 @@ cp src/libluajit.a ../libraries/luajit/libluajit_arm64.a ISDKP=$(xcrun --sdk iphonesimulator --show-sdk-path) ICC=$(xcrun --sdk iphonesimulator --find clang) -ISDKF="-arch i386 -isysroot $ISDKP -mios-simulator-version-min=8.0" -make clean -make -j8 HOST_CC="clang -m32 -arch i386" CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS -cp src/libluajit.a ../libraries/luajit/libluajit_x86.a - ISDKF="-arch x86_64 -isysroot $ISDKP -mios-simulator-version-min=8.0" -make clean -make -j8 CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS -cp src/libluajit.a ../libraries/luajit/libluajit_x86_64.a +make clean TARGET_SYS=iOS +make -j8 CC="clang" CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS +cp src/libluajit.a ../libraries/luajit/libluajit_x86_64_sim.a + +ISDKF="-arch arm64 -isysroot $ISDKP -mios-simulator-version-min=8.0" +make clean TARGET_SYS=iOS +make -j8 CC="clang" CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS +cp src/libluajit.a ../libraries/luajit/libluajit_arm64_sim.a # copy includes @@ -49,4 +49,9 @@ cp src/luajit.h ../include/luajit # combine lib cd ../libraries/luajit -lipo -create -output libluajit.a libluajit_arm7.a libluajit_arm64.a libluajit_x86.a libluajit_x86_64.a +lipo -create -output libluajit_device.a libluajit_arm64_device.a +lipo -create -output libluajit_sim.a libluajit_x86_64_sim.a libluajit_arm64_sim.a + +# create xcframework with all platforms +rm -rf Lua.xcframework +xcodebuild -create-xcframework -library libluajit_device.a -headers ../../include/luajit -library libluajit_sim.a -headers ../../include/luajit -output Lua.xcframework diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 77c9884e5..19b702fdd 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -794,7 +794,6 @@ FA56AA381FAFF02000A43D5F /* memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA56AA361FAFF02000A43D5F /* memory.cpp */; }; FA56AA391FAFF02000A43D5F /* memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA56AA361FAFF02000A43D5F /* memory.cpp */; }; FA56AA3A1FAFF02000A43D5F /* memory.h in Headers */ = {isa = PBXBuildFile; fileRef = FA56AA371FAFF02000A43D5F /* memory.h */; }; - FA56D9BC1C208A0200D8D3C7 /* libmodplug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA56D9BA1C2089EE00D8D3C7 /* libmodplug.a */; }; FA577AB016C7507900860150 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7916C71A1700860150 /* Cocoa.framework */; }; FA577AC516C7513400860150 /* libmodplug.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A8216C71A5300860150 /* libmodplug.framework */; }; FA577AC816C7513C00860150 /* ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7116C719F400860150 /* ogg.framework */; }; @@ -804,10 +803,6 @@ FA57FB991AE1993600F2AD6D /* noise1234.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA57FB961AE1993600F2AD6D /* noise1234.cpp */; }; FA57FB9A1AE1993600F2AD6D /* noise1234.h in Headers */ = {isa = PBXBuildFile; fileRef = FA57FB971AE1993600F2AD6D /* noise1234.h */; }; FA59A2D31C06481400328DBA /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE272501C05A15B00A67640 /* ParticleSystem.cpp */; }; - FA59A2D81C0649C200328DBA /* libtheora.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA59A2D61C0649BB00328DBA /* libtheora.a */; }; - FA5D24B31A96D2EC00C6FC8F /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA5D24AB1A96D2EC00C6FC8F /* libogg.a */; }; - FA5D24B51A96D2EC00C6FC8F /* libvorbis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA5D24AF1A96D2EC00C6FC8F /* libvorbis.a */; }; - FA5D24CF1A96E68300C6FC8F /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA5D24CD1A96E63D00C6FC8F /* libSDL2.a */; }; FA620A321AA2F8DB005DB4C2 /* wrap_Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A2E1AA2F8DB005DB4C2 /* wrap_Quad.cpp */; }; FA620A331AA2F8DB005DB4C2 /* wrap_Quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A2E1AA2F8DB005DB4C2 /* wrap_Quad.cpp */; }; FA620A341AA2F8DB005DB4C2 /* wrap_Quad.h in Headers */ = {isa = PBXBuildFile; fileRef = FA620A2F1AA2F8DB005DB4C2 /* wrap_Quad.h */; }; @@ -831,12 +826,16 @@ FA6A2B7A1F60B8250074C308 /* wrap_ByteData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */; }; FA6A2B7B1F60B8250074C308 /* wrap_ByteData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */; }; FA6BDE5C1F31725300786805 /* Color.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6BDE5B1F31725300786805 /* Color.h */; }; - FA7550A81AEBE276003E311E /* libluajit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA7550A71AEBE276003E311E /* libluajit.a */; }; FA76344A1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; }; FA76344B1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; }; FA76344C1E28722A0066EF9E /* StreamBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7634491E28722A0066EF9E /* StreamBuffer.h */; }; FA84DE612778D7F3002674C6 /* SpirvIntrinsics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA84DE602778D7F3002674C6 /* SpirvIntrinsics.cpp */; }; FA84DE622778D7F3002674C6 /* SpirvIntrinsics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA84DE602778D7F3002674C6 /* SpirvIntrinsics.cpp */; }; + FA7E9207277E120900C24CB2 /* theora.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA7E9206277E120900C24CB2 /* theora.xcframework */; }; + FA84DE76277CB3D5002674C6 /* SDL2.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA84DE75277CB3D4002674C6 /* SDL2.xcframework */; }; + FA84DE7A277D4C88002674C6 /* modplug.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA84DE79277D4C88002674C6 /* modplug.xcframework */; }; + FA84DE7C277E045E002674C6 /* ogg.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA84DE7B277E045E002674C6 /* ogg.xcframework */; }; + FA84DE7E277E0A43002674C6 /* vorbis.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA84DE7D277E0A43002674C6 /* vorbis.xcframework */; }; FA8951A21AA2EDF300EC385A /* wrap_Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA8951A01AA2EDF300EC385A /* wrap_Event.cpp */; }; FA8951A31AA2EDF300EC385A /* wrap_Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA8951A01AA2EDF300EC385A /* wrap_Event.cpp */; }; FA8951A41AA2EDF300EC385A /* wrap_Event.h in Headers */ = {isa = PBXBuildFile; fileRef = FA8951A11AA2EDF300EC385A /* wrap_Event.h */; }; @@ -1091,6 +1090,8 @@ FACA02FB1F5E397E0084B28F /* HashFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E61F5E396B0084B28F /* HashFunction.cpp */; }; FACA02FC1F5E39810084B28F /* wrap_CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E81F5E396B0084B28F /* wrap_CompressedData.cpp */; }; FACA02FD1F5E39840084B28F /* wrap_DataModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02EA1F5E396B0084B28F /* wrap_DataModule.cpp */; }; + FACFB751276D7E3B0089F78D /* freetype.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FACFB750276D7E2B0089F78D /* freetype.xcframework */; }; + FACFB753276D7F860089F78D /* Lua.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = FACFB752276D7F6F0089F78D /* Lua.xcframework */; }; FAD19A171DFF8CA200D5398A /* ImageDataBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAD19A151DFF8CA200D5398A /* ImageDataBase.cpp */; }; FAD19A181DFF8CA200D5398A /* ImageDataBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAD19A151DFF8CA200D5398A /* ImageDataBase.cpp */; }; FAD19A191DFF8CA200D5398A /* ImageDataBase.h in Headers */ = {isa = PBXBuildFile; fileRef = FAD19A161DFF8CA200D5398A /* ImageDataBase.h */; }; @@ -1131,7 +1132,6 @@ FADF543D1E3DAFF700012CC0 /* wrap_Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */; }; FAE272521C05A15B00A67640 /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE272501C05A15B00A67640 /* ParticleSystem.cpp */; }; FAE272531C05A15B00A67640 /* ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE272511C05A15B00A67640 /* ParticleSystem.h */; }; - FAE64A7F207135AD00BC7981 /* libfreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FAE64A7D2071359C00BC7981 /* libfreetype.a */; }; FAE64A802071362A00BC7981 /* physfs_archiver_7z.c in Sources */ = {isa = PBXBuildFile; fileRef = FAC7CD5D1FE35E95006A60C7 /* physfs_archiver_7z.c */; }; FAE64A812071363100BC7981 /* physfs_archiver_dir.c in Sources */ = {isa = PBXBuildFile; fileRef = FAC7CD6C1FE35E95006A60C7 /* physfs_archiver_dir.c */; }; FAE64A822071363100BC7981 /* physfs_archiver_grp.c in Sources */ = {isa = PBXBuildFile; fileRef = FAC7CD741FE35E95006A60C7 /* physfs_archiver_grp.c */; }; @@ -1861,7 +1861,6 @@ FA522D5923FA5ED40059EE3C /* NotoSans-Regular.ttf.gzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NotoSans-Regular.ttf.gzip.h"; sourceTree = ""; }; FA56AA361FAFF02000A43D5F /* memory.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = memory.cpp; sourceTree = ""; }; FA56AA371FAFF02000A43D5F /* memory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = ""; }; - FA56D9BA1C2089EE00D8D3C7 /* libmodplug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libmodplug.a; sourceTree = ""; }; FA577A6D16C719EA00860150 /* Lua.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Lua.framework; path = macosx/Frameworks/Lua.framework; sourceTree = ""; }; FA577A7116C719F400860150 /* ogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ogg.framework; path = macosx/Frameworks/ogg.framework; sourceTree = ""; }; FA577A7716C71A0800860150 /* vorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = vorbis.framework; path = macosx/Frameworks/vorbis.framework; sourceTree = ""; }; @@ -1873,10 +1872,6 @@ FA577AAF16C7507900860150 /* love.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FA57FB961AE1993600F2AD6D /* noise1234.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = noise1234.cpp; sourceTree = ""; }; FA57FB971AE1993600F2AD6D /* noise1234.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = noise1234.h; sourceTree = ""; }; - FA59A2D61C0649BB00328DBA /* libtheora.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libtheora.a; sourceTree = ""; }; - FA5D24AB1A96D2EC00C6FC8F /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libogg.a; sourceTree = ""; }; - FA5D24AF1A96D2EC00C6FC8F /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libvorbis.a; sourceTree = ""; }; - FA5D24CD1A96E63D00C6FC8F /* libSDL2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libSDL2.a; sourceTree = ""; }; FA620A2E1AA2F8DB005DB4C2 /* wrap_Quad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Quad.cpp; sourceTree = ""; }; FA620A2F1AA2F8DB005DB4C2 /* wrap_Quad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Quad.h; sourceTree = ""; }; FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = ""; }; @@ -1894,7 +1889,6 @@ FA6A2B771F60B8250074C308 /* wrap_ByteData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_ByteData.h; sourceTree = ""; }; FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_ByteData.cpp; sourceTree = ""; }; FA6BDE5B1F31725300786805 /* Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Color.h; sourceTree = ""; }; - FA7550A71AEBE276003E311E /* libluajit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libluajit.a; sourceTree = ""; }; FA7634481E28722A0066EF9E /* StreamBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamBuffer.cpp; sourceTree = ""; }; FA7634491E28722A0066EF9E /* StreamBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamBuffer.h; sourceTree = ""; }; FA7DA04C1C16874A0056B200 /* wrap_Math.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wrap_Math.lua; sourceTree = ""; }; @@ -1902,6 +1896,11 @@ FA84DE5E2778D7DC002674C6 /* glslang_c_interface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glslang_c_interface.h; sourceTree = ""; }; FA84DE5F2778D7DC002674C6 /* glslang_c_shader_types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = glslang_c_shader_types.h; sourceTree = ""; }; FA84DE602778D7F3002674C6 /* SpirvIntrinsics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpirvIntrinsics.cpp; sourceTree = ""; }; + FA7E9206277E120900C24CB2 /* theora.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = theora.xcframework; path = ios/libraries/theora.xcframework; sourceTree = ""; }; + FA84DE75277CB3D4002674C6 /* SDL2.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = SDL2.xcframework; path = ios/libraries/SDL2.xcframework; sourceTree = ""; }; + FA84DE79277D4C88002674C6 /* modplug.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = modplug.xcframework; path = ios/libraries/modplug.xcframework; sourceTree = ""; }; + FA84DE7B277E045E002674C6 /* ogg.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ogg.xcframework; path = ios/libraries/ogg.xcframework; sourceTree = ""; }; + FA84DE7D277E0A43002674C6 /* vorbis.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = vorbis.xcframework; path = ios/libraries/vorbis.xcframework; sourceTree = ""; }; FA8951A01AA2EDF300EC385A /* wrap_Event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Event.cpp; sourceTree = ""; }; FA8951A11AA2EDF300EC385A /* wrap_Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = ""; }; FA91DA891F377C3900C80E33 /* deprecation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = deprecation.cpp; sourceTree = ""; }; @@ -2091,6 +2090,8 @@ FACA02E91F5E396B0084B28F /* wrap_CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_CompressedData.h; sourceTree = ""; }; FACA02EA1F5E396B0084B28F /* wrap_DataModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_DataModule.cpp; sourceTree = ""; }; FACA02EB1F5E396B0084B28F /* wrap_DataModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DataModule.h; sourceTree = ""; }; + FACFB750276D7E2B0089F78D /* freetype.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = freetype.xcframework; path = ios/libraries/freetype.xcframework; sourceTree = ""; }; + FACFB752276D7F6F0089F78D /* Lua.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Lua.xcframework; path = ios/libraries/Lua.xcframework; sourceTree = ""; }; FAD19A151DFF8CA200D5398A /* ImageDataBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDataBase.cpp; sourceTree = ""; }; FAD19A161DFF8CA200D5398A /* ImageDataBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDataBase.h; sourceTree = ""; }; FAD43ECB1FF312D800831BB8 /* freetype.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = freetype.framework; path = macosx/Frameworks/freetype.framework; sourceTree = ""; }; @@ -2121,8 +2122,6 @@ FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Graphics.h; sourceTree = ""; }; FAE272501C05A15B00A67640 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = ""; }; FAE272511C05A15B00A67640 /* ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSystem.h; sourceTree = ""; }; - FAE64A7D2071359C00BC7981 /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libfreetype.a; sourceTree = ""; }; - FAEC22942534EE6700EBD925 /* NonSemanticDebugPrintf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NonSemanticDebugPrintf.h; sourceTree = ""; }; FAEC229F2534F25100EBD925 /* build_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = build_info.h; sourceTree = ""; }; FAECA1B01F3164700095D008 /* CompressedSlice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedSlice.cpp; sourceTree = ""; }; FAECA1B11F3164700095D008 /* CompressedSlice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompressedSlice.h; sourceTree = ""; }; @@ -2221,13 +2220,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - FA5D24B51A96D2EC00C6FC8F /* libvorbis.a in Frameworks */, - FAE64A7F207135AD00BC7981 /* libfreetype.a in Frameworks */, - FA5D24B31A96D2EC00C6FC8F /* libogg.a in Frameworks */, - FA59A2D81C0649C200328DBA /* libtheora.a in Frameworks */, - FA56D9BC1C208A0200D8D3C7 /* libmodplug.a in Frameworks */, - FA7550A81AEBE276003E311E /* libluajit.a in Frameworks */, - FA5D24CF1A96E68300C6FC8F /* libSDL2.a in Frameworks */, + FACFB751276D7E3B0089F78D /* freetype.xcframework in Frameworks */, + FA84DE7A277D4C88002674C6 /* modplug.xcframework in Frameworks */, + FA84DE7C277E045E002674C6 /* ogg.xcframework in Frameworks */, + FACFB753276D7F860089F78D /* Lua.xcframework in Frameworks */, + FA7E9207277E120900C24CB2 /* theora.xcframework in Frameworks */, + FA84DE76277CB3D5002674C6 /* SDL2.xcframework in Frameworks */, + FA84DE7E277E0A43002674C6 /* vorbis.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3439,15 +3438,6 @@ path = dr; sourceTree = ""; }; - FA56D9B91C2089CE00D8D3C7 /* modplug */ = { - isa = PBXGroup; - children = ( - FA56D9BA1C2089EE00D8D3C7 /* libmodplug.a */, - ); - name = modplug; - path = ios/libraries/modplug; - sourceTree = ""; - }; FA577A6616C7199700860150 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -3457,15 +3447,6 @@ name = Frameworks; sourceTree = ""; }; - FA59A2D51C0649BB00328DBA /* theora */ = { - isa = PBXGroup; - children = ( - FA59A2D61C0649BB00328DBA /* libtheora.a */, - ); - name = theora; - path = ios/libraries/theora; - sourceTree = ""; - }; FA5D24A11A96D24500C6FC8F /* Libraries */ = { isa = PBXGroup; children = ( @@ -3477,62 +3458,17 @@ FA5D24A31A96D2C300C6FC8F /* ios */ = { isa = PBXGroup; children = ( - FA5D24A41A96D2EC00C6FC8F /* freetype */, - FA7550A61AEBE250003E311E /* luajit */, - FA56D9B91C2089CE00D8D3C7 /* modplug */, - FA5D24AA1A96D2EC00C6FC8F /* ogg */, - FA5D24CC1A96E63D00C6FC8F /* SDL2 */, - FA59A2D51C0649BB00328DBA /* theora */, - FA5D24AE1A96D2EC00C6FC8F /* vorbis */, + FACFB750276D7E2B0089F78D /* freetype.xcframework */, + FACFB752276D7F6F0089F78D /* Lua.xcframework */, + FA84DE79277D4C88002674C6 /* modplug.xcframework */, + FA84DE7B277E045E002674C6 /* ogg.xcframework */, + FA84DE75277CB3D4002674C6 /* SDL2.xcframework */, + FA7E9206277E120900C24CB2 /* theora.xcframework */, + FA84DE7D277E0A43002674C6 /* vorbis.xcframework */, ); name = ios; sourceTree = ""; }; - FA5D24A41A96D2EC00C6FC8F /* freetype */ = { - isa = PBXGroup; - children = ( - FAE64A7D2071359C00BC7981 /* libfreetype.a */, - ); - name = freetype; - path = ios/libraries/freetype; - sourceTree = ""; - }; - FA5D24AA1A96D2EC00C6FC8F /* ogg */ = { - isa = PBXGroup; - children = ( - FA5D24AB1A96D2EC00C6FC8F /* libogg.a */, - ); - name = ogg; - path = ios/libraries/ogg; - sourceTree = ""; - }; - FA5D24AE1A96D2EC00C6FC8F /* vorbis */ = { - isa = PBXGroup; - children = ( - FA5D24AF1A96D2EC00C6FC8F /* libvorbis.a */, - ); - name = vorbis; - path = ios/libraries/vorbis; - sourceTree = ""; - }; - FA5D24CC1A96E63D00C6FC8F /* SDL2 */ = { - isa = PBXGroup; - children = ( - FA5D24CD1A96E63D00C6FC8F /* libSDL2.a */, - ); - name = SDL2; - path = ios/libraries/SDL2; - sourceTree = ""; - }; - FA7550A61AEBE250003E311E /* luajit */ = { - isa = PBXGroup; - children = ( - FA7550A71AEBE276003E311E /* libluajit.a */, - ); - name = luajit; - path = ios/libraries/luajit; - sourceTree = ""; - }; FAAA3FD21F64B3AD00F89E99 /* lua53 */ = { isa = PBXGroup; children = ( @@ -5436,32 +5372,17 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD_64_BIT)"; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/ios/libraries"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", LOVE_SUPPORT_COREAUDIO, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - ios/include, - ios/include/luajit, - ios/include/freetype, - ios/include/SDL2, - ios/include/modplug, - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ios/libraries/freetype", - "$(PROJECT_DIR)/ios/libraries/lua", - "$(PROJECT_DIR)/ios/libraries/ogg", - "$(PROJECT_DIR)/ios/libraries/physfs", - "$(PROJECT_DIR)/ios/libraries/vorbis", - "$(PROJECT_DIR)/ios/libraries/SDL2", - "$(PROJECT_DIR)/ios/libraries/luajit", - "$(PROJECT_DIR)/ios/libraries/theora", - "$(PROJECT_DIR)/ios/libraries/modplug", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = love; @@ -5475,33 +5396,18 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD_64_BIT)"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/ios/libraries"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", LOVE_SUPPORT_COREAUDIO, ); GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - ios/include, - ios/include/luajit, - ios/include/freetype, - ios/include/SDL2, - ios/include/modplug, - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ios/libraries/freetype", - "$(PROJECT_DIR)/ios/libraries/lua", - "$(PROJECT_DIR)/ios/libraries/ogg", - "$(PROJECT_DIR)/ios/libraries/physfs", - "$(PROJECT_DIR)/ios/libraries/vorbis", - "$(PROJECT_DIR)/ios/libraries/SDL2", - "$(PROJECT_DIR)/ios/libraries/luajit", - "$(PROJECT_DIR)/ios/libraries/theora", - "$(PROJECT_DIR)/ios/libraries/modplug", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = love; @@ -5516,33 +5422,18 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD_64_BIT)"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/ios/libraries"; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", LOVE_SUPPORT_COREAUDIO, ); GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - ios/include, - ios/include/luajit, - ios/include/freetype, - ios/include/SDL2, - ios/include/modplug, - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ios/libraries/freetype", - "$(PROJECT_DIR)/ios/libraries/lua", - "$(PROJECT_DIR)/ios/libraries/ogg", - "$(PROJECT_DIR)/ios/libraries/physfs", - "$(PROJECT_DIR)/ios/libraries/vorbis", - "$(PROJECT_DIR)/ios/libraries/SDL2", - "$(PROJECT_DIR)/ios/libraries/luajit", - "$(PROJECT_DIR)/ios/libraries/theora", - "$(PROJECT_DIR)/ios/libraries/modplug", - ); + HEADER_SEARCH_PATHS = "$(inherited)"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = love; diff --git a/platform/xcode/love.xcodeproj/project.pbxproj b/platform/xcode/love.xcodeproj/project.pbxproj index 3fb686283..8689ff40e 100644 --- a/platform/xcode/love.xcodeproj/project.pbxproj +++ b/platform/xcode/love.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ FA5D24C21A96D78000C6FC8F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA5D24C11A96D78000C6FC8F /* Foundation.framework */; }; FA5D24D11A96E73300C6FC8F /* liblove.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA0B7EEF1A95924A000E1D17 /* liblove.a */; }; FA7C636A1A9C49570000FD29 /* Launch Screen.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA7C63691A9C49570000FD29 /* Launch Screen.xib */; }; + FA84DE78277CB55B002674C6 /* CoreHaptics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA84DE77277CB55B002674C6 /* CoreHaptics.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; FA9B4A0A16E1579F00074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0916E1579F00074F42 /* SDL2.framework */; }; FA9B4A0B16E157B500074F42 /* SDL2.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0916E1579F00074F42 /* SDL2.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; FAAFF04716CB120000CCDE45 /* OpenAL-Soft.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04616CB120000CCDE45 /* OpenAL-Soft.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -125,6 +126,7 @@ FA5D249A1A96CF4300C6FC8F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; FA5D24C11A96D78000C6FC8F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; FA7C63691A9C49570000FD29 /* Launch Screen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = "Launch Screen.xib"; path = "ios/Launch Screen.xib"; sourceTree = ""; }; + FA84DE77277CB55B002674C6 /* CoreHaptics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreHaptics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/CoreHaptics.framework; sourceTree = DEVELOPER_DIR; }; FA9B4A0916E1579F00074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = macosx/Frameworks/SDL2.framework; sourceTree = ""; }; FAAFF04616CB120000CCDE45 /* OpenAL-Soft.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OpenAL-Soft.framework"; path = "macosx/Frameworks/OpenAL-Soft.framework"; sourceTree = ""; }; FAC1A448196F5DC600125284 /* license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = license.txt; path = ../../license.txt; sourceTree = ""; }; @@ -150,6 +152,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + FA84DE78277CB55B002674C6 /* CoreHaptics.framework in Frameworks */, FAE64A9D2072738600BC7981 /* Metal.framework in Frameworks */, FA15DFB41F9B8D9E0042AB22 /* libbz2.tbd in Frameworks */, CE73F8001EEB64150052DAB3 /* AVFoundation.framework in Frameworks */, @@ -173,6 +176,7 @@ 1058C7A0FEA54F0111CA2CBB /* Frameworks */ = { isa = PBXGroup; children = ( + FA84DE77277CB55B002674C6 /* CoreHaptics.framework */, FAE64A9C2072738600BC7981 /* Metal.framework */, FA15DFB31F9B8D9E0042AB22 /* libbz2.tbd */, CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */, @@ -645,6 +649,7 @@ FA0B7F261A95AAF4000E1D17 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; ASSETCATALOG_COMPILER_APPICON_NAME = "iOS AppIcon"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -661,11 +666,10 @@ DEVELOPMENT_TEAM = ""; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - EXCLUDED_ARCHS = ""; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", + "$(PROJECT_DIR)/ios/libraries", ); GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -681,8 +685,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", ios/include, - ios/include/luajit, - ios/include/SDL2, ); INFOPLIST_FILE = "$(SRCROOT)/ios/love-ios.plist"; LD_RUNPATH_SEARCH_PATHS = ( @@ -702,6 +704,7 @@ FA0B7F271A95AAF4000E1D17 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; ASSETCATALOG_COMPILER_APPICON_NAME = "iOS AppIcon"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -719,11 +722,10 @@ ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - EXCLUDED_ARCHS = ""; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", + "$(PROJECT_DIR)/ios/libraries", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -733,8 +735,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", ios/include, - ios/include/luajit, - ios/include/SDL2, ); INFOPLIST_FILE = "$(SRCROOT)/ios/love-ios.plist"; LD_RUNPATH_SEARCH_PATHS = ( @@ -755,6 +755,7 @@ FA0B7F281A95AAF4000E1D17 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; ASSETCATALOG_COMPILER_APPICON_NAME = "iOS AppIcon"; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -772,11 +773,10 @@ ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - EXCLUDED_ARCHS = ""; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", + "$(PROJECT_DIR)/ios/libraries", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -786,8 +786,6 @@ HEADER_SEARCH_PATHS = ( "$(inherited)", ios/include, - ios/include/luajit, - ios/include/SDL2, ); INFOPLIST_FILE = "$(SRCROOT)/ios/love-ios.plist"; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/readme.md b/readme.md index 4134a8e11..aa6c337e2 100644 --- a/readme.md +++ b/readme.md @@ -54,15 +54,26 @@ Run `platform/unix/automagic` from the repository root, then run ./configure and When using a source release, automagic has already been run, and the first step can be skipped. ### macOS -Download or clone [this repository][dependencies-macos] and place the Frameworks subfolder in love's `platform/xcode/macosx/` folder. +Download or clone [this repository][dependencies-apple] and copy, move, or symlink the `macOS/Frameworks` subfolder into love's `platform/xcode/macosx` folder. Then use the Xcode project found at `platform/xcode/love.xcodeproj` to build the `love-macosx` target. ### iOS Building for iOS requires macOS and Xcode. -Download the `ios-libraries` zip file corresponding to the LÖVE version being used from [here][dependencies-ios], -unzip it, and place the `include` and `libraries` subfolders into LÖVE's `platform/xcode/ios` folder. +#### 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. + +Or, download or clone [this repository][dependencies-apple] and copy, move, or symlink the `iOS/libraries` subfolder 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. + +#### 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. @@ -88,7 +99,7 @@ Dependencies [forums]: https://love2d.org/forums [discord]: https://discord.gg/rhUets9 [irc]: irc://irc.oftc.net/love -[dependencies-macos]: https://github.com/slime73/love-apple-dependencies +[dependencies-apple]: https://github.com/love2d/love-apple-dependencies [dependencies-ios]: https://github.com/love2d/love/releases [megasource]: https://github.com/love2d/megasource [unstableppa]: https://launchpad.net/~bartbes/+archive/love-unstable diff --git a/src/modules/data/ByteData.cpp b/src/modules/data/ByteData.cpp index 2c59a159e..218522004 100644 --- a/src/modules/data/ByteData.cpp +++ b/src/modules/data/ByteData.cpp @@ -42,7 +42,8 @@ ByteData::ByteData(const void *d, size_t size) : size(size) { create(); - memcpy(data, d, size); + if (d != nullptr) + memcpy(data, d, size); } ByteData::ByteData(void *d, size_t size, bool own) @@ -53,7 +54,8 @@ ByteData::ByteData(void *d, size_t size, bool own) else { create(); - memcpy(data, d, size); + if (d != nullptr) + memcpy(data, d, size); } } diff --git a/src/modules/graphics/Buffer.cpp b/src/modules/graphics/Buffer.cpp index 569bb1e8a..47ea3d76d 100644 --- a/src/modules/graphics/Buffer.cpp +++ b/src/modules/graphics/Buffer.cpp @@ -46,14 +46,10 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectorgetCapabilities(); bool supportsGLSL3 = caps.features[Graphics::FEATURE_GLSL3]; - bool indexbuffer = settings.usageFlags & BUFFERUSAGEFLAG_INDEX; - bool vertexbuffer = settings.usageFlags & BUFFERUSAGEFLAG_VERTEX; - bool texelbuffer = settings.usageFlags & BUFFERUSAGEFLAG_TEXEL; - bool storagebuffer = settings.usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE; - bool copydest = settings.usageFlags & BUFFERUSAGEFLAG_COPY_DEST; - - if (!indexbuffer && !vertexbuffer && !texelbuffer && !storagebuffer) - throw love::Exception("Buffer must be created with at least one buffer type (index, vertex, texel, or shaderstorage)."); + bool indexbuffer = usageFlags & BUFFERUSAGEFLAG_INDEX; + bool vertexbuffer = usageFlags & BUFFERUSAGEFLAG_VERTEX; + bool texelbuffer = usageFlags & BUFFERUSAGEFLAG_TEXEL; + bool storagebuffer = usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE; if (texelbuffer && !caps.features[Graphics::FEATURE_TEXEL_BUFFER]) throw love::Exception("Texel buffers are not supported on this system."); @@ -61,8 +57,11 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vectorgetUsageFlags() & BUFFERUSAGEFLAG_COPY_SOURCE)) - throw love::Exception("Copy source buffer must be created with the copysource flag."); - - if (!(dest->getUsageFlags() & BUFFERUSAGEFLAG_COPY_DEST)) - throw love::Exception("Copy destination buffer must be created with the copydest flag."); - Range sourcerange(sourceoffset, size); Range destrange(destoffset, size); + if (dest->getDataUsage() == BUFFERDATAUSAGE_STREAM) + throw love::Exception("Buffers created with 'stream' data usage cannot be used as a copy destination."); + if (sourcerange.getMax() >= source->getSize()) throw love::Exception("Buffer copy source offset and size doesn't fit within the source Buffer's size."); @@ -1125,6 +1122,169 @@ void Graphics::copyBuffer(Buffer *source, Buffer *dest, size_t sourceoffset, siz source->copyTo(dest, sourceoffset, destoffset, size); } +void Graphics::copyTextureToBuffer(Texture *source, Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth) +{ + if (!capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER]) + { + if (!source->isRenderTarget()) + throw love::Exception("Copying a non-render target Texture to a Buffer is not supported on this system."); + + if (!capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER]) + throw love::Exception("Copying a render target Texture to a Buffer is not supported on this system."); + } + + PixelFormat format = source->getPixelFormat(); + + if (isPixelFormatDepthStencil(format)) + throw love::Exception("Copying a depth/stencil Texture to a Buffer is not supported."); + + if (!source->isReadable()) + throw love::Exception("copyTextureToBuffer can only be called on readable Textures."); + + if (dest->getDataUsage() == BUFFERDATAUSAGE_STREAM) + throw love::Exception("Buffers created with 'stream' data usage cannot be used as a copy destination."); + + if (isRenderTargetActive(source)) + throw love::Exception("copyTextureToBuffer cannot be called while the Texture is an active render target."); + + if (mipmap < 0 || mipmap >= source->getMipmapCount()) + throw love::Exception("Invalid texture mipmap index %d.", mipmap + 1); + + TextureType textype = source->getTextureType(); + if (slice < 0 || (textype == TEXTURE_CUBE && slice >= 6) + || (textype == TEXTURE_VOLUME && slice >= source->getDepth(mipmap)) + || (textype == TEXTURE_2D_ARRAY && slice >= source->getLayerCount())) + { + throw love::Exception("Invalid texture slice index %d.", slice + 1); + } + + int mipw = source->getPixelWidth(mipmap); + int miph = source->getPixelHeight(mipmap); + + if (rect.x < 0 || rect.y < 0 || rect.w <= 0 || rect.h <= 0 + || (rect.x + rect.w) > mipw || (rect.y + rect.h) > miph) + { + throw love::Exception("Invalid rectangle dimensions (x=%d, y=%d, w=%d, h=%d) for %dx%d texture.", rect.x, rect.y, rect.w, rect.h, mipw, miph); + } + + if (destwidth <= 0) + destwidth = rect.w; + + size_t size = 0; + + if (isPixelFormatCompressed(format)) + { + if (destwidth != rect.w) // OpenGL limitation... + throw love::Exception("Copying a compressed texture to a buffer cannot use a custom destination width."); + + const PixelFormatInfo &info = getPixelFormatInfo(format); + int bw = (int) info.blockWidth; + int bh = (int) info.blockHeight; + if (rect.x % bw != 0 || rect.y % bh != 0 || + ((rect.w % bw != 0 || rect.h % bh != 0) && rect.x + rect.w != source->getPixelWidth(mipmap))) + { + const char *name = nullptr; + love::getConstant(format, name); + throw love::Exception("Compressed texture format %s only supports copying a sub-rectangle with offset and dimensions that are a multiple of %d x %d.", name, bw, bh); + } + + // Note: this will need to change if destwidth == rect.w restriction + // is removed. + size = getPixelFormatSliceSize(format, destwidth, rect.h); + } + else + { + // Not the cleanest, but should work since uncompressed formats always + // have 1x1 blocks. + int pixels = (rect.h - 1) * destwidth + rect.w; + size = getPixelFormatUncompressedRowSize(format, pixels); + } + + Range destrange(destoffset, size); + + if (destrange.getMax() >= dest->getSize()) + throw love::Exception("Buffer copy destination offset and width/height doesn't fit within the destination Buffer."); + + source->copyToBuffer(dest, slice, mipmap, rect, destoffset, destwidth, size); +} + +void Graphics::copyBufferToTexture(Buffer *source, Texture *dest, size_t sourceoffset, int sourcewidth, int slice, int mipmap, const Rect &rect) +{ + if (!capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE]) + throw love::Exception("Copying a Buffer to a Texture is not supported on this system."); + + PixelFormat format = dest->getPixelFormat(); + + if (isPixelFormatDepthStencil(format)) + throw love::Exception("Copying a Buffer to a depth/stencil Texture is not supported."); + + if (!dest->isReadable()) + throw love::Exception("copyBufferToTexture can only be called on readable Textures."); + + if (isRenderTargetActive(dest)) + throw love::Exception("copyBufferToTexture cannot be called while the Texture is an active render target."); + + if (mipmap < 0 || mipmap >= dest->getMipmapCount()) + throw love::Exception("Invalid texture mipmap index %d.", mipmap + 1); + + TextureType textype = dest->getTextureType(); + if (slice < 0 || (textype == TEXTURE_CUBE && slice >= 6) + || (textype == TEXTURE_VOLUME && slice >= dest->getDepth(mipmap)) + || (textype == TEXTURE_2D_ARRAY && slice >= dest->getLayerCount())) + { + throw love::Exception("Invalid texture slice index %d.", slice + 1); + } + + int mipw = dest->getPixelWidth(mipmap); + int miph = dest->getPixelHeight(mipmap); + + if (rect.x < 0 || rect.y < 0 || rect.w <= 0 || rect.h <= 0 + || (rect.x + rect.w) > mipw || (rect.y + rect.h) > miph) + { + throw love::Exception("Invalid rectangle dimensions (x=%d, y=%d, w=%d, h=%d) for %dx%d texture.", rect.x, rect.y, rect.w, rect.h, mipw, miph); + } + + if (sourcewidth <= 0) + sourcewidth = rect.w; + + size_t size = 0; + + if (isPixelFormatCompressed(format)) + { + if (sourcewidth != rect.w) // OpenGL limitation... + throw love::Exception("Copying a buffer to a compressed texture cannot use a custom source width."); + + const PixelFormatInfo &info = getPixelFormatInfo(format); + int bw = (int) info.blockWidth; + int bh = (int) info.blockHeight; + if (rect.x % bw != 0 || rect.y % bh != 0 || + ((rect.w % bw != 0 || rect.h % bh != 0) && rect.x + rect.w != dest->getPixelWidth(mipmap))) + { + const char *name = nullptr; + love::getConstant(format, name); + throw love::Exception("Compressed texture format %s only supports copying a sub-rectangle with offset and dimensions that are a multiple of %d x %d.", name, bw, bh); + } + + // Note: this will need to change if sourcewidth == rect.w restriction + // is removed. + size = getPixelFormatSliceSize(format, sourcewidth, rect.h); + } + else + { + // Not the cleanest, but should work since uncompressed formats always + // have 1x1 blocks. + int pixels = (rect.h - 1) * sourcewidth + rect.w; + size = getPixelFormatUncompressedRowSize(format, pixels); + } + + Range sourcerange(sourceoffset, size); + + if (sourcerange.getMax() >= source->getSize()) + throw love::Exception("Buffer copy source offset and width/height doesn't fit within the source Buffer."); + + dest->copyFromBuffer(source, sourceoffset, sourcewidth, size, slice, mipmap, rect); +} + void Graphics::dispatchThreadgroups(Shader* shader, int x, int y, int z) { if (!shader->hasStage(SHADERSTAGE_COMPUTE)) @@ -1956,6 +2116,9 @@ STRINGMAP_CLASS_BEGIN(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, f { "instancing", Graphics::FEATURE_INSTANCING }, { "texelbuffer", Graphics::FEATURE_TEXEL_BUFFER }, { "copybuffer", Graphics::FEATURE_COPY_BUFFER }, + { "copybuffertotexture", Graphics::FEATURE_COPY_BUFFER_TO_TEXTURE }, + { "copytexturetobuffer", Graphics::FEATURE_COPY_TEXTURE_TO_BUFFER }, + { "copyrendertargettobuffer", Graphics::FEATURE_COPY_RENDER_TARGET_TO_BUFFER }, } STRINGMAP_CLASS_END(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, feature) diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index f9f9ac7fd..56119b96c 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -145,6 +145,9 @@ public: FEATURE_INSTANCING, FEATURE_TEXEL_BUFFER, FEATURE_COPY_BUFFER, + FEATURE_COPY_BUFFER_TO_TEXTURE, + FEATURE_COPY_TEXTURE_TO_BUFFER, + FEATURE_COPY_RENDER_TARGET_TO_BUFFER, FEATURE_MAX_ENUM }; @@ -675,6 +678,8 @@ public: void captureScreenshot(const ScreenshotInfo &info); void copyBuffer(Buffer *source, Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size); + void copyTextureToBuffer(Texture *source, Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth); + void copyBufferToTexture(Buffer *source, Texture *dest, size_t sourceoffset, int sourcewidth, int slice, int mipmap, const Rect &rect); void dispatchThreadgroups(Shader* shader, int x, int y, int z); diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 02ea677fc..f27e77d11 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -473,9 +473,18 @@ void Texture::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap throw love::Exception("Invalid rectangle dimensions (x=%d, y=%d, w=%d, h=%d) for %dx%d Texture.", rect.x, rect.y, rect.w, rect.h, mipw, miph); } - // We don't currently support partial updates of compressed textures. if (isPixelFormatCompressed(d->getFormat()) && (rect.x != 0 || rect.y != 0 || rect.w != mipw || rect.h != miph)) - throw love::Exception("Compressed textures only support replacing the entire Texture."); + { + const PixelFormatInfo &info = getPixelFormatInfo(d->getFormat()); + int bw = (int) info.blockWidth; + int bh = (int) info.blockHeight; + if (rect.x % bw != 0 || rect.y % bh != 0 || rect.w % bw != 0 || rect.h % bh != 0) + { + const char *name = nullptr; + love::getConstant(d->getFormat(), name); + throw love::Exception("Compressed texture format %s only supports replacing a sub-rectangle with offset and dimensions that are a multiple of %d x %d.", name, bw, bh); + } + } Graphics::flushBatchedDrawsGlobal(); diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index 99a1ba556..08cbce8bb 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -46,6 +46,7 @@ namespace graphics { class Graphics; +class Buffer; enum TextureType { @@ -246,6 +247,9 @@ public: love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect); + virtual void copyFromBuffer(Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) = 0; + virtual void copyToBuffer(Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) = 0; + virtual ptrdiff_t getRenderTargetHandle() const = 0; virtual ptrdiff_t getSamplerHandle() const = 0; diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index 19d31a24d..eb42048e8 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -2100,7 +2100,10 @@ void Graphics::initCapabilities() capabilities.features[FEATURE_INSTANCING] = true; capabilities.features[FEATURE_TEXEL_BUFFER] = true; capabilities.features[FEATURE_COPY_BUFFER] = true; - static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); + capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = true; + capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = true; + capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER] = true; + static_assert(FEATURE_MAX_ENUM == 15, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf capabilities.limits[LIMIT_POINT_SIZE] = 511; diff --git a/src/modules/graphics/metal/Texture.h b/src/modules/graphics/metal/Texture.h index 605ea7092..ac941f4e3 100644 --- a/src/modules/graphics/metal/Texture.h +++ b/src/modules/graphics/metal/Texture.h @@ -40,6 +40,9 @@ public: Texture(love::graphics::Graphics *gfx, id device, const Settings &settings, const Slices *data); virtual ~Texture(); + void copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) override; + void copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) override; + void setSamplerState(const SamplerState &s) override; ptrdiff_t getHandle() const override { return (ptrdiff_t) texture; } diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index 1bc681fa4..8b4c96571 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/src/modules/graphics/metal/Texture.mm @@ -258,6 +258,16 @@ void Texture::readbackImageData(love::image::ImageData *imagedata, int slice, in memcpy(imagedata->getData(), buffer.contents, imagedata->getSize()); }} +void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) +{ + // TODO +} + +void Texture::copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) +{ + // TODO +} + void Texture::setSamplerState(const SamplerState &s) { @autoreleasepool { // Base class does common validation and assigns samplerState. diff --git a/src/modules/graphics/opengl/Buffer.cpp b/src/modules/graphics/opengl/Buffer.cpp index bda488159..d9f880281 100644 --- a/src/modules/graphics/opengl/Buffer.cpp +++ b/src/modules/graphics/opengl/Buffer.cpp @@ -80,10 +80,6 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st mapUsage = BUFFERUSAGE_INDEX; else if (usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE) mapUsage = BUFFERUSAGE_SHADER_STORAGE; - else if (usageFlags & BUFFERUSAGEFLAG_COPY_SOURCE) - mapUsage = BUFFERUSAGE_COPY_SOURCE; - else if (usageFlags & BUFFERUSAGEFLAG_COPY_DEST) - mapUsage = BUFFERUSAGE_COPY_DEST; target = OpenGL::getGLBufferType(mapUsage); @@ -161,6 +157,11 @@ bool Buffer::load(const void *initialdata) return (glGetError() == GL_NO_ERROR); } +bool Buffer::supportsOrphan() const +{ + return dataUsage == BUFFERDATAUSAGE_STREAM || dataUsage == BUFFERDATAUSAGE_DYNAMIC; +} + void *Buffer::map(MapType /*map*/, size_t offset, size_t size) { if (size == 0) @@ -206,7 +207,7 @@ void Buffer::unmap(size_t usedoffset, size_t usedsize) mapped = false; // Orphan optimization - see fill(). - if (dataUsage != BUFFERDATAUSAGE_STATIC && mappedRange.first == 0 && mappedRange.getSize() == getSize()) + if (supportsOrphan() && mappedRange.first == 0 && mappedRange.getSize() == getSize()) { usedoffset = 0; usedsize = getSize(); @@ -238,15 +239,14 @@ void Buffer::fill(size_t offset, size_t size, const void *data) gl.bindBuffer(mapUsage, buffer); - if (dataUsage != BUFFERDATAUSAGE_STATIC && size == buffersize) + if (supportsOrphan() && size == buffersize) { // "orphan" current buffer to avoid implicit synchronisation on the GPU: // http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf - gl.bindBuffer(mapUsage, buffer); glBufferData(target, (GLsizeiptr) buffersize, nullptr, gldatausage); #if LOVE_WINDOWS - // TODO: Verify that this codepath is a useful optimization. + // TODO: Verify that this intel codepath is a useful optimization. if (gl.getVendor() == OpenGL::VENDOR_INTEL) glBufferData(target, (GLsizeiptr) buffersize, data, gldatausage); else @@ -261,8 +261,9 @@ void Buffer::fill(size_t offset, size_t size, const void *data) void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) { - gl.bindBuffer(BUFFERUSAGE_COPY_SOURCE, buffer); - gl.bindBuffer(BUFFERUSAGE_COPY_DEST, ((Buffer *) dest)->buffer); + // TODO: tracked state for these bind types? + glBindBuffer(GL_COPY_READ_BUFFER, buffer); + glBindBuffer(GL_COPY_WRITE_BUFFER, ((Buffer *) dest)->buffer); glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sourceoffset, destoffset, size); } diff --git a/src/modules/graphics/opengl/Buffer.h b/src/modules/graphics/opengl/Buffer.h index f25f61bc0..87b89cb7c 100644 --- a/src/modules/graphics/opengl/Buffer.h +++ b/src/modules/graphics/opengl/Buffer.h @@ -61,9 +61,7 @@ public: private: bool load(const void *initialdata); - - void unmapStatic(size_t offset, size_t size); - void unmapStream(); + bool supportsOrphan() const; BufferUsage mapUsage = BUFFERUSAGE_VERTEX; GLenum target = 0; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 5859f0631..95d11176d 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -509,8 +509,7 @@ static bool computeDispatchBarriers(Shader *shader, GLbitfield &preDispatchBarri if (usage & BUFFERUSAGEFLAG_VERTEX) postDispatchBarriers |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; - if (usage & (BUFFERUSAGEFLAG_COPY_SOURCE | BUFFERUSAGEFLAG_COPY_DEST)) - postDispatchBarriers |= GL_PIXEL_BUFFER_BARRIER_BIT; + postDispatchBarriers |= GL_PIXEL_BUFFER_BARRIER_BIT; } for (const auto &binding : shader->getStorageTextureBindings()) @@ -858,7 +857,7 @@ void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth if (c.hasValue) { - Colorf cf((float)c.value.r, (float)c.value.g, (float)c.value.b, (float)c.value.b); + Colorf cf((float)c.value.r, (float)c.value.g, (float)c.value.b, (float)c.value.a); gammaCorrectColor(cf); glClearColor(cf.r, cf.g, cf.b, cf.a); flags |= GL_COLOR_BUFFER_BIT; @@ -1658,8 +1657,11 @@ void Graphics::initCapabilities() capabilities.features[FEATURE_GLSL4] = GLAD_ES_VERSION_3_1 || (gl.isCoreProfile() && GLAD_VERSION_4_3); capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported(); capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_TEXEL); - capabilities.features[FEATURE_COPY_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_COPY_SOURCE); - static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); + capabilities.features[FEATURE_COPY_BUFFER] = gl.isCopyBufferSupported(); + capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = gl.isCopyBufferToTextureSupported(); + capabilities.features[FEATURE_COPY_TEXTURE_TO_BUFFER] = gl.isCopyTextureToBufferSupported(); + capabilities.features[FEATURE_COPY_RENDER_TARGET_TO_BUFFER] = gl.isCopyRenderTargetToBufferSupported(); + static_assert(FEATURE_MAX_ENUM == 15, "Graphics::initCapabilities must be updated when adding a new graphics feature!"); capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize(); capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize(); diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index cc0997441..83ec7fbc9 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -666,8 +666,6 @@ GLenum OpenGL::getGLBufferType(BufferUsage usage) case BUFFERUSAGE_INDEX: return GL_ELEMENT_ARRAY_BUFFER; case BUFFERUSAGE_TEXEL: return GL_TEXTURE_BUFFER; case BUFFERUSAGE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER; - case BUFFERUSAGE_COPY_SOURCE: return GL_COPY_READ_BUFFER; - case BUFFERUSAGE_COPY_DEST: return GL_COPY_WRITE_BUFFER; case BUFFERUSAGE_MAX_ENUM: return GL_ZERO; } @@ -844,6 +842,8 @@ GLenum OpenGL::getGLBufferDataUsage(BufferDataUsage usage) case BUFFERDATAUSAGE_STREAM: return GL_STREAM_DRAW; case BUFFERDATAUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW; case BUFFERDATAUSAGE_STATIC: return GL_STATIC_DRAW; + case BUFFERDATAUSAGE_STAGING: + return (GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0) ? GL_STREAM_READ : GL_STREAM_DRAW; default: return 0; } } @@ -1483,9 +1483,6 @@ bool OpenGL::isBufferUsageSupported(BufferUsage usage) const return GLAD_VERSION_3_1; case BUFFERUSAGE_SHADER_STORAGE: return (GLAD_VERSION_4_3 && isCoreProfile()) || GLAD_ES_VERSION_3_1; - case BUFFERUSAGE_COPY_SOURCE: - case BUFFERUSAGE_COPY_DEST: - return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0; case BUFFERUSAGE_MAX_ENUM: return false; } @@ -1530,6 +1527,29 @@ bool OpenGL::isMultiFormatMRTSupported() const return getMaxRenderTargets() > 1 && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); } +bool OpenGL::isCopyBufferSupported() const +{ + return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0; +} + +bool OpenGL::isCopyBufferToTextureSupported() const +{ + // Requires pixel unpack buffer binding support. + return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0; +} + +bool OpenGL::isCopyTextureToBufferSupported() const +{ + // Requires glGetTextureSubImage support. + return GLAD_VERSION_4_5 || GLAD_ARB_get_texture_sub_image; +} + +bool OpenGL::isCopyRenderTargetToBufferSupported() const +{ + // Requires pixel pack buffer binding support. + return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0; +} + int OpenGL::getMax2DTextureSize() const { return std::max(max2DTextureSize, 1); diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 4c073d1ae..37564365e 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -371,6 +371,10 @@ public: bool isSamplerLODBiasSupported() const; bool isBaseVertexSupported() const; bool isMultiFormatMRTSupported() const; + bool isCopyBufferSupported() const; + bool isCopyBufferToTextureSupported() const; + bool isCopyTextureToBufferSupported() const; + bool isCopyRenderTargetToBufferSupported() const; /** * Returns the maximum supported width or height of a texture. diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index 813abbf60..78ef3291b 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -22,6 +22,7 @@ #include "graphics/Graphics.h" #include "Graphics.h" +#include "Buffer.h" #include "common/int.h" // STD @@ -466,13 +467,16 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s if (isPixelFormatCompressed(pixelformat)) { - if (r.x != 0 || r.y != 0) - throw love::Exception("x and y parameters must be 0 for compressed textures."); - if (texType == TEXTURE_2D || texType == TEXTURE_CUBE) - glCompressedTexImage2D(gltarget, level, fmt.internalformat, r.w, r.h, 0, size, data); + { + // Possible issues on some very old drivers if TexSubImage is used. + if (r.x != 0 || r.y != 0 || r.w != getPixelWidth(level) || r.h != getPixelHeight(level)) + glCompressedTexSubImage2D(gltarget, level, r.x, r.y, r.w, r.h, fmt.internalformat, size, data); + else + glCompressedTexImage2D(gltarget, level, fmt.internalformat, r.w, r.h, 0, size, data); + } else if (texType == TEXTURE_2D_ARRAY || texType == TEXTURE_VOLUME) - glCompressedTexSubImage3D(gltarget, level, 0, 0, slice, r.w, r.h, 1, fmt.internalformat, size, data); + glCompressedTexSubImage3D(gltarget, level, r.x, r.y, slice, r.w, r.h, 1, fmt.internalformat, size, data); } else { @@ -521,6 +525,75 @@ void Texture::readbackImageData(love::image::ImageData *data, int slice, int mip gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo); } +void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) +{ + // Higher level code does validation. + + GLuint glbuffer = (GLuint) source->getHandle(); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glbuffer); + + if (!isCompressed()) // Not supported in GL with compressed textures... + glPixelStorei(GL_UNPACK_ROW_LENGTH, sourcewidth); + + // 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); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); +} + +void Texture::copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) +{ + // Higher level code does validation. + + GLuint glbuffer = (GLuint) dest->getHandle(); + glBindBuffer(GL_PIXEL_PACK_BUFFER, glbuffer); + + if (!isCompressed()) // Not supported in GL with compressed textures... + glPixelStorei(GL_PACK_ROW_LENGTH, destwidth); + + gl.bindTextureToUnit(this, 0, false); + + bool isSRGB = false; + OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, isSRGB); + + // glTexSubImage and friends copy from the active pixel_unpack_buffer by + // treating the pointer as a byte offset. + uint8 *byteoffset = (uint8 *)(ptrdiff_t)destoffset; + + if (gl.isCopyTextureToBufferSupported()) + { + if (isCompressed()) + glGetCompressedTextureSubImage(texture, mipmap, rect.x, rect.y, slice, rect.w, rect.h, 1, size, byteoffset); + else + glGetTextureSubImage(texture, mipmap, rect.x, rect.y, slice, rect.w, rect.h, 1, fmt.externalformat, fmt.type, size, byteoffset); + } + else if (fbo) + { + GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL); + gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, getFBO()); + + if (slice > 0 || mipmap > 0) + { + int layer = texType == TEXTURE_CUBE ? 0 : slice; + int face = texType == TEXTURE_CUBE ? slice : 0; + gl.framebufferTexture(GL_COLOR_ATTACHMENT0, texType, texture, mipmap, layer, face); + } + + glReadPixels(rect.x, rect.y, rect.w, rect.h, fmt.externalformat, fmt.type, byteoffset); + + if (slice > 0 || mipmap > 0) + gl.framebufferTexture(GL_COLOR_ATTACHMENT0, texType, texture, 0, 0, 0); + + gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, current_fbo); + } + + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); +} + void Texture::setSamplerState(const SamplerState &s) { if (s.depthSampleMode.hasValue && !gl.isDepthCompareSampleSupported()) diff --git a/src/modules/graphics/opengl/Texture.h b/src/modules/graphics/opengl/Texture.h index 3746f88dc..fbaebe0e1 100644 --- a/src/modules/graphics/opengl/Texture.h +++ b/src/modules/graphics/opengl/Texture.h @@ -46,6 +46,9 @@ public: bool loadVolatile() override; void unloadVolatile() override; + void copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) override; + void copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) override; + void setSamplerState(const SamplerState &s) override; ptrdiff_t getHandle() const override; diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index e8e31c999..4f088c554 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -371,8 +371,6 @@ STRINGMAP_BEGIN(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsageName) { "index", BUFFERUSAGE_INDEX }, { "texel", BUFFERUSAGE_TEXEL }, { "shaderstorage", BUFFERUSAGE_SHADER_STORAGE }, - { "copysource", BUFFERUSAGE_COPY_SOURCE }, - { "copydest", BUFFERUSAGE_COPY_DEST }, } STRINGMAP_END(BufferUsage, BUFFERUSAGE_MAX_ENUM, bufferUsageName) @@ -388,6 +386,7 @@ STRINGMAP_BEGIN(BufferDataUsage, BUFFERDATAUSAGE_MAX_ENUM, bufferDataUsage) { "stream", BUFFERDATAUSAGE_STREAM }, { "dynamic", BUFFERDATAUSAGE_DYNAMIC }, { "static", BUFFERDATAUSAGE_STATIC }, + { "staging", BUFFERDATAUSAGE_STAGING }, } STRINGMAP_END(BufferDataUsage, BUFFERDATAUSAGE_MAX_ENUM, bufferDataUsage) diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index ffe83b254..3913e81f7 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -60,8 +60,6 @@ enum BufferUsage BUFFERUSAGE_INDEX, BUFFERUSAGE_TEXEL, BUFFERUSAGE_SHADER_STORAGE, - BUFFERUSAGE_COPY_SOURCE, - BUFFERUSAGE_COPY_DEST, BUFFERUSAGE_MAX_ENUM }; @@ -72,8 +70,6 @@ enum BufferUsageFlags BUFFERUSAGEFLAG_INDEX = 1 << BUFFERUSAGE_INDEX, BUFFERUSAGEFLAG_TEXEL = 1 << BUFFERUSAGE_TEXEL, BUFFERUSAGEFLAG_SHADER_STORAGE = 1 << BUFFERUSAGE_SHADER_STORAGE, - BUFFERUSAGEFLAG_COPY_SOURCE = 1 << BUFFERUSAGE_COPY_SOURCE, - BUFFERUSAGEFLAG_COPY_DEST = 1 << BUFFERUSAGE_COPY_DEST, }; enum IndexDataType @@ -114,6 +110,7 @@ enum BufferDataUsage BUFFERDATAUSAGE_STREAM, BUFFERDATAUSAGE_DYNAMIC, BUFFERDATAUSAGE_STATIC, + BUFFERDATAUSAGE_STAGING, BUFFERDATAUSAGE_MAX_ENUM }; diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index e76d3c7c9..fb398de03 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3353,6 +3353,70 @@ int w_copyBuffer(lua_State *L) return 0; } +int w_copyBufferToTexture(lua_State *L) +{ + Buffer *source = luax_checkbuffer(L, 1); + Texture *dest = luax_checktexture(L, 2); + + ptrdiff_t sourceoffset = luaL_optinteger(L, 3, 0); + if (sourceoffset < 0) + return luaL_error(L, "copyBufferToTexture source offset cannot be negative."); + + int sourcewidth = (int) luaL_optinteger(L, 4, 0); + + int slice = 0; + int mipmap = 0; + + if (dest->getTextureType() != TEXTURE_2D) + slice = (int) luaL_checkinteger(L, 5) - 1; + + mipmap = (int) luaL_optinteger(L, 6, 1) - 1; + + Rect rect = {0, 0, dest->getPixelWidth(mipmap), dest->getPixelHeight(mipmap)}; + if (!lua_isnoneornil(L, 7)) + { + rect.x = (int) luaL_checkinteger(L, 7); + rect.y = (int) luaL_checkinteger(L, 8); + rect.w = (int) luaL_checkinteger(L, 9); + rect.h = (int) luaL_checkinteger(L, 10); + } + + luax_catchexcept(L, [&](){ instance()->copyBufferToTexture(source, dest, sourceoffset, sourcewidth, slice, mipmap, rect); }); + return 0; +} + +int w_copyTextureToBuffer(lua_State *L) +{ + Texture *source = luax_checktexture(L, 1); + Buffer *dest = luax_checkbuffer(L, 2); + + int slice = 0; + int mipmap = 0; + + if (source->getTextureType() != TEXTURE_2D) + slice = (int) luaL_checkinteger(L, 3) - 1; + + mipmap = (int) luaL_optinteger(L, 4, 1) - 1; + + Rect rect = {0, 0, source->getPixelWidth(mipmap), source->getPixelHeight(mipmap)}; + if (!lua_isnoneornil(L, 5)) + { + rect.x = (int) luaL_checkinteger(L, 5); + rect.y = (int) luaL_checkinteger(L, 6); + rect.w = (int) luaL_checkinteger(L, 7); + rect.h = (int) luaL_checkinteger(L, 8); + } + + ptrdiff_t destoffset = luaL_optinteger(L, 9, 0); + if (destoffset < 0) + return luaL_error(L, "copyTextureToBuffer dest offset cannot be negative."); + + int destwidth = (int) luaL_optinteger(L, 10, 0); + + luax_catchexcept(L, [&](){ instance()->copyTextureToBuffer(source, dest, slice, mipmap, rect, destoffset, destwidth); }); + return 0; +} + int w_flushBatch(lua_State *) { instance()->flushBatchedDraws(); @@ -3553,6 +3617,8 @@ static const luaL_Reg functions[] = { "dispatchThreadgroups", w_dispatchThreadgroups }, { "copyBuffer", w_copyBuffer }, + { "copyBufferToTexture", w_copyBufferToTexture }, + { "copyTextureToBuffer", w_copyTextureToBuffer }, { "isCreated", w_isCreated }, { "isActive", w_isActive }, diff --git a/src/modules/graphics/wrap_Texture.cpp b/src/modules/graphics/wrap_Texture.cpp index a0fee702c..a5695a74a 100644 --- a/src/modules/graphics/wrap_Texture.cpp +++ b/src/modules/graphics/wrap_Texture.cpp @@ -390,13 +390,13 @@ int w_Texture_newImageData(lua_State *L) int slice = 0; int mipmap = 0; - Rect rect = {0, 0, t->getPixelWidth(), t->getPixelHeight()}; if (t->getTextureType() != TEXTURE_2D) slice = (int) luaL_checkinteger(L, 2) - 1; mipmap = (int) luaL_optinteger(L, 3, 1) - 1; + Rect rect = {0, 0, t->getPixelWidth(mipmap), t->getPixelHeight(mipmap)}; if (!lua_isnoneornil(L, 4)) { rect.x = (int) luaL_checkinteger(L, 4);