Merge branch '12.0-development' into 12.0-testsuite

This commit is contained in:
ellraiser
2023-11-14 17:57:38 +00:00
committed by GitHub
106 changed files with 3009 additions and 2352 deletions
-4
View File
@@ -837,8 +837,6 @@ set(LOVE_SRC_MODULE_PHYSICS_BOX2D
src/modules/physics/box2d/DistanceJoint.h
src/modules/physics/box2d/EdgeShape.cpp
src/modules/physics/box2d/EdgeShape.h
src/modules/physics/box2d/Fixture.cpp
src/modules/physics/box2d/Fixture.h
src/modules/physics/box2d/FrictionJoint.cpp
src/modules/physics/box2d/FrictionJoint.h
src/modules/physics/box2d/GearJoint.cpp
@@ -881,8 +879,6 @@ set(LOVE_SRC_MODULE_PHYSICS_BOX2D
src/modules/physics/box2d/wrap_DistanceJoint.h
src/modules/physics/box2d/wrap_EdgeShape.cpp
src/modules/physics/box2d/wrap_EdgeShape.h
src/modules/physics/box2d/wrap_Fixture.cpp
src/modules/physics/box2d/wrap_Fixture.h
src/modules/physics/box2d/wrap_FrictionJoint.cpp
src/modules/physics/box2d/wrap_FrictionJoint.h
src/modules/physics/box2d/wrap_GearJoint.cpp
@@ -51,6 +51,9 @@
217DFC111D9F6D490055D849 /* usocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 217DFBD51D9F6D490055D849 /* usocket.c */; };
217DFC121D9F6D490055D849 /* usocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 217DFBD61D9F6D490055D849 /* usocket.h */; };
D923E7D3296B85B9002FF1B3 /* harfbuzz.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = D923E7D2296B85B9002FF1B3 /* harfbuzz.xcframework */; };
D943E58E2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
D943E58F2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
D943E5902A24D56000D80361 /* PhysfsIo.h in Headers */ = {isa = PBXBuildFile; fileRef = D943E58D2A24D56000D80361 /* PhysfsIo.h */; };
D9DAB9222961F0EE00C64820 /* HarfbuzzShaper.h in Headers */ = {isa = PBXBuildFile; fileRef = D9DAB9202961F0EE00C64820 /* HarfbuzzShaper.h */; };
D9DAB9232961F0EE00C64820 /* HarfbuzzShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */; };
D9DAB9242961F0EE00C64820 /* HarfbuzzShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */; };
@@ -61,9 +64,6 @@
D9DAB92D2961F10000C64820 /* TextShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9282961F10000C64820 /* TextShaper.cpp */; };
D9DAB92E2961F10000C64820 /* TextShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9282961F10000C64820 /* TextShaper.cpp */; };
D9DAB9322963CD7500C64820 /* harfbuzz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9DAB9312963CD7500C64820 /* harfbuzz.framework */; };
D943E58E2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
D943E58F2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
D943E5902A24D56000D80361 /* PhysfsIo.h in Headers */ = {isa = PBXBuildFile; fileRef = D943E58D2A24D56000D80361 /* PhysfsIo.h */; };
FA0A3A5F23366CE9001C269E /* floattypes.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0A3A5D23366CE9001C269E /* floattypes.h */; };
FA0A3A6023366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; };
FA0A3A6123366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; };
@@ -407,9 +407,6 @@
FA0B7E091A95902C000E1D17 /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */; };
FA0B7E0A1A95902C000E1D17 /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */; };
FA0B7E0B1A95902C000E1D17 /* EdgeShape.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */; };
FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */; };
FA0B7E0D1A95902C000E1D17 /* Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */; };
FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2C1A95902C000E1D17 /* Fixture.h */; };
FA0B7E0F1A95902C000E1D17 /* FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */; };
FA0B7E101A95902C000E1D17 /* FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */; };
FA0B7E111A95902C000E1D17 /* FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */; };
@@ -473,9 +470,6 @@
FA0B7E4B1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */; };
FA0B7E4C1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */; };
FA0B7E4D1A95902C000E1D17 /* wrap_EdgeShape.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */; };
FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */; };
FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */; };
FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */; };
FA0B7E511A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */; };
FA0B7E521A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */; };
FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */; };
@@ -1406,6 +1400,8 @@
217DFBD51D9F6D490055D849 /* usocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usocket.c; sourceTree = "<group>"; };
217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = "<group>"; };
D923E7D2296B85B9002FF1B3 /* harfbuzz.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = harfbuzz.xcframework; path = ios/libraries/harfbuzz.xcframework; sourceTree = "<group>"; };
D943E58C2A24D56000D80361 /* PhysfsIo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PhysfsIo.cpp; sourceTree = "<group>"; };
D943E58D2A24D56000D80361 /* PhysfsIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysfsIo.h; sourceTree = "<group>"; };
D9DAB9202961F0EE00C64820 /* HarfbuzzShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HarfbuzzShaper.h; sourceTree = "<group>"; };
D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HarfbuzzShaper.cpp; sourceTree = "<group>"; };
D9DAB9252961F0FF00C64820 /* GenericShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericShaper.h; sourceTree = "<group>"; };
@@ -1413,8 +1409,6 @@
D9DAB9272961F0FF00C64820 /* TextShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextShaper.h; sourceTree = "<group>"; };
D9DAB9282961F10000C64820 /* TextShaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextShaper.cpp; sourceTree = "<group>"; };
D9DAB9312963CD7500C64820 /* harfbuzz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = harfbuzz.framework; path = macosx/Frameworks/harfbuzz.framework; sourceTree = "<group>"; };
D943E58C2A24D56000D80361 /* PhysfsIo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PhysfsIo.cpp; sourceTree = "<group>"; };
D943E58D2A24D56000D80361 /* PhysfsIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysfsIo.h; sourceTree = "<group>"; };
FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = "<group>"; };
FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = "<group>"; };
FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = "<group>"; };
@@ -1652,8 +1646,6 @@
FA0B7C281A95902C000E1D17 /* DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DistanceJoint.h; sourceTree = "<group>"; };
FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeShape.cpp; sourceTree = "<group>"; };
FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdgeShape.h; sourceTree = "<group>"; };
FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Fixture.cpp; sourceTree = "<group>"; };
FA0B7C2C1A95902C000E1D17 /* Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fixture.h; sourceTree = "<group>"; };
FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrictionJoint.cpp; sourceTree = "<group>"; };
FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrictionJoint.h; sourceTree = "<group>"; };
FA0B7C2F1A95902C000E1D17 /* GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GearJoint.cpp; sourceTree = "<group>"; };
@@ -1696,8 +1688,6 @@
FA0B7C541A95902C000E1D17 /* wrap_DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DistanceJoint.h; sourceTree = "<group>"; };
FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_EdgeShape.cpp; sourceTree = "<group>"; };
FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_EdgeShape.h; sourceTree = "<group>"; };
FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Fixture.cpp; sourceTree = "<group>"; };
FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Fixture.h; sourceTree = "<group>"; };
FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_FrictionJoint.cpp; sourceTree = "<group>"; };
FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_FrictionJoint.h; sourceTree = "<group>"; };
FA0B7C5B1A95902C000E1D17 /* wrap_GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_GearJoint.cpp; sourceTree = "<group>"; };
@@ -3165,8 +3155,6 @@
FA0B7C281A95902C000E1D17 /* DistanceJoint.h */,
FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */,
FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */,
FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */,
FA0B7C2C1A95902C000E1D17 /* Fixture.h */,
FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */,
FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */,
FA0B7C2F1A95902C000E1D17 /* GearJoint.cpp */,
@@ -3209,8 +3197,6 @@
FA0B7C541A95902C000E1D17 /* wrap_DistanceJoint.h */,
FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */,
FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */,
FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */,
FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */,
FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */,
FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */,
FA0B7C5B1A95902C000E1D17 /* wrap_GearJoint.cpp */,
@@ -4272,7 +4258,6 @@
FAFEB29B28F210550025D7D0 /* unixdgram.h in Headers */,
FA0B7E051A95902C000E1D17 /* Contact.h in Headers */,
FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */,
FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */,
FA6A2B661F5F7B6B0074C308 /* wrap_Data.h in Headers */,
FA18CEE423DBC6E000263725 /* Graphics.h in Headers */,
217DFBE81D9F6D490055D849 /* inet.h in Headers */,
@@ -4467,7 +4452,6 @@
FA4F2B7A1DE0125B00CA37D7 /* xxhash.h in Headers */,
FA0B7DDE1A95902C000E1D17 /* wrap_BezierCurve.h in Headers */,
FA0B7DED1A95902C000E1D17 /* Cursor.h in Headers */,
FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */,
FA28EBD71E352DB5003446F4 /* FenceSync.h in Headers */,
FADF542C1E3DAADA00012CC0 /* wrap_Mesh.h in Headers */,
FAA3A9B01B7D465A00CED060 /* android.h in Headers */,
@@ -4707,7 +4691,6 @@
FA3C5E431F8C368C0003C579 /* ShaderStage.cpp in Sources */,
FA0B7E191A95902C000E1D17 /* MotorJoint.cpp in Sources */,
FAF1406F1E20934C00F898D2 /* Initialize.cpp in Sources */,
FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
FA0B7EBF1A95902C000E1D17 /* Thread.cpp in Sources */,
FACA02F91F5E39790084B28F /* Compressor.cpp in Sources */,
FABDAA002552448300B5C523 /* b2_time_of_impact.cpp in Sources */,
@@ -4725,7 +4708,6 @@
FA4F2C111DE936FE00CA37D7 /* unix.c in Sources */,
FA1BA0A31E16D97500AA2803 /* wrap_Font.cpp in Sources */,
FABDA9842552448200B5C523 /* b2_chain_polygon_contact.cpp in Sources */,
FA0B7E0D1A95902C000E1D17 /* Fixture.cpp in Sources */,
FADF53FE1E3D74F200012CC0 /* TextBatch.cpp in Sources */,
FA0B7D191A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */,
FAC271E723B5B5B400C200D3 /* renderstate.cpp in Sources */,
@@ -5140,7 +5122,6 @@
FAF140971E20934C00F898D2 /* PpTokens.cpp in Sources */,
FAF140A91E20934C00F898D2 /* SymbolTable.cpp in Sources */,
FA0B7E181A95902C000E1D17 /* MotorJoint.cpp in Sources */,
FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
FA18CEC523D3AE6700263725 /* wrap_Buffer.cpp in Sources */,
FAF6C9F423C2DE2900D7B5BC /* Logger.cpp in Sources */,
FABDA9FF2552448300B5C523 /* b2_time_of_impact.cpp in Sources */,
@@ -5159,7 +5140,6 @@
FABDA9832552448200B5C523 /* b2_chain_polygon_contact.cpp in Sources */,
FA0B7AD61A958EA3000E1D17 /* win32.c in Sources */,
FADF54341E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */,
FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */,
FA0B7D181A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */,
FA84DE6627791C36002674C6 /* GraphicsReadback.cpp in Sources */,
FA0B7CFA1A95902C000E1D17 /* Filesystem.cpp in Sources */,
@@ -5531,7 +5511,7 @@
);
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = macosx;
USE_HEADERMAP = NO;
@@ -5597,7 +5577,7 @@
);
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "";
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
USE_HEADERMAP = NO;
@@ -5736,7 +5716,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "";
LLVM_LTO = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = NO;
SDKROOT = macosx;
USE_HEADERMAP = NO;
@@ -564,7 +564,7 @@
INFOPLIST_FILE = "love-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = love;
SDKROOT = macosx;
@@ -640,7 +640,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
LLVM_LTO = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = love;
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
@@ -874,7 +874,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
LLVM_LTO = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = love;
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
+2 -2
View File
@@ -6,7 +6,7 @@ Documentation
-------------
We use our [wiki][wiki] for documentation.
If you need further help, feel free to ask on our [forums][forums], our [Discord server][discord], or our IRC channel [#love on OFTC][irc].
If you need further help, feel free to ask on our [forums][forums], our [Discord server][discord], or our [subreddit][subreddit].
Repository
----------
@@ -97,7 +97,7 @@ Dependencies
[wiki]: https://love2d.org/wiki
[forums]: https://love2d.org/forums
[discord]: https://discord.gg/rhUets9
[irc]: irc://irc.oftc.net/love
[subreddit]: https://www.reddit.com/r/love2d
[dependencies-apple]: https://github.com/love2d/love-apple-dependencies
[dependencies-ios]: https://github.com/love2d/love/releases
[megasource]: https://github.com/love2d/megasource
+1 -1
View File
@@ -46,7 +46,7 @@ struct Optional
hasValue = true;
}
T get(T defaultVal)
T get(T defaultVal) const
{
return hasValue ? value : defaultVal;
}
+6
View File
@@ -107,8 +107,12 @@ std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere)
if (info.apiType == API_FUNCTION)
notice << "function ";
else if (info.apiType == API_FUNCTION_VARIANT)
notice << "function variant in ";
else if (info.apiType == API_METHOD)
notice << "method ";
else if (info.apiType == API_METHOD_VARIANT)
notice << "method variant in ";
else if (info.apiType == API_CALLBACK)
notice << "callback ";
else if (info.apiType == API_FIELD)
@@ -188,7 +192,9 @@ MarkDeprecated::~MarkDeprecated()
STRINGMAP_BEGIN(APIType, API_MAX_ENUM, apiType)
{
{ "function", API_FUNCTION },
{ "functionvariant", API_FUNCTION_VARIANT },
{ "method", API_METHOD },
{ "methodvariant", API_METHOD_VARIANT },
{ "callback", API_CALLBACK },
{ "field", API_FIELD },
{ "constant", API_CONSTANT },
+2
View File
@@ -32,7 +32,9 @@ namespace love
enum APIType
{
API_FUNCTION,
API_FUNCTION_VARIANT,
API_METHOD,
API_METHOD_VARIANT,
API_CALLBACK,
API_FIELD,
API_CONSTANT,
+242 -145
View File
@@ -26,101 +26,126 @@ namespace love
static PixelFormatInfo formatInfo[] =
{
// components, blockW, blockH, blockSize, color, depth, stencil, compressed, dataType
{ 0, 1, 1, 0, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN
// components, blockW, blockH, blockSize, color, depth, stencil, compressed, sRGB, dataType
{ 0, 1, 1, 0, false, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN
{ 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL
{ 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR
{ 0, 1, 1, 0, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL
{ 0, 1, 1, 0, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR
{ 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM
{ 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT
{ 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT
{ 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT
{ 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT
{ 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT
{ 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM
{ 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT
{ 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT
{ 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT
{ 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT
{ 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT
{ 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT
{ 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT
{ 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT
{ 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT
{ 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT
{ 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM_sRGB
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM_sRGB
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT
{ 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT
{ 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT
{ 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM
{ 4, 1, 1, 4, true, false, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_sRGB
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM
{ 4, 1, 1, 4, true, false, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_sRGB
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT
{ 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT
{ 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT
{ 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT
{ 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM
{ 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM
{ 3, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM
{ 3, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT
{ 4, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM
{ 4, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM
{ 3, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM
{ 3, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT
{ 1, 1, 1, 1, false, false, true , false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8
{ 1, 1, 1, 2, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM
{ 1, 1, 1, 3, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM
{ 1, 1, 1, 4, false, true, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT
{ 2, 1, 1, 4, false, true, true , false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8
{ 2, 1, 1, 5, false, true, true , false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8
{ 1, 1, 1, 1, false, false, true , false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8
{ 1, 1, 1, 2, false, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM
{ 1, 1, 1, 3, false, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM
{ 1, 1, 1, 4, false, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT
{ 2, 1, 1, 4, false, true, true , false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8
{ 2, 1, 1, 5, false, true, true , false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8
{ 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM
{ 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT
{ 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM
{ 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM
{ 3, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_sRGB
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_sRGB
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_sRGB
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM
{ 3, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT
{ 3, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_sRGB
{ 3, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM
{ 3, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM
{ 4, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM
{ 4, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM
{ 3, 16, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM
{ 3, 16, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_sRGB
{ 3, 8, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM
{ 3, 8, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_sRGB
{ 4, 16, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM
{ 4, 16, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_sRGB
{ 4, 8, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM
{ 4, 8, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_sRGB
{ 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM
{ 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM
{ 4, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM
{ 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM
{ 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM
{ 3, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_sRGB
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_sRGB
{ 4, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM
{ 4, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_sRGB
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM
{ 4, 4, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4
{ 4, 5, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4
{ 4, 5, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5
{ 4, 6, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5
{ 4, 6, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6
{ 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5
{ 4, 8, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6
{ 4, 8, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8
{ 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5
{ 4, 10, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6
{ 4, 10, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8
{ 4, 10, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10
{ 4, 12, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10
{ 4, 12, 12, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12
{ 4, 4, 4, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4_UNORM
{ 4, 5, 4, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4_UNORM
{ 4, 5, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5_UNORM
{ 4, 6, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5_UNORM
{ 4, 6, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6_UNORM
{ 4, 8, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5_UNORM
{ 4, 8, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6_UNORM
{ 4, 8, 8, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8_UNORM
{ 4, 8, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5_UNORM
{ 4, 10, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6_UNORM
{ 4, 10, 8, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8_UNORM
{ 4, 10, 10, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10_UNORM
{ 4, 12, 10, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10_UNORM
{ 4, 12, 12, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12_UNORM
{ 4, 4, 4, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4_sRGB
{ 4, 5, 4, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4_sRGB
{ 4, 5, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5_sRGB
{ 4, 6, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5_sRGB
{ 4, 6, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6_sRGB
{ 4, 8, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5_sRGB
{ 4, 8, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6_sRGB
{ 4, 8, 8, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8_sRGB
{ 4, 8, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5_sRGB
{ 4, 10, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6_sRGB
{ 4, 10, 8, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8_sRGB
{ 4, 10, 10, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10_sRGB
{ 4, 12, 10, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10_sRGB
{ 4, 12, 12, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12_sRGB
};
static_assert(sizeof(formatInfo) / sizeof(PixelFormatInfo) == PIXELFORMAT_MAX_ENUM, "Update the formatInfo array when adding or removing a PixelFormat");
@@ -155,19 +180,19 @@ static StringMap<PixelFormat, PIXELFORMAT_MAX_ENUM>::Entry formatEntries[] =
{ "rg32i", PIXELFORMAT_RG32_INT },
{ "rg32ui", PIXELFORMAT_RG32_UINT },
{ "rgba8", PIXELFORMAT_RGBA8_UNORM },
{ "srgba8", PIXELFORMAT_RGBA8_UNORM_sRGB },
{ "bgra8", PIXELFORMAT_BGRA8_UNORM },
{ "bgra8srgb", PIXELFORMAT_BGRA8_UNORM_sRGB },
{ "rgba8i", PIXELFORMAT_RGBA8_INT },
{ "rgba8ui", PIXELFORMAT_RGBA8_UINT },
{ "rgba16", PIXELFORMAT_RGBA16_UNORM },
{ "rgba16f", PIXELFORMAT_RGBA16_FLOAT },
{ "rgba16i", PIXELFORMAT_RGBA16_INT },
{ "rgba16ui", PIXELFORMAT_RGBA16_UINT },
{ "rgba32f", PIXELFORMAT_RGBA32_FLOAT },
{ "rgba32i", PIXELFORMAT_RGBA32_INT },
{ "rgba32ui", PIXELFORMAT_RGBA32_UINT },
{ "rgba8", PIXELFORMAT_RGBA8_UNORM },
{ "srgba8", PIXELFORMAT_RGBA8_sRGB },
{ "bgra8", PIXELFORMAT_BGRA8_UNORM },
{ "bgra8srgb", PIXELFORMAT_BGRA8_sRGB },
{ "rgba8i", PIXELFORMAT_RGBA8_INT },
{ "rgba8ui", PIXELFORMAT_RGBA8_UINT },
{ "rgba16", PIXELFORMAT_RGBA16_UNORM },
{ "rgba16f", PIXELFORMAT_RGBA16_FLOAT },
{ "rgba16i", PIXELFORMAT_RGBA16_INT },
{ "rgba16ui", PIXELFORMAT_RGBA16_UINT },
{ "rgba32f", PIXELFORMAT_RGBA32_FLOAT },
{ "rgba32i", PIXELFORMAT_RGBA32_INT },
{ "rgba32ui", PIXELFORMAT_RGBA32_UINT },
{ "rgba4", PIXELFORMAT_RGBA4_UNORM },
{ "rgb5a1", PIXELFORMAT_RGB5A1_UNORM },
@@ -182,43 +207,70 @@ static StringMap<PixelFormat, PIXELFORMAT_MAX_ENUM>::Entry formatEntries[] =
{ "depth24stencil8", PIXELFORMAT_DEPTH24_UNORM_STENCIL8 },
{ "depth32fstencil8", PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 },
{ "DXT1", PIXELFORMAT_DXT1_UNORM },
{ "DXT3", PIXELFORMAT_DXT3_UNORM },
{ "DXT5", PIXELFORMAT_DXT5_UNORM },
{ "BC4", PIXELFORMAT_BC4_UNORM },
{ "BC4s", PIXELFORMAT_BC4_SNORM },
{ "BC5", PIXELFORMAT_BC5_UNORM },
{ "BC5s", PIXELFORMAT_BC5_SNORM },
{ "BC6h", PIXELFORMAT_BC6H_UFLOAT },
{ "BC6hs", PIXELFORMAT_BC6H_FLOAT },
{ "BC7", PIXELFORMAT_BC7_UNORM },
{ "PVR1rgb2", PIXELFORMAT_PVR1_RGB2_UNORM },
{ "PVR1rgb4", PIXELFORMAT_PVR1_RGB4_UNORM },
{ "PVR1rgba2", PIXELFORMAT_PVR1_RGBA2_UNORM },
{ "PVR1rgba4", PIXELFORMAT_PVR1_RGBA4_UNORM },
{ "ETC1", PIXELFORMAT_ETC1_UNORM },
{ "ETC2rgb", PIXELFORMAT_ETC2_RGB_UNORM },
{ "ETC2rgba", PIXELFORMAT_ETC2_RGBA_UNORM },
{ "ETC2rgba1", PIXELFORMAT_ETC2_RGBA1_UNORM },
{ "EACr", PIXELFORMAT_EAC_R_UNORM },
{ "EACrs", PIXELFORMAT_EAC_R_SNORM },
{ "EACrg", PIXELFORMAT_EAC_RG_UNORM },
{ "EACrgs", PIXELFORMAT_EAC_RG_SNORM },
{ "DXT1", PIXELFORMAT_DXT1_UNORM },
{ "DXT1srgb", PIXELFORMAT_DXT1_sRGB },
{ "DXT3", PIXELFORMAT_DXT3_UNORM },
{ "DXT3srgb", PIXELFORMAT_DXT3_sRGB },
{ "DXT5", PIXELFORMAT_DXT5_UNORM },
{ "DXT5srgb", PIXELFORMAT_DXT5_sRGB },
{ "BC4", PIXELFORMAT_BC4_UNORM },
{ "BC4s", PIXELFORMAT_BC4_SNORM },
{ "BC5", PIXELFORMAT_BC5_UNORM },
{ "BC5s", PIXELFORMAT_BC5_SNORM },
{ "BC6h", PIXELFORMAT_BC6H_UFLOAT },
{ "BC6hs", PIXELFORMAT_BC6H_FLOAT },
{ "BC7", PIXELFORMAT_BC7_UNORM },
{ "BC7srgb", PIXELFORMAT_BC7_sRGB },
{ "ASTC4x4", PIXELFORMAT_ASTC_4x4 },
{ "ASTC5x4", PIXELFORMAT_ASTC_5x4 },
{ "ASTC5x5", PIXELFORMAT_ASTC_5x5 },
{ "ASTC6x5", PIXELFORMAT_ASTC_6x5 },
{ "ASTC6x6", PIXELFORMAT_ASTC_6x6 },
{ "ASTC8x5", PIXELFORMAT_ASTC_8x5 },
{ "ASTC8x6", PIXELFORMAT_ASTC_8x6 },
{ "ASTC8x8", PIXELFORMAT_ASTC_8x8 },
{ "ASTC10x5", PIXELFORMAT_ASTC_10x5 },
{ "ASTC10x6", PIXELFORMAT_ASTC_10x6 },
{ "ASTC10x8", PIXELFORMAT_ASTC_10x8 },
{ "ASTC10x10", PIXELFORMAT_ASTC_10x10 },
{ "ASTC12x10", PIXELFORMAT_ASTC_12x10 },
{ "ASTC12x12", PIXELFORMAT_ASTC_12x12 },
{ "PVR1rgb2", PIXELFORMAT_PVR1_RGB2_UNORM },
{ "PVR1rgb2srgb", PIXELFORMAT_PVR1_RGB2_sRGB },
{ "PVR1rgb4", PIXELFORMAT_PVR1_RGB4_UNORM },
{ "PVR1rgb4srgb", PIXELFORMAT_PVR1_RGB4_sRGB },
{ "PVR1rgba2", PIXELFORMAT_PVR1_RGBA2_UNORM },
{ "PVR1rgba2srgb", PIXELFORMAT_PVR1_RGBA2_sRGB },
{ "PVR1rgba4", PIXELFORMAT_PVR1_RGBA4_UNORM },
{ "PVR1rgba4srgb", PIXELFORMAT_PVR1_RGBA4_sRGB },
{ "ETC1", PIXELFORMAT_ETC1_UNORM },
{ "ETC2rgb", PIXELFORMAT_ETC2_RGB_UNORM },
{ "ETC2srgb", PIXELFORMAT_ETC2_RGB_sRGB },
{ "ETC2rgba", PIXELFORMAT_ETC2_RGBA_UNORM },
{ "ETC2srgba", PIXELFORMAT_ETC2_RGBA_sRGB },
{ "ETC2rgba1", PIXELFORMAT_ETC2_RGBA1_UNORM },
{ "ETC2srgba1", PIXELFORMAT_ETC2_RGBA1_sRGB },
{ "EACr", PIXELFORMAT_EAC_R_UNORM },
{ "EACrs", PIXELFORMAT_EAC_R_SNORM },
{ "EACrg", PIXELFORMAT_EAC_RG_UNORM },
{ "EACrgs", PIXELFORMAT_EAC_RG_SNORM },
{ "ASTC4x4", PIXELFORMAT_ASTC_4x4_UNORM },
{ "ASTC5x4", PIXELFORMAT_ASTC_5x4_UNORM },
{ "ASTC5x5", PIXELFORMAT_ASTC_5x5_UNORM },
{ "ASTC6x5", PIXELFORMAT_ASTC_6x5_UNORM },
{ "ASTC6x6", PIXELFORMAT_ASTC_6x6_UNORM },
{ "ASTC8x5", PIXELFORMAT_ASTC_8x5_UNORM },
{ "ASTC8x6", PIXELFORMAT_ASTC_8x6_UNORM },
{ "ASTC8x8", PIXELFORMAT_ASTC_8x8_UNORM },
{ "ASTC10x5", PIXELFORMAT_ASTC_10x5_UNORM },
{ "ASTC10x6", PIXELFORMAT_ASTC_10x6_UNORM },
{ "ASTC10x8", PIXELFORMAT_ASTC_10x8_UNORM },
{ "ASTC10x10", PIXELFORMAT_ASTC_10x10_UNORM },
{ "ASTC12x10", PIXELFORMAT_ASTC_12x10_UNORM },
{ "ASTC12x12", PIXELFORMAT_ASTC_12x12_UNORM },
{ "ASTC4x4srgb", PIXELFORMAT_ASTC_4x4_sRGB },
{ "ASTC5x4srgb", PIXELFORMAT_ASTC_5x4_sRGB },
{ "ASTC5x5srgb", PIXELFORMAT_ASTC_5x5_sRGB },
{ "ASTC6x5srgb", PIXELFORMAT_ASTC_6x5_sRGB },
{ "ASTC6x6srgb", PIXELFORMAT_ASTC_6x6_sRGB },
{ "ASTC8x5srgb", PIXELFORMAT_ASTC_8x5_sRGB },
{ "ASTC8x6srgb", PIXELFORMAT_ASTC_8x6_sRGB },
{ "ASTC8x8srgb", PIXELFORMAT_ASTC_8x8_sRGB },
{ "ASTC10x5srgb", PIXELFORMAT_ASTC_10x5_sRGB },
{ "ASTC10x6srgb", PIXELFORMAT_ASTC_10x6_sRGB },
{ "ASTC10x8srgb", PIXELFORMAT_ASTC_10x8_sRGB },
{ "ASTC10x10srgb", PIXELFORMAT_ASTC_10x10_sRGB },
{ "ASTC12x10srgb", PIXELFORMAT_ASTC_12x10_sRGB },
{ "ASTC12x12srgb", PIXELFORMAT_ASTC_12x12_sRGB },
};
static_assert(sizeof(formatEntries) / sizeof(formatEntries[0]) == (size_t) PIXELFORMAT_MAX_ENUM, "pixel format string map is missing entries!");
@@ -275,7 +327,7 @@ bool isPixelFormatStencil(PixelFormat format)
bool isPixelFormatSRGB(PixelFormat format)
{
return format == PIXELFORMAT_RGBA8_UNORM_sRGB || format == PIXELFORMAT_BGRA8_UNORM_sRGB;
return formatInfo[format].sRGB;
}
bool isPixelFormatInteger(PixelFormat format)
@@ -286,20 +338,65 @@ bool isPixelFormatInteger(PixelFormat format)
PixelFormat getSRGBPixelFormat(PixelFormat format)
{
if (format == PIXELFORMAT_RGBA8_UNORM)
return PIXELFORMAT_RGBA8_UNORM_sRGB;
else if (format == PIXELFORMAT_BGRA8_UNORM)
return PIXELFORMAT_BGRA8_UNORM_sRGB;
return format;
switch (format)
{
case PIXELFORMAT_RGBA8_UNORM: return PIXELFORMAT_RGBA8_sRGB;
case PIXELFORMAT_BGRA8_UNORM: return PIXELFORMAT_BGRA8_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;
case PIXELFORMAT_PVR1_RGBA4_UNORM: return PIXELFORMAT_PVR1_RGBA4_sRGB;
case PIXELFORMAT_ETC1_UNORM: return PIXELFORMAT_ETC2_RGB_sRGB; // ETC2 can load ETC1 data.
case PIXELFORMAT_ETC2_RGB_UNORM: return PIXELFORMAT_ETC2_RGB_sRGB;
case PIXELFORMAT_ETC2_RGBA_UNORM: return PIXELFORMAT_ETC2_RGBA_sRGB;
case PIXELFORMAT_ETC2_RGBA1_UNORM: return PIXELFORMAT_ETC2_RGBA1_sRGB;
case PIXELFORMAT_ASTC_4x4_UNORM: return PIXELFORMAT_ASTC_4x4_sRGB;
case PIXELFORMAT_ASTC_5x4_UNORM: return PIXELFORMAT_ASTC_5x4_sRGB;
case PIXELFORMAT_ASTC_5x5_UNORM: return PIXELFORMAT_ASTC_5x5_sRGB;
case PIXELFORMAT_ASTC_6x5_UNORM: return PIXELFORMAT_ASTC_6x5_sRGB;
case PIXELFORMAT_ASTC_6x6_UNORM: return PIXELFORMAT_ASTC_6x6_sRGB;
case PIXELFORMAT_ASTC_8x5_UNORM: return PIXELFORMAT_ASTC_8x5_sRGB;
case PIXELFORMAT_ASTC_8x6_UNORM: return PIXELFORMAT_ASTC_8x6_sRGB;
case PIXELFORMAT_ASTC_8x8_UNORM: return PIXELFORMAT_ASTC_8x8_sRGB;
case PIXELFORMAT_ASTC_10x5_UNORM: return PIXELFORMAT_ASTC_10x5_sRGB;
case PIXELFORMAT_ASTC_10x6_UNORM: return PIXELFORMAT_ASTC_10x6_sRGB;
case PIXELFORMAT_ASTC_10x8_UNORM: return PIXELFORMAT_ASTC_10x8_sRGB;
case PIXELFORMAT_ASTC_10x10_UNORM: return PIXELFORMAT_ASTC_10x10_sRGB;
case PIXELFORMAT_ASTC_12x10_UNORM: return PIXELFORMAT_ASTC_12x10_sRGB;
case PIXELFORMAT_ASTC_12x12_UNORM: return PIXELFORMAT_ASTC_12x12_sRGB;
default: return format;
}
}
PixelFormat getLinearPixelFormat(PixelFormat format)
{
if (format == PIXELFORMAT_RGBA8_UNORM_sRGB)
return PIXELFORMAT_RGBA8_UNORM;
else if (format == PIXELFORMAT_BGRA8_UNORM_sRGB)
return PIXELFORMAT_BGRA8_UNORM;
return format;
switch (format)
{
case PIXELFORMAT_RGBA8_sRGB: return PIXELFORMAT_RGBA8_UNORM;
case PIXELFORMAT_BGRA8_sRGB: return PIXELFORMAT_BGRA8_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;
case PIXELFORMAT_PVR1_RGBA4_sRGB: return PIXELFORMAT_PVR1_RGBA4_UNORM;
case PIXELFORMAT_ETC2_RGB_sRGB: return PIXELFORMAT_ETC2_RGB_UNORM;
case PIXELFORMAT_ETC2_RGBA_sRGB: return PIXELFORMAT_ETC2_RGBA_UNORM;
case PIXELFORMAT_ETC2_RGBA1_sRGB: return PIXELFORMAT_ETC2_RGBA1_UNORM;
case PIXELFORMAT_ASTC_4x4_sRGB: return PIXELFORMAT_ASTC_4x4_UNORM;
case PIXELFORMAT_ASTC_5x4_sRGB: return PIXELFORMAT_ASTC_5x4_UNORM;
case PIXELFORMAT_ASTC_5x5_sRGB: return PIXELFORMAT_ASTC_5x5_UNORM;
case PIXELFORMAT_ASTC_6x5_sRGB: return PIXELFORMAT_ASTC_6x5_UNORM;
case PIXELFORMAT_ASTC_6x6_sRGB: return PIXELFORMAT_ASTC_6x6_UNORM;
case PIXELFORMAT_ASTC_8x5_sRGB: return PIXELFORMAT_ASTC_8x5_UNORM;
case PIXELFORMAT_ASTC_8x6_sRGB: return PIXELFORMAT_ASTC_8x6_UNORM;
case PIXELFORMAT_ASTC_8x8_sRGB: return PIXELFORMAT_ASTC_8x8_UNORM;
case PIXELFORMAT_ASTC_10x5_sRGB: return PIXELFORMAT_ASTC_10x5_UNORM;
case PIXELFORMAT_ASTC_10x6_sRGB: return PIXELFORMAT_ASTC_10x6_UNORM;
case PIXELFORMAT_ASTC_10x8_sRGB: return PIXELFORMAT_ASTC_10x8_UNORM;
case PIXELFORMAT_ASTC_10x10_sRGB: return PIXELFORMAT_ASTC_10x10_UNORM;
case PIXELFORMAT_ASTC_12x10_sRGB: return PIXELFORMAT_ASTC_12x10_UNORM;
case PIXELFORMAT_ASTC_12x12_sRGB: return PIXELFORMAT_ASTC_12x12_UNORM;
default: return format;
}
}
size_t getPixelFormatBlockSize(PixelFormat format)
+45 -16
View File
@@ -60,9 +60,9 @@ enum PixelFormat
// 4-channel normal formats
PIXELFORMAT_RGBA8_UNORM,
PIXELFORMAT_RGBA8_UNORM_sRGB,
PIXELFORMAT_RGBA8_sRGB,
PIXELFORMAT_BGRA8_UNORM,
PIXELFORMAT_BGRA8_UNORM_sRGB,
PIXELFORMAT_BGRA8_sRGB,
PIXELFORMAT_RGBA8_INT,
PIXELFORMAT_RGBA8_UINT,
PIXELFORMAT_RGBA16_UNORM,
@@ -90,8 +90,11 @@ enum PixelFormat
// compressed formats
PIXELFORMAT_DXT1_UNORM,
PIXELFORMAT_DXT1_sRGB,
PIXELFORMAT_DXT3_UNORM,
PIXELFORMAT_DXT3_sRGB,
PIXELFORMAT_DXT5_UNORM,
PIXELFORMAT_DXT5_sRGB,
PIXELFORMAT_BC4_UNORM,
PIXELFORMAT_BC4_SNORM,
PIXELFORMAT_BC5_UNORM,
@@ -99,32 +102,57 @@ enum PixelFormat
PIXELFORMAT_BC6H_UFLOAT,
PIXELFORMAT_BC6H_FLOAT,
PIXELFORMAT_BC7_UNORM,
PIXELFORMAT_BC7_sRGB,
PIXELFORMAT_PVR1_RGB2_UNORM,
PIXELFORMAT_PVR1_RGB2_sRGB,
PIXELFORMAT_PVR1_RGB4_UNORM,
PIXELFORMAT_PVR1_RGB4_sRGB,
PIXELFORMAT_PVR1_RGBA2_UNORM,
PIXELFORMAT_PVR1_RGBA2_sRGB,
PIXELFORMAT_PVR1_RGBA4_UNORM,
PIXELFORMAT_PVR1_RGBA4_sRGB,
PIXELFORMAT_ETC1_UNORM,
PIXELFORMAT_ETC2_RGB_UNORM,
PIXELFORMAT_ETC2_RGB_sRGB,
PIXELFORMAT_ETC2_RGBA_UNORM,
PIXELFORMAT_ETC2_RGBA_sRGB,
PIXELFORMAT_ETC2_RGBA1_UNORM,
PIXELFORMAT_ETC2_RGBA1_sRGB,
PIXELFORMAT_EAC_R_UNORM,
PIXELFORMAT_EAC_R_SNORM,
PIXELFORMAT_EAC_RG_UNORM,
PIXELFORMAT_EAC_RG_SNORM,
PIXELFORMAT_ASTC_4x4,
PIXELFORMAT_ASTC_5x4,
PIXELFORMAT_ASTC_5x5,
PIXELFORMAT_ASTC_6x5,
PIXELFORMAT_ASTC_6x6,
PIXELFORMAT_ASTC_8x5,
PIXELFORMAT_ASTC_8x6,
PIXELFORMAT_ASTC_8x8,
PIXELFORMAT_ASTC_10x5,
PIXELFORMAT_ASTC_10x6,
PIXELFORMAT_ASTC_10x8,
PIXELFORMAT_ASTC_10x10,
PIXELFORMAT_ASTC_12x10,
PIXELFORMAT_ASTC_12x12,
PIXELFORMAT_ASTC_4x4_UNORM,
PIXELFORMAT_ASTC_5x4_UNORM,
PIXELFORMAT_ASTC_5x5_UNORM,
PIXELFORMAT_ASTC_6x5_UNORM,
PIXELFORMAT_ASTC_6x6_UNORM,
PIXELFORMAT_ASTC_8x5_UNORM,
PIXELFORMAT_ASTC_8x6_UNORM,
PIXELFORMAT_ASTC_8x8_UNORM,
PIXELFORMAT_ASTC_10x5_UNORM,
PIXELFORMAT_ASTC_10x6_UNORM,
PIXELFORMAT_ASTC_10x8_UNORM,
PIXELFORMAT_ASTC_10x10_UNORM,
PIXELFORMAT_ASTC_12x10_UNORM,
PIXELFORMAT_ASTC_12x12_UNORM,
PIXELFORMAT_ASTC_4x4_sRGB,
PIXELFORMAT_ASTC_5x4_sRGB,
PIXELFORMAT_ASTC_5x5_sRGB,
PIXELFORMAT_ASTC_6x5_sRGB,
PIXELFORMAT_ASTC_6x6_sRGB,
PIXELFORMAT_ASTC_8x5_sRGB,
PIXELFORMAT_ASTC_8x6_sRGB,
PIXELFORMAT_ASTC_8x8_sRGB,
PIXELFORMAT_ASTC_10x5_sRGB,
PIXELFORMAT_ASTC_10x6_sRGB,
PIXELFORMAT_ASTC_10x8_sRGB,
PIXELFORMAT_ASTC_10x10_sRGB,
PIXELFORMAT_ASTC_12x10_sRGB,
PIXELFORMAT_ASTC_12x12_sRGB,
PIXELFORMAT_MAX_ENUM
};
@@ -149,6 +177,7 @@ struct PixelFormatInfo
bool depth;
bool stencil;
bool compressed;
bool sRGB;
PixelFormatType dataType;
};
+1 -1
View File
@@ -56,7 +56,7 @@ int w_ByteData_setString(lua_State *L)
if (size == 0)
return 0;
if (offset < 0 || offset + size > (int64) t->getSize())
if (offset < 0 || offset + (int64) size > (int64) t->getSize())
return luaL_error(L, "The given string offset and size don't fit within the Data's size.");
memcpy((char *) t->getData() + (size_t) offset, str, size);
+3 -13
View File
@@ -45,14 +45,9 @@ Font::Font()
defaultFontData.set(new data::ByteData(fontdata, rawsize, true), Acquire::NORETAIN);
}
Rasterizer *Font::newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting)
Rasterizer *Font::newTrueTypeRasterizer(int size, const TrueTypeRasterizer::Settings &settings)
{
return newTrueTypeRasterizer(defaultFontData.get(), size, hinting);
}
Rasterizer *Font::newTrueTypeRasterizer(int size, float dpiscale, TrueTypeRasterizer::Hinting hinting)
{
return newTrueTypeRasterizer(defaultFontData.get(), size, dpiscale, hinting);
return newTrueTypeRasterizer(defaultFontData.get(), size, settings);
}
Rasterizer *Font::newBMFontRasterizer(love::filesystem::FileData *fontdef, const std::vector<image::ImageData *> &images, float dpiscale)
@@ -78,12 +73,7 @@ Rasterizer *Font::newImageRasterizer(love::image::ImageData *data, const std::st
throw love::Exception("UTF-8 decoding error: %s", e.what());
}
return newImageRasterizer(data, &glyphs[0], (int) glyphs.size(), extraspacing, dpiscale);
}
Rasterizer *Font::newImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int numglyphs, int extraspacing, float dpiscale)
{
return new ImageRasterizer(data, glyphs, numglyphs, extraspacing, dpiscale);
return new ImageRasterizer(data, glyphs.data(), (int) glyphs.size(), extraspacing, dpiscale);
}
GlyphData *Font::newGlyphData(Rasterizer *r, const std::string &text)
+2 -5
View File
@@ -48,15 +48,12 @@ public:
virtual Rasterizer *newRasterizer(love::filesystem::FileData *data) = 0;
virtual Rasterizer *newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting);
virtual Rasterizer *newTrueTypeRasterizer(int size, float dpiscale, TrueTypeRasterizer::Hinting hinting);
virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) = 0;
virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) = 0;
Rasterizer *newTrueTypeRasterizer(int size, const TrueTypeRasterizer::Settings &settings);
virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const TrueTypeRasterizer::Settings &settings) = 0;
virtual Rasterizer *newBMFontRasterizer(love::filesystem::FileData *fontdef, const std::vector<image::ImageData *> &images, float dpiscale);
virtual Rasterizer *newImageRasterizer(love::image::ImageData *data, const std::string &glyphs, int extraspacing, float dpiscale);
virtual Rasterizer *newImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int length, int extraspacing, float dpiscale);
virtual GlyphData *newGlyphData(Rasterizer *r, const std::string &glyph);
virtual GlyphData *newGlyphData(Rasterizer *r, uint32 glyph);
+7
View File
@@ -24,6 +24,7 @@
// LOVE
#include "Rasterizer.h"
#include "common/StringMap.h"
#include "common/Optional.h"
namespace love
{
@@ -44,6 +45,12 @@ public:
HINTING_MAX_ENUM
};
struct Settings
{
Hinting hinting = HINTING_NORMAL;
OptionalFloat dpiScale;
};
virtual ~TrueTypeRasterizer() {}
static bool getConstant(const char *in, Hinting &out);
+5 -10
View File
@@ -49,26 +49,21 @@ Font::~Font()
Rasterizer *Font::newRasterizer(love::filesystem::FileData *data)
{
if (TrueTypeRasterizer::accepts(library, data))
return newTrueTypeRasterizer(data, 12, TrueTypeRasterizer::HINTING_NORMAL);
return newTrueTypeRasterizer(data, 12, font::TrueTypeRasterizer::Settings());
else if (BMFontRasterizer::accepts(data))
return newBMFontRasterizer(data, {}, 1.0f);
throw love::Exception("Invalid font file: %s", data->getFilename().c_str());
}
Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting)
Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings)
{
float dpiscale = 1.0f;
float defaultdpiscale = 1.0f;
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window != nullptr)
dpiscale = window->getDPIScale();
defaultdpiscale = window->getDPIScale();
return newTrueTypeRasterizer(data, size, dpiscale, hinting);
}
Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting)
{
return new TrueTypeRasterizer(library, data, size, dpiscale, hinting);
return new TrueTypeRasterizer(library, data, size, settings, defaultdpiscale);
}
const char *Font::getName() const
+1 -2
View File
@@ -45,8 +45,7 @@ public:
// Implements Font
Rasterizer *newRasterizer(love::filesystem::FileData *data) override;
Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) override;
Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) override;
Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings) override;
// Implement Module
const char *getName() const override;
+6 -6
View File
@@ -153,18 +153,18 @@ void HarfbuzzShaper::computeBufferRanges(const ColoredCodepoints &codepoints, Ra
hb_shape(hbFonts[rasti], hbb, nullptr, 0);
int glyphcount = (int)hb_buffer_get_length(hbb);
size_t glyphcount = (size_t)hb_buffer_get_length(hbb);
const hb_glyph_info_t *glyphinfos = hb_buffer_get_glyph_infos(hbb, nullptr);
hb_direction_t direction = hb_buffer_get_direction(hbb);
fallbackranges.clear();
for (int i = 0; i < glyphcount; i++)
for (size_t i = 0; i < glyphcount; i++)
{
if (isValidGlyph(glyphinfos[i].codepoint, codepoints.cps, glyphinfos[i].cluster))
{
if (bufferranges.empty() || bufferranges.back().index != rasti || bufferranges.back().range.getMax() + 1 != i)
bufferranges.push_back({(int)rasti, (int)glyphinfos[i].cluster, Range(i, 1)});
bufferranges.push_back({rasti, (int)glyphinfos[i].cluster, Range(i, 1)});
else
bufferranges.back().range.last++;
}
@@ -247,7 +247,7 @@ void HarfbuzzShaper::computeGlyphPositions(const ColoredCodepoints &codepoints,
// TODO: this doesn't handle situations where the user inserted a color
// change in the middle of some characters that get combined into a single
// cluster.
if (colors && colorindex < ncolors && codepoints.colors[colorindex].index == info.cluster)
if (colors && colorindex < ncolors && codepoints.colors[colorindex].index == (int)info.cluster)
{
colorToAdd.set(codepoints.colors[colorindex].color);
colorindex++;
@@ -273,7 +273,7 @@ void HarfbuzzShaper::computeGlyphPositions(const ColoredCodepoints &codepoints,
continue;
// This is a glyph index at this point, despite the name.
GlyphIndex gindex = { (int) info.codepoint, bufferrange.index };
GlyphIndex gindex = { (int) info.codepoint, (int)bufferrange.index };
if (clustercodepoint == '\t' && isUsingSpacesForTab())
{
@@ -390,7 +390,7 @@ int HarfbuzzShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ra
if (newwidth > wraplimit)
{
// If this is the first character, wrap from the next one instead of this one.
int wrapindex = info.cluster > (int) range.first ? info.cluster : (int) range.first + 1;
int wrapindex = (int)info.cluster > (int)range.first ? (int)info.cluster : (int)range.first + 1;
// Rewind to after the last seen space when wrapping.
if (firstindexafterspace != -1)
+1 -1
View File
@@ -53,7 +53,7 @@ private:
struct BufferRange
{
int index;
size_t index;
int codepointStart;
Range range;
};
@@ -33,12 +33,12 @@ namespace font
namespace freetype
{
TrueTypeRasterizer::TrueTypeRasterizer(FT_Library library, love::Data *data, int size, float dpiscale, Hinting hinting)
TrueTypeRasterizer::TrueTypeRasterizer(FT_Library library, love::Data *data, int size, const Settings &settings, float defaultdpiscale)
: data(data)
, hinting(hinting)
, hinting(settings.hinting)
{
this->dpiScale = dpiscale;
size = floorf(size * dpiscale + 0.5f);
dpiScale = settings.dpiScale.get(defaultdpiscale);
size = floorf(size * dpiScale + 0.5f);
if (size <= 0)
throw love::Exception("Invalid TrueType font size: %d", size);
@@ -44,7 +44,7 @@ class TrueTypeRasterizer : public love::font::TrueTypeRasterizer
{
public:
TrueTypeRasterizer(FT_Library library, love::Data *data, int size, float dpiscale, Hinting hinting);
TrueTypeRasterizer(FT_Library library, love::Data *data, int size, const Settings &settings, float defaultdpiscale);
virtual ~TrueTypeRasterizer();
// Implement Rasterizer
+51 -33
View File
@@ -64,30 +64,65 @@ int w_newRasterizer(lua_State *L)
}
}
static TrueTypeRasterizer::Settings luax_checktruetypesettings(lua_State* L, int startidx)
{
TrueTypeRasterizer::Settings s;
if (lua_type(L, startidx) == LUA_TSTRING)
{
// Legacy parameters.
const char *hintstr = lua_isnoneornil(L, startidx) ? nullptr : luaL_checkstring(L, startidx);
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, s.hinting))
luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(s.hinting), hintstr);
if (!lua_isnoneornil(L, startidx + 1))
s.dpiScale.set((float)luaL_checknumber(L, startidx + 1));
}
else
{
luaL_checktype(L, startidx, LUA_TTABLE);
lua_getfield(L, startidx, "hinting");
if (!lua_isnoneornil(L, -1))
{
const char *hintstr = luaL_checkstring(L, -1);
if (!TrueTypeRasterizer::getConstant(hintstr, s.hinting))
luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(s.hinting), hintstr);
}
lua_pop(L, 1);
lua_getfield(L, startidx, "dpiscale");
if (!lua_isnoneornil(L, -1))
s.dpiScale.set((float)luaL_checknumber(L, -1));
lua_pop(L, 1);
}
return s;
}
int w_newTrueTypeRasterizer(lua_State *L)
{
Rasterizer *t = nullptr;
TrueTypeRasterizer::Hinting hinting = TrueTypeRasterizer::HINTING_NORMAL;
if (lua_type(L, 1) == LUA_TNUMBER || lua_isnone(L, 1))
{
// First argument is a number: use the default TrueType font.
int size = (int) luaL_optinteger(L, 1, 13);
const char *hintstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting))
return luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(hinting), hintstr);
TrueTypeRasterizer::Settings settings;
if (!lua_isnoneornil(L, 2))
settings = luax_checktruetypesettings(L, 2);
if (lua_isnoneornil(L, 3))
luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, hinting); });
else
{
float dpiscale = (float) luaL_checknumber(L, 3);
luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, dpiscale, hinting); });
}
luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, settings); });
}
else
{
int size = (int) luaL_optinteger(L, 2, 12);
TrueTypeRasterizer::Settings settings;
if (!lua_isnoneornil(L, 3))
settings = luax_checktruetypesettings(L, 3);
love::Data *d = nullptr;
if (luax_istype(L, 1, love::Data::type))
@@ -98,27 +133,10 @@ int w_newTrueTypeRasterizer(lua_State *L)
else
d = filesystem::luax_getfiledata(L, 1);
int size = (int) luaL_optinteger(L, 2, 12);
const char *hintstr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3);
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting))
return luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(hinting), hintstr);
if (lua_isnoneornil(L, 4))
{
luax_catchexcept(L,
[&]() { t = instance()->newTrueTypeRasterizer(d, size, hinting); },
[&](bool) { d->release(); }
);
}
else
{
float dpiscale = (float) luaL_checknumber(L, 4);
luax_catchexcept(L,
[&]() { t = instance()->newTrueTypeRasterizer(d, size, dpiscale, hinting); },
[&](bool) { d->release(); }
);
}
luax_catchexcept(L,
[&]() { t = instance()->newTrueTypeRasterizer(d, size, settings); },
[&](bool) { d->release(); }
);
}
luax_pushtype(L, t);
@@ -154,7 +172,7 @@ int w_newBMFontRasterizer(lua_State *L)
lua_pop(L, 1);
}
}
else
else if (!lua_isnoneornil(L, 2))
{
convimagedata(L, 2);
image::ImageData *id = luax_checktype<image::ImageData>(L, 2);
+3 -3
View File
@@ -74,12 +74,12 @@ void Deprecations::draw(Graphics *gfx)
if (font.get() == nullptr)
{
auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL;
font::TrueTypeRasterizer::Settings settings;
if (!isGammaCorrect() && gfx->getScreenDPIScale() <= 1.0)
hinting = font::TrueTypeRasterizer::HINTING_LIGHT;
settings.hinting = font::TrueTypeRasterizer::HINTING_LIGHT;
font.set(gfx->newDefaultFont(9, hinting), Acquire::NORETAIN);
font.set(gfx->newDefaultFont(9, settings), Acquire::NORETAIN);
}
gfx->flushBatchedDraws();
+23 -4
View File
@@ -294,13 +294,13 @@ Font *Graphics::newFont(love::font::Rasterizer *data)
return new Font(data, states.back().defaultSamplerState);
}
Font *Graphics::newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting)
Font *Graphics::newDefaultFont(int size, const font::TrueTypeRasterizer::Settings &settings)
{
auto fontmodule = Module::getInstance<font::Font>(M_FONT);
if (!fontmodule)
throw love::Exception("Font module has not been loaded.");
StrongRef<font::Rasterizer> r(fontmodule->newTrueTypeRasterizer(size, hinting), Acquire::NORETAIN);
StrongRef<font::Rasterizer> r(fontmodule->newTrueTypeRasterizer(size, settings), Acquire::NORETAIN);
return newFont(r.get());
}
@@ -731,7 +731,10 @@ void Graphics::checkSetDefaultFont()
// Create a new default font if we don't have one yet.
if (!defaultFont.get())
defaultFont.set(newDefaultFont(13, font::TrueTypeRasterizer::HINTING_NORMAL), Acquire::NORETAIN);
{
font::TrueTypeRasterizer::Settings settings;
defaultFont.set(newDefaultFont(13, settings), Acquire::NORETAIN);
}
states.back().font.set(defaultFont.get());
}
@@ -925,7 +928,7 @@ void Graphics::setRenderTargets(const RenderTargets &rts)
PixelFormat dsformat = PIXELFORMAT_STENCIL8;
if (wantsdepth && wantsstencil)
dsformat = PIXELFORMAT_DEPTH24_UNORM_STENCIL8;
else if (wantsdepth && isPixelFormatSupported(PIXELFORMAT_DEPTH24_UNORM, PIXELFORMATUSAGEFLAGS_RENDERTARGET, false))
else if (wantsdepth && isPixelFormatSupported(PIXELFORMAT_DEPTH24_UNORM, PIXELFORMATUSAGEFLAGS_RENDERTARGET))
dsformat = PIXELFORMAT_DEPTH24_UNORM;
else if (wantsdepth)
dsformat = PIXELFORMAT_DEPTH16_UNORM;
@@ -2389,6 +2392,22 @@ const Graphics::Capabilities &Graphics::getCapabilities() const
return capabilities;
}
PixelFormat Graphics::getSizedFormat(PixelFormat format) const
{
switch (format)
{
case PIXELFORMAT_NORMAL:
if (isGammaCorrect())
return PIXELFORMAT_RGBA8_sRGB;
else
return PIXELFORMAT_RGBA8_UNORM;
case PIXELFORMAT_HDR:
return PIXELFORMAT_RGBA16_FLOAT;
default:
return format;
}
}
Graphics::Stats Graphics::getStats() const
{
Stats stats;
+3 -3
View File
@@ -459,7 +459,7 @@ public:
Quad *newQuad(Quad::Viewport v, double sw, double sh);
Font *newFont(love::font::Rasterizer *data);
Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting);
Font *newDefaultFont(int size, const font::TrueTypeRasterizer::Settings &settings);
Video *newVideo(love::video::VideoStream *stream, float dpiscale);
SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferDataUsage usage);
@@ -819,12 +819,12 @@ public:
/**
* Converts PIXELFORMAT_NORMAL and PIXELFORMAT_HDR into a real format.
**/
virtual PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const = 0;
PixelFormat getSizedFormat(PixelFormat format) const;
/**
* Gets whether the specified pixel format usage is supported.
**/
virtual bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) = 0;
virtual bool isPixelFormatSupported(PixelFormat format, uint32 usage) = 0;
/**
* Gets the renderer used by love.graphics.
+3 -1
View File
@@ -81,6 +81,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture
}
textureFormat = getLinearPixelFormat(texture->getPixelFormat());
isFormatLinear = isGammaCorrect() && !isPixelFormatSRGB(texture->getPixelFormat());
if (!image::ImageData::validPixelFormat(textureFormat))
{
@@ -96,7 +97,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture
if (isRT && !caps.features[Graphics::FEATURE_COPY_RENDER_TARGET_TO_BUFFER])
throw love::Exception("readbackTextureAsync is not supported on this system.");
else if (!isRT && !caps.features[Graphics::FEATURE_COPY_TEXTURE_TO_BUFFER])
throw love::Exception("readbackTextureAsync a with non-render-target textures is not supported on this system.");
throw love::Exception("readbackTextureAsync with a non-render-target texture is not supported on this system.");
}
else
{
@@ -158,6 +159,7 @@ void *GraphicsReadback::prepareReadbackDest(size_t size)
throw love::Exception("The love.image module must be loaded for readbackTexture.");
imageData.set(module->newImageData(rect.w, rect.h, textureFormat, nullptr), Acquire::NORETAIN);
imageData->setLinear(isFormatLinear);
return imageData->getData();
}
}
+1
View File
@@ -103,6 +103,7 @@ protected:
StrongRef<love::image::ImageData> imageData;
Rect rect = {};
PixelFormat textureFormat = PIXELFORMAT_UNKNOWN;
bool isFormatLinear = false;
int imageDataX = 0;
int imageDataY = 0;
+9 -1
View File
@@ -1010,8 +1010,16 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
values[i].u = convertData<uint32>((*constarray)[i]);
}
break;
case glslang::EbtInt:
case glslang::EbtBool:
u.dataType = DATA_BASETYPE_BOOL;
if (constarray != nullptr)
{
values.resize(constarray->size());
for (int i = 0; i < constarray->size(); i++)
values[i].u = convertData<uint32>((*constarray)[i]);
}
break;
case glslang::EbtInt:
default:
u.dataType = DATA_BASETYPE_INT;
if (constarray != nullptr)
+10 -5
View File
@@ -168,7 +168,6 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
, computeWrite(settings.computeWrite)
, readable(true)
, mipmapsMode(settings.mipmaps)
, sRGB(isGammaCorrect() && !settings.linear)
, width(settings.width)
, height(settings.height)
, depth(settings.type == TEXTURE_VOLUME ? settings.layers : 1)
@@ -204,7 +203,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
love::image::ImageDataBase *slice = slices->get(0, 0);
format = slice->getFormat();
if (sRGB)
if (isGammaCorrect() && !slice->isLinear())
format = getSRGBPixelFormat(format);
pixelWidth = slice->getWidth();
@@ -235,7 +234,9 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
else
readable = !renderTarget || !isPixelFormatDepthStencil(format);
format = gfx->getSizedFormat(format, renderTarget, readable);
format = gfx->getSizedFormat(format);
if (!isGammaCorrect() || settings.linear)
format = getLinearPixelFormat(format);
if (mipmapsMode == MIPMAPS_AUTO && isCompressed())
mipmapsMode = MIPMAPS_MANUAL;
@@ -290,7 +291,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
if (computeWrite)
usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE;
if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, sRGB))
if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage))
{
const char *fstr = "unknown";
love::getConstant(format, fstr);
@@ -621,7 +622,7 @@ bool Texture::isCompressed() const
bool Texture::isFormatLinear() const
{
return isGammaCorrect() && !sRGB && !isPixelFormatSRGB(format);
return isGammaCorrect() && !isPixelFormatSRGB(format);
}
bool Texture::isValidSlice(int slice, int mip) const
@@ -885,6 +886,7 @@ bool Texture::Slices::validate() const
int w = firstdata->getWidth();
int h = firstdata->getHeight();
PixelFormat format = firstdata->getFormat();
bool linear = firstdata->isLinear();
if (textureType == TEXTURE_CUBE && w != h)
throw love::Exception("Cube textures must have equal widths and heights for each cube face.");
@@ -924,6 +926,9 @@ bool Texture::Slices::validate() const
if (format != slicedata->getFormat())
throw love::Exception("All texture slices and mipmaps must have the same pixel format.");
if (linear != slicedata->isLinear())
throw love::Exception("All texture slices and mipmaps must have the same linear setting.");
}
mipw = std::max(mipw / 2, 1);
-2
View File
@@ -325,8 +325,6 @@ protected:
MipmapsMode mipmapsMode;
bool sRGB;
int width;
int height;
+1 -2
View File
@@ -110,8 +110,7 @@ public:
void setWireframe(bool enable) override;
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
bool isPixelFormatSupported(PixelFormat format, uint32 usage) override;
Renderer getRenderer() const override;
bool usesGLSLES() const override;
RendererInfo getRendererInfo() const override;
+46 -43
View File
@@ -503,7 +503,7 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
backbufferMSAA.set(nullptr);
if (settings.msaa > 1)
{
settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM;
backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN);
}
@@ -681,7 +681,7 @@ id<MTLRenderCommandEncoder> Graphics::useRenderEncoder()
attachmentStoreActions.stencil = MTLStoreActionDontCare;
auto &key = lastRenderPipelineKey;
key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM;
key.depthStencilFormat = backbufferDepthStencil->getPixelFormat();
key.msaa = backbufferMSAA ? (uint8) backbufferMSAA->getMSAA() : 1;
}
@@ -1864,31 +1864,9 @@ void Graphics::setWireframe(bool enable)
}
}
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool /*rendertarget*/, bool /*readable*/) const
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
{
switch (format)
{
case PIXELFORMAT_NORMAL:
if (isGammaCorrect())
return PIXELFORMAT_RGBA8_UNORM_sRGB;
else
return PIXELFORMAT_RGBA8_UNORM;
case PIXELFORMAT_HDR:
return PIXELFORMAT_RGBA16_FLOAT;
default:
return format;
}
}
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
{
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
format = getSizedFormat(format, rendertarget, readable);
if (sRGB)
format = getSRGBPixelFormat(format);
format = getSizedFormat(format);
const uint32 sample = PIXELFORMATUSAGEFLAGS_SAMPLE;
const uint32 filter = PIXELFORMATUSAGEFLAGS_LINEAR;
@@ -1902,7 +1880,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
uint32 flags = PIXELFORMATUSAGEFLAGS_NONE;
if (isPixelFormatCompressed(format) && rendertarget)
if (isPixelFormatCompressed(format) && (usage & rt) != 0)
return false;
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
@@ -1977,8 +1955,8 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
case PIXELFORMAT_BGRA8_UNORM:
flags |= all;
break;
case PIXELFORMAT_RGBA8_UNORM_sRGB:
case PIXELFORMAT_BGRA8_UNORM_sRGB:
case PIXELFORMAT_RGBA8_sRGB:
case PIXELFORMAT_BGRA8_sRGB:
if (families.apple[1] || families.mac[1] || families.macCatalyst[1])
flags |= commonsample | commonrender;
if (families.apple[2])
@@ -2077,8 +2055,11 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
break;
case PIXELFORMAT_DXT1_UNORM:
case PIXELFORMAT_DXT1_sRGB:
case PIXELFORMAT_DXT3_UNORM:
case PIXELFORMAT_DXT3_sRGB:
case PIXELFORMAT_DXT5_UNORM:
case PIXELFORMAT_DXT5_sRGB:
case PIXELFORMAT_BC4_UNORM:
case PIXELFORMAT_BC4_SNORM:
case PIXELFORMAT_BC5_UNORM:
@@ -2086,22 +2067,30 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
case PIXELFORMAT_BC6H_UFLOAT:
case PIXELFORMAT_BC6H_FLOAT:
case PIXELFORMAT_BC7_UNORM:
case PIXELFORMAT_BC7_sRGB:
if (families.mac[1] || families.macCatalyst[1])
flags |= commonsample;
break;
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:
if (families.apple[1])
flags |= commonsample;
break;
case PIXELFORMAT_ETC1_UNORM:
case PIXELFORMAT_ETC2_RGB_UNORM:
case PIXELFORMAT_ETC2_RGB_sRGB:
case PIXELFORMAT_ETC2_RGBA_UNORM:
case PIXELFORMAT_ETC2_RGBA_sRGB:
case PIXELFORMAT_ETC2_RGBA1_UNORM:
case PIXELFORMAT_ETC2_RGBA1_sRGB:
case PIXELFORMAT_EAC_R_UNORM:
case PIXELFORMAT_EAC_R_SNORM:
case PIXELFORMAT_EAC_RG_UNORM:
@@ -2110,20 +2099,34 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
flags |= commonsample;
break;
case PIXELFORMAT_ASTC_4x4:
case PIXELFORMAT_ASTC_5x4:
case PIXELFORMAT_ASTC_5x5:
case PIXELFORMAT_ASTC_6x5:
case PIXELFORMAT_ASTC_6x6:
case PIXELFORMAT_ASTC_8x5:
case PIXELFORMAT_ASTC_8x6:
case PIXELFORMAT_ASTC_8x8:
case PIXELFORMAT_ASTC_10x5:
case PIXELFORMAT_ASTC_10x6:
case PIXELFORMAT_ASTC_10x8:
case PIXELFORMAT_ASTC_10x10:
case PIXELFORMAT_ASTC_12x10:
case PIXELFORMAT_ASTC_12x12:
case PIXELFORMAT_ASTC_4x4_UNORM:
case PIXELFORMAT_ASTC_5x4_UNORM:
case PIXELFORMAT_ASTC_5x5_UNORM:
case PIXELFORMAT_ASTC_6x5_UNORM:
case PIXELFORMAT_ASTC_6x6_UNORM:
case PIXELFORMAT_ASTC_8x5_UNORM:
case PIXELFORMAT_ASTC_8x6_UNORM:
case PIXELFORMAT_ASTC_8x8_UNORM:
case PIXELFORMAT_ASTC_10x5_UNORM:
case PIXELFORMAT_ASTC_10x6_UNORM:
case PIXELFORMAT_ASTC_10x8_UNORM:
case PIXELFORMAT_ASTC_10x10_UNORM:
case PIXELFORMAT_ASTC_12x10_UNORM:
case PIXELFORMAT_ASTC_12x12_UNORM:
case PIXELFORMAT_ASTC_4x4_sRGB:
case PIXELFORMAT_ASTC_5x4_sRGB:
case PIXELFORMAT_ASTC_5x5_sRGB:
case PIXELFORMAT_ASTC_6x5_sRGB:
case PIXELFORMAT_ASTC_6x6_sRGB:
case PIXELFORMAT_ASTC_8x5_sRGB:
case PIXELFORMAT_ASTC_8x6_sRGB:
case PIXELFORMAT_ASTC_8x8_sRGB:
case PIXELFORMAT_ASTC_10x5_sRGB:
case PIXELFORMAT_ASTC_10x6_sRGB:
case PIXELFORMAT_ASTC_10x8_sRGB:
case PIXELFORMAT_ASTC_10x10_sRGB:
case PIXELFORMAT_ASTC_12x10_sRGB:
case PIXELFORMAT_ASTC_12x12_sRGB:
if (families.apple[2])
flags |= commonsample;
break;
+1 -1
View File
@@ -43,7 +43,7 @@ public:
API_AVAILABLE(macos(10.15), ios(13.0)) MTLTextureSwizzleChannels swizzle;
};
static PixelFormatDesc convertPixelFormat(id<MTLDevice> device, PixelFormat format, bool &isSRGB);
static PixelFormatDesc convertPixelFormat(id<MTLDevice> device, PixelFormat format);
}; // Metal
+148 -67
View File
@@ -28,17 +28,11 @@ namespace graphics
namespace metal
{
Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelFormat format, bool &isSRGB)
Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelFormat format)
{
MTLPixelFormat mtlformat = MTLPixelFormatInvalid;
PixelFormatDesc desc = {};
if (isSRGB)
format = getSRGBPixelFormat(format);
if (!isPixelFormatCompressed(format) && !isPixelFormatSRGB(format))
isSRGB = false;
switch (format)
{
case PIXELFORMAT_R8_UNORM:
@@ -50,13 +44,13 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelForm
case PIXELFORMAT_RGBA8_UNORM:
mtlformat = MTLPixelFormatRGBA8Unorm;
break;
case PIXELFORMAT_RGBA8_UNORM_sRGB:
case PIXELFORMAT_RGBA8_sRGB:
mtlformat = MTLPixelFormatRGBA8Unorm_sRGB;
break;
case PIXELFORMAT_BGRA8_UNORM:
mtlformat = MTLPixelFormatBGRA8Unorm;
break;
case PIXELFORMAT_BGRA8_UNORM_sRGB:
case PIXELFORMAT_BGRA8_sRGB:
mtlformat = MTLPixelFormatBGRA8Unorm_sRGB;
break;
case PIXELFORMAT_R16_UNORM:
@@ -205,177 +199,264 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelForm
case PIXELFORMAT_DXT1_UNORM:
#ifndef LOVE_IOS
mtlformat = isSRGB ? MTLPixelFormatBC1_RGBA_sRGB : MTLPixelFormatBC1_RGBA;
mtlformat = MTLPixelFormatBC1_RGBA;
#endif
break;
case PIXELFORMAT_DXT1_sRGB:
#ifndef LOVE_IOS
mtlformat = MTLPixelFormatBC1_RGBA_sRGB;
#endif
break;
case PIXELFORMAT_DXT3_UNORM:
#ifndef LOVE_IOS
mtlformat = isSRGB ? MTLPixelFormatBC2_RGBA_sRGB : MTLPixelFormatBC2_RGBA;
mtlformat = MTLPixelFormatBC2_RGBA;
#endif
break;
case PIXELFORMAT_DXT3_sRGB:
#ifndef LOVE_IOS
mtlformat = MTLPixelFormatBC2_RGBA_sRGB;
#endif
break;
case PIXELFORMAT_DXT5_UNORM:
#ifndef LOVE_IOS
mtlformat = isSRGB ? MTLPixelFormatBC3_RGBA_sRGB : MTLPixelFormatBC3_RGBA;
mtlformat = MTLPixelFormatBC3_RGBA;
#endif
break;
case PIXELFORMAT_DXT5_sRGB:
#ifndef LOVE_IOS
mtlformat = MTLPixelFormatBC3_RGBA_sRGB;
#endif
break;
case PIXELFORMAT_BC4_UNORM:
#ifndef LOVE_IOS
isSRGB = false;
mtlformat = MTLPixelFormatBC4_RUnorm;
#endif
break;
case PIXELFORMAT_BC4_SNORM:
#ifndef LOVE_IOS
isSRGB = false;
mtlformat = MTLPixelFormatBC4_RSnorm;
#endif
break;
case PIXELFORMAT_BC5_UNORM:
#ifndef LOVE_IOS
isSRGB = false;
mtlformat = MTLPixelFormatBC5_RGUnorm;
#endif
break;
case PIXELFORMAT_BC5_SNORM:
#ifndef LOVE_IOS
isSRGB = false;
mtlformat = MTLPixelFormatBC5_RGSnorm;
#endif
break;
case PIXELFORMAT_BC6H_UFLOAT:
#ifndef LOVE_IOS
isSRGB = false;
mtlformat = MTLPixelFormatBC6H_RGBUfloat;
#endif
break;
case PIXELFORMAT_BC6H_FLOAT:
#ifndef LOVE_IOS
isSRGB = false;
mtlformat = MTLPixelFormatBC6H_RGBFloat;
#endif
break;
case PIXELFORMAT_BC7_UNORM:
#ifndef LOVE_IOS
mtlformat = isSRGB ? MTLPixelFormatBC7_RGBAUnorm_sRGB : MTLPixelFormatBC7_RGBAUnorm;
mtlformat = MTLPixelFormatBC7_RGBAUnorm;
#endif
break;
case PIXELFORMAT_BC7_sRGB:
#ifndef LOVE_IOS
mtlformat = MTLPixelFormatBC7_RGBAUnorm_sRGB;
#endif
break;
case PIXELFORMAT_PVR1_RGB2_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_2BPP_sRGB : MTLPixelFormatPVRTC_RGB_2BPP;
mtlformat = MTLPixelFormatPVRTC_RGB_2BPP;
break;
case PIXELFORMAT_PVR1_RGB2_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatPVRTC_RGB_2BPP_sRGB;
break;
case PIXELFORMAT_PVR1_RGB4_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_4BPP_sRGB : MTLPixelFormatPVRTC_RGB_4BPP;
mtlformat = MTLPixelFormatPVRTC_RGB_4BPP;
break;
case PIXELFORMAT_PVR1_RGB4_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatPVRTC_RGB_4BPP_sRGB;
break;
case PIXELFORMAT_PVR1_RGBA2_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_2BPP_sRGB : MTLPixelFormatPVRTC_RGBA_2BPP;
mtlformat = MTLPixelFormatPVRTC_RGBA_2BPP;
break;
case PIXELFORMAT_PVR1_RGBA2_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatPVRTC_RGB_2BPP_sRGB;
break;
case PIXELFORMAT_PVR1_RGBA4_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_4BPP_sRGB : MTLPixelFormatPVRTC_RGBA_4BPP;
mtlformat = MTLPixelFormatPVRTC_RGBA_4BPP;
break;
case PIXELFORMAT_PVR1_RGBA4_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatPVRTC_RGB_4BPP_sRGB;
break;
case PIXELFORMAT_ETC1_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
mtlformat = MTLPixelFormatETC2_RGB8;
break;
case PIXELFORMAT_ETC2_RGB_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
mtlformat = MTLPixelFormatETC2_RGB8;
break;
case PIXELFORMAT_ETC2_RGB_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatETC2_RGB8_sRGB;
break;
case PIXELFORMAT_ETC2_RGBA_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8;
mtlformat = MTLPixelFormatEAC_RGBA8;
break;
case PIXELFORMAT_ETC2_RGBA_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatEAC_RGBA8_sRGB;
break;
case PIXELFORMAT_ETC2_RGBA1_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1;
mtlformat = MTLPixelFormatETC2_RGB8A1;
break;
case PIXELFORMAT_ETC2_RGBA1_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatETC2_RGB8A1_sRGB;
break;
case PIXELFORMAT_EAC_R_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
{
isSRGB = false;
mtlformat = MTLPixelFormatEAC_R11Unorm;
}
break;
case PIXELFORMAT_EAC_R_SNORM:
if (@available(macOS 11.0, iOS 8.0, *))
{
isSRGB = false;
mtlformat = MTLPixelFormatEAC_R11Snorm;
}
break;
case PIXELFORMAT_EAC_RG_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
{
isSRGB = false;
mtlformat = MTLPixelFormatEAC_RG11Unorm;
}
break;
case PIXELFORMAT_EAC_RG_SNORM:
if (@available(macOS 11.0, iOS 8.0, *))
{
isSRGB = false;
mtlformat = MTLPixelFormatEAC_RG11Snorm;
}
break;
case PIXELFORMAT_ASTC_4x4:
case PIXELFORMAT_ASTC_4x4_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR;
mtlformat = MTLPixelFormatASTC_4x4_LDR;
break;
case PIXELFORMAT_ASTC_5x4:
case PIXELFORMAT_ASTC_5x4_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR;
mtlformat = MTLPixelFormatASTC_5x4_LDR;
break;
case PIXELFORMAT_ASTC_5x5:
case PIXELFORMAT_ASTC_5x5_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR;
mtlformat = MTLPixelFormatASTC_5x5_LDR;
break;
case PIXELFORMAT_ASTC_6x5:
case PIXELFORMAT_ASTC_6x5_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR;
mtlformat = MTLPixelFormatASTC_6x5_LDR;
break;
case PIXELFORMAT_ASTC_6x6:
case PIXELFORMAT_ASTC_6x6_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR;
mtlformat = MTLPixelFormatASTC_6x6_LDR;
break;
case PIXELFORMAT_ASTC_8x5:
case PIXELFORMAT_ASTC_8x5_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR;
mtlformat = MTLPixelFormatASTC_8x5_LDR;
break;
case PIXELFORMAT_ASTC_8x6:
case PIXELFORMAT_ASTC_8x6_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR;
mtlformat = MTLPixelFormatASTC_8x6_LDR;
break;
case PIXELFORMAT_ASTC_8x8:
case PIXELFORMAT_ASTC_8x8_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR;
mtlformat = MTLPixelFormatASTC_8x8_LDR;
break;
case PIXELFORMAT_ASTC_10x5:
case PIXELFORMAT_ASTC_10x5_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR;
mtlformat = MTLPixelFormatASTC_10x5_LDR;
break;
case PIXELFORMAT_ASTC_10x6:
case PIXELFORMAT_ASTC_10x6_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR;
mtlformat = MTLPixelFormatASTC_10x6_LDR;
break;
case PIXELFORMAT_ASTC_10x8:
case PIXELFORMAT_ASTC_10x8_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR;
mtlformat = MTLPixelFormatASTC_10x8_LDR;
break;
case PIXELFORMAT_ASTC_10x10:
case PIXELFORMAT_ASTC_10x10_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR;
mtlformat = MTLPixelFormatASTC_10x10_LDR;
break;
case PIXELFORMAT_ASTC_12x10:
case PIXELFORMAT_ASTC_12x10_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR;
mtlformat = MTLPixelFormatASTC_12x10_LDR;
break;
case PIXELFORMAT_ASTC_12x12:
case PIXELFORMAT_ASTC_12x12_UNORM:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = isSRGB ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
mtlformat = MTLPixelFormatASTC_12x12_LDR;
break;
case PIXELFORMAT_ASTC_4x4_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_4x4_sRGB;
break;
case PIXELFORMAT_ASTC_5x4_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_5x4_sRGB;
break;
case PIXELFORMAT_ASTC_5x5_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_5x5_sRGB;
break;
case PIXELFORMAT_ASTC_6x5_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_6x5_sRGB;
break;
case PIXELFORMAT_ASTC_6x6_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_6x6_sRGB;
break;
case PIXELFORMAT_ASTC_8x5_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_8x5_sRGB;
break;
case PIXELFORMAT_ASTC_8x6_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_8x6_sRGB;
break;
case PIXELFORMAT_ASTC_8x8_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_8x8_sRGB;
break;
case PIXELFORMAT_ASTC_10x5_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_10x5_sRGB;
break;
case PIXELFORMAT_ASTC_10x6_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_10x6_sRGB;
break;
case PIXELFORMAT_ASTC_10x8_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_10x8_sRGB;
break;
case PIXELFORMAT_ASTC_10x10_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_10x10_sRGB;
break;
case PIXELFORMAT_ASTC_12x10_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_12x10_sRGB;
break;
case PIXELFORMAT_ASTC_12x12_sRGB:
if (@available(macOS 11.0, iOS 8.0, *))
mtlformat = MTLPixelFormatASTC_12x12_sRGB;
break;
case PIXELFORMAT_UNKNOWN:
+2 -4
View File
@@ -1087,8 +1087,7 @@ id<MTLRenderPipelineState> Shader::getCachedRenderPipeline(const RenderPipelineK
MTLRenderPipelineColorAttachmentDescriptor *attachment = desc.colorAttachments[i];
bool isSRGB = false;
auto formatdesc = Metal::convertPixelFormat(device, format, isSRGB);
auto formatdesc = Metal::convertPixelFormat(device, format);
attachment.pixelFormat = formatdesc.format;
if (key.blend.enable)
@@ -1124,8 +1123,7 @@ id<MTLRenderPipelineState> Shader::getCachedRenderPipeline(const RenderPipelineK
{
// We already don't really support metal on older systems, this just
// silences a compiler warning about it.
bool isSRGB = false;
auto formatdesc = Metal::convertPixelFormat(device, dsformat, isSRGB);
auto formatdesc = Metal::convertPixelFormat(device, dsformat);
if (isPixelFormatDepth(dsformat))
desc.depthAttachmentPixelFormat = formatdesc.format;
if (isPixelFormatStencil(dsformat))
+1 -1
View File
@@ -62,7 +62,7 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id<MTLDevice> device, const
desc.mipmapLevelCount = mipmapCount;
desc.textureType = getMTLTextureType(texType, 1);
auto formatdesc = Metal::convertPixelFormat(device, format, sRGB);
auto formatdesc = Metal::convertPixelFormat(device, format);
desc.pixelFormat = formatdesc.format;
if (formatdesc.swizzled)
{
+41 -71
View File
@@ -250,7 +250,7 @@ void Graphics::updateBackbuffer(int width, int height, int /*pixelwidth*/, int p
settings.renderTarget = true;
settings.readable.set(false);
settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_UNORM_sRGB : PIXELFORMAT_RGBA8_UNORM;
settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_sRGB : PIXELFORMAT_RGBA8_UNORM;
internalBackbuffer.set(newTexture(settings), Acquire::NORETAIN);
settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8;
@@ -909,6 +909,30 @@ void Graphics::endPass(bool presenting)
void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth)
{
if (c.hasValue)
{
bool hasintegerformat = false;
const auto &rts = states.back().renderTargets;
for (const auto &rt : rts.colors)
{
if (rt.texture.get() && isPixelFormatInteger(rt.texture->getPixelFormat()))
hasintegerformat = true;
}
// This variant of clear() uses glClear() which can't clear integer formats,
// so we switch to the MRT variant if needed.
if (hasintegerformat)
{
std::vector<OptionalColorD> colors(rts.colors.size());
for (size_t i = 0; i < colors.size(); i++)
colors[i] = c;
clear(colors, stencil, depth);
return;
}
}
if (c.hasValue || stencil.hasValue || depth.hasValue)
flushBatchedDraws();
@@ -922,36 +946,23 @@ void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth
flags |= GL_COLOR_BUFFER_BIT;
}
uint32 stencilwrites = gl.getStencilWriteMask();
if (stencil.hasValue)
{
if (stencilwrites != LOVE_UINT32_MAX)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
glClearStencil(stencil.value);
flags |= GL_STENCIL_BUFFER_BIT;
}
bool hadDepthWrites = gl.hasDepthWrites();
if (depth.hasValue)
{
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
gl.clearDepth(depth.value);
flags |= GL_DEPTH_BUFFER_BIT;
}
if (flags != 0)
{
OpenGL::CleanClearState cs(flags);
glClear(flags);
if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX)
gl.setStencilWriteMask(stencilwrites);
if (depth.hasValue && !hadDepthWrites)
gl.setDepthWrites(hadDepthWrites);
}
if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
{
@@ -1041,36 +1052,23 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
GLbitfield flags = 0;
uint32 stencilwrites = gl.getStencilWriteMask();
if (stencil.hasValue)
{
if (stencilwrites != LOVE_UINT32_MAX)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
glClearStencil(stencil.value);
flags |= GL_STENCIL_BUFFER_BIT;
}
bool hadDepthWrites = gl.hasDepthWrites();
if (depth.hasValue)
{
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
gl.clearDepth(depth.value);
flags |= GL_DEPTH_BUFFER_BIT;
}
if (flags != 0)
{
OpenGL::CleanClearState cs(flags);
glClear(flags);
if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX)
gl.setStencilWriteMask(stencilwrites);
if (depth.hasValue && !hadDepthWrites)
gl.setDepthWrites(hadDepthWrites);
}
if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
{
@@ -1191,8 +1189,7 @@ GLuint Graphics::bindCachedFBO(const RenderTargets &targets)
auto attachRT = [&](const RenderTarget &rt)
{
bool renderbuffer = msaa > 1 || !rt.texture->isReadable();
bool srgb = false;
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer, srgb);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer);
if (fmt.framebufferAttachments[0] == GL_COLOR_ATTACHMENT0)
{
@@ -1568,7 +1565,11 @@ void Graphics::setColorMask(ColorChannelMask mask)
{
flushBatchedDraws();
glColorMask(mask.r, mask.g, mask.b, mask.a);
uint32 maskbits =
((mask.r ? 1 : 0) << 0) | ((mask.g ? 1 : 0) << 1) |
((mask.b ? 1 : 0) << 2) | ((mask.a ? 1 : 0) << 3);
gl.setColorWriteMask(maskbits);
states.back().colorMask = mask;
}
@@ -1732,31 +1733,6 @@ void Graphics::initCapabilities()
}
}
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
{
uint32 requiredflags = 0;
if (rendertarget)
requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET;
if (readable)
requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE;
switch (format)
{
case PIXELFORMAT_NORMAL:
if (isGammaCorrect())
return PIXELFORMAT_RGBA8_UNORM_sRGB;
else if ((OpenGL::getPixelFormatUsageFlags(PIXELFORMAT_RGBA8_UNORM) & requiredflags) != requiredflags)
// 32-bit render targets don't have guaranteed support on GLES2.
return PIXELFORMAT_RGBA4_UNORM;
else
return PIXELFORMAT_RGBA8_UNORM;
case PIXELFORMAT_HDR:
return PIXELFORMAT_RGBA16_FLOAT;
default:
return format;
}
}
uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
{
uint32 usage = OpenGL::getPixelFormatUsageFlags(format);
@@ -1777,9 +1753,8 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
{
GLuint texture = 0;
GLuint renderbuffer = 0;
bool sRGB = isPixelFormatSRGB(format);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable);
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
@@ -1801,7 +1776,7 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST;
gl.setSamplerState(TEXTURE_2D, s);
gl.rawTexStorage(TEXTURE_2D, 1, format, sRGB, 1, 1);
gl.rawTexStorage(TEXTURE_2D, 1, format, 1, 1);
}
else
{
@@ -1837,16 +1812,11 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
return usage;
}
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
{
if (sRGB)
format = getSRGBPixelFormat(format);
format = getSizedFormat(format);
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
format = getSizedFormat(format, rendertarget, readable);
return (usage & pixelFormatUsage[format][readable ? 1 : 0]) == usage;
}
+1 -2
View File
@@ -106,8 +106,7 @@ public:
void setWireframe(bool enable) override;
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
bool isPixelFormatSupported(PixelFormat format, uint32 usage) override;
Renderer getRenderer() const override;
bool usesGLSLES() const override;
RendererInfo getRendererInfo() const override;
+257 -120
View File
@@ -91,12 +91,49 @@ OpenGL::TempDebugGroup::~TempDebugGroup()
}
}
OpenGL::CleanClearState::CleanClearState(GLbitfield clearFlags)
: clearFlags(clearFlags)
, colorWriteMask(gl.getColorWriteMask())
, stencilWriteMask(gl.getStencilWriteMask())
, depthWrites(gl.hasDepthWrites())
, scissor(gl.isStateEnabled(ENABLE_SCISSOR_TEST))
{
if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX)
gl.setColorWriteMask(LOVE_UINT32_MAX);
if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && !depthWrites)
gl.setDepthWrites(true);
if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
if (clearFlags != 0 && scissor)
gl.setEnableState(ENABLE_SCISSOR_TEST, false);
}
OpenGL::CleanClearState::~CleanClearState()
{
if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX)
gl.setColorWriteMask(colorWriteMask);
if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && !depthWrites)
gl.setDepthWrites(depthWrites);
if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF)
gl.setStencilWriteMask(stencilWriteMask);
if (clearFlags != 0 && scissor)
gl.setEnableState(ENABLE_SCISSOR_TEST, scissor);
}
OpenGL::OpenGL()
: stats()
, bugs()
, contextInitialized(false)
, pixelShaderHighpSupported(false)
, baseVertexSupported(false)
, maxAnisotropy(1.0f)
, maxLODBias(0.0f)
, max2DTextureSize(0)
, max3DTextureSize(0)
, maxCubeTextureSize(0)
@@ -284,6 +321,7 @@ void OpenGL::setupContext()
setDepthWrites(state.depthWritesEnabled);
setStencilWriteMask(state.stencilWriteMask);
setColorWriteMask(state.colorWriteMask);
createDefaultTexture();
@@ -608,11 +646,9 @@ void OpenGL::createDefaultTexture()
const GLubyte *p = datatype == DATA_BASETYPE_FLOAT ? pix : intpix;
bool isSRGB = false;
rawTexStorage(type, 1, format, isSRGB, 1, 1);
TextureFormat fmt = convertPixelFormat(format, false, isSRGB);
rawTexStorage(type, 1, format, 1, 1);
TextureFormat fmt = convertPixelFormat(format, false);
int slices = type == TEXTURE_CUBE ? 6 : 1;
for (int slice = 0; slice < slices; slice++)
@@ -1125,6 +1161,17 @@ uint32 OpenGL::getStencilWriteMask() const
return state.stencilWriteMask;
}
void OpenGL::setColorWriteMask(uint32 mask)
{
glColorMask(mask & (1 << 0), mask & (1 << 1), mask & (1 << 2), mask & (1 << 3));
state.colorWriteMask = mask;
}
uint32 OpenGL::getColorWriteMask() const
{
return state.colorWriteMask;
}
void OpenGL::useProgram(GLuint program)
{
glUseProgram(program);
@@ -1384,10 +1431,10 @@ void OpenGL::setSamplerState(TextureType target, SamplerState &s)
}
}
bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth)
bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, int width, int height, int depth)
{
GLenum gltarget = getGLTextureType(target);
TextureFormat fmt = convertPixelFormat(pixelformat, false, isSRGB);
TextureFormat fmt = convertPixelFormat(pixelformat, false);
// This shouldn't be needed for glTexStorage, but some drivers don't follow
// the spec apparently.
@@ -1651,16 +1698,14 @@ OpenGL::Vendor OpenGL::getVendor() const
return vendor;
}
OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB)
OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool renderbuffer)
{
TextureFormat f;
f.framebufferAttachments[0] = GL_COLOR_ATTACHMENT0;
f.framebufferAttachments[1] = GL_NONE;
if (isSRGB)
pixelformat = getSRGBPixelFormat(pixelformat);
else if (pixelformat == PIXELFORMAT_ETC1_UNORM)
if (pixelformat == PIXELFORMAT_ETC1_UNORM)
{
// The ETC2 format can load ETC1 textures.
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility)
@@ -1693,7 +1738,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
f.externalformat = GL_RGBA;
f.type = GL_UNSIGNED_BYTE;
break;
case PIXELFORMAT_RGBA8_UNORM_sRGB:
case PIXELFORMAT_RGBA8_sRGB:
f.internalformat = GL_SRGB8_ALPHA8;
f.type = GL_UNSIGNED_BYTE;
if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0)
@@ -1702,7 +1747,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
f.externalformat = GL_RGBA;
break;
case PIXELFORMAT_BGRA8_UNORM:
case PIXELFORMAT_BGRA8_UNORM_sRGB:
case PIXELFORMAT_BGRA8_sRGB:
// Not supported right now.
break;
case PIXELFORMAT_R16_UNORM:
@@ -1977,123 +2022,190 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
break;
case PIXELFORMAT_DXT1_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case PIXELFORMAT_DXT1_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
break;
case PIXELFORMAT_DXT3_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case PIXELFORMAT_DXT3_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
break;
case PIXELFORMAT_DXT5_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
case PIXELFORMAT_DXT5_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
break;
case PIXELFORMAT_BC4_UNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_RED_RGTC1;
break;
case PIXELFORMAT_BC4_SNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_SIGNED_RED_RGTC1;
break;
case PIXELFORMAT_BC5_UNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_RG_RGTC2;
break;
case PIXELFORMAT_BC5_SNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_SIGNED_RG_RGTC2;
break;
case PIXELFORMAT_BC6H_UFLOAT:
isSRGB = false;
f.internalformat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
break;
case PIXELFORMAT_BC6H_FLOAT:
isSRGB = false;
f.internalformat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
break;
case PIXELFORMAT_BC7_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : GL_COMPRESSED_RGBA_BPTC_UNORM;
f.internalformat = GL_COMPRESSED_RGBA_BPTC_UNORM;
break;
case PIXELFORMAT_BC7_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;
case PIXELFORMAT_PVR1_RGB2_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
f.internalformat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
break;
case PIXELFORMAT_PVR1_RGB2_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
break;
case PIXELFORMAT_PVR1_RGB4_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
f.internalformat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
break;
case PIXELFORMAT_PVR1_RGB4_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
break;
case PIXELFORMAT_PVR1_RGBA2_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
f.internalformat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
break;
case PIXELFORMAT_PVR1_RGBA2_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
break;
case PIXELFORMAT_PVR1_RGBA4_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
f.internalformat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
break;
case PIXELFORMAT_PVR1_RGBA4_sRGB:
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
break;
case PIXELFORMAT_ETC1_UNORM:
isSRGB = false;
f.internalformat = GL_ETC1_RGB8_OES;
break;
case PIXELFORMAT_ETC2_RGB_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ETC2 : GL_COMPRESSED_RGB8_ETC2;
f.internalformat = GL_COMPRESSED_RGB8_ETC2;
break;
case PIXELFORMAT_ETC2_RGB_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ETC2;
break;
case PIXELFORMAT_ETC2_RGBA_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : GL_COMPRESSED_RGBA8_ETC2_EAC;
f.internalformat = GL_COMPRESSED_RGBA8_ETC2_EAC;
break;
case PIXELFORMAT_ETC2_RGBA_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
break;
case PIXELFORMAT_ETC2_RGBA1_UNORM:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
f.internalformat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case PIXELFORMAT_ETC2_RGBA1_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
break;
case PIXELFORMAT_EAC_R_UNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_R11_EAC;
break;
case PIXELFORMAT_EAC_R_SNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_SIGNED_R11_EAC;
break;
case PIXELFORMAT_EAC_RG_UNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_RG11_EAC;
break;
case PIXELFORMAT_EAC_RG_SNORM:
isSRGB = false;
f.internalformat = GL_COMPRESSED_SIGNED_RG11_EAC;
break;
case PIXELFORMAT_ASTC_4x4:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
case PIXELFORMAT_ASTC_4x4_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
break;
case PIXELFORMAT_ASTC_5x4:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
case PIXELFORMAT_ASTC_4x4_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
break;
case PIXELFORMAT_ASTC_5x5:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
case PIXELFORMAT_ASTC_5x4_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
break;
case PIXELFORMAT_ASTC_6x5:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
case PIXELFORMAT_ASTC_5x4_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
break;
case PIXELFORMAT_ASTC_6x6:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
case PIXELFORMAT_ASTC_5x5_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
break;
case PIXELFORMAT_ASTC_8x5:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
case PIXELFORMAT_ASTC_5x5_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
break;
case PIXELFORMAT_ASTC_8x6:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
case PIXELFORMAT_ASTC_6x5_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
break;
case PIXELFORMAT_ASTC_8x8:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
case PIXELFORMAT_ASTC_6x5_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
break;
case PIXELFORMAT_ASTC_10x5:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
case PIXELFORMAT_ASTC_6x6_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
break;
case PIXELFORMAT_ASTC_10x6:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
case PIXELFORMAT_ASTC_6x6_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
break;
case PIXELFORMAT_ASTC_10x8:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
case PIXELFORMAT_ASTC_8x5_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
break;
case PIXELFORMAT_ASTC_10x10:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
case PIXELFORMAT_ASTC_8x5_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
break;
case PIXELFORMAT_ASTC_12x10:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
case PIXELFORMAT_ASTC_8x6_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
break;
case PIXELFORMAT_ASTC_12x12:
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
case PIXELFORMAT_ASTC_8x6_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
break;
case PIXELFORMAT_ASTC_8x8_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
break;
case PIXELFORMAT_ASTC_8x8_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
break;
case PIXELFORMAT_ASTC_10x5_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
break;
case PIXELFORMAT_ASTC_10x5_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
break;
case PIXELFORMAT_ASTC_10x6_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
break;
case PIXELFORMAT_ASTC_10x6_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
break;
case PIXELFORMAT_ASTC_10x8_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
break;
case PIXELFORMAT_ASTC_10x8_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
break;
case PIXELFORMAT_ASTC_10x10_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
break;
case PIXELFORMAT_ASTC_10x10_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
break;
case PIXELFORMAT_ASTC_12x10_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
break;
case PIXELFORMAT_ASTC_12x10_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
break;
case PIXELFORMAT_ASTC_12x12_UNORM:
f.internalformat = GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
break;
case PIXELFORMAT_ASTC_12x12_sRGB:
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;
break;
default:
@@ -2115,9 +2227,6 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
{
f.internalformat = f.externalformat;
}
if (!isPixelFormatSRGB(pixelformat))
isSRGB = false;
}
return f;
@@ -2149,7 +2258,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_1)
flags |= computewrite;
break;
case PIXELFORMAT_RGBA8_UNORM_sRGB:
case PIXELFORMAT_RGBA8_sRGB:
if (gl.bugs.brokenSRGB)
break;
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB)
@@ -2161,7 +2270,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
flags |= computewrite;
break;
case PIXELFORMAT_BGRA8_UNORM:
case PIXELFORMAT_BGRA8_UNORM_sRGB:
case PIXELFORMAT_BGRA8_sRGB:
// Not supported right now.
break;
case PIXELFORMAT_R16_UNORM:
@@ -2229,47 +2338,47 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
flags |= computewrite;
break;
case PIXELFORMAT_R8_INT:
case PIXELFORMAT_R8_UINT:
case PIXELFORMAT_RG8_INT:
case PIXELFORMAT_RG8_UINT:
case PIXELFORMAT_RGBA8_INT:
case PIXELFORMAT_RGBA8_UINT:
case PIXELFORMAT_R16_INT:
case PIXELFORMAT_R16_UINT:
case PIXELFORMAT_RG16_INT:
case PIXELFORMAT_RG16_UINT:
case PIXELFORMAT_RGBA16_INT:
case PIXELFORMAT_RGBA16_UINT:
case PIXELFORMAT_R32_INT:
case PIXELFORMAT_R32_UINT:
case PIXELFORMAT_RG32_INT:
case PIXELFORMAT_RG32_UINT:
case PIXELFORMAT_RGBA32_INT:
case PIXELFORMAT_RGBA32_UINT:
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0)
flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET;
if (GLAD_VERSION_4_3)
flags |= computewrite;
if (GLAD_ES_VERSION_3_1)
case PIXELFORMAT_R8_INT:
case PIXELFORMAT_R8_UINT:
case PIXELFORMAT_RG8_INT:
case PIXELFORMAT_RG8_UINT:
case PIXELFORMAT_RGBA8_INT:
case PIXELFORMAT_RGBA8_UINT:
case PIXELFORMAT_R16_INT:
case PIXELFORMAT_R16_UINT:
case PIXELFORMAT_RG16_INT:
case PIXELFORMAT_RG16_UINT:
case PIXELFORMAT_RGBA16_INT:
case PIXELFORMAT_RGBA16_UINT:
case PIXELFORMAT_R32_INT:
case PIXELFORMAT_R32_UINT:
case PIXELFORMAT_RG32_INT:
case PIXELFORMAT_RG32_UINT:
case PIXELFORMAT_RGBA32_INT:
case PIXELFORMAT_RGBA32_UINT:
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0)
flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET;
if (GLAD_VERSION_4_3)
flags |= computewrite;
if (GLAD_ES_VERSION_3_1)
{
switch (pixelformat)
{
switch (pixelformat)
{
case PIXELFORMAT_RGBA8_INT:
case PIXELFORMAT_RGBA8_UINT:
case PIXELFORMAT_RGBA16_INT:
case PIXELFORMAT_RGBA16_UINT:
case PIXELFORMAT_R32_INT:
case PIXELFORMAT_R32_UINT:
case PIXELFORMAT_RGBA32_INT:
case PIXELFORMAT_RGBA32_UINT:
flags |= computewrite;
break;
default:
break;
}
case PIXELFORMAT_RGBA8_INT:
case PIXELFORMAT_RGBA8_UINT:
case PIXELFORMAT_RGBA16_INT:
case PIXELFORMAT_RGBA16_UINT:
case PIXELFORMAT_R32_INT:
case PIXELFORMAT_R32_UINT:
case PIXELFORMAT_RGBA32_INT:
case PIXELFORMAT_RGBA32_UINT:
flags |= computewrite;
break;
default:
break;
}
break;
}
break;
case PIXELFORMAT_LA8_UNORM:
flags |= commonsample;
@@ -2331,14 +2440,17 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
break;
case PIXELFORMAT_DXT1_UNORM:
case PIXELFORMAT_DXT1_sRGB:
if (GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1)
flags |= commonsample;
break;
case PIXELFORMAT_DXT3_UNORM:
case PIXELFORMAT_DXT3_sRGB:
if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3)
flags |= commonsample;
break;
case PIXELFORMAT_DXT5_UNORM:
case PIXELFORMAT_DXT5_sRGB:
if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5)
flags |= commonsample;
break;
@@ -2352,6 +2464,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
case PIXELFORMAT_BC6H_UFLOAT:
case PIXELFORMAT_BC6H_FLOAT:
case PIXELFORMAT_BC7_UNORM:
case PIXELFORMAT_BC7_sRGB:
if (GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc)
flags |= commonsample;
break;
@@ -2362,14 +2475,24 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
if (GLAD_IMG_texture_compression_pvrtc)
flags |= commonsample;
break;
case PIXELFORMAT_PVR1_RGB2_sRGB:
case PIXELFORMAT_PVR1_RGB4_sRGB:
case PIXELFORMAT_PVR1_RGBA2_sRGB:
case PIXELFORMAT_PVR1_RGBA4_sRGB:
if (GLAD_EXT_pvrtc_sRGB)
flags |= commonsample;
break;
case PIXELFORMAT_ETC1_UNORM:
// ETC2 support guarantees ETC1 support as well.
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture)
flags |= commonsample;
break;
case PIXELFORMAT_ETC2_RGB_UNORM:
case PIXELFORMAT_ETC2_RGB_sRGB:
case PIXELFORMAT_ETC2_RGBA_UNORM:
case PIXELFORMAT_ETC2_RGBA_sRGB:
case PIXELFORMAT_ETC2_RGBA1_UNORM:
case PIXELFORMAT_ETC2_RGBA1_sRGB:
case PIXELFORMAT_EAC_R_UNORM:
case PIXELFORMAT_EAC_R_SNORM:
case PIXELFORMAT_EAC_RG_UNORM:
@@ -2377,20 +2500,34 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility)
flags |= commonsample;
break;
case PIXELFORMAT_ASTC_4x4:
case PIXELFORMAT_ASTC_5x4:
case PIXELFORMAT_ASTC_5x5:
case PIXELFORMAT_ASTC_6x5:
case PIXELFORMAT_ASTC_6x6:
case PIXELFORMAT_ASTC_8x5:
case PIXELFORMAT_ASTC_8x6:
case PIXELFORMAT_ASTC_8x8:
case PIXELFORMAT_ASTC_10x5:
case PIXELFORMAT_ASTC_10x6:
case PIXELFORMAT_ASTC_10x8:
case PIXELFORMAT_ASTC_10x10:
case PIXELFORMAT_ASTC_12x10:
case PIXELFORMAT_ASTC_12x12:
case PIXELFORMAT_ASTC_4x4_UNORM:
case PIXELFORMAT_ASTC_5x4_UNORM:
case PIXELFORMAT_ASTC_5x5_UNORM:
case PIXELFORMAT_ASTC_6x5_UNORM:
case PIXELFORMAT_ASTC_6x6_UNORM:
case PIXELFORMAT_ASTC_8x5_UNORM:
case PIXELFORMAT_ASTC_8x6_UNORM:
case PIXELFORMAT_ASTC_8x8_UNORM:
case PIXELFORMAT_ASTC_10x5_UNORM:
case PIXELFORMAT_ASTC_10x6_UNORM:
case PIXELFORMAT_ASTC_10x8_UNORM:
case PIXELFORMAT_ASTC_10x10_UNORM:
case PIXELFORMAT_ASTC_12x10_UNORM:
case PIXELFORMAT_ASTC_12x12_UNORM:
case PIXELFORMAT_ASTC_4x4_sRGB:
case PIXELFORMAT_ASTC_5x4_sRGB:
case PIXELFORMAT_ASTC_5x5_sRGB:
case PIXELFORMAT_ASTC_6x5_sRGB:
case PIXELFORMAT_ASTC_6x6_sRGB:
case PIXELFORMAT_ASTC_8x5_sRGB:
case PIXELFORMAT_ASTC_8x6_sRGB:
case PIXELFORMAT_ASTC_8x8_sRGB:
case PIXELFORMAT_ASTC_10x5_sRGB:
case PIXELFORMAT_ASTC_10x6_sRGB:
case PIXELFORMAT_ASTC_10x8_sRGB:
case PIXELFORMAT_ASTC_10x10_sRGB:
case PIXELFORMAT_ASTC_12x10_sRGB:
case PIXELFORMAT_ASTC_12x12_sRGB:
if (GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr)
flags |= commonsample;
break;
+21 -2
View File
@@ -124,6 +124,21 @@ public:
~TempDebugGroup();
};
// glClear() is affected by various OpenGL state...
class CleanClearState
{
public:
CleanClearState(GLbitfield clearFlags);
~CleanClearState();
private:
GLenum clearFlags;
uint32 colorWriteMask;
uint32 stencilWriteMask;
bool depthWrites;
bool scissor;
};
struct Stats
{
int shaderSwitches;
@@ -301,6 +316,9 @@ public:
void setStencilWriteMask(uint32 mask);
uint32 getStencilWriteMask() const;
void setColorWriteMask(uint32 mask);
uint32 getColorWriteMask() const;
/**
* Calls glUseProgram.
**/
@@ -363,7 +381,7 @@ public:
* to glTexImage2D/3D for all levels and slices of a texture otherwise.
* NOTE: this does not handle compressed texture formats.
**/
bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth = 1);
bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, int width, int height, int depth = 1);
bool isTextureTypeSupported(TextureType type) const;
bool isBufferUsageSupported(BufferUsage usage) const;
@@ -457,7 +475,7 @@ public:
static GLint getGLWrapMode(SamplerState::WrapMode wmode);
static GLint getGLCompareMode(CompareMode mode);
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer);
static bool isTexStorageSupported();
static uint32 getPixelFormatUsageFlags(PixelFormat pixelformat);
@@ -528,6 +546,7 @@ private:
bool depthWritesEnabled = true;
uint32 stencilWriteMask = LOVE_UINT32_MAX;
uint32 colorWriteMask = LOVE_UINT32_MAX;
GLuint boundFramebuffers[2];
+1 -2
View File
@@ -175,8 +175,7 @@ void Shader::mapActiveUniforms()
else if ((u.access & ACCESS_READ) != 0)
binding.access = GL_READ_ONLY;
bool sRGB = false;
auto fmt = OpenGL::convertPixelFormat(u.storageTextureFormat, false, sRGB);
auto fmt = OpenGL::convertPixelFormat(u.storageTextureFormat, false);
binding.internalFormat = fmt.internalformat;
for (int i = 0; i < u.count; i++)
+56 -39
View File
@@ -56,8 +56,7 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
glReadBuffer(GL_NONE);
}
bool unusedSRGB = false;
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false, unusedSRGB);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false);
int faces = texType == TEXTURE_CUBE ? 6 : 1;
@@ -78,33 +77,38 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
gl.framebufferTexture(attachment, texType, texture, mip, layer, face);
}
if (clear)
if (clear && isPixelFormatInteger(format))
{
if (isPixelFormatDepthStencil(format))
PixelFormatType datatype = getPixelFormatInfo(format).dataType;
if (datatype == PIXELFORMATTYPE_SINT)
{
bool hadDepthWrites = gl.hasDepthWrites();
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
const GLint carray[] = { 0, 0, 0, 0 };
glClearBufferiv(GL_COLOR, 0, carray);
}
else
{
const GLuint carray[] = { 0, 0, 0, 0 };
glClearBufferuiv(GL_COLOR, 0, carray);
}
}
else if (clear)
{
bool ds = isPixelFormatDepthStencil(format);
uint32 stencilwrite = gl.getStencilWriteMask();
if (stencilwrite != LOVE_UINT32_MAX)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
OpenGL::CleanClearState cleanClearState(clearflags);
if (ds)
{
gl.clearDepth(1.0);
glClearStencil(0);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if (!hadDepthWrites)
gl.setDepthWrites(hadDepthWrites);
if (stencilwrite != LOVE_UINT32_MAX)
gl.setStencilWriteMask(stencilwrite);
}
else
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
glClear(clearflags);
}
}
}
@@ -120,8 +124,7 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat pixelformat, GLuint &buffer)
{
bool unusedSRGB = false;
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true, unusedSRGB);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true);
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
@@ -167,24 +170,39 @@ static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat p
if (status == GL_FRAMEBUFFER_COMPLETE)
{
if (isPixelFormatDepthStencil(pixelformat))
if (isPixelFormatInteger(pixelformat))
{
bool hadDepthWrites = gl.hasDepthWrites();
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
gl.clearDepth(1.0);
glClearStencil(0);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if (!hadDepthWrites)
gl.setDepthWrites(hadDepthWrites);
PixelFormatType datatype = getPixelFormatInfo(pixelformat).dataType;
if (datatype == PIXELFORMATTYPE_SINT)
{
const GLint carray[] = { 0, 0, 0, 0 };
glClearBufferiv(GL_COLOR, 0, carray);
}
else
{
const GLuint carray[] = { 0, 0, 0, 0 };
glClearBufferuiv(GL_COLOR, 0, carray);
}
}
else
{
// Initialize the buffer to transparent black.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
bool ds = isPixelFormatDepthStencil(pixelformat);
GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
OpenGL::CleanClearState cleanClearState(clearflags);
if (ds)
{
gl.clearDepth(1.0);
glClearStencil(0);
}
else
{
// Initialize the buffer to transparent black.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
glClear(clearflags);
}
}
else
@@ -262,7 +280,7 @@ void Texture::createTexture()
// remember some driver issues on some old Android systems, maybe...
// For now, the base class enforces data on init for compressed textures.
if (!isCompressed())
gl.rawTexStorage(texType, mipcount, format, sRGB, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers);
gl.rawTexStorage(texType, mipcount, format, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers);
// rawTexStorage handles this for uncompressed textures.
if (isCompressed() && (GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0))
@@ -272,7 +290,7 @@ void Texture::createTexture()
int h = pixelHeight;
int d = depth;
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, sRGB);
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false);
for (int mip = 0; mip < mipcount; mip++)
{
@@ -440,7 +458,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s
gl.bindTextureToUnit(this, 0, false);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false, sRGB);
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false);
GLenum gltarget = OpenGL::getGLTextureType(texType);
if (texType == TEXTURE_CUBE)
@@ -488,8 +506,7 @@ void Texture::readbackInternal(int slice, int mipmap, const Rect &rect, int dest
gl.bindTextureToUnit(this, 0, false);
bool isSRGB = false;
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, isSRGB);
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false);
if (gl.isCopyTextureToBufferSupported())
{
+151 -155
View File
@@ -65,29 +65,100 @@ const char *Graphics::getName() const
return "love.graphics.vulkan";
}
const VkDevice Graphics::getDevice() const
VkDevice Graphics::getDevice() const
{
return device;
}
const VmaAllocator Graphics::getVmaAllocator() const
VmaAllocator Graphics::getVmaAllocator() const
{
return vmaAllocator;
}
static void checkOptionalInstanceExtensions(OptionalInstanceExtensions& ext)
{
uint32_t count;
vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
std::vector<VkExtensionProperties> extensions(count);
vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
for (const auto& extension : extensions)
{
if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
ext.physicalDeviceProperties2 = true;
}
}
Graphics::Graphics()
{
if (SDL_Vulkan_LoadLibrary(nullptr))
throw love::Exception("could not find vulkan");
volkInitializeCustom((PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr());
if (isDebugEnabled() && !checkValidationSupport())
throw love::Exception("validation layers requested, but not available");
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "LOVE";
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else?
appInfo.pEngineName = "LOVE Game Framework";
appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
appInfo.apiVersion = VK_API_VERSION_1_3;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.pNext = nullptr;
// GetInstanceExtensions works with a null window parameter as long as
// SDL_Vulkan_LoadLibrary has been called (which we do earlier).
unsigned int count;
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, nullptr) != SDL_TRUE)
throw love::Exception("couldn't retrieve sdl vulkan extensions");
std::vector<const char*> extensions = {};
checkOptionalInstanceExtensions(optionalInstanceExtensions);
if (optionalInstanceExtensions.physicalDeviceProperties2)
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
size_t additional_extension_count = extensions.size();
extensions.resize(additional_extension_count + count);
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, extensions.data() + additional_extension_count) != SDL_TRUE)
throw love::Exception("couldn't retrieve sdl vulkan extensions");
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
if (isDebugEnabled())
{
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
throw love::Exception("couldn't create vulkan instance");
volkLoadInstance(instance);
}
Graphics::~Graphics()
{
defaultConstantTexCoord.set(nullptr);
defaultConstantColor.set(nullptr);
defaultTexture.set(nullptr);
Volatile::unloadAll();
cleanup();
vkDestroyInstance(instance, nullptr);
SDL_Vulkan_UnloadLibrary();
}
@@ -302,14 +373,14 @@ void Graphics::discard(const std::vector<bool> &colorbuffers, bool depthstencil)
startRenderPass();
}
void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallbackData)
{
flushBatchedDraws();
if (renderPassState.active)
endRenderPass();
if (present)
if (submitMode == SUBMIT_PRESENT)
{
if (pendingScreenshotCallbacks.empty())
Vulkan::cmdTransitionImageLayout(
@@ -435,7 +506,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
VkFence fence = VK_NULL_HANDLE;
if (present)
if (submitMode == SUBMIT_PRESENT)
{
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
@@ -447,7 +518,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS)
throw love::Exception("failed to submit draw command buffer");
if (!present)
if (submitMode == SUBMIT_NOPRESENT || submitMode == SUBMIT_RESTART)
{
vkQueueWaitIdle(graphicsQueue);
@@ -458,7 +529,8 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
callbacks.clear();
}
startRecordingGraphicsCommands();
if (submitMode == SUBMIT_RESTART)
startRecordingGraphicsCommands();
}
}
@@ -475,7 +547,7 @@ void Graphics::present(void *screenshotCallbackdata)
deprecations.draw(this);
submitGpuCommands(true, screenshotCallbackdata);
submitGpuCommands(SUBMIT_PRESENT, screenshotCallbackdata);
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@@ -540,64 +612,80 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
readbackCallbacks.clear();
readbackCallbacks.resize(MAX_FRAMES_IN_FLIGHT);
createVulkanInstance();
bool createBaseObjects = physicalDevice == VK_NULL_HANDLE;
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createPipelineCache();
initVMA();
initCapabilities();
if (createBaseObjects)
{
pickPhysicalDevice();
createLogicalDevice();
createPipelineCache();
initVMA();
initCapabilities();
}
msaaSamples = getMsaaCount(requestedMsaa);
createSwapChain();
createImageViews();
createScreenshotCallbackBuffers();
createSyncObjects();
createColorResources();
createDepthResources();
transitionColorDepthLayouts = true;
createCommandPool();
createCommandBuffers();
if (createBaseObjects)
{
createCommandPool();
createCommandBuffers();
createSyncObjects();
}
beginFrame();
if (batchedDrawState.vb[0] == nullptr)
if (createBaseObjects)
{
// Initial sizes that should be good enough for most cases. It will
// resize to fit if needed, later.
batchedDrawState.vb[0] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
batchedDrawState.vb[1] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
}
if (batchedDrawState.vb[0] == nullptr)
{
// Initial sizes that should be good enough for most cases. It will
// resize to fit if needed, later.
batchedDrawState.vb[0] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
batchedDrawState.vb[1] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
}
// sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0)
if (defaultConstantTexCoord == nullptr)
{
float zeroTexCoord[2] = { 0.0f, 0.0f };
Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2);
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1);
}
// sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0)
if (defaultConstantTexCoord == nullptr)
{
float zeroTexCoord[2] = { 0.0f, 0.0f };
Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2);
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1);
}
// sometimes the VertexColor is not set, so we manually adjust it to white color
if (defaultConstantColor == nullptr)
{
uint8 whiteColor[] = { 255, 255, 255, 255 };
Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4);
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1);
}
// sometimes the VertexColor is not set, so we manually adjust it to white color
if (defaultConstantColor == nullptr)
{
uint8 whiteColor[] = { 255, 255, 255, 255 };
Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4);
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1);
}
createDefaultTexture();
createDefaultShaders();
Shader::current = Shader::standardShaders[Shader::StandardShader::STANDARD_DEFAULT];
createQuadIndexBuffer();
createFanIndexBuffer();
createDefaultTexture();
createDefaultShaders();
Shader::current = Shader::standardShaders[Shader::StandardShader::STANDARD_DEFAULT];
createQuadIndexBuffer();
createFanIndexBuffer();
frameCounter = 0;
currentFrame = 0;
}
restoreState(states.back());
Vulkan::resetShaderSwitches();
frameCounter = 0;
currentFrame = 0;
created = true;
drawCalls = 0;
drawCallsBatched = 0;
@@ -659,14 +747,12 @@ void Graphics::getAPIStats(int &shaderswitches) const
void Graphics::unSetMode()
{
renderPassUsages.clear();
framebufferUsages.clear();
pipelineUsages.clear();
submitGpuCommands(SUBMIT_NOPRESENT);
created = false;
vkDeviceWaitIdle(device);
Volatile::unloadAll();
cleanup();
cleanupSwapChain();
vkDestroySurfaceKHR(instance, surface, nullptr);
}
void Graphics::setActive(bool enable)
@@ -971,30 +1057,11 @@ void Graphics::setWireframe(bool enable)
states.back().wireframe = enable;
}
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
{
switch (format)
{
case PIXELFORMAT_NORMAL:
if (isGammaCorrect())
return PIXELFORMAT_RGBA8_UNORM_sRGB;
else
return PIXELFORMAT_RGBA8_UNORM;
case PIXELFORMAT_HDR:
return PIXELFORMAT_RGBA16_FLOAT;
default:
return format;
}
}
format = getSizedFormat(format);
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
{
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
format = getSizedFormat(format, rendertarget, readable);
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
auto vulkanFormat = Vulkan::getTextureFormat(format);
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(physicalDevice, vulkanFormat.internalFormat, &formatProperties);
@@ -1332,75 +1399,6 @@ const OptionalDeviceExtensions &Graphics::getEnabledOptionalDeviceExtensions() c
return optionalDeviceExtensions;
}
static void checkOptionalInstanceExtensions(OptionalInstanceExtensions &ext)
{
uint32_t count;
vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
std::vector<VkExtensionProperties> extensions(count);
vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
for (const auto &extension : extensions)
{
if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
ext.physicalDeviceProperties2 = true;
}
}
void Graphics::createVulkanInstance()
{
if (isDebugEnabled() && !checkValidationSupport())
throw love::Exception("validation layers requested, but not available");
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "LOVE";
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else?
appInfo.pEngineName = "LOVE Game Framework";
appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
appInfo.apiVersion = VK_API_VERSION_1_3;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.pNext = nullptr;
// GetInstanceExtensions works with a null window parameter as long as
// SDL_Vulkan_LoadLibrary has been called (which we do earlier).
unsigned int count;
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, nullptr) != SDL_TRUE)
throw love::Exception("couldn't retrieve sdl vulkan extensions");
std::vector<const char*> extensions = {};
checkOptionalInstanceExtensions(optionalInstanceExtensions);
if (optionalInstanceExtensions.physicalDeviceProperties2)
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
size_t additional_extension_count = extensions.size();
extensions.resize(additional_extension_count + count);
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, extensions.data() + additional_extension_count) != SDL_TRUE)
throw love::Exception("couldn't retrieve sdl vulkan extensions");
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
if (isDebugEnabled())
{
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
throw love::Exception("couldn't create vulkan instance");
volkLoadInstance(instance);
}
bool Graphics::checkValidationSupport()
{
uint32_t layerCount;
@@ -1458,7 +1456,6 @@ void Graphics::pickPhysicalDevice()
minUniformBufferOffsetAlignment = properties.limits.minUniformBufferOffsetAlignment;
deviceApiVersion = properties.apiVersion;
msaaSamples = getMsaaCount(requestedMsaa);
depthStencilFormat = findDepthFormat();
}
@@ -1573,7 +1570,7 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option
optionalDeviceExtensions.memoryRequirements2 = true;
if (strcmp(extension.extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
optionalDeviceExtensions.dedicatedAllocation = true;
if (strcmp(extension.extensionName, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0)
if (strcmp(extension.extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
optionalDeviceExtensions.memoryBudget = true;
if (strcmp(extension.extensionName, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) == 0)
optionalDeviceExtensions.shaderFloatControls = true;
@@ -2447,12 +2444,12 @@ void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, b
RenderPassConfiguration renderPassConfiguration{};
for (const auto &color : rts.colors)
renderPassConfiguration.colorAttachments.push_back({
Vulkan::getTextureFormat(color.texture->getPixelFormat(), isPixelFormatSRGB(color.texture->getPixelFormat())).internalFormat,
Vulkan::getTextureFormat(color.texture->getPixelFormat()).internalFormat,
VK_ATTACHMENT_LOAD_OP_LOAD,
dynamic_cast<Texture*>(color.texture)->getMsaaSamples() });
if (rts.depthStencil.texture != nullptr)
renderPassConfiguration.staticData.depthStencilAttachment = {
Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat(), false).internalFormat,
Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat()).internalFormat,
VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_LOAD_OP_LOAD,
dynamic_cast<Texture*>(rts.depthStencil.texture)->getMsaaSamples() };
@@ -3040,8 +3037,6 @@ void Graphics::createDefaultTexture()
void Graphics::cleanup()
{
cleanupSwapChain();
for (auto &cleanUpFns : cleanUpFunctions)
for (auto &cleanUpFn : cleanUpFns)
cleanUpFn();
@@ -3076,8 +3071,6 @@ void Graphics::cleanup()
vkDestroyCommandPool(device, commandPool, nullptr);
vkDestroyPipelineCache(device, pipelineCache, nullptr);
vkDestroyDevice(device, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyInstance(instance, nullptr);
}
void Graphics::cleanupSwapChain()
@@ -3087,8 +3080,11 @@ void Graphics::cleanupSwapChain()
vmaDestroyBuffer(vmaAllocator, readbackBuffer.buffer, readbackBuffer.allocation);
vmaDestroyImage(vmaAllocator, readbackBuffer.image, readbackBuffer.imageAllocation);
}
vkDestroyImageView(device, colorImageView, nullptr);
vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
if (colorImage)
{
vkDestroyImageView(device, colorImageView, nullptr);
vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
}
vkDestroyImageView(device, depthImageView, nullptr);
vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation);
for (const auto &swapChainImageView : swapChainImageViews)
+12 -6
View File
@@ -256,6 +256,14 @@ struct ScreenshotReadbackBuffer
VmaAllocation imageAllocation;
};
enum SubmitMode
{
SUBMIT_PRESENT,
SUBMIT_NOPRESENT,
SUBMIT_RESTART,
SUBMIT_MAXENUM,
};
class Graphics final : public love::graphics::Graphics
{
public:
@@ -289,8 +297,7 @@ public:
void setBlendState(const BlendState &blend) override;
void setPointSize(float size) override;
void setWireframe(bool enable) override;
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) override;
bool isPixelFormatSupported(PixelFormat format, uint32 usage) override;
Renderer getRenderer() const override;
bool usesGLSLES() const override;
RendererInfo getRendererInfo() const override;
@@ -300,12 +307,12 @@ public:
// internal functions.
const VkDevice getDevice() const;
const VmaAllocator getVmaAllocator() const;
VkDevice getDevice() const;
VmaAllocator getVmaAllocator() const;
VkCommandBuffer getCommandBufferForDataTransfer();
void queueCleanUp(std::function<void()> cleanUp);
void addReadbackCallback(std::function<void()> callback);
void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
void submitGpuCommands(SubmitMode, void *screenshotCallbackData = nullptr);
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
VkSampler getCachedSampler(const SamplerState &sampler);
void setComputeShader(Shader *computeShader);
@@ -326,7 +333,6 @@ protected:
void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
private:
void createVulkanInstance();
bool checkValidationSupport();
void pickPhysicalDevice();
int rateDeviceSuitability(VkPhysicalDevice device);
@@ -44,7 +44,7 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod
if (method == READBACK_IMMEDIATE)
{
vgfx->submitGpuCommands(false);
vgfx->submitGpuCommands(SUBMIT_RESTART);
if (stagingBuffer.get()) {
status = readbackBuffer(stagingBuffer, 0, size);
gfx->releaseTemporaryBuffer(stagingBuffer);
@@ -79,7 +79,7 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod
});
if (method == READBACK_IMMEDIATE)
vgfx->submitGpuCommands(false);
vgfx->submitGpuCommands(SUBMIT_RESTART);
}
GraphicsReadback::~GraphicsReadback()
@@ -89,7 +89,7 @@ GraphicsReadback::~GraphicsReadback()
void GraphicsReadback::wait()
{
if (status == STATUS_WAITING)
vgfx->submitGpuCommands(false);
vgfx->submitGpuCommands(SUBMIT_RESTART);
}
void GraphicsReadback::update()
+5 -1
View File
@@ -551,7 +551,8 @@ int Shader::getVertexAttributeIndex(const std::string &name)
const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const
{
return &uniformInfos.at(name);
const auto it = uniformInfos.find(name);
return it != uniformInfos.end() ? &(it->second) : nullptr;
}
const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const
@@ -656,6 +657,9 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::
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;
if (!values.empty())
memcpy(
+8 -4
View File
@@ -41,6 +41,10 @@ Texture::Texture(love::graphics::Graphics *gfx, const Settings &settings, const
slices = *data;
loadVolatile();
// ImageData is referenced by the first loadVolatile call, but we don't
// hang on to it after that so we can save memory.
slices.clear();
}
bool Texture::loadVolatile()
@@ -55,7 +59,7 @@ bool Texture::loadVolatile()
if (isPixelFormatColor(format))
imageAspect |= VK_IMAGE_ASPECT_COLOR_BIT;
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
auto vulkanFormat = Vulkan::getTextureFormat(format);
VkImageUsageFlags usageFlags =
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
@@ -150,7 +154,7 @@ bool Texture::loadVolatile()
createTextureImageView();
textureSampler = vgfx->getCachedSampler(samplerState);
if (!isPixelFormatDepthStencil(format) && mipmapCount > 1 && getMipmapsMode() != MIPMAPS_NONE)
if (!isPixelFormatDepthStencil(format) && slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE)
generateMipmaps();
if (renderTarget)
@@ -273,7 +277,7 @@ VkImageLayout Texture::getImageLayout() const
void Texture::createTextureImageView()
{
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
auto vulkanFormat = Vulkan::getTextureFormat(format);
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -345,7 +349,7 @@ void Texture::clear()
VkClearColorValue Texture::getClearValue()
{
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
auto vulkanFormat = Vulkan::getTextureFormat(format);
VkClearColorValue clearColor{};
switch (vulkanFormat.internalFormatRepresentation)
+118 -49
View File
@@ -130,16 +130,10 @@ VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
}
}
TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
TextureFormat Vulkan::getTextureFormat(PixelFormat format)
{
TextureFormat textureFormat{};
if (sRGB)
format = getSRGBPixelFormat(format);
if (!isPixelFormatCompressed(format) && !isPixelFormatSRGB(format))
sRGB = false;
switch (format)
{
case PIXELFORMAT_UNKNOWN:
@@ -231,13 +225,13 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
case PIXELFORMAT_RGBA8_UNORM:
textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_UNORM;
break;
case PIXELFORMAT_RGBA8_UNORM_sRGB:
case PIXELFORMAT_RGBA8_sRGB:
textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
break;
case PIXELFORMAT_BGRA8_UNORM:
textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM;
break;
case PIXELFORMAT_BGRA8_UNORM_sRGB:
case PIXELFORMAT_BGRA8_sRGB:
textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB;
break;
case PIXELFORMAT_RGBA8_INT:
@@ -308,13 +302,22 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
textureFormat.internalFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
break;
case PIXELFORMAT_DXT1_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC1_RGBA_SRGB_BLOCK : VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
break;
case PIXELFORMAT_DXT1_sRGB:
textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
break;
case PIXELFORMAT_DXT3_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC2_SRGB_BLOCK : VK_FORMAT_BC2_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_BC2_UNORM_BLOCK;
break;
case PIXELFORMAT_DXT3_sRGB:
textureFormat.internalFormat = VK_FORMAT_BC2_SRGB_BLOCK;
break;
case PIXELFORMAT_DXT5_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_BC3_UNORM_BLOCK;
break;
case PIXELFORMAT_DXT5_sRGB:
textureFormat.internalFormat = VK_FORMAT_BC3_SRGB_BLOCK;
break;
case PIXELFORMAT_BC4_UNORM:
textureFormat.internalFormat = VK_FORMAT_BC4_UNORM_BLOCK;
@@ -335,31 +338,55 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
textureFormat.internalFormat = VK_FORMAT_BC6H_SFLOAT_BLOCK;
break;
case PIXELFORMAT_BC7_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_BC7_UNORM_BLOCK;
break;
case PIXELFORMAT_BC7_sRGB:
textureFormat.internalFormat = VK_FORMAT_BC7_SRGB_BLOCK;
break;
case PIXELFORMAT_PVR1_RGB2_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGB2_sRGB:
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGB4_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGB4_sRGB:
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGBA2_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGBA2_sRGB:
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGBA4_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
break;
case PIXELFORMAT_PVR1_RGBA4_sRGB:
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
break;
case PIXELFORMAT_ETC1_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
break;
case PIXELFORMAT_ETC2_RGB_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
break;
case PIXELFORMAT_ETC2_RGB_sRGB:
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
break;
case PIXELFORMAT_ETC2_RGBA_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
break;
case PIXELFORMAT_ETC2_RGBA_sRGB:
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
break;
case PIXELFORMAT_ETC2_RGBA1_UNORM:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
break;
case PIXELFORMAT_ETC2_RGBA1_sRGB:
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
break;
case PIXELFORMAT_EAC_R_UNORM:
textureFormat.internalFormat = VK_FORMAT_EAC_R11_UNORM_BLOCK;
@@ -373,47 +400,89 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
case PIXELFORMAT_EAC_RG_SNORM:
textureFormat.internalFormat = VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_4x4:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_4x4_SRGB_BLOCK : VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
case PIXELFORMAT_ASTC_4x4_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_5x4:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_5x4_SRGB_BLOCK : VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
case PIXELFORMAT_ASTC_5x4_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_5x5:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_5x5_SRGB_BLOCK : VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
case PIXELFORMAT_ASTC_5x5_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_6x5:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_6x5_SRGB_BLOCK : VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
case PIXELFORMAT_ASTC_6x5_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_6x6:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_6x6_SRGB_BLOCK : VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
case PIXELFORMAT_ASTC_6x6_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_8x5:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x5_SRGB_BLOCK : VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
case PIXELFORMAT_ASTC_8x5_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_8x6:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x6_SRGB_BLOCK : VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
case PIXELFORMAT_ASTC_8x6_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_8x8:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x8_SRGB_BLOCK : VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
case PIXELFORMAT_ASTC_8x8_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_10x5:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x5_SRGB_BLOCK : VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
case PIXELFORMAT_ASTC_10x5_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_10x6:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x6_SRGB_BLOCK : VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
case PIXELFORMAT_ASTC_10x6_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_10x8:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x8_SRGB_BLOCK : VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
case PIXELFORMAT_ASTC_10x8_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_10x10:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x10_SRGB_BLOCK : VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
case PIXELFORMAT_ASTC_10x10_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_12x10:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_12x10_SRGB_BLOCK : VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
case PIXELFORMAT_ASTC_12x10_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_12x12:
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_12x12_SRGB_BLOCK : VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
case PIXELFORMAT_ASTC_12x12_UNORM:
textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
break;
case PIXELFORMAT_ASTC_4x4_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_5x4_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_5x5_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_6x5_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_6x6_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_8x5_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_8x6_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_8x8_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_10x5_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_10x6_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_10x8_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_10x10_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_12x10_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_SRGB_BLOCK;
break;
case PIXELFORMAT_ASTC_12x12_sRGB:
textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
break;
default:
throw love::Exception("unknown pixel format");
+1 -1
View File
@@ -59,7 +59,7 @@ public:
static void resetShaderSwitches();
static VkFormat getVulkanVertexFormat(DataFormat format);
static TextureFormat getTextureFormat(PixelFormat, bool sRGB);
static TextureFormat getTextureFormat(PixelFormat format);
static std::string getVendorName(uint32_t vendorId);
static std::string getVulkanApiVersion(uint32_t apiVersion);
static VkPrimitiveTopology getPrimitiveTypeTopology(graphics::PrimitiveType);
+10 -9
View File
@@ -2355,7 +2355,11 @@ int w_setColorMask(lua_State *L)
{
ColorChannelMask mask;
if (lua_gettop(L) <= 1)
if (lua_isnoneornil(L, 1))
{
mask.r = mask.g = mask.b = mask.a = true;
}
else if (lua_gettop(L) <= 1)
{
// Set all color components if a single argument is given.
mask.r = mask.g = mask.b = mask.a = luax_checkboolean(L, 1);
@@ -2783,7 +2787,6 @@ int w_getTextureFormats(lua_State *L)
luaL_checktype(L, 1, LUA_TTABLE);
bool rt = luax_checkboolflag(L, 1, Texture::getConstant(Texture::SETTING_RENDER_TARGET));
bool linear = luax_boolflag(L, 1, Texture::getConstant(Texture::SETTING_LINEAR), false);
bool computewrite = luax_boolflag(L, 1, Texture::getConstant(Texture::SETTING_COMPUTE_WRITE), false);
OptionalBool readable;
@@ -2808,8 +2811,6 @@ int w_getTextureFormats(lua_State *L)
if (rt && isPixelFormatDepth(format))
continue;
bool sRGB = isGammaCorrect() && !linear;
uint32 usage = PIXELFORMATUSAGEFLAGS_NONE;
if (rt)
usage |= PIXELFORMATUSAGEFLAGS_RENDERTARGET;
@@ -2818,7 +2819,7 @@ int w_getTextureFormats(lua_State *L)
if (computewrite)
usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE;
luax_pushboolean(L, instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, sRGB));
luax_pushboolean(L, instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage));
lua_setfield(L, -2, name);
}
@@ -2862,14 +2863,14 @@ int w_getCanvasFormats(lua_State *L)
supported = [](PixelFormat format) -> bool
{
const uint32 usage = PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET;
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, false);
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage);
};
}
else
{
supported = [](PixelFormat format) -> bool
{
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_RENDERTARGET, false);
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_RENDERTARGET);
};
}
}
@@ -2881,7 +2882,7 @@ int w_getCanvasFormats(lua_State *L)
uint32 usage = PIXELFORMATUSAGEFLAGS_RENDERTARGET;
if (readable)
usage |= PIXELFORMATUSAGEFLAGS_SAMPLE;
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, false);
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage);
};
}
@@ -2894,7 +2895,7 @@ int w_getImageFormats(lua_State *L)
const auto supported = [](PixelFormat format) -> bool
{
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_SAMPLE, false);
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_SAMPLE);
};
const auto ignore = [](PixelFormat format) -> bool
+13 -5
View File
@@ -30,7 +30,6 @@ love::Type CompressedImageData::type("CompressedImageData", &Data::type);
CompressedImageData::CompressedImageData(const std::list<FormatHandler *> &formats, Data *filedata)
: format(PIXELFORMAT_UNKNOWN)
, sRGB(false)
{
FormatHandler *parser = nullptr;
@@ -46,7 +45,7 @@ CompressedImageData::CompressedImageData(const std::list<FormatHandler *> &forma
if (parser == nullptr)
throw love::Exception("Could not parse compressed data: Unknown format.");
memory = parser->parseCompressed(filedata, dataImages, format, sRGB);
memory = parser->parseCompressed(filedata, dataImages, format);
if (memory == nullptr)
throw love::Exception("Could not parse compressed data.");
@@ -56,11 +55,14 @@ CompressedImageData::CompressedImageData(const std::list<FormatHandler *> &forma
if (dataImages.size() == 0 || memory->getSize() == 0)
throw love::Exception("Could not parse compressed data: No valid data?");
// This throws away some information the decoder could give us, but we
// can't really rely on it I think...
format = getLinearPixelFormat(format);
}
CompressedImageData::CompressedImageData(const CompressedImageData &c)
: format(c.format)
, sRGB(c.sRGB)
{
memory.set(c.memory->clone(), Acquire::NORETAIN);
@@ -134,9 +136,15 @@ PixelFormat CompressedImageData::getFormat() const
return format;
}
bool CompressedImageData::isSRGB() const
void CompressedImageData::setLinear(bool linear)
{
return sRGB;
for (auto &slice : dataImages)
slice->setLinear(linear);
}
bool CompressedImageData::isLinear() const
{
return dataImages.empty() ? false : dataImages[0]->isLinear();
}
CompressedSlice *CompressedImageData::getSlice(int slice, int miplevel) const
+2 -2
View File
@@ -93,14 +93,14 @@ public:
**/
PixelFormat getFormat() const;
bool isSRGB() const;
void setLinear(bool linear);
bool isLinear() const;
CompressedSlice *getSlice(int slice, int miplevel) const;
protected:
PixelFormat format;
bool sRGB;
// Single block of memory containing all of the sub-images.
StrongRef<ByteData> memory;
-2
View File
@@ -31,7 +31,6 @@ CompressedSlice::CompressedSlice(PixelFormat format, int width, int height, Byte
, memory(memory)
, offset(offset)
, dataSize(size)
, sRGB(false)
{
}
@@ -40,7 +39,6 @@ CompressedSlice::CompressedSlice(const CompressedSlice &s)
, memory(s.memory)
, offset(s.offset)
, dataSize(s.dataSize)
, sRGB(s.sRGB)
{
}
-2
View File
@@ -46,7 +46,6 @@ public:
CompressedSlice *clone() const override;
void *getData() const override { return (uint8 *) memory->getData() + offset; }
size_t getSize() const override { return dataSize; }
bool isSRGB() const override { return sRGB; }
size_t getOffset() const { return offset; }
private:
@@ -54,7 +53,6 @@ private:
StrongRef<ByteData> memory;
size_t offset;
size_t dataSize;
bool sRGB;
}; // CompressedSlice
+1 -1
View File
@@ -60,7 +60,7 @@ bool FormatHandler::canParseCompressed(Data* /*data*/)
return false;
}
StrongRef<ByteData> FormatHandler::parseCompressed(Data* /*filedata*/, std::vector<StrongRef<CompressedSlice>>& /*images*/, PixelFormat& /*format*/, bool& /*sRGB*/)
StrongRef<ByteData> FormatHandler::parseCompressed(Data* /*filedata*/, std::vector<StrongRef<CompressedSlice>>& /*images*/, PixelFormat& /*format*/)
{
throw love::Exception("Compressed image parsing is not implemented for this format backend.");
}
+1 -2
View File
@@ -106,13 +106,12 @@ public:
* @param[out] images The list of sub-images generated. Byte data is a
* pointer to the returned data.
* @param[out] format The format of the Compressed Data.
* @param[out] sRGB Whether the texture is sRGB-encoded.
*
* @return The single block of memory containing the parsed images.
**/
virtual StrongRef<ByteData> parseCompressed(Data *filedata,
std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB);
PixelFormat &format);
/**
* Frees raw pixel memory allocated by the format handler.
+4 -5
View File
@@ -152,6 +152,10 @@ void ImageData::decode(Data *data)
else
delete[] this->data;
// This throws away some information the decoder could give us, but we
// can't really rely on it I think...
decodedimage.format = getLinearPixelFormat(decodedimage.format);
this->width = decodedimage.width;
this->height = decodedimage.height;
this->data = decodedimage.data;
@@ -247,11 +251,6 @@ void *ImageData::getData() const
return data;
}
bool ImageData::isSRGB() const
{
return false;
}
bool ImageData::inside(int x, int y) const
{
return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
+1 -2
View File
@@ -62,7 +62,7 @@ public:
static love::Type type;
ImageData(Data *data);
ImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8_UNORM);
ImageData(int width, int height, PixelFormat format);
ImageData(int width, int height, PixelFormat format, void *data, bool own);
ImageData(const ImageData &c);
virtual ~ImageData();
@@ -116,7 +116,6 @@ public:
ImageData *clone() const override;
void *getData() const override;
size_t getSize() const override;
bool isSRGB() const override;
size_t getPixelSize() const;
+11
View File
@@ -29,6 +29,7 @@ ImageDataBase::ImageDataBase(PixelFormat format, int width, int height)
: format(format)
, width(width)
, height(height)
, linear(false)
{
}
@@ -47,5 +48,15 @@ int ImageDataBase::getHeight() const
return height;
}
void ImageDataBase::setLinear(bool linear)
{
this->linear = linear;
}
bool ImageDataBase::isLinear() const
{
return linear;
}
} // image
} // love
+4 -1
View File
@@ -40,7 +40,8 @@ public:
int getWidth() const;
int getHeight() const;
virtual bool isSRGB() const = 0;
void setLinear(bool linear);
bool isLinear() const;
protected:
@@ -50,6 +51,8 @@ protected:
int width;
int height;
bool linear;
}; // ImageDataBase
} // image
+15 -17
View File
@@ -54,33 +54,33 @@ static PixelFormat convertFormat(uint32 blockX, uint32 blockY, uint32 blockZ)
return PIXELFORMAT_UNKNOWN;
if (blockX == 4 && blockY == 4)
return PIXELFORMAT_ASTC_4x4;
return PIXELFORMAT_ASTC_4x4_UNORM;
else if (blockX == 5 && blockY == 4)
return PIXELFORMAT_ASTC_5x4;
return PIXELFORMAT_ASTC_5x4_UNORM;
else if (blockX == 5 && blockY == 5)
return PIXELFORMAT_ASTC_5x5;
return PIXELFORMAT_ASTC_5x5_UNORM;
else if (blockX == 6 && blockY == 5)
return PIXELFORMAT_ASTC_6x5;
return PIXELFORMAT_ASTC_6x5_UNORM;
else if (blockX == 6 && blockY == 6)
return PIXELFORMAT_ASTC_6x6;
return PIXELFORMAT_ASTC_6x6_UNORM;
else if (blockX == 8 && blockY == 5)
return PIXELFORMAT_ASTC_8x5;
return PIXELFORMAT_ASTC_8x5_UNORM;
else if (blockX == 8 && blockY == 6)
return PIXELFORMAT_ASTC_8x6;
return PIXELFORMAT_ASTC_8x6_UNORM;
else if (blockX == 8 && blockY == 8)
return PIXELFORMAT_ASTC_8x8;
return PIXELFORMAT_ASTC_8x8_UNORM;
else if (blockX == 10 && blockY == 5)
return PIXELFORMAT_ASTC_10x5;
return PIXELFORMAT_ASTC_10x5_UNORM;
else if (blockX == 10 && blockY == 6)
return PIXELFORMAT_ASTC_10x6;
return PIXELFORMAT_ASTC_10x6_UNORM;
else if (blockX == 10 && blockY == 8)
return PIXELFORMAT_ASTC_10x8;
return PIXELFORMAT_ASTC_10x8_UNORM;
else if (blockX == 10 && blockY == 10)
return PIXELFORMAT_ASTC_10x10;
return PIXELFORMAT_ASTC_10x10_UNORM;
else if (blockX == 12 && blockY == 10)
return PIXELFORMAT_ASTC_12x10;
return PIXELFORMAT_ASTC_12x10_UNORM;
else if (blockX == 12 && blockY == 12)
return PIXELFORMAT_ASTC_12x12;
return PIXELFORMAT_ASTC_12x12_UNORM;
return PIXELFORMAT_UNKNOWN;
}
@@ -105,7 +105,7 @@ bool ASTCHandler::canParseCompressed(Data *data)
return true;
}
StrongRef<ByteData> ASTCHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
StrongRef<ByteData> ASTCHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
{
if (!canParseCompressed(filedata))
throw love::Exception("Could not decode compressed data (not an .astc file?)");
@@ -138,8 +138,6 @@ StrongRef<ByteData> ASTCHandler::parseCompressed(Data *filedata, std::vector<Str
images.emplace_back(new CompressedSlice(cformat, sizeX, sizeY, memory, 0, totalsize), Acquire::NORETAIN);
format = cformat;
sRGB = false;
return memory;
}
+1 -1
View File
@@ -45,7 +45,7 @@ public:
StrongRef<ByteData> parseCompressed(Data *filedata,
std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) override;
PixelFormat &format) override;
}; // ASTCHandler
+38 -46
View File
@@ -137,10 +137,8 @@ enum KTXGLInternalFormat
KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD
};
PixelFormat convertFormat(uint32 glformat, bool &sRGB)
PixelFormat convertFormat(uint32 glformat)
{
sRGB = false;
// hnnngg ASTC...
switch (glformat)
@@ -160,18 +158,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
case KTX_GL_COMPRESSED_RGB8_ETC2:
return PIXELFORMAT_ETC2_RGB_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ETC2:
sRGB = true;
return PIXELFORMAT_ETC2_RGB_UNORM;
return PIXELFORMAT_ETC2_RGB_sRGB;
case KTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
return PIXELFORMAT_ETC2_RGBA1_UNORM;
case KTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
sRGB = true;
return PIXELFORMAT_ETC2_RGBA1_UNORM;
return PIXELFORMAT_ETC2_RGBA1_sRGB;
case KTX_GL_COMPRESSED_RGBA8_ETC2_EAC:
return PIXELFORMAT_ETC2_RGBA_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
sRGB = true;
return PIXELFORMAT_ETC2_RGBA_UNORM;
return PIXELFORMAT_ETC2_RGBA_sRGB;
// PVRTC.
case KTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
@@ -185,15 +180,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
// DXT.
case KTX_GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
sRGB = true;
return PIXELFORMAT_DXT1_sRGB;
case KTX_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return PIXELFORMAT_DXT1_UNORM;
case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
sRGB = true;
return PIXELFORMAT_DXT3_sRGB;
case KTX_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return PIXELFORMAT_DXT3_UNORM;
case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
sRGB = true;
return PIXELFORMAT_DXT5_sRGB;
case KTX_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return PIXELFORMAT_DXT5_UNORM;
@@ -209,7 +204,7 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
// BC6 and BC7.
case KTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
sRGB = true;
return PIXELFORMAT_BC7_sRGB;
case KTX_GL_COMPRESSED_RGBA_BPTC_UNORM:
return PIXELFORMAT_BC7_UNORM;
case KTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
@@ -219,61 +214,61 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
// ASTC.
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_4x4_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
return PIXELFORMAT_ASTC_4x4;
return PIXELFORMAT_ASTC_4x4_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_5x4_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
return PIXELFORMAT_ASTC_5x4;
return PIXELFORMAT_ASTC_5x4_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_5x5_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
return PIXELFORMAT_ASTC_5x5;
return PIXELFORMAT_ASTC_5x5_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_6x5_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
return PIXELFORMAT_ASTC_6x5;
return PIXELFORMAT_ASTC_6x5_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_6x6_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
return PIXELFORMAT_ASTC_6x6;
return PIXELFORMAT_ASTC_6x6_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_8x5_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
return PIXELFORMAT_ASTC_8x5;
return PIXELFORMAT_ASTC_8x5_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_8x6_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
return PIXELFORMAT_ASTC_8x6;
return PIXELFORMAT_ASTC_8x6_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_8x8_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
return PIXELFORMAT_ASTC_8x8;
return PIXELFORMAT_ASTC_8x8_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_10x5_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
return PIXELFORMAT_ASTC_10x5;
return PIXELFORMAT_ASTC_10x5_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_10x6_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
return PIXELFORMAT_ASTC_10x6;
return PIXELFORMAT_ASTC_10x6_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_10x8_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
return PIXELFORMAT_ASTC_10x8;
return PIXELFORMAT_ASTC_10x8_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_10x10_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
return PIXELFORMAT_ASTC_10x10;
return PIXELFORMAT_ASTC_10x10_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_12x10_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
return PIXELFORMAT_ASTC_12x10;
return PIXELFORMAT_ASTC_12x10_UNORM;
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
sRGB = true;
return PIXELFORMAT_ASTC_12x12_sRGB;
case KTX_GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
return PIXELFORMAT_ASTC_12x12;
return PIXELFORMAT_ASTC_12x12_UNORM;
default:
return PIXELFORMAT_UNKNOWN;
}
@@ -298,7 +293,7 @@ bool KTXHandler::canParseCompressed(Data *data)
return true;
}
StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
{
if (!canParseCompressed(filedata))
throw love::Exception("Could not decode compressed data (not a KTX file?)");
@@ -314,8 +309,7 @@ StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<Stro
header.numberOfMipmapLevels = std::max(header.numberOfMipmapLevels, 1u);
bool isSRGB = false;
PixelFormat cformat = convertFormat(header.glInternalFormat, isSRGB);
PixelFormat cformat = convertFormat(header.glInternalFormat);
if (cformat == PIXELFORMAT_UNKNOWN)
throw love::Exception("Unsupported image format in KTX file.");
@@ -386,8 +380,6 @@ StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<Stro
}
format = cformat;
sRGB = isSRGB;
return memory;
}
+1 -1
View File
@@ -44,7 +44,7 @@ public:
StrongRef<ByteData> parseCompressed(Data *filedata,
std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) override;
PixelFormat &format) override;
}; // KTXHandler
+1 -3
View File
@@ -114,7 +114,7 @@ bool PKMHandler::canParseCompressed(Data *data)
return true;
}
StrongRef<ByteData> PKMHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
StrongRef<ByteData> PKMHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
{
if (!canParseCompressed(filedata))
throw love::Exception("Could not decode compressed data (not a PKM file?)");
@@ -148,8 +148,6 @@ StrongRef<ByteData> PKMHandler::parseCompressed(Data *filedata, std::vector<Stro
images.emplace_back(new CompressedSlice(cformat, width, height, memory, 0, totalsize), Acquire::NORETAIN);
format = cformat;
sRGB = false;
return memory;
}
+1 -1
View File
@@ -44,7 +44,7 @@ public:
StrongRef<ByteData> parseCompressed(Data *filedata,
std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) override;
PixelFormat &format) override;
}; // PKMHandler
+18 -17
View File
@@ -256,33 +256,33 @@ static PixelFormat convertFormat(PVRV3PixelFormat format, PVRV3ChannelType chann
case ePVRTPF_EAC_RG:
return snorm ? PIXELFORMAT_EAC_RG_SNORM : PIXELFORMAT_EAC_RG_UNORM;
case ePVRTPF_ASTC_4x4:
return PIXELFORMAT_ASTC_4x4;
return PIXELFORMAT_ASTC_4x4_UNORM;
case ePVRTPF_ASTC_5x4:
return PIXELFORMAT_ASTC_5x4;
return PIXELFORMAT_ASTC_5x4_UNORM;
case ePVRTPF_ASTC_5x5:
return PIXELFORMAT_ASTC_5x5;
return PIXELFORMAT_ASTC_5x5_UNORM;
case ePVRTPF_ASTC_6x5:
return PIXELFORMAT_ASTC_6x5;
return PIXELFORMAT_ASTC_6x5_UNORM;
case ePVRTPF_ASTC_6x6:
return PIXELFORMAT_ASTC_6x6;
return PIXELFORMAT_ASTC_6x6_UNORM;
case ePVRTPF_ASTC_8x5:
return PIXELFORMAT_ASTC_8x5;
return PIXELFORMAT_ASTC_8x5_UNORM;
case ePVRTPF_ASTC_8x6:
return PIXELFORMAT_ASTC_8x6;
return PIXELFORMAT_ASTC_8x6_UNORM;
case ePVRTPF_ASTC_8x8:
return PIXELFORMAT_ASTC_8x8;
return PIXELFORMAT_ASTC_8x8_UNORM;
case ePVRTPF_ASTC_10x5:
return PIXELFORMAT_ASTC_10x5;
return PIXELFORMAT_ASTC_10x5_UNORM;
case ePVRTPF_ASTC_10x6:
return PIXELFORMAT_ASTC_10x6;
return PIXELFORMAT_ASTC_10x6_UNORM;
case ePVRTPF_ASTC_10x8:
return PIXELFORMAT_ASTC_10x8;
return PIXELFORMAT_ASTC_10x8_UNORM;
case ePVRTPF_ASTC_10x10:
return PIXELFORMAT_ASTC_10x10;
return PIXELFORMAT_ASTC_10x10_UNORM;
case ePVRTPF_ASTC_12x10:
return PIXELFORMAT_ASTC_12x10;
return PIXELFORMAT_ASTC_12x10_UNORM;
case ePVRTPF_ASTC_12x12:
return PIXELFORMAT_ASTC_12x12;
return PIXELFORMAT_ASTC_12x12_UNORM;
default:
return PIXELFORMAT_UNKNOWN;
}
@@ -475,7 +475,7 @@ bool PVRHandler::canParseCompressed(Data *data)
return false;
}
StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
{
if (!canParseCompressed(filedata))
throw love::Exception("Could not decode compressed data (not a PVR file?)");
@@ -510,6 +510,9 @@ StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<Stro
PixelFormat cformat = convertFormat(pixelformat, channeltype);
if (header3.colorSpace == 1)
cformat = getSRGBPixelFormat(cformat);
if (cformat == PIXELFORMAT_UNKNOWN)
throw love::Exception("Could not parse PVR file: unsupported image format.");
@@ -551,8 +554,6 @@ StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<Stro
}
format = cformat;
sRGB = (header3.colorSpace == 1);
return memory;
}
+1 -1
View File
@@ -42,7 +42,7 @@ public:
StrongRef<ByteData> parseCompressed(Data *filedata,
std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) override;
PixelFormat &format) override;
}; // PVRHandler
+34 -27
View File
@@ -32,13 +32,10 @@ namespace image
namespace magpie
{
static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, bool &bgra)
static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat)
{
using namespace dds::dxinfo;
sRGB = false;
bgra = false;
switch (dxformat)
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
@@ -65,9 +62,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
sRGB = (dxformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
return PIXELFORMAT_RGBA8_UNORM;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
return PIXELFORMAT_RGBA8_sRGB;
case DXGI_FORMAT_R16G16_TYPELESS:
case DXGI_FORMAT_R16G16_FLOAT:
@@ -98,21 +95,21 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB:
sRGB = (dxformat == DXGI_FORMAT_BC1_UNORM_SRGB);
return PIXELFORMAT_DXT1_UNORM;
case DXGI_FORMAT_BC1_UNORM_SRGB:
return PIXELFORMAT_DXT1_sRGB;
case DXGI_FORMAT_BC2_TYPELESS:
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC2_UNORM_SRGB:
sRGB = (dxformat == DXGI_FORMAT_BC2_UNORM_SRGB);
return PIXELFORMAT_DXT3_UNORM;
case DXGI_FORMAT_BC2_UNORM_SRGB:
return PIXELFORMAT_DXT3_sRGB;
case DXGI_FORMAT_BC3_TYPELESS:
case DXGI_FORMAT_BC3_UNORM:
case DXGI_FORMAT_BC3_UNORM_SRGB:
sRGB = (dxformat == DXGI_FORMAT_BC3_UNORM_SRGB);
return PIXELFORMAT_DXT5_UNORM;
case DXGI_FORMAT_BC3_UNORM_SRGB:
return PIXELFORMAT_DXT5_sRGB;
case DXGI_FORMAT_BC4_TYPELESS:
case DXGI_FORMAT_BC4_UNORM:
@@ -136,10 +133,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
return PIXELFORMAT_BGRA8_UNORM;
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
sRGB = (dxformat == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB);
bgra = true;
return PIXELFORMAT_RGBA8_UNORM;
return PIXELFORMAT_BGRA8_sRGB;
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
@@ -150,9 +146,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB:
sRGB = (dxformat == DXGI_FORMAT_BC7_UNORM_SRGB);
return PIXELFORMAT_BC7_UNORM;
case DXGI_FORMAT_BC7_UNORM_SRGB:
return PIXELFORMAT_BC7_sRGB;
default:
return PIXELFORMAT_UNKNOWN;
@@ -164,9 +160,13 @@ bool DDSHandler::canDecode(Data *data)
using namespace dds::dxinfo;
DXGIFormat dxformat = dds::getDDSPixelFormat(data->getData(), data->getSize());
bool isSRGB = false;
bool bgra = false;
PixelFormat format = convertFormat(dxformat, isSRGB, bgra);
PixelFormat format = convertFormat(dxformat);
// We convert BGRA to RGBA
if (format == PIXELFORMAT_BGRA8_UNORM)
format = PIXELFORMAT_RGBA8_UNORM;
else if (format == PIXELFORMAT_BGRA8_sRGB)
format = PIXELFORMAT_RGBA8_sRGB;
return ImageData::validPixelFormat(format);
}
@@ -177,9 +177,19 @@ FormatHandler::DecodedImage DDSHandler::decode(Data *data)
dds::Parser parser(data->getData(), data->getSize());
bool isSRGB = false;
img.format = convertFormat(parser.getFormat());
bool bgra = false;
img.format = convertFormat(parser.getFormat(), isSRGB, bgra);
if (img.format == PIXELFORMAT_BGRA8_UNORM)
{
img.format = PIXELFORMAT_RGBA8_UNORM;
bgra = true;
}
else if (img.format == PIXELFORMAT_BGRA8_sRGB)
{
img.format = PIXELFORMAT_RGBA8_sRGB;
bgra = true;
}
if (!ImageData::validPixelFormat(img.format))
throw love::Exception("Could not parse DDS pixel data: Unsupported format.");
@@ -229,14 +239,12 @@ bool DDSHandler::canParseCompressed(Data *data)
return dds::isCompressedDDS(data->getData(), data->getSize());
}
StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
{
if (!dds::isCompressedDDS(filedata->getData(), filedata->getSize()))
throw love::Exception("Could not decode compressed data (not a DDS file?)");
PixelFormat texformat = PIXELFORMAT_UNKNOWN;
bool isSRGB = false;
bool bgra = false;
size_t dataSize = 0;
@@ -245,7 +253,7 @@ StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<Stro
// Attempt to parse the dds file.
dds::Parser parser(filedata->getData(), filedata->getSize());
texformat = convertFormat(parser.getFormat(), isSRGB, bgra);
texformat = convertFormat(parser.getFormat());
if (texformat == PIXELFORMAT_UNKNOWN)
throw love::Exception("Could not parse compressed data: Unsupported format.");
@@ -280,7 +288,6 @@ StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<Stro
}
format = texformat;
sRGB = isSRGB;
return memory;
}
+1 -1
View File
@@ -48,7 +48,7 @@ public:
bool canParseCompressed(Data *data) override;
StrongRef<ByteData> parseCompressed(Data *filedata,
std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) override;
PixelFormat &format) override;
}; // DDSHandler
@@ -103,6 +103,20 @@ int w_CompressedImageData_getFormat(lua_State *L)
return 1;
}
int w_CompressedImageData_setLinear(lua_State *L)
{
CompressedImageData *t = luax_checkcompressedimagedata(L, 1);
t->setLinear(luax_checkboolean(L, 2));
return 0;
}
int w_CompressedImageData_isLinear(lua_State *L)
{
CompressedImageData *t = luax_checkcompressedimagedata(L, 1);
luax_pushboolean(L, t->isLinear());
return 1;
}
static const luaL_Reg w_CompressedImageData_functions[] =
{
{ "clone", w_CompressedImageData_clone },
@@ -111,6 +125,8 @@ static const luaL_Reg w_CompressedImageData_functions[] =
{ "getDimensions", w_CompressedImageData_getDimensions },
{ "getMipmapCount", w_CompressedImageData_getMipmapCount },
{ "getFormat", w_CompressedImageData_getFormat },
{ "setLinear", w_CompressedImageData_setLinear },
{ "isLinear", w_CompressedImageData_isLinear },
{ 0, 0 },
};
+16
View File
@@ -66,6 +66,20 @@ int w_ImageData_getFormat(lua_State *L)
return 1;
}
int w_ImageData_setLinear(lua_State *L)
{
ImageData *t = luax_checkimagedata(L, 1);
t->setLinear(luax_checkboolean(L, 2));
return 0;
}
int w_ImageData_isLinear(lua_State *L)
{
ImageData *t = luax_checkimagedata(L, 1);
luax_pushboolean(L, t->isLinear());
return 1;
}
int w_ImageData_getWidth(lua_State *L)
{
ImageData *t = luax_checkimagedata(L, 1);
@@ -314,6 +328,8 @@ static const luaL_Reg w_ImageData_functions[] =
{
{ "clone", w_ImageData_clone },
{ "getFormat", w_ImageData_getFormat },
{ "setLinear", w_ImageData_setLinear },
{ "isLinear", w_ImageData_isLinear },
{ "getWidth", w_ImageData_getWidth },
{ "getHeight", w_ImageData_getHeight },
{ "getDimensions", w_ImageData_getDimensions },
+24 -6
View File
@@ -23,12 +23,12 @@
#include "common/math.h"
#include "Shape.h"
#include "Fixture.h"
#include "World.h"
#include "Physics.h"
// Needed for luax_pushjoint.
#include "wrap_Joint.h"
#include "wrap_Shape.h"
namespace love
{
@@ -39,6 +39,7 @@ namespace box2d
Body::Body(World *world, b2Vec2 p, Body::Type type)
: world(world)
, hasCustomMass(false)
{
b2BodyDef def;
def.position = Physics::scaleDown(p);
@@ -249,6 +250,7 @@ void Body::setLinearDamping(float d)
void Body::resetMassData()
{
body->ResetMassData();
hasCustomMass = false;
}
void Body::setMassData(float x, float y, float m, float i)
@@ -258,6 +260,7 @@ void Body::setMassData(float x, float y, float m, float i)
massData.mass = m;
massData.I = Physics::scaleDown(Physics::scaleDown(i));
body->SetMassData(&massData);
hasCustomMass = true;
}
void Body::setMass(float m)
@@ -266,6 +269,7 @@ void Body::setMass(float m)
body->GetMassData(&data);
data.mass = m;
body->SetMassData(&data);
hasCustomMass = true;
}
void Body::setInertia(float i)
@@ -275,6 +279,7 @@ void Body::setInertia(float i)
massData.mass = body->GetMass();
massData.I = Physics::scaleDown(Physics::scaleDown(i));
body->SetMassData(&massData);
hasCustomMass = true;
}
void Body::setGravityScale(float scale)
@@ -461,7 +466,20 @@ World *Body::getWorld() const
return world;
}
int Body::getFixtures(lua_State *L) const
Shape *Body::getShape() const
{
b2Fixture *f = body->GetFixtureList();
if (f == nullptr)
return nullptr;
Shape *shape = (Shape *)(f->GetUserData().pointer);
if (!shape)
throw love::Exception("A Shape has escaped Memoizer!");
return shape;
}
int Body::getShapes(lua_State *L) const
{
lua_newtable(L);
b2Fixture *f = body->GetFixtureList();
@@ -470,10 +488,10 @@ int Body::getFixtures(lua_State *L) const
{
if (!f)
break;
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
if (!fixture)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, fixture);
Shape *shape = (Shape *)(f->GetUserData().pointer);
if (!shape)
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, shape);
lua_rawseti(L, -2, i);
i++;
}
+11 -5
View File
@@ -39,7 +39,6 @@ namespace box2d
// Forward declarations.
class World;
class Shape;
class Fixture;
/**
* A Body is an entity which has position and orientation
@@ -57,7 +56,6 @@ public:
friend class CircleShape;
friend class PolygonShape;
friend class Shape;
friend class Fixture;
// Public because joints et al ask for b2body
b2Body *body;
@@ -139,6 +137,8 @@ public:
**/
int getMassData(lua_State *L);
bool hasCustomMassData() const { return hasCustomMass; }
/**
* Gets the Body's angular damping.
**/
@@ -391,10 +391,14 @@ public:
World *getWorld() const;
/**
* Get an array of all the Fixtures attached to this Body.
* @return An array of Fixtures.
* Gets the first Shape attached to this Body.
**/
int getFixtures(lua_State *L) const;
Shape *getShape() const;
/**
* Get an array of all the Shapes attached to this Body.
**/
int getShapes(lua_State *L) const;
/**
* Get an array of all Joints attached to this Body.
@@ -431,6 +435,8 @@ private:
// unowned?
World *world;
bool hasCustomMass;
// Reference to arbitrary data.
Reference* ref = nullptr;
+14 -15
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type ChainShape::type("ChainShape", &Shape::type);
ChainShape::ChainShape(b2ChainShape *c, bool own)
: Shape(c, own)
ChainShape::ChainShape(Body *body, const b2ChainShape &c)
: Shape(body, c)
{
}
@@ -45,6 +45,7 @@ ChainShape::~ChainShape()
void ChainShape::setNextVertex(float x, float y)
{
throwIfShapeNotValid();
b2Vec2 v(x, y);
b2ChainShape *c = (b2ChainShape *)shape;
c->m_nextVertex = Physics::scaleDown(v);
@@ -52,6 +53,7 @@ void ChainShape::setNextVertex(float x, float y)
void ChainShape::setPreviousVertex(float x, float y)
{
throwIfShapeNotValid();
b2Vec2 v(x, y);
b2ChainShape *c = (b2ChainShape *)shape;
c->m_prevVertex = Physics::scaleDown(v);
@@ -59,44 +61,40 @@ void ChainShape::setPreviousVertex(float x, float y)
b2Vec2 ChainShape::getNextVertex() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return Physics::scaleUp(c->m_nextVertex);
}
b2Vec2 ChainShape::getPreviousVertex() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return Physics::scaleUp(c->m_prevVertex);
}
EdgeShape *ChainShape::getChildEdge(int index) const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
b2EdgeShape *e = new b2EdgeShape;
try
{
c->GetChildEdge(e, index);
}
catch (love::Exception &)
{
delete e;
throw;
}
b2EdgeShape e;
c->GetChildEdge(&e, index);
return new EdgeShape(e, true);
return new EdgeShape(nullptr, e);
}
int ChainShape::getVertexCount() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return c->m_count;
}
b2Vec2 ChainShape::getPoint(int index) const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
if (index < 0 || index >= c->m_count)
throw love::Exception("Physics error: index out of bounds");
@@ -106,6 +104,7 @@ b2Vec2 ChainShape::getPoint(int index) const
const b2Vec2 *ChainShape::getPoints() const
{
throwIfShapeNotValid();
b2ChainShape *c = (b2ChainShape *)shape;
return c->m_vertices;
}
+1 -1
View File
@@ -45,7 +45,7 @@ public:
* Create a new ChainShape from a Box2D chain shape.
* @param c The chain shape.
**/
ChainShape(b2ChainShape *c, bool own = true);
ChainShape(Body *body, const b2ChainShape &c);
virtual ~ChainShape();
+6 -2
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type CircleShape::type("CircleShape", &Shape::type);
CircleShape::CircleShape(b2CircleShape *c, bool own)
: Shape(c, own)
CircleShape::CircleShape(Body *body, const b2CircleShape &c)
: Shape(body, c)
{
}
@@ -45,16 +45,19 @@ CircleShape::~CircleShape()
float CircleShape::getRadius() const
{
throwIfShapeNotValid();
return Physics::scaleUp(shape->m_radius);
}
void CircleShape::setRadius(float r)
{
throwIfShapeNotValid();
shape->m_radius = Physics::scaleDown(r);
}
void CircleShape::getPoint(float &x_o, float &y_o) const
{
throwIfShapeNotValid();
b2CircleShape *c = (b2CircleShape *) shape;
x_o = Physics::scaleUp(c->m_p.x);
y_o = Physics::scaleUp(c->m_p.y);
@@ -62,6 +65,7 @@ void CircleShape::getPoint(float &x_o, float &y_o) const
void CircleShape::setPoint(float x, float y)
{
throwIfShapeNotValid();
b2CircleShape *c = (b2CircleShape *) shape;
c->m_p = Physics::scaleDown(b2Vec2(x, y));
}
+1 -1
View File
@@ -50,7 +50,7 @@ public:
* Create a new CircleShape from the a Box2D CircleShape definition.
* @param c The CircleShape definition.
**/
CircleShape(b2CircleShape *c, bool own = true);
CircleShape(Body *body, const b2CircleShape &c);
virtual ~CircleShape();
+8 -9
View File
@@ -35,7 +35,6 @@ Contact::Contact(World *world, b2Contact *contact)
: contact(contact)
, world(world)
{
//contact->user
world->registerObject(contact, this);
}
@@ -46,16 +45,16 @@ Contact::~Contact()
void Contact::invalidate()
{
if (contact != NULL)
if (contact != nullptr)
{
world->unregisterObject(contact);
contact = NULL;
contact = nullptr;
}
}
bool Contact::isValid()
{
return contact != NULL;
return contact != nullptr;
}
int Contact::getPositions(lua_State *L)
@@ -144,13 +143,13 @@ void Contact::getChildren(int &childA, int &childB)
childB = contact->GetChildIndexB();
}
void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB)
void Contact::getShapes(Shape *&shapeA, Shape *&shapeB)
{
fixtureA = (Fixture *) (contact->GetFixtureA()->GetUserData().pointer);
fixtureB = (Fixture *) (contact->GetFixtureB()->GetUserData().pointer);
shapeA = (Shape *) (contact->GetFixtureA()->GetUserData().pointer);
shapeB = (Shape *) (contact->GetFixtureB()->GetUserData().pointer);
if (!fixtureA || !fixtureB)
throw love::Exception("A fixture has escaped Memoizer!");
if (!shapeA || !shapeB)
throw love::Exception("A Shape has escaped Memoizer!");
}
} // box2d
+2 -2
View File
@@ -151,9 +151,9 @@ public:
void getChildren(int &childA, int &childB);
/**
* Gets the Fixtures associated with this Contact.
* Gets the Shapes associated with this Contact.
**/
void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB);
void getShapes(Shape *&shapeA, Shape *&shapeB);
private:
+7 -4
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type EdgeShape::type("EdgeShape", &Shape::type);
EdgeShape::EdgeShape(b2EdgeShape *e, bool own)
: Shape(e, own)
EdgeShape::EdgeShape(Body *body, const b2EdgeShape &e)
: Shape(body, e)
{
}
@@ -45,6 +45,7 @@ EdgeShape::~EdgeShape()
void EdgeShape::setNextVertex(float x, float y)
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
b2Vec2 v(x, y);
e->m_vertex3 = Physics::scaleDown(v);
@@ -52,13 +53,14 @@ void EdgeShape::setNextVertex(float x, float y)
b2Vec2 EdgeShape::getNextVertex() const
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
return Physics::scaleUp(e->m_vertex3);
}
void EdgeShape::setPreviousVertex(float x, float y)
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
b2Vec2 v(x, y);
e->m_vertex0 = Physics::scaleDown(v);
@@ -66,13 +68,14 @@ void EdgeShape::setPreviousVertex(float x, float y)
b2Vec2 EdgeShape::getPreviousVertex() const
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
return Physics::scaleUp(e->m_vertex0);
}
int EdgeShape::getPoints(lua_State *L)
{
throwIfShapeNotValid();
b2EdgeShape *e = (b2EdgeShape *)shape;
b2Vec2 v1 = Physics::scaleUp(e->m_vertex1);
b2Vec2 v2 = Physics::scaleUp(e->m_vertex2);
+1 -1
View File
@@ -45,7 +45,7 @@ public:
* Create a new EdgeShape from a Box2D edge shape.
* @param e The edge shape.
**/
EdgeShape(b2EdgeShape *e, bool own = true);
EdgeShape(Body *body, const b2EdgeShape &e);
virtual ~EdgeShape();
-349
View File
@@ -1,349 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Fixture.h"
// Module
#include "Body.h"
#include "World.h"
#include "Physics.h"
// STD
#include <bitset>
namespace love
{
namespace physics
{
namespace box2d
{
love::Type Fixture::type("Fixture", &Object::type);
Fixture::Fixture(Body *body, Shape *shape, float density)
: body(body)
, fixture(nullptr)
{
b2FixtureDef def;
def.shape = shape->shape;
def.userData.pointer = (uintptr_t)this;
def.density = density;
fixture = body->body->CreateFixture(&def);
this->retain();
}
Fixture::~Fixture()
{
if (ref)
delete ref;
}
void Fixture::checkCreateShape()
{
if (shape.get() != nullptr || fixture == nullptr || fixture->GetShape() == nullptr)
return;
b2Shape *bshape = fixture->GetShape();
switch (bshape->GetType())
{
case b2Shape::e_circle:
shape.set(new CircleShape((b2CircleShape *) bshape, false), Acquire::NORETAIN);
break;
case b2Shape::e_edge:
shape.set(new EdgeShape((b2EdgeShape *) bshape, false), Acquire::NORETAIN);
break;
case b2Shape::e_polygon:
shape.set(new PolygonShape((b2PolygonShape *) bshape, false), Acquire::NORETAIN);
break;
case b2Shape::e_chain:
shape.set(new ChainShape((b2ChainShape *) bshape, false), Acquire::NORETAIN);
break;
default:
break;
}
}
Shape::Type Fixture::getType()
{
checkCreateShape();
if (shape.get() == nullptr)
return Shape::SHAPE_INVALID;
else
return shape->getType();
}
void Fixture::setFriction(float friction)
{
fixture->SetFriction(friction);
}
void Fixture::setRestitution(float restitution)
{
fixture->SetRestitution(restitution);
}
void Fixture::setDensity(float density)
{
fixture->SetDensity(density);
}
void Fixture::setSensor(bool sensor)
{
fixture->SetSensor(sensor);
}
float Fixture::getFriction() const
{
return fixture->GetFriction();
}
float Fixture::getRestitution() const
{
return fixture->GetRestitution();
}
float Fixture::getDensity() const
{
return fixture->GetDensity();
}
bool Fixture::isSensor() const
{
return fixture->IsSensor();
}
Body *Fixture::getBody() const
{
return body;
}
Shape *Fixture::getShape()
{
checkCreateShape();
return shape;
}
bool Fixture::isValid() const
{
return fixture != nullptr;
}
void Fixture::setFilterData(int *v)
{
b2Filter f;
f.categoryBits = (uint16) v[0];
f.maskBits = (uint16) v[1];
f.groupIndex = (int16) v[2];
fixture->SetFilterData(f);
}
void Fixture::getFilterData(int *v)
{
b2Filter f = fixture->GetFilterData();
v[0] = (int) f.categoryBits;
v[1] = (int) f.maskBits;
v[2] = (int) f.groupIndex;
}
int Fixture::setCategory(lua_State *L)
{
b2Filter f = fixture->GetFilterData();
f.categoryBits = (uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
int Fixture::setMask(lua_State *L)
{
b2Filter f = fixture->GetFilterData();
f.maskBits = ~(uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
void Fixture::setGroupIndex(int index)
{
b2Filter f = fixture->GetFilterData();
f.groupIndex = (uint16)index;
fixture->SetFilterData(f);
}
int Fixture::getGroupIndex() const
{
b2Filter f = fixture->GetFilterData();
return f.groupIndex;
}
int Fixture::getCategory(lua_State *L)
{
return pushBits(L, fixture->GetFilterData().categoryBits);
}
int Fixture::getMask(lua_State *L)
{
return pushBits(L, ~(fixture->GetFilterData().maskBits));
}
uint16 Fixture::getBits(lua_State *L)
{
// Get number of args.
bool istable = lua_istable(L, 1);
int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
// The new bitset.
std::bitset<16> b;
for (int i = 1; i <= argc; i++)
{
size_t bpos = 0;
if (istable)
{
lua_rawgeti(L, 1, i);
bpos = (size_t) (lua_tointeger(L, -1) - 1);
lua_pop(L, 1);
}
else
bpos = (size_t) (lua_tointeger(L, i) - 1);
if (bpos >= 16)
luaL_error(L, "Values must be in range 1-16.");
b.set(bpos, true);
}
return (uint16)b.to_ulong();
}
int Fixture::pushBits(lua_State *L, uint16 bits)
{
// Create a bitset.
std::bitset<16> b((int)bits);
// Push all set bits.
for (int i = 0; i<16; i++)
if (b.test(i))
lua_pushinteger(L, i+1);
// Count number of set bits.
return (int)b.count();
}
int Fixture::setUserData(lua_State *L)
{
love::luax_assert_argc(L, 1, 1);
if(!ref)
ref = new Reference();
ref->ref(L);
return 0;
}
int Fixture::getUserData(lua_State *L)
{
if (ref != nullptr)
ref->push(L);
else
lua_pushnil(L);
return 1;
}
bool Fixture::testPoint(float x, float y) const
{
return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y)));
}
int Fixture::rayCast(lua_State *L) const
{
float p1x = Physics::scaleDown((float)luaL_checknumber(L, 1));
float p1y = Physics::scaleDown((float)luaL_checknumber(L, 2));
float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
float maxFraction = (float)luaL_checknumber(L, 5);
int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index
b2RayCastInput input;
input.p1.Set(p1x, p1y);
input.p2.Set(p2x, p2y);
input.maxFraction = maxFraction;
b2RayCastOutput output;
if (!fixture->RayCast(&output, input, childIndex))
return 0; // Nothing hit.
lua_pushnumber(L, output.normal.x);
lua_pushnumber(L, output.normal.y);
lua_pushnumber(L, output.fraction);
return 3;
}
int Fixture::getBoundingBox(lua_State *L) const
{
int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index
b2AABB box;
luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); });
box = Physics::scaleUp(box);
lua_pushnumber(L, box.lowerBound.x);
lua_pushnumber(L, box.lowerBound.y);
lua_pushnumber(L, box.upperBound.x);
lua_pushnumber(L, box.upperBound.y);
return 4;
}
int Fixture::getMassData(lua_State *L) const
{
b2MassData data;
fixture->GetMassData(&data);
b2Vec2 center = Physics::scaleUp(data.center);
lua_pushnumber(L, center.x);
lua_pushnumber(L, center.y);
lua_pushnumber(L, data.mass);
lua_pushnumber(L, data.I);
return 4;
}
void Fixture::destroy(bool implicit)
{
if (body->world->world->IsLocked())
{
// Called during time step. Save reference for destruction afterwards.
this->retain();
body->world->destructFixtures.push_back(this);
return;
}
shape.set(nullptr);
if (!implicit && fixture != nullptr)
body->body->DestroyFixture(fixture);
fixture = nullptr;
// Remove userdata reference to avoid it sticking around after GC
if (ref)
ref->unref();
// Box2D fixture destroyed. Release its reference to the love Fixture.
this->release();
}
} // box2d
} // physics
} // love
-216
View File
@@ -1,216 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_PHYSICS_BOX2D_FIXTURE_H
#define LOVE_PHYSICS_BOX2D_FIXTURE_H
// LOVE
#include "physics/Shape.h"
#include "physics/box2d/Body.h"
#include "physics/box2d/Shape.h"
#include "common/Object.h"
#include "common/Reference.h"
// Box2D
#include <box2d/Box2D.h>
namespace love
{
namespace physics
{
namespace box2d
{
class World;
/**
* A Fixture is used to attach a shape to a body for collision detection.
* A Fixture inherits its transform from its parent. Fixtures hold
* additional non-geometric data such as friction, collision filters,
* etc.
**/
class Fixture : public Object
{
public:
friend class Physics;
static love::Type type;
/**
* Creates a Fixture.
**/
Fixture(Body *body, Shape *shape, float density);
virtual ~Fixture();
/**
* Gets the type of the Fixture's Shape. Useful for
* debug drawing.
**/
Shape::Type getType();
/**
* Gets the Shape attached to this Fixture.
**/
Shape *getShape();
/**
* Returns true if the fixture is active in a Box2D world.
**/
bool isValid() const;
/**
* Checks whether this Fixture acts as a sensor.
* @return True if sensor, false otherwise.
**/
bool isSensor() const;
/**
* Set whether this Fixture should be a sensor or not.
* @param sensor True if sensor, false if not.
**/
void setSensor(bool sensor);
/**
* Gets the Body this Fixture is attached to.
**/
Body *getBody() const;
/**
* Sets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void setFilterData(int *v);
/**
* Gets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void getFilterData(int *v);
/**
* This function stores an in-C reference to
* arbitrary Lua data in the Box2D Fixture object.
**/
int setUserData(lua_State *L);
/**
* Gets the data set with setData. If no
* data is set, nil is returned.
**/
int getUserData(lua_State *L);
/**
* Sets the friction of the Fixture.
* @param friction The new friction.
**/
void setFriction(float friction);
/**
* Sets the restitution for the Fixture.
* @param restitution The restitution.
**/
void setRestitution(float restitution);
/**
* Sets the density of the Fixture.
* @param density The density of the Fixture.
**/
void setDensity(float density);
/**
* Gets the friction of the Fixture.
* @returns The friction.
**/
float getFriction() const;
/**
* Gets the restitution of the Fixture.
* @return The restitution of the Fixture.
**/
float getRestitution() const;
/**
* Gets the density of the Fixture.
* @return The density.
**/
float getDensity() const;
/**
* Checks if a point is inside the Fixture.
* @param x The x-component of the point.
* @param y The y-component of the point.
**/
bool testPoint(float x, float y) const;
/**
* Cast a ray against this Fixture.
**/
int rayCast(lua_State *L) const;
void setGroupIndex(int index);
int getGroupIndex() const;
int setCategory(lua_State *L);
int setMask(lua_State *L);
int getCategory(lua_State *L);
int getMask(lua_State *L);
uint16 getBits(lua_State *L);
int pushBits(lua_State *L, uint16 bits);
/**
* Gets the bounding box for this Fixture.
* The function returns eight values which can be
* passed directly to love.graphics.polygon.
**/
int getBoundingBox(lua_State *L) const;
/**
* Gets the mass data for this Fixture.
* This operation may be expensive.
**/
int getMassData(lua_State *L) const;
/**
* Destroys this fixture.
**/
void destroy(bool implicit = false);
protected:
void checkCreateShape();
Body *body;
b2Fixture *fixture;
// Reference to arbitrary data.
Reference* ref = nullptr;
StrongRef<Shape> shape;
};
} // box2d
} // physics
} // love
#endif // LOVE_PHYSICS_BOX2D_FIXTURE_H
+126 -137
View File
@@ -35,6 +35,7 @@ namespace box2d
float Physics::meter = Physics::DEFAULT_METER;
Physics::Physics()
: blockAllocator()
{
meter = DEFAULT_METER;
}
@@ -63,173 +64,164 @@ Body *Physics::newBody(World *world, Body::Type type)
return new Body(world, b2Vec2(0, 0), type);
}
CircleShape *Physics::newCircleShape(float radius)
Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, float radius)
{
return newCircleShape(0, 0, radius);
StrongRef<Body> body(newBody(world, x, y, type), Acquire::NORETAIN);
StrongRef<CircleShape> shape(newCircleShape(body, 0, 0, radius), Acquire::NORETAIN);
body->retain();
return body.get();
}
CircleShape *Physics::newCircleShape(float x, float y, float radius)
Body *Physics::newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle)
{
b2CircleShape *s = new b2CircleShape();
s->m_p = Physics::scaleDown(b2Vec2(x, y));
s->m_radius = Physics::scaleDown(radius);
return new CircleShape(s);
StrongRef<Body> body(newBody(world, x, y, type), Acquire::NORETAIN);
StrongRef<PolygonShape> shape(newRectangleShape(body, 0, 0, w, h, angle), Acquire::NORETAIN);
body->retain();
return body.get();
}
PolygonShape *Physics::newRectangleShape(float w, float h)
Body *Physics::newPolygonBody(World *world, Body::Type type, const Vector2 *coords, int count)
{
return newRectangleShape(0, 0, w, h, 0);
Vector2 origin(0, 0);
for (int i = 0; i < count; i++)
origin += coords[i] / count;
std::vector<Vector2> localcoords;
for (int i = 0; i < count; i++)
localcoords.push_back(coords[i] - origin);
StrongRef<Body> body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN);
StrongRef<PolygonShape> shape(newPolygonShape(body, localcoords.data(), count), Acquire::NORETAIN);
body->retain();
return body.get();
}
PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h)
Body *Physics::newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided)
{
return newRectangleShape(x, y, w, h, 0);
float wx = (x2 - x1) / 2.0f;
float wy = (y2 - y1) / 2.0f;
StrongRef<Body> body(newBody(world, wx, wy, type), Acquire::NORETAIN);
StrongRef<EdgeShape> shape(newEdgeShape(body, x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN);
body->retain();
return body.get();
}
PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h, float angle)
Body *Physics::newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count)
{
b2PolygonShape *s = new b2PolygonShape();
s->SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle);
return new PolygonShape(s);
Vector2 origin(0, 0);
for (int i = 0; i < count; i++)
origin += coords[i] / count;
std::vector<Vector2> localcoords;
for (int i = 0; i < count; i++)
localcoords.push_back(coords[i] - origin);
StrongRef<Body> body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN);
StrongRef<ChainShape> shape(newChainShape(body, loop, localcoords.data(), count), Acquire::NORETAIN);
body->retain();
return body.get();
}
EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided)
Shape *Physics::newAttachedShape(Body *body, Shape *prototype, float density)
{
b2EdgeShape *s = new b2EdgeShape();
if (prototype->isValid())
throw love::Exception("The given Shape must not be part of the World.");
Shape *shape = nullptr;
switch (prototype->getType())
{
case Shape::SHAPE_CIRCLE:
shape = new CircleShape(body, *(b2CircleShape *) prototype->shape);
break;
case Shape::SHAPE_POLYGON:
shape = new PolygonShape(body, *(b2PolygonShape *) prototype->shape);
break;
case Shape::SHAPE_EDGE:
shape = new EdgeShape(body, *(b2EdgeShape *) prototype->shape);
break;
case Shape::SHAPE_CHAIN:
shape = new ChainShape(body, *(b2ChainShape *) prototype->shape);
break;
default:
throw love::Exception("Unknown shape type.");
break;
}
shape->setDensity(density);
body->resetMassData();
return shape;
}
CircleShape *Physics::newCircleShape(Body *body, float x, float y, float radius)
{
b2CircleShape s;
s.m_p = Physics::scaleDown(b2Vec2(x, y));
s.m_radius = Physics::scaleDown(radius);
return new CircleShape(body, s);
}
PolygonShape *Physics::newRectangleShape(Body *body, float x, float y, float w, float h, float angle)
{
b2PolygonShape s;
s.SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle);
return new PolygonShape(body, s);
}
EdgeShape *Physics::newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided)
{
b2EdgeShape s;
if (oneSided)
{
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
s->SetOneSided(v1, v1, v2, v2);
s.SetOneSided(v1, v1, v2, v2);
}
else
{
s->SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2)));
s.SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2)));
}
return new EdgeShape(s);
return new EdgeShape(body, s);
}
int Physics::newPolygonShape(lua_State *L)
PolygonShape *Physics::newPolygonShape(Body *body, const Vector2 *coords, int count)
{
int argc = lua_gettop(L);
bool istable = lua_istable(L, 1);
if (istable)
argc = (int) luax_objlen(L, 1);
if (argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
// 3 to 8 (b2_maxPolygonVertices) vertices
int vcount = argc / 2;
if (vcount < 3)
return luaL_error(L, "Expected a minimum of 3 vertices, got %d.", vcount);
else if (vcount > b2_maxPolygonVertices)
return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount);
if (count < 3)
throw love::Exception("Expected a minimum of 3 vertices, got %d.", count);
else if (count > b2_maxPolygonVertices)
throw love::Exception("Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, count);
b2Vec2 vecs[b2_maxPolygonVertices];
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, 1, 1 + i * 2);
lua_rawgeti(L, 1, 2 + i * 2);
float x = (float)luaL_checknumber(L, -2);
float y = (float)luaL_checknumber(L, -1);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
lua_pop(L, 2);
}
}
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 1 + i * 2);
float y = (float)luaL_checknumber(L, 2 + i * 2);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
}
}
for (int i = 0; i < count; i++)
vecs[i] = Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y));
b2PolygonShape *s = new b2PolygonShape();
b2PolygonShape s;
try
{
s->Set(vecs, vcount);
}
catch (love::Exception &)
{
delete s;
throw;
}
s.Set(vecs, count);
PolygonShape *p = new PolygonShape(s);
luax_pushtype(L, p);
p->release();
return 1;
return new PolygonShape(body, s);
}
int Physics::newChainShape(lua_State *L)
ChainShape *Physics::newChainShape(Body *body, bool loop, const Vector2 *coords, int count)
{
int argc = lua_gettop(L)-1; // first argument is looping
std::vector<b2Vec2> vecs;
bool istable = lua_istable(L, 2);
for (int i = 0; i < count; i++)
vecs.push_back(Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y)));
if (istable)
argc = (int) luax_objlen(L, 2);
b2ChainShape s;
if (argc == 0 || argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = argc/2;
bool loop = luax_checkboolean(L, 1);
b2Vec2 *vecs = new b2Vec2[vcount];
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, 2, 1 + i * 2);
lua_rawgeti(L, 2, 2 + i * 2);
float x = (float)lua_tonumber(L, -2);
float y = (float)lua_tonumber(L, -1);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
lua_pop(L, 2);
}
}
if (loop)
s.CreateLoop(vecs.data(), count);
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 2 + i * 2);
float y = (float)luaL_checknumber(L, 3 + i * 2);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
}
}
s.CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]);
b2ChainShape *s = new b2ChainShape();
try
{
if (loop)
s->CreateLoop(vecs, vcount);
else
s->CreateChain(vecs, vcount, vecs[0], vecs[vcount-1]);
}
catch (love::Exception &)
{
delete[] vecs;
delete s;
throw;
}
delete[] vecs;
ChainShape *c = new ChainShape(s);
luax_pushtype(L, c);
c->release();
return 1;
return new ChainShape(body, s);
}
DistanceJoint *Physics::newDistanceJoint(Body *body1, Body *body2, float x1, float y1, float x2, float y2, bool collideConnected)
@@ -307,16 +299,10 @@ MotorJoint *Physics::newMotorJoint(Body *body1, Body *body2, float correctionFac
return new MotorJoint(body1, body2, correctionFactor, collideConnected);
}
Fixture *Physics::newFixture(Body *body, Shape *shape, float density)
{
return new Fixture(body, shape, density);
}
int Physics::getDistance(lua_State *L)
{
Fixture *fixtureA = luax_checktype<Fixture>(L, 1);
Fixture *fixtureB = luax_checktype<Fixture>(L, 2);
Shape *shapeA = luax_checktype<Shape>(L, 1);
Shape *shapeB = luax_checktype<Shape>(L, 2);
b2DistanceProxy pA, pB;
b2DistanceInput i;
b2DistanceOutput o;
@@ -324,12 +310,15 @@ int Physics::getDistance(lua_State *L)
c.count = 0;
luax_catchexcept(L, [&]() {
pA.Set(fixtureA->fixture->GetShape(), 0);
pB.Set(fixtureB->fixture->GetShape(), 0);
if (!shapeA->isValid() || !shapeB->isValid())
throw love::Exception("The given Shape is not active in the physics World.");
pA.Set(shapeA->fixture->GetShape(), 0);
pB.Set(shapeB->fixture->GetShape(), 0);
i.proxyA = pA;
i.proxyB = pB;
i.transformA = fixtureA->fixture->GetBody()->GetTransform();
i.transformB = fixtureB->fixture->GetBody()->GetTransform();
i.transformA = shapeA->fixture->GetBody()->GetTransform();
i.transformB = shapeB->fixture->GetBody()->GetTransform();
i.useRadii = true;
b2Distance(&o, &c, &i);
});
+23 -36
View File
@@ -23,10 +23,11 @@
// LOVE
#include "common/Module.h"
#include "common/Vector.h"
#include "World.h"
#include "Contact.h"
#include "Body.h"
#include "Fixture.h"
#include "Shape.h"
#include "CircleShape.h"
#include "PolygonShape.h"
@@ -93,10 +94,18 @@ public:
Body *newBody(World *world, Body::Type type);
/**
* Creates a new CircleShape at (0, 0).
* @param radius The radius of the circle.
* Convenience functions for creating a Body and Shape all in one call. The
* body's world position is the center/average of the given coordinates,
* and the shape is centered at the local origin.
**/
CircleShape *newCircleShape(float radius);
Body *newCircleBody(World *world, Body::Type type, float x, float y, float radius);
Body *newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle);
Body *newPolygonBody(World *world, Body::Type type, const Vector2 *coords, int count);
Body *newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided);
Body *newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count);
// Necessary to support the deprecated newFixture API.
Shape *newAttachedShape(Body *body, Shape *prototype, float density);
/**
* Creates a new CircleShape at (x,y) in local coordinates.
@@ -104,25 +113,7 @@ public:
* @param y The offset along the y-axis.
* @param radius The radius of the circle.
**/
CircleShape *newCircleShape(float x, float y, float radius);
/**
* Shorthand for creating rectangular PolygonShapes. The rectangle
* will be created at the local origin.
* @param w The width of the rectangle.
* @param h The height of the rectangle.
**/
PolygonShape *newRectangleShape(float w, float h);
/**
* Shorthand for creating rectangular PolygonShapes. The rectangle
* will be created at (x,y) in local coordinates.
* @param x The offset along the x-axis.
* @param y The offset along the y-axis.
* @param w The width of the rectangle.
* @param h The height of the rectangle.
**/
PolygonShape *newRectangleShape(float x, float y, float w, float h);
CircleShape *newCircleShape(Body *body, float x, float y, float radius);
/**
* Shorthand for creating rectangular PolygonShapes. The rectangle
@@ -133,7 +124,7 @@ public:
* @param h The height of the rectangle.
* @param angle The angle of the rectangle. (rad)
**/
PolygonShape *newRectangleShape(float x, float y, float w, float h, float angle);
PolygonShape *newRectangleShape(Body *body, float x, float y, float w, float h, float angle);
/**
* Creates a new EdgeShape. The edge will be created from
@@ -143,17 +134,17 @@ public:
* @param x2 The x coordinate of the second point.
* @param y2 The y coordinate of the second point.
**/
EdgeShape *newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided);
EdgeShape *newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided);
/**
* Creates a new PolygonShape from a variable number of vertices.
**/
int newPolygonShape(lua_State *L);
PolygonShape *newPolygonShape(Body *body, const Vector2 *coords, int count);
/**
* Creates a new ChainShape from a variable number of vertices.
**/
int newChainShape(lua_State *L);
ChainShape *newChainShape(Body *body, bool loop, const Vector2 *coords, int count);
/**
* Creates a new DistanceJoint connecting body1 with body2.
@@ -273,15 +264,6 @@ public:
MotorJoint *newMotorJoint(Body *body1, Body *body2);
MotorJoint *newMotorJoint(Body *body1, Body *body2, float correctionFactor, bool collideConnected);
/**
* Creates a new Fixture attaching shape to body.
* @param body The body to attach the Fixture to.
* @param shape The shape to attach to the Fixture,
* @param density The density of the Fixture.
**/
Fixture *newFixture(Body *body, Shape *shape, float density);
/**
* Calculates the distance between two Fixtures.
* @param fixtureA The first Fixture.
@@ -403,10 +385,15 @@ public:
**/
static void computeAngularFrequency(float &frequency, float &ratio, float stiffness, float damping, b2Body *bodyA, b2Body *bodyB);
b2BlockAllocator *getBlockAllocator() { return &blockAllocator; }
private:
// The length of one meter in pixels.
static float meter;
b2BlockAllocator blockAllocator;
}; // Physics
} // box2d
+4 -2
View File
@@ -34,8 +34,8 @@ namespace box2d
love::Type PolygonShape::type("PolygonShape", &Shape::type);
PolygonShape::PolygonShape(b2PolygonShape *p, bool own)
: Shape(p, own)
PolygonShape::PolygonShape(Body *body, const b2PolygonShape &p)
: Shape(body, p)
{
}
@@ -45,6 +45,7 @@ PolygonShape::~PolygonShape()
int PolygonShape::getPoints(lua_State *L)
{
throwIfShapeNotValid();
love::luax_assert_argc(L, 0);
b2PolygonShape *p = (b2PolygonShape *)shape;
int count = p->m_count;
@@ -59,6 +60,7 @@ int PolygonShape::getPoints(lua_State *L)
bool PolygonShape::validate() const
{
throwIfShapeNotValid();
b2PolygonShape *p = (b2PolygonShape *)shape;
return p->Validate();
}
+1 -1
View File
@@ -48,7 +48,7 @@ public:
* Create a new PolygonShape from a Box2D polygon definition.
* @param p The polygon definition.
**/
PolygonShape(b2PolygonShape *p, bool own = true);
PolygonShape(Body *body, const b2PolygonShape &p);
virtual ~PolygonShape();
+376 -28
View File
@@ -35,54 +35,357 @@ namespace physics
namespace box2d
{
Shape::Shape()
Shape::Shape(Body *body, const b2Shape &shape)
: shape(nullptr)
, own(false)
, shapeType(SHAPE_INVALID)
, body(body)
, fixture(nullptr)
{
}
if (body)
{
b2FixtureDef def;
def.shape = &shape;
def.userData.pointer = (uintptr_t)this;
Shape::Shape(b2Shape *shape, bool own)
: shape(shape)
, own(own)
{
// 0 density stops CreateFixture from calling b2Body::ResetMassData().
def.density = body->hasCustomMassData() ? 0.0f : 1.0f;
fixture = body->body->CreateFixture(&def);
this->shape = fixture->GetShape();
if (body->hasCustomMassData())
setDensity(1.0f);
retain(); // Shape::destroy does the release().
}
else
{
// Path to support deprecated APIs.
auto physics = Module::getInstance<Physics>(Module::M_PHYSICS);
this->shape = shape.Clone(physics->getBlockAllocator());
own = true;
}
switch (this->shape->GetType())
{
case b2Shape::e_circle:
shapeType = SHAPE_CIRCLE;
break;
case b2Shape::e_polygon:
shapeType = SHAPE_POLYGON;
break;
case b2Shape::e_edge:
shapeType = SHAPE_EDGE;
break;
case b2Shape::e_chain:
shapeType = SHAPE_CHAIN;
break;
default:
shapeType = SHAPE_INVALID;
break;
}
}
Shape::~Shape()
{
if (shape && own)
delete shape;
{
auto physics = Module::getInstance<Physics>(Module::M_PHYSICS);
auto allocator = physics->getBlockAllocator();
// Taken from b2Fixture::Destroy. Not very pretty...
switch (shapeType)
{
case SHAPE_CIRCLE:
{
b2CircleShape *s = (b2CircleShape*)shape;
s->~b2CircleShape();
allocator->Free(s, sizeof(b2CircleShape));
break;
}
case SHAPE_EDGE:
{
b2EdgeShape *s = (b2EdgeShape*)shape;
s->~b2EdgeShape();
allocator->Free(s, sizeof(b2EdgeShape));
break;
}
case SHAPE_POLYGON:
{
b2PolygonShape *s = (b2PolygonShape*)shape;
s->~b2PolygonShape();
allocator->Free(s, sizeof(b2PolygonShape));
break;
}
case SHAPE_CHAIN:
{
b2ChainShape *s = (b2ChainShape*)shape;
s->~b2ChainShape();
allocator->Free(s, sizeof(b2ChainShape));
break;
}
default:
break;
}
}
if (ref)
delete ref;
}
void Shape::destroy(bool implicit)
{
if (fixture == nullptr)
return;
if (body->world->world->IsLocked())
{
// Called during time step. Save reference for destruction afterwards.
this->retain();
body->world->destructShapes.push_back(this);
return;
}
if (!implicit && fixture != nullptr)
body->body->DestroyFixture(fixture);
fixture = nullptr;
shape = nullptr;
body = nullptr;
// Remove userdata reference to avoid it sticking around after GC
if (ref)
ref->unref();
// Box2D fixture destroyed. Release its reference to the love Shape.
release();
}
void Shape::throwIfFixtureNotValid() const
{
if (fixture == nullptr)
throw love::Exception("Shape must be active in the physics World to use this method.");
}
void Shape::throwIfShapeNotValid() const
{
if (shape == nullptr)
throw love::Exception("Cannot call this method on a destroyed Shape.");
}
Shape::Type Shape::getType() const
{
switch (shape->GetType())
{
case b2Shape::e_circle:
return SHAPE_CIRCLE;
case b2Shape::e_polygon:
return SHAPE_POLYGON;
case b2Shape::e_edge:
return SHAPE_EDGE;
case b2Shape::e_chain:
return SHAPE_CHAIN;
default:
return SHAPE_INVALID;
}
return shapeType;
}
void Shape::setFriction(float friction)
{
throwIfFixtureNotValid();
fixture->SetFriction(friction);
}
void Shape::setRestitution(float restitution)
{
throwIfFixtureNotValid();
fixture->SetRestitution(restitution);
}
void Shape::setDensity(float density)
{
throwIfFixtureNotValid();
fixture->SetDensity(density);
if (!body->hasCustomMassData())
body->resetMassData();
}
void Shape::setSensor(bool sensor)
{
throwIfFixtureNotValid();
fixture->SetSensor(sensor);
}
float Shape::getFriction() const
{
throwIfFixtureNotValid();
return fixture->GetFriction();
}
float Shape::getRestitution() const
{
throwIfFixtureNotValid();
return fixture->GetRestitution();
}
float Shape::getDensity() const
{
throwIfFixtureNotValid();
return fixture->GetDensity();
}
bool Shape::isSensor() const
{
throwIfFixtureNotValid();
return fixture->IsSensor();
}
Body *Shape::getBody() const
{
return body;
}
float Shape::getRadius() const
{
throwIfShapeNotValid();
return Physics::scaleUp(shape->m_radius);
}
int Shape::getChildCount() const
{
throwIfShapeNotValid();
return shape->GetChildCount();
}
void Shape::setFilterData(int *v)
{
throwIfFixtureNotValid();
b2Filter f;
f.categoryBits = (uint16) v[0];
f.maskBits = (uint16) v[1];
f.groupIndex = (int16) v[2];
fixture->SetFilterData(f);
}
void Shape::getFilterData(int *v)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
v[0] = (int) f.categoryBits;
v[1] = (int) f.maskBits;
v[2] = (int) f.groupIndex;
}
int Shape::setCategory(lua_State *L)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
f.categoryBits = (uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
int Shape::setMask(lua_State *L)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
f.maskBits = ~(uint16)getBits(L);
fixture->SetFilterData(f);
return 0;
}
void Shape::setGroupIndex(int index)
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
f.groupIndex = (uint16)index;
fixture->SetFilterData(f);
}
int Shape::getGroupIndex() const
{
throwIfFixtureNotValid();
b2Filter f = fixture->GetFilterData();
return f.groupIndex;
}
int Shape::getCategory(lua_State *L)
{
throwIfFixtureNotValid();
return pushBits(L, fixture->GetFilterData().categoryBits);
}
int Shape::getMask(lua_State *L)
{
throwIfFixtureNotValid();
return pushBits(L, ~(fixture->GetFilterData().maskBits));
}
uint16 Shape::getBits(lua_State *L)
{
// Get number of args.
bool istable = lua_istable(L, 1);
int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
// The new bitset.
std::bitset<16> b;
for (int i = 1; i <= argc; i++)
{
size_t bpos = 0;
if (istable)
{
lua_rawgeti(L, 1, i);
bpos = (size_t) (lua_tointeger(L, -1) - 1);
lua_pop(L, 1);
}
else
bpos = (size_t) (lua_tointeger(L, i) - 1);
if (bpos >= 16)
luaL_error(L, "Values must be in range 1-16.");
b.set(bpos, true);
}
return (uint16)b.to_ulong();
}
int Shape::pushBits(lua_State *L, uint16 bits)
{
// Create a bitset.
std::bitset<16> b((int)bits);
// Push all set bits.
for (int i = 0; i<16; i++)
if (b.test(i))
lua_pushinteger(L, i+1);
// Count number of set bits.
return (int)b.count();
}
int Shape::setUserData(lua_State *L)
{
love::luax_assert_argc(L, 1, 1);
if(!ref)
ref = new Reference();
ref->ref(L);
return 0;
}
int Shape::getUserData(lua_State *L)
{
if (ref != nullptr)
ref->push(L);
else
lua_pushnil(L);
return 1;
}
bool Shape::testPoint(float x, float y) const
{
throwIfFixtureNotValid();
return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y)));
}
bool Shape::testPoint(float x, float y, float r, float px, float py) const
{
throwIfShapeNotValid();
b2Vec2 point(px, py);
b2Transform transform(Physics::scaleDown(b2Vec2(x, y)), b2Rot(r));
return shape->TestPoint(transform, Physics::scaleDown(point));
@@ -95,18 +398,34 @@ int Shape::rayCast(lua_State *L) const
float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
float maxFraction = (float)luaL_checknumber(L, 5);
float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
float r = (float)luaL_checknumber(L, 8);
int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
b2RayCastInput input;
b2RayCastOutput output;
input.p1.Set(p1x, p1y);
input.p2.Set(p2x, p2y);
input.maxFraction = maxFraction;
b2Transform transform(b2Vec2(x, y), b2Rot(r));
b2RayCastOutput output;
if (!shape->RayCast(&output, input, transform, childIndex))
return 0; // No hit.
if (lua_isnoneornil(L, 7))
{
throwIfFixtureNotValid();
int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index
if (!fixture->RayCast(&output, input, childIndex))
return 0; // Nothing hit.
}
else
{
throwIfShapeNotValid();
float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
float r = (float)luaL_checknumber(L, 8);
int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
b2Transform transform(b2Vec2(x, y), b2Rot(r));
if (!shape->RayCast(&output, input, transform, childIndex))
return 0; // No hit.
}
lua_pushnumber(L, output.normal.x);
lua_pushnumber(L, output.normal.y);
lua_pushnumber(L, output.fraction);
@@ -115,6 +434,7 @@ int Shape::rayCast(lua_State *L) const
int Shape::computeAABB(lua_State *L) const
{
throwIfShapeNotValid();
float x = Physics::scaleDown((float)luaL_checknumber(L, 1));
float y = Physics::scaleDown((float)luaL_checknumber(L, 2));
float r = (float)luaL_checknumber(L, 3);
@@ -132,6 +452,7 @@ int Shape::computeAABB(lua_State *L) const
int Shape::computeMass(lua_State *L) const
{
throwIfShapeNotValid();
float density = (float)luaL_checknumber(L, 1);
b2MassData data;
shape->ComputeMass(&data, density);
@@ -143,6 +464,33 @@ int Shape::computeMass(lua_State *L) const
return 4;
}
int Shape::getBoundingBox(lua_State *L) const
{
throwIfFixtureNotValid();
int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index
b2AABB box;
luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); });
box = Physics::scaleUp(box);
lua_pushnumber(L, box.lowerBound.x);
lua_pushnumber(L, box.lowerBound.y);
lua_pushnumber(L, box.upperBound.x);
lua_pushnumber(L, box.upperBound.y);
return 4;
}
int Shape::getMassData(lua_State *L) const
{
throwIfFixtureNotValid();
b2MassData data;
fixture->GetMassData(&data);
b2Vec2 center = Physics::scaleUp(data.center);
lua_pushnumber(L, center.x);
lua_pushnumber(L, center.y);
lua_pushnumber(L, data.mass);
lua_pushnumber(L, data.I);
return 4;
}
} // box2d
} // physics
} // love
+127 -5
View File
@@ -24,6 +24,7 @@
// LOVE
#include "physics/Shape.h"
#include "physics/box2d/Body.h"
#include "common/Reference.h"
// Box2D
#include <box2d/Box2D.h>
@@ -45,34 +46,155 @@ class Shape : public love::physics::Shape
{
public:
friend class Fixture;
friend class Physics;
/**
* Creates a Shape.
**/
Shape();
Shape(b2Shape *shape, bool own = true);
Shape(Body *body, const b2Shape &shape);
virtual ~Shape();
void destroy(bool implicit = false);
/**
* Returns true if the shape is active in a Box2D world.
**/
bool isValid() const { return fixture != nullptr; }
/**
* Returns true if the shape has not been destroyed.
**/
bool isShapeValid() const { return shape != nullptr; }
/**
* Checks whether this Shape acts as a sensor.
**/
bool isSensor() const;
/**
* Set whether this Shape should be a sensor or not.
**/
void setSensor(bool sensor);
/**
* Gets the Body this Shape is attached to.
**/
Body *getBody() const;
/**
* Sets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void setFilterData(int *v);
/**
* Gets the filter data. An integer array is used even though the
* first two elements are unsigned shorts. The elements are:
* category (16-bits), mask (16-bits) and group (32-bits/int).
**/
void getFilterData(int *v);
/**
* This function stores an in-C reference to
* arbitrary Lua data in the Shape object.
**/
int setUserData(lua_State *L);
/**
* Gets the data set with setUserData. If no
* data is set, nil is returned.
**/
int getUserData(lua_State *L);
/**
* Sets the friction of the Shape.
**/
void setFriction(float friction);
/**
* Sets the restitution for the Shape.
**/
void setRestitution(float restitution);
/**
* Sets the density of the Shape.
**/
void setDensity(float density);
/**
* Gets the friction of the Shape.
**/
float getFriction() const;
/**
* Gets the restitution of the Shape.
**/
float getRestitution() const;
/**
* Gets the density of the Shape.
**/
float getDensity() const;
/**
* Checks if a point is inside the Shape.
**/
bool testPoint(float x, float y) const;
bool testPoint(float x, float y, float r, float px, float py) const;
/**
* Gets the type of Shape. Useful for
* debug drawing.
**/
Type getType() const;
float getRadius() const;
int getChildCount() const;
bool testPoint(float x, float y, float r, float px, float py) const;
int rayCast(lua_State *L) const;
int computeAABB(lua_State *L) const;
int computeMass(lua_State *L) const;
void setGroupIndex(int index);
int getGroupIndex() const;
int setCategory(lua_State *L);
int setMask(lua_State *L);
int getCategory(lua_State *L);
int getMask(lua_State *L);
uint16 getBits(lua_State *L);
int pushBits(lua_State *L, uint16 bits);
/**
* Gets the bounding box for this Shape.
**/
int getBoundingBox(lua_State *L) const;
/**
* Gets the mass data for this Shape.
* This operation may be expensive.
**/
int getMassData(lua_State *L) const;
void throwIfFixtureNotValid() const;
void throwIfShapeNotValid() const;
protected:
// The Box2D shape.
b2Shape *shape;
bool own;
};
Shape::Type shapeType;
Body *body;
b2Fixture *fixture;
// Reference to arbitrary data.
Reference* ref = nullptr;
}; // Shape
} // box2d
} // physics
+54 -56
View File
@@ -20,7 +20,6 @@
#include "World.h"
#include "Fixture.h"
#include "Shape.h"
#include "Contact.h"
#include "Physics.h"
@@ -28,6 +27,7 @@
// Needed for World::getJoints. It should be moved to wrapper code...
#include "wrap_Joint.h"
#include "wrap_Shape.h"
namespace love
{
@@ -58,22 +58,22 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
{
ref->push(L);
// Push first fixture.
// Push first shape.
{
Fixture *a = (Fixture *)(contact->GetFixtureA()->GetUserData().pointer);
Shape *a = (Shape *)(contact->GetFixtureA()->GetUserData().pointer);
if (a != nullptr)
luax_pushtype(L, a);
luax_pushshape(L, a);
else
throw love::Exception("A fixture has escaped Memoizer!");
throw love::Exception("A Shape has escaped Memoizer!");
}
// Push second fixture.
// Push second shape.
{
Fixture *b = (Fixture *)(contact->GetFixtureB()->GetUserData().pointer);
Shape *b = (Shape *)(contact->GetFixtureB()->GetUserData().pointer);
if (b != nullptr)
luax_pushtype(L, b);
luax_pushshape(L, b);
else
throw love::Exception("A fixture has escaped Memoizer!");
throw love::Exception("A Shape has escaped Memoizer!");
}
Contact *cobj = (Contact *)world->findObject(contact);
@@ -112,32 +112,17 @@ World::ContactFilter::~ContactFilter()
delete ref;
}
bool World::ContactFilter::process(Fixture *a, Fixture *b)
bool World::ContactFilter::process(Shape *a, Shape *b)
{
// Handle masks, reimplemented from the manual
int filterA[3], filterB[3];
// [0] categoryBits
// [1] maskBits
// [2] groupIndex
a->getFilterData(filterA);
b->getFilterData(filterB);
if (filterA[2] != 0 && // 0 is the default group, so this does not count
filterA[2] == filterB[2]) // if they are in the same group
return filterA[2] > 0; // Negative indexes mean you don't collide
if ((filterA[1] & filterB[0]) == 0 ||
(filterB[1] & filterA[0]) == 0)
return false; // A and B aren't set to collide
if (ref != nullptr && L != nullptr)
{
ref->push(L);
luax_pushtype(L, a);
luax_pushtype(L, b);
luax_pushshape(L, a);
luax_pushshape(L, b);
lua_call(L, 2, 1);
return luax_toboolean(L, -1);
}
return true;
}
@@ -159,10 +144,10 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture)
if (L != nullptr)
{
lua_pushvalue(L, funcidx);
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Shape *f = (Shape *)(fixture->GetUserData().pointer);
if (!f)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, f);
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, f);
for (int i = 1; i <= userargs; i++)
lua_pushvalue(L, funcidx + i);
lua_call(L, 1 + userargs, 1);
@@ -191,10 +176,10 @@ bool World::CollectCallback::ReportFixture(b2Fixture *f)
if (categoryMask != 0xFFFF && (categoryMask & f->GetFilterData().categoryBits) == 0)
return true;
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
if (!fixture)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, fixture);
Shape *shape = (Shape *)(f->GetUserData().pointer);
if (!shape)
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, shape);
lua_rawseti(L, -2, i);
i++;
return true;
@@ -218,10 +203,10 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po
if (L != nullptr)
{
lua_pushvalue(L, funcidx);
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Shape *f = (Shape *)(fixture->GetUserData().pointer);
if (!f)
throw love::Exception("A fixture has escaped Memoizer!");
luax_pushtype(L, f);
throw love::Exception("A Shape has escaped Memoizer!");
luax_pushshape(L, f);
b2Vec2 scaledPoint = Physics::scaleUp(point);
lua_pushnumber(L, scaledPoint.x);
lua_pushnumber(L, scaledPoint.y);
@@ -267,9 +252,9 @@ float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2
void World::SayGoodbye(b2Fixture *fixture)
{
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Shape *s = (Shape *)(fixture->GetUserData().pointer);
// Hint implicit destruction with true.
if (f) f->destroy(true);
if (s) s->destroy(true);
}
void World::SayGoodbye(b2Joint *joint)
@@ -336,11 +321,11 @@ void World::update(float dt, int velocityIterations, int positionIterations)
// Release for reference in vector.
b->release();
}
for (Fixture *f : destructFixtures)
for (Shape *s : destructShapes)
{
if (f->isValid()) f->destroy();
if (s->isValid()) s->destroy();
// Release for reference in vector.
f->release();
s->release();
}
for (Joint *j : destructJoints)
{
@@ -349,7 +334,7 @@ void World::update(float dt, int velocityIterations, int positionIterations)
j->release();
}
destructBodies.clear();
destructFixtures.clear();
destructShapes.clear();
destructJoints.clear();
if (destructWorld)
@@ -384,11 +369,24 @@ void World::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse)
bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB)
{
// Fixtures should be memoized, if we created them
Fixture *a = (Fixture *)(fixtureA->GetUserData().pointer);
Fixture *b = (Fixture *)(fixtureB->GetUserData().pointer);
const b2Filter &filterA = fixtureA->GetFilterData();
const b2Filter &filterB = fixtureB->GetFilterData();
// From b2_world_callbacks.cpp
// 0 is the default group index. If they're customized to be the same group,
// allow collisions if it's positive and disallow if it's negative.
if (filterA.groupIndex != 0 && filterA.groupIndex == filterB.groupIndex)
return filterA.groupIndex > 0;
if ((filterA.maskBits & filterB.categoryBits) == 0 || (filterA.categoryBits & filterB.maskBits) == 0)
return false;
// Shapes should be memoized, if we created them
Shape *a = (Shape *)(fixtureA->GetUserData().pointer);
Shape *b = (Shape *)(fixtureB->GetUserData().pointer);
if (!a || !b)
throw love::Exception("A fixture has escaped Memoizer!");
throw love::Exception("A Shape has escaped Memoizer!");
return filter.process(a, b);
}
@@ -597,7 +595,7 @@ b2Body *World::getGroundBody() const
return groundBody;
}
int World::queryFixturesInArea(lua_State *L)
int World::queryShapesInArea(lua_State *L)
{
b2AABB box;
float lx = (float)luaL_checknumber(L, 1);
@@ -612,7 +610,7 @@ int World::queryFixturesInArea(lua_State *L)
return 0;
}
int World::getFixturesInArea(lua_State *L)
int World::getShapesInArea(lua_State *L)
{
float lx = (float)luaL_checknumber(L, 1);
float ly = (float)luaL_checknumber(L, 2);
@@ -654,10 +652,10 @@ int World::rayCastAny(lua_State *L)
world->RayCast(&raycast, v1, v2);
if (raycast.hitFixture)
{
Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer);
Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer);
if (f == nullptr)
return luaL_error(L, "A fixture has escaped Memoizer!");
luax_pushtype(L, f);
return luaL_error(L, "A Shape has escaped Memoizer!");
luax_pushshape(L, f);
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
lua_pushnumber(L, hitPoint.x);
@@ -683,10 +681,10 @@ int World::rayCastClosest(lua_State *L)
world->RayCast(&raycast, v1, v2);
if (raycast.hitFixture)
{
Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer);
Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer);
if (f == nullptr)
return luaL_error(L, "A fixture has escaped Memoizer!");
luax_pushtype(L, f);
return luaL_error(L, "A Shape has escaped Memoizer!");
luax_pushshape(L, f);
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
lua_pushnumber(L, hitPoint.x);
+8 -8
View File
@@ -42,7 +42,7 @@ namespace box2d
class Contact;
class Body;
class Fixture;
class Shape;
class Joint;
/**
@@ -65,7 +65,7 @@ public:
friend class DistanceJoint;
friend class MouseJoint;
friend class Body;
friend class Fixture;
friend class Shape;
static love::Type type;
@@ -87,7 +87,7 @@ public:
lua_State *L;
ContactFilter();
~ContactFilter();
bool process(Fixture *a, Fixture *b);
bool process(Shape *a, Shape *b);
};
class QueryCallback : public b2QueryCallback
@@ -302,14 +302,14 @@ public:
b2Body *getGroundBody() const;
/**
* Calls a callback on all fixtures that overlap a given bounding box.
* Calls a callback on all Shapes that overlap a given bounding box.
**/
int queryFixturesInArea(lua_State *L);
int queryShapesInArea(lua_State *L);
/**
* Gets all fixtures that overlap a given bounding box.
* Gets all Shapes that overlap a given bounding box.
**/
int getFixturesInArea(lua_State *L);
int getShapesInArea(lua_State *L);
/**
* Raycasts the World for all Fixtures in the path of the ray.
@@ -338,7 +338,7 @@ private:
// The list of to be destructed bodies.
std::vector<Body *> destructBodies;
std::vector<Fixture *> destructFixtures;
std::vector<Shape *> destructShapes;
std::vector<Joint *> destructJoints;
bool destructWorld;
+33 -3
View File
@@ -20,6 +20,7 @@
#include "wrap_Body.h"
#include "wrap_Physics.h"
#include "wrap_Shape.h"
namespace love
{
@@ -161,6 +162,13 @@ int w_Body_getMassData(lua_State *L)
return t->getMassData(L);
}
int w_Body_hasCustomMassData(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
luax_pushboolean(L, t->hasCustomMassData());
return 1;
}
int w_Body_getAngularDamping(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
@@ -599,15 +607,32 @@ int w_Body_getWorld(lua_State *L)
return 1;
}
int w_Body_getFixtures(lua_State *L)
int w_Body_getShape(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
Shape *s = t->getShape();
if (s)
luax_pushshape(L, s);
else
lua_pushnil(L);
return 1;
}
int w_Body_getShapes(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
lua_remove(L, 1);
int n = 0;
luax_catchexcept(L, [&](){ n = t->getFixtures(L); });
luax_catchexcept(L, [&](){ n = t->getShapes(L); });
return n;
}
int w_Body_getFixtures(lua_State *L)
{
luax_markdeprecated(L, 1, "Body:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Body:getShapes");
return w_Body_getShapes(L);
}
int w_Body_getJoints(lua_State *L)
{
Body *t = luax_checkbody(L, 1);
@@ -670,6 +695,7 @@ static const luaL_Reg w_Body_functions[] =
{ "getMass", w_Body_getMass },
{ "getInertia", w_Body_getInertia },
{ "getMassData", w_Body_getMassData },
{ "hasCustomMassData", w_Body_hasCustomMassData },
{ "getAngularDamping", w_Body_getAngularDamping },
{ "getLinearDamping", w_Body_getLinearDamping },
{ "getGravityScale", w_Body_getGravityScale },
@@ -713,7 +739,8 @@ static const luaL_Reg w_Body_functions[] =
{ "isFixedRotation", w_Body_isFixedRotation },
{ "isTouching", w_Body_isTouching },
{ "getWorld", w_Body_getWorld },
{ "getFixtures", w_Body_getFixtures },
{ "getShape", w_Body_getShape },
{ "getShapes", w_Body_getShapes },
{ "getJoints", w_Body_getJoints },
{ "getContacts", w_Body_getContacts },
{ "destroy", w_Body_destroy },
@@ -721,6 +748,9 @@ static const luaL_Reg w_Body_functions[] =
{ "setUserData", w_Body_setUserData },
{ "getUserData", w_Body_getUserData },
// Deprecated
{ "getFixtures", w_Body_getFixtures },
{ 0, 0 }
};
+10 -5
View File
@@ -54,9 +54,10 @@ int w_ChainShape_setPreviousVertex(lua_State *L)
int w_ChainShape_getChildEdge(lua_State *L)
{
luax_markdeprecated(L, 1, "ChainShape:getChildEdge", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr);
ChainShape *c = luax_checkchainshape(L, 1);
int index = (int) luaL_checkinteger(L, 2) - 1; // Convert from 1-based index
EdgeShape *e = 0;
EdgeShape *e = nullptr;
luax_catchexcept(L, [&](){ e = c->getChildEdge(index); });
luax_pushtype(L, e);
e->release();
@@ -66,7 +67,8 @@ int w_ChainShape_getChildEdge(lua_State *L)
int w_ChainShape_getVertexCount(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
int count = c->getVertexCount();
int count = 0;
luax_catchexcept(L, [&]() { count = c->getVertexCount(); });
lua_pushinteger(L, count);
return 1;
}
@@ -85,7 +87,8 @@ int w_ChainShape_getPoint(lua_State *L)
int w_ChainShape_getNextVertex(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
b2Vec2 v = c->getNextVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = c->getNextVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -94,7 +97,8 @@ int w_ChainShape_getNextVertex(lua_State *L)
int w_ChainShape_getPreviousVertex(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
b2Vec2 v = c->getPreviousVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = c->getPreviousVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -103,7 +107,8 @@ int w_ChainShape_getPreviousVertex(lua_State *L)
int w_ChainShape_getPoints(lua_State *L)
{
ChainShape *c = luax_checkchainshape(L, 1);
const b2Vec2 *verts = c->getPoints();
const b2Vec2 *verts;
luax_catchexcept(L, [&]() { verts = c->getPoints(); });
int count = c->getVertexCount();
if (!lua_checkstack(L, count*2))
return luaL_error(L, "Too many return values");
@@ -35,7 +35,9 @@ CircleShape *luax_checkcircleshape(lua_State *L, int idx)
int w_CircleShape_getRadius(lua_State *L)
{
CircleShape *c = luax_checkcircleshape(L, 1);
lua_pushnumber(L, c->getRadius());
float r = 0;
luax_catchexcept(L, [&]() { r = c->getRadius(); });
lua_pushnumber(L, r);
return 1;
}
@@ -43,7 +45,7 @@ int w_CircleShape_setRadius(lua_State *L)
{
CircleShape *c = luax_checkcircleshape(L, 1);
float r = (float)luaL_checknumber(L, 2);
c->setRadius(r);
luax_catchexcept(L, [&]() { c->setRadius(r); });
return 0;
}
@@ -51,7 +53,7 @@ int w_CircleShape_getPoint(lua_State *L)
{
CircleShape *c = luax_checkcircleshape(L, 1);
float x, y;
c->getPoint(x, y);
luax_catchexcept(L, [&]() { c->getPoint(x, y); });
lua_pushnumber(L, x);
lua_pushnumber(L, y);
return 2;
+18 -8
View File
@@ -19,7 +19,7 @@
**/
#include "wrap_Contact.h"
#include "Fixture.h"
#include "wrap_Shape.h"
namespace love
{
@@ -139,18 +139,24 @@ int w_Contact_getChildren(lua_State *L)
return 2;
}
int w_Contact_getFixtures(lua_State *L)
int w_Contact_getShapes(lua_State *L)
{
Contact *t = luax_checkcontact(L, 1);
Fixture *a = nullptr;
Fixture *b = nullptr;
luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
Shape *a = nullptr;
Shape *b = nullptr;
luax_catchexcept(L, [&](){ t->getShapes(a, b); });
luax_pushtype(L, a);
luax_pushtype(L, b);
luax_pushshape(L, a);
luax_pushshape(L, b);
return 2;
}
int w_Contact_getFixtures(lua_State *L)
{
luax_markdeprecated(L, 1, "Contact:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Contact:getShapes");
return w_Contact_getShapes(L);
}
int w_Contact_isDestroyed(lua_State *L)
{
Contact *c = luax_checktype<Contact>(L, 1);
@@ -174,8 +180,12 @@ static const luaL_Reg w_Contact_functions[] =
{ "setTangentSpeed", w_Contact_setTangentSpeed },
{ "getTangentSpeed", w_Contact_getTangentSpeed },
{ "getChildren", w_Contact_getChildren },
{ "getFixtures", w_Contact_getFixtures },
{ "getShapes", w_Contact_getShapes },
{ "isDestroyed", w_Contact_isDestroyed },
// Deprecated
{ "getFixtures", w_Contact_getFixtures },
{ 0, 0 }
};
+9 -5
View File
@@ -37,7 +37,7 @@ int w_EdgeShape_setNextVertex(lua_State *L)
EdgeShape *t = luax_checkedgeshape(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
t->setNextVertex(x, y);
luax_catchexcept(L, [&]() { t->setNextVertex(x, y); });
return 0;
}
@@ -46,14 +46,15 @@ int w_EdgeShape_setPreviousVertex(lua_State *L)
EdgeShape *t = luax_checkedgeshape(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
t->setPreviousVertex(x, y);
luax_catchexcept(L, [&]() { t->setPreviousVertex(x, y); });
return 0;
}
int w_EdgeShape_getNextVertex(lua_State *L)
{
EdgeShape *t = luax_checkedgeshape(L, 1);
b2Vec2 v = t->getNextVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = t->getNextVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -62,7 +63,8 @@ int w_EdgeShape_getNextVertex(lua_State *L)
int w_EdgeShape_getPreviousVertex(lua_State *L)
{
EdgeShape *t = luax_checkedgeshape(L, 1);
b2Vec2 v = t->getPreviousVertex();
b2Vec2 v;
luax_catchexcept(L, [&]() { v = t->getPreviousVertex(); });
lua_pushnumber(L, v.x);
lua_pushnumber(L, v.y);
return 2;
@@ -72,7 +74,9 @@ int w_EdgeShape_getPoints(lua_State *L)
{
EdgeShape *t = luax_checkedgeshape(L, 1);
lua_remove(L, 1);
return t->getPoints(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getPoints(L); });
return ret;
}
static const luaL_Reg w_EdgeShape_functions[] =
-311
View File
@@ -1,311 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_Fixture.h"
#include "common/StringMap.h"
namespace love
{
namespace physics
{
namespace box2d
{
Fixture *luax_checkfixture(lua_State *L, int idx)
{
Fixture *f = luax_checktype<Fixture>(L, idx);
if (!f->isValid())
luaL_error(L, "Attempt to use destroyed fixture.");
return f;
}
int w_Fixture_getType(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
const char *type = "";
Shape::getConstant(t->getType(), type);
lua_pushstring(L, type);
return 1;
}
int w_Fixture_setFriction(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
t->setFriction(arg1);
return 0;
}
int w_Fixture_setRestitution(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
t->setRestitution(arg1);
return 0;
}
int w_Fixture_setDensity(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&](){ t->setDensity(arg1); });
return 0;
}
int w_Fixture_setSensor(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
bool arg1 = luax_checkboolean(L, 2);
t->setSensor(arg1);
return 0;
}
int w_Fixture_getFriction(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_pushnumber(L, t->getFriction());
return 1;
}
int w_Fixture_getRestitution(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_pushnumber(L, t->getRestitution());
return 1;
}
int w_Fixture_getDensity(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_pushnumber(L, t->getDensity());
return 1;
}
int w_Fixture_isSensor(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
luax_pushboolean(L, t->isSensor());
return 1;
}
int w_Fixture_getBody(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
Body *body = t->getBody();
if (body == 0)
return 0;
luax_pushtype(L, body);
return 1;
}
int w_Fixture_getShape(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
Shape * shape = t->getShape();
if (shape == nullptr)
return 0;
switch (shape->getType())
{
case Shape::SHAPE_EDGE:
luax_pushtype(L, dynamic_cast<EdgeShape *>(shape));
break;
case Shape::SHAPE_CHAIN:
luax_pushtype(L, dynamic_cast<ChainShape *>(shape));
break;
case Shape::SHAPE_CIRCLE:
luax_pushtype(L, dynamic_cast<CircleShape *>(shape));
break;
case Shape::SHAPE_POLYGON:
luax_pushtype(L, dynamic_cast<PolygonShape *>(shape));
break;
default:
luax_pushtype(L, shape);
break;
}
return 1;
}
int w_Fixture_testPoint(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
luax_pushboolean(L, t->testPoint(x, y));
return 1;
}
int w_Fixture_rayCast(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&](){ ret = t->rayCast(L); });
return ret;
}
int w_Fixture_setFilterData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int v[3];
v[0] = (int) luaL_checkinteger(L, 2);
v[1] = (int) luaL_checkinteger(L, 3);
v[2] = (int) luaL_checkinteger(L, 4);
t->setFilterData(v);
return 0;
}
int w_Fixture_getFilterData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int v[3];
t->getFilterData(v);
lua_pushinteger(L, v[0]);
lua_pushinteger(L, v[1]);
lua_pushinteger(L, v[2]);
return 3;
}
int w_Fixture_setCategory(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->setCategory(L);
}
int w_Fixture_getCategory(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getCategory(L);
}
int w_Fixture_setMask(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->setMask(L);
}
int w_Fixture_getMask(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getMask(L);
}
int w_Fixture_setUserData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->setUserData(L);
}
int w_Fixture_getUserData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getUserData(L);
}
int w_Fixture_getBoundingBox(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getBoundingBox(L);
}
int w_Fixture_getMassData(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
lua_remove(L, 1);
return t->getMassData(L);
}
int w_Fixture_getGroupIndex(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int i = t->getGroupIndex();
lua_pushinteger(L, i);
return 1;
}
int w_Fixture_setGroupIndex(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
int i = (int) luaL_checkinteger(L, 2);
t->setGroupIndex(i);
return 0;
}
int w_Fixture_destroy(lua_State *L)
{
Fixture *t = luax_checkfixture(L, 1);
luax_catchexcept(L, [&](){ t->destroy(); });
return 0;
}
int w_Fixture_isDestroyed(lua_State *L)
{
Fixture *f = luax_checktype<Fixture>(L, 1);
luax_pushboolean(L, !f->isValid());
return 1;
}
static const luaL_Reg w_Fixture_functions[] =
{
{ "getType", w_Fixture_getType },
{ "setFriction", w_Fixture_setFriction },
{ "setRestitution", w_Fixture_setRestitution },
{ "setDensity", w_Fixture_setDensity },
{ "setSensor", w_Fixture_setSensor },
{ "getFriction", w_Fixture_getFriction },
{ "getRestitution", w_Fixture_getRestitution },
{ "getDensity", w_Fixture_getDensity },
{ "getBody", w_Fixture_getBody },
{ "getShape", w_Fixture_getShape },
{ "isSensor", w_Fixture_isSensor },
{ "testPoint", w_Fixture_testPoint },
{ "rayCast", w_Fixture_rayCast },
{ "setFilterData", w_Fixture_setFilterData },
{ "getFilterData", w_Fixture_getFilterData },
{ "setCategory", w_Fixture_setCategory },
{ "getCategory", w_Fixture_getCategory },
{ "setMask", w_Fixture_setMask },
{ "getMask", w_Fixture_getMask },
{ "setUserData", w_Fixture_setUserData },
{ "getUserData", w_Fixture_getUserData },
{ "getBoundingBox", w_Fixture_getBoundingBox },
{ "getMassData", w_Fixture_getMassData },
{ "getGroupIndex", w_Fixture_getGroupIndex },
{ "setGroupIndex", w_Fixture_setGroupIndex },
{ "destroy", w_Fixture_destroy },
{ "isDestroyed", w_Fixture_isDestroyed },
{ 0, 0 }
};
extern "C" int luaopen_fixture(lua_State *L)
{
return luax_register_type(L, &Fixture::type, w_Fixture_functions, nullptr);
}
} // box2d
} // physics
} // love
-43
View File
@@ -1,43 +0,0 @@
/**
* Copyright (c) 2006-2023 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#ifndef LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
#define LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
// LOVE
#include "common/runtime.h"
#include "Fixture.h"
#include "wrap_Physics.h"
namespace love
{
namespace physics
{
namespace box2d
{
Fixture *luax_checkfixture(lua_State *L, int idx);
extern "C" int luaopen_fixture(lua_State *L);
} // box2d
} // physics
} // love
#endif // LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
+316 -36
View File
@@ -23,7 +23,6 @@
#include "wrap_World.h"
#include "wrap_Contact.h"
#include "wrap_Body.h"
#include "wrap_Fixture.h"
#include "wrap_Shape.h"
#include "wrap_CircleShape.h"
#include "wrap_PolygonShape.h"
@@ -83,38 +82,225 @@ int w_newBody(lua_State *L)
return 1;
}
int w_newCircleBody(lua_State *L)
{
World *world = luax_checkworld(L, 1);
const char *typestr = luaL_checkstring(L, 2);
Body::Type btype = Body::BODY_STATIC;
if (!Body::getConstant(typestr, btype))
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
float x = (float)luaL_checknumber(L, 3);
float y = (float)luaL_checknumber(L, 4);
float radius = (float)luaL_checknumber(L, 5);
Body *body = nullptr;
luax_catchexcept(L, [&]() { body = instance()->newCircleBody(world, btype, x, y, radius); });
luax_pushtype(L, body);
body->release();
return 1;
}
int w_newRectangleBody(lua_State *L)
{
World *world = luax_checkworld(L, 1);
const char *typestr = luaL_checkstring(L, 2);
Body::Type btype = Body::BODY_STATIC;
if (!Body::getConstant(typestr, btype))
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
float x = (float)luaL_checknumber(L, 3);
float y = (float)luaL_checknumber(L, 4);
float w = (float)luaL_checknumber(L, 5);
float h = (float)luaL_checknumber(L, 6);
float angle = (float)luaL_optnumber(L, 7, 0.0);
Body *body = nullptr;
luax_catchexcept(L, [&]() { body = instance()->newRectangleBody(world, btype, x, y, w, h, angle); });
luax_pushtype(L, body);
body->release();
return 1;
}
int w_newPolygonBody(lua_State *L)
{
World *world = luax_checkworld(L, 1);
const char *typestr = luaL_checkstring(L, 2);
Body::Type btype = Body::BODY_STATIC;
if (!Body::getConstant(typestr, btype))
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
int argc = lua_gettop(L);
bool istable = lua_istable(L, 3);
if (istable)
argc = (int)luax_objlen(L, 3);
if (argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = argc / 2;
std::vector<Vector2> coords;
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, 3, 1 + i * 2);
lua_rawgeti(L, 3, 2 + i * 2);
float x = (float)luaL_checknumber(L, -2);
float y = (float)luaL_checknumber(L, -1);
coords.emplace_back(x, y);
lua_pop(L, 2);
}
}
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 3 + i * 2);
float y = (float)luaL_checknumber(L, 4 + i * 2);
coords.emplace_back(x, y);
}
}
Body *body = nullptr;
luax_catchexcept(L, [&]() { body = instance()->newPolygonBody(world, btype, coords.data(), (int)coords.size()); });
luax_pushtype(L, body);
body->release();
return 1;
}
int w_newEdgeBody(lua_State *L)
{
World *world = luax_checkworld(L, 1);
const char *typestr = luaL_checkstring(L, 2);
Body::Type btype = Body::BODY_STATIC;
if (!Body::getConstant(typestr, btype))
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
float x1 = (float)luaL_checknumber(L, 3);
float y1 = (float)luaL_checknumber(L, 4);
float x2 = (float)luaL_checknumber(L, 5);
float y2 = (float)luaL_checknumber(L, 6);
bool oneSided = luax_optboolean(L, 7, false);
Body *body = nullptr;
luax_catchexcept(L, [&]() { body = instance()->newEdgeBody(world, btype, x1, y1, x2, y2, oneSided); });
luax_pushtype(L, body);
body->release();
return 1;
}
int w_newChainBody(lua_State *L)
{
World *world = luax_checkworld(L, 1);
const char *typestr = luaL_checkstring(L, 2);
Body::Type btype = Body::BODY_STATIC;
if (!Body::getConstant(typestr, btype))
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
bool loop = luax_checkboolean(L, 3);
int argc = lua_gettop(L) - 3;
bool istable = lua_istable(L, 4);
if (istable)
argc = (int)luax_objlen(L, 4);
if (argc == 0 || argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = argc / 2;
std::vector<Vector2> coords;
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, 4, 1 + i * 2);
lua_rawgeti(L, 4, 2 + i * 2);
float x = (float)lua_tonumber(L, -2);
float y = (float)lua_tonumber(L, -1);
coords.emplace_back(x, y);
lua_pop(L, 2);
}
}
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 4 + i * 2);
float y = (float)luaL_checknumber(L, 5 + i * 2);
coords.emplace_back(x, y);
}
}
Body *body = nullptr;
luax_catchexcept(L, [&]() { body = instance()->newChainBody(world, btype, loop, coords.data(), (int)coords.size()); });
luax_pushtype(L, body);
body->release();
return 1;
}
int w_newFixture(lua_State *L)
{
luax_markdeprecated(L, 1, "love.physics.newFixture", API_FUNCTION, DEPRECATED_REPLACED, "love.physics.newCircle/Rectangle/Polygon/Edge/ChainShape");
Body *body = luax_checkbody(L, 1);
Shape *shape = luax_checkshape(L, 2);
float density = (float)luaL_optnumber(L, 3, 1.0f);
Fixture *fixture;
luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); });
luax_pushtype(L, fixture);
fixture->release();
Shape *newShape;
luax_catchexcept(L, [&]() { newShape = instance()->newAttachedShape(body, shape, density); });
luax_pushshape(L, newShape);
newShape->release();
return 1;
}
static Body *luax_optbodyforshape(lua_State *L, int idx, const char *name)
{
if (lua_isnoneornil(L, idx) || luax_istype(L, idx, Object::type))
return luax_checkbody(L, idx);
luax_markdeprecated(L, 1, name, API_FUNCTION_VARIANT, DEPRECATED_REPLACED, "variant with Body parameter");
return nullptr;
}
int w_newCircleShape(lua_State *L)
{
int top = lua_gettop(L);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newCircleShape");
int bodyidx = body ? 1 : 0;
int top = lua_gettop(L) - bodyidx;
if (top == 1)
{
float radius = (float)luaL_checknumber(L, 1);
float radius = (float)luaL_checknumber(L, bodyidx + 1);
CircleShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(radius); });
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, 0, 0, radius); });
luax_pushtype(L, shape);
shape->release();
return 1;
}
else if (top == 3)
{
float x = (float)luaL_checknumber(L, 1);
float y = (float)luaL_checknumber(L, 2);
float radius = (float)luaL_checknumber(L, 3);
float x = (float)luaL_checknumber(L, bodyidx + 1);
float y = (float)luaL_checknumber(L, bodyidx + 2);
float radius = (float)luaL_checknumber(L, bodyidx + 3);
CircleShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); });
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, x, y, radius); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -125,27 +311,30 @@ int w_newCircleShape(lua_State *L)
int w_newRectangleShape(lua_State *L)
{
int top = lua_gettop(L);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newRectangleShape");
int bodyidx = body ? 1 : 0;
int top = lua_gettop(L) - bodyidx;
if (top == 2)
{
float w = (float)luaL_checknumber(L, 1);
float h = (float)luaL_checknumber(L, 2);
float w = (float)luaL_checknumber(L, bodyidx + 1);
float h = (float)luaL_checknumber(L, bodyidx + 2);
PolygonShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(w, h); });
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, 0, 0, w, h, 0); });
luax_pushtype(L, shape);
shape->release();
return 1;
}
else if (top == 4 || top == 5)
{
float x = (float)luaL_checknumber(L, 1);
float y = (float)luaL_checknumber(L, 2);
float w = (float)luaL_checknumber(L, 3);
float h = (float)luaL_checknumber(L, 4);
float angle = (float)luaL_optnumber(L, 5, 0);
float x = (float)luaL_checknumber(L, bodyidx + 1);
float y = (float)luaL_checknumber(L, bodyidx + 2);
float w = (float)luaL_checknumber(L, bodyidx + 3);
float h = (float)luaL_checknumber(L, bodyidx + 4);
float angle = (float)luaL_optnumber(L, bodyidx + 5, 0);
PolygonShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); });
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, x, y, w, h, angle); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -156,13 +345,16 @@ int w_newRectangleShape(lua_State *L)
int w_newEdgeShape(lua_State *L)
{
float x1 = (float)luaL_checknumber(L, 1);
float y1 = (float)luaL_checknumber(L, 2);
float x2 = (float)luaL_checknumber(L, 3);
float y2 = (float)luaL_checknumber(L, 4);
bool oneSided = luax_optboolean(L, 5, false);
Body *body = luax_optbodyforshape(L, 1, "love.physics.newEdgeShape");
int bodyidx = body ? 1 : 0;
float x1 = (float)luaL_checknumber(L, bodyidx + 1);
float y1 = (float)luaL_checknumber(L, bodyidx + 2);
float x2 = (float)luaL_checknumber(L, bodyidx + 3);
float y2 = (float)luaL_checknumber(L, bodyidx + 4);
bool oneSided = luax_optboolean(L, bodyidx + 5, false);
EdgeShape *shape;
luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2, oneSided); });
luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(body, x1, y1, x2, y2, oneSided); });
luax_pushtype(L, shape);
shape->release();
return 1;
@@ -170,16 +362,97 @@ int w_newEdgeShape(lua_State *L)
int w_newPolygonShape(lua_State *L)
{
int ret = 0;
luax_catchexcept(L, [&](){ ret = instance()->newPolygonShape(L); });
return ret;
Body *body = luax_optbodyforshape(L, 1, "love.physics.newPolygonShape");
int bodyidx = body ? 1 : 0;
int argc = lua_gettop(L) - bodyidx;
bool istable = lua_istable(L, bodyidx + 1);
if (istable)
argc = (int)luax_objlen(L, bodyidx + 1);
if (argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = argc / 2;
std::vector<Vector2> coords;
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, bodyidx + 1, 1 + i * 2);
lua_rawgeti(L, bodyidx + 1, 2 + i * 2);
float x = (float)luaL_checknumber(L, -2);
float y = (float)luaL_checknumber(L, -1);
coords.emplace_back(x, y);
lua_pop(L, 2);
}
}
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, bodyidx + 1 + i * 2);
float y = (float)luaL_checknumber(L, bodyidx + 2 + i * 2);
coords.emplace_back(x, y);
}
}
PolygonShape *shape = nullptr;
luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(body, coords.data(), (int)coords.size()); });
luax_pushtype(L, shape);
shape->release();
return 1;
}
int w_newChainShape(lua_State *L)
{
int ret = 0;
luax_catchexcept(L, [&](){ ret = instance()->newChainShape(L); });
return ret;
Body *body = luax_optbodyforshape(L, 1, "love.physics.newChainShape");
int bodyidx = body ? 1 : 0;
int argc = lua_gettop(L) - 1 - bodyidx; // first argument is looping
bool istable = lua_istable(L, bodyidx + 2);
if (istable)
argc = (int)luax_objlen(L, bodyidx + 2);
if (argc == 0 || argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = argc / 2;
bool loop = luax_checkboolean(L, bodyidx + 1);
std::vector<Vector2> coords;
if (istable)
{
for (int i = 0; i < vcount; i++)
{
lua_rawgeti(L, bodyidx + 2, 1 + i * 2);
lua_rawgeti(L, bodyidx + 2, 2 + i * 2);
float x = (float)lua_tonumber(L, -2);
float y = (float)lua_tonumber(L, -1);
coords.emplace_back(x, y);
lua_pop(L, 2);
}
}
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, bodyidx + 2 + i * 2);
float y = (float)luaL_checknumber(L, bodyidx + 3 + i * 2);
coords.emplace_back(x, y);
}
}
ChainShape *shape = nullptr;
luax_catchexcept(L, [&]() { shape = instance()->newChainShape(body, loop, coords.data(), coords.size()); });
luax_pushtype(L, shape);
shape->release();
return 1;
}
int w_newDistanceJoint(lua_State *L)
@@ -573,7 +846,11 @@ static const luaL_Reg functions[] =
{
{ "newWorld", w_newWorld },
{ "newBody", w_newBody },
{ "newFixture", w_newFixture },
{ "newCircleBody", w_newCircleBody },
{ "newRectangleBody", w_newRectangleBody },
{ "newPolygonBody", w_newPolygonBody },
{ "newEdgeBody", w_newEdgeBody },
{ "newChainBody", w_newChainBody },
{ "newCircleShape", w_newCircleShape },
{ "newRectangleShape", w_newRectangleShape },
{ "newPolygonShape", w_newPolygonShape },
@@ -597,6 +874,10 @@ static const luaL_Reg functions[] =
{ "computeLinearFrequency", w_computeLinearFrequency },
{ "computeAngularStiffness", w_computeAngularStiffness },
{ "computeAngularFrequency", w_computeAngularFrequency },
// Deprecated
{ "newFixture", w_newFixture },
{ 0, 0 },
};
@@ -605,7 +886,6 @@ static const lua_CFunction types[] =
luaopen_world,
luaopen_contact,
luaopen_body,
luaopen_fixture,
luaopen_shape,
luaopen_circleshape,
luaopen_polygonshape,
@@ -36,13 +36,17 @@ int w_PolygonShape_getPoints(lua_State *L)
{
PolygonShape *t = luax_checkpolygonshape(L, 1);
lua_remove(L, 1);
return t->getPoints(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getPoints(L); });
return ret;
}
int w_PolygonShape_validate(lua_State *L)
{
PolygonShape *t = luax_checkpolygonshape(L, 1);
luax_pushboolean(L, t->validate());
bool valid = false;
luax_catchexcept(L, [&]() { valid = t->validate(); });
luax_pushboolean(L, valid);
return 1;
}
+285 -8
View File
@@ -33,6 +33,35 @@ Shape *luax_checkshape(lua_State *L, int idx)
return luax_checktype<Shape>(L, idx);
}
void luax_pushshape(lua_State *L, Shape *shape)
{
if (shape != nullptr)
{
switch (shape->getType())
{
case Shape::SHAPE_CIRCLE:
luax_pushtype(L, (CircleShape *) shape);
break;
case Shape::SHAPE_POLYGON:
luax_pushtype(L, (PolygonShape *) shape);
break;
case Shape::SHAPE_EDGE:
luax_pushtype(L, (EdgeShape *) shape);
break;
case Shape::SHAPE_CHAIN:
luax_pushtype(L, (ChainShape *) shape);
break;
default:
luax_pushtype(L, shape);
break;
}
}
else
{
lua_pushnil(L);
}
}
int w_Shape_getType(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
@@ -45,7 +74,8 @@ int w_Shape_getType(lua_State *L)
int w_Shape_getRadius(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float radius = t->getRadius();
float radius = 0;
luax_catchexcept(L, [&]() { radius = t->getRadius(); });
lua_pushnumber(L, radius);
return 1;
}
@@ -53,20 +83,115 @@ int w_Shape_getRadius(lua_State *L)
int w_Shape_getChildCount(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int childCount = t->getChildCount();
int childCount = 0;
luax_catchexcept(L, [&]() { childCount = t->getChildCount(); });
lua_pushinteger(L, childCount);
return 1;
}
int w_Shape_setFriction(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&]() { t->setFriction(arg1); });
return 0;
}
int w_Shape_setRestitution(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&]() { t->setRestitution(arg1); });
return 0;
}
int w_Shape_setDensity(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
luax_catchexcept(L, [&](){ t->setDensity(arg1); });
return 0;
}
int w_Shape_setSensor(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
bool arg1 = luax_checkboolean(L, 2);
luax_catchexcept(L, [&]() { t->setSensor(arg1); });
return 0;
}
int w_Shape_getFriction(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float friction = 0;
luax_catchexcept(L, [&]() { friction = t->getFriction(); });
lua_pushnumber(L, friction);
return 1;
}
int w_Shape_getRestitution(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float r = 0;
luax_catchexcept(L, [&]() { r = t->getRestitution(); });
lua_pushnumber(L, r);
return 1;
}
int w_Shape_getDensity(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float d = 0;
luax_catchexcept(L, [&]() { d = t->getDensity(); });
lua_pushnumber(L, d);
return 1;
}
int w_Shape_isSensor(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
bool sensor = false;
luax_catchexcept(L, [&]() { sensor = t->isSensor(); });
luax_pushboolean(L, sensor);
return 1;
}
int w_Shape_getBody(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
Body *body = t->getBody();
if (body == nullptr)
return 0;
luax_pushtype(L, body);
return 1;
}
int w_Shape_getShape(lua_State *L)
{
luax_markdeprecated(L, 1, "Fixture:getShape", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr);
Shape *t = luax_checkshape(L, 1);
luax_pushshape(L, t);
return 1;
}
int w_Shape_testPoint(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
float r = (float)luaL_checknumber(L, 4);
float px = (float)luaL_checknumber(L, 5);
float py = (float)luaL_checknumber(L, 6);
bool result = t->testPoint(x, y, r, px, py);
bool result = false;
if (!lua_isnoneornil(L, 4))
{
float r = (float)luaL_checknumber(L, 4);
float px = (float)luaL_checknumber(L, 5);
float py = (float)luaL_checknumber(L, 6);
result = luax_catchexcept(L, [&]() { t->testPoint(x, y, r, px, py); });
}
else
{
result = luax_catchexcept(L, [&]() { t->testPoint(x, y); });
}
lua_pushboolean(L, result);
return 1;
}
@@ -84,14 +209,143 @@ int w_Shape_computeAABB(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
return t->computeAABB(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->computeAABB(L); });
return ret;
}
int w_Shape_computeMass(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
return t->computeMass(L);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->computeMass(L); });
return ret;
}
int w_Shape_setFilterData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int v[3];
v[0] = (int) luaL_checkinteger(L, 2);
v[1] = (int) luaL_checkinteger(L, 3);
v[2] = (int) luaL_checkinteger(L, 4);
luax_catchexcept(L, [&]() { t->setFilterData(v); });
return 0;
}
int w_Shape_getFilterData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int v[3];
luax_catchexcept(L, [&]() { t->getFilterData(v); });
lua_pushinteger(L, v[0]);
lua_pushinteger(L, v[1]);
lua_pushinteger(L, v[2]);
return 3;
}
int w_Shape_setCategory(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->setCategory(L); });
return ret;
}
int w_Shape_getCategory(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getCategory(L); });
return ret;
}
int w_Shape_setMask(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->setMask(L); });
return ret;
}
int w_Shape_getMask(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getMask(L); });
return ret;
}
int w_Shape_setUserData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->setUserData(L); });
return ret;
}
int w_Shape_getUserData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getUserData(L); });
return ret;
}
int w_Shape_getBoundingBox(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getBoundingBox(L); });
return ret;
}
int w_Shape_getMassData(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->getMassData(L); });
return ret;
}
int w_Shape_getGroupIndex(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int i = 0;
luax_catchexcept(L, [&]() { i = t->getGroupIndex(); });
lua_pushinteger(L, i);
return 1;
}
int w_Shape_setGroupIndex(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
int i = (int) luaL_checkinteger(L, 2);
luax_catchexcept(L, [&]() { t->setGroupIndex(i); });
return 0;
}
int w_Shape_destroy(lua_State *L)
{
Shape *t = luax_checkshape(L, 1);
luax_catchexcept(L, [&](){ t->destroy(); });
return 0;
}
int w_Shape_isDestroyed(lua_State *L)
{
Shape *f = luax_checktype<Shape>(L, 1);
luax_pushboolean(L, !f->isValid());
return 1;
}
const luaL_Reg w_Shape_functions[] =
@@ -99,10 +353,33 @@ const luaL_Reg w_Shape_functions[] =
{ "getType", w_Shape_getType },
{ "getRadius", w_Shape_getRadius },
{ "getChildCount", w_Shape_getChildCount },
{ "setFriction", w_Shape_setFriction },
{ "setRestitution", w_Shape_setRestitution },
{ "setDensity", w_Shape_setDensity },
{ "setSensor", w_Shape_setSensor },
{ "getFriction", w_Shape_getFriction },
{ "getRestitution", w_Shape_getRestitution },
{ "getDensity", w_Shape_getDensity },
{ "getBody", w_Shape_getBody },
{ "isSensor", w_Shape_isSensor },
{ "testPoint", w_Shape_testPoint },
{ "rayCast", w_Shape_rayCast },
{ "computeAABB", w_Shape_computeAABB },
{ "computeMass", w_Shape_computeMass },
{ "setFilterData", w_Shape_setFilterData },
{ "getFilterData", w_Shape_getFilterData },
{ "setCategory", w_Shape_setCategory },
{ "getCategory", w_Shape_getCategory },
{ "setMask", w_Shape_setMask },
{ "getMask", w_Shape_getMask },
{ "setUserData", w_Shape_setUserData },
{ "getUserData", w_Shape_getUserData },
{ "getBoundingBox", w_Shape_getBoundingBox },
{ "getMassData", w_Shape_getMassData },
{ "getGroupIndex", w_Shape_getGroupIndex },
{ "setGroupIndex", w_Shape_setGroupIndex },
{ "destroy", w_Shape_destroy },
{ "isDestroyed", w_Shape_isDestroyed },
{ 0, 0 }
};

Some files were not shown because too many files have changed in this diff Show More