From f12596dd193072bc7dff865c0609af9fc98149fe Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Fri, 30 Dec 2016 18:36:54 -0400 Subject: [PATCH] More code restructuring. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move all love.graphics functionality that doesn’t call OpenGL out of the OpenGL backend Graphics class. --HG-- branch : minor --- CMakeLists.txt | 12 +- .../xcode/liblove.xcodeproj/project.pbxproj | 58 +- src/modules/graphics/Canvas.cpp | 52 ++ src/modules/graphics/Canvas.h | 65 ++ src/modules/graphics/Font.h | 3 +- src/modules/graphics/Graphics.cpp | 500 ++++++++++++- src/modules/graphics/Graphics.h | 312 ++++++++- src/modules/graphics/Shader.cpp | 145 ++++ src/modules/graphics/Shader.h | 184 +++++ src/modules/graphics/Texture.cpp | 15 +- src/modules/graphics/Texture.h | 11 +- src/modules/graphics/opengl/Canvas.cpp | 30 +- src/modules/graphics/opengl/Canvas.h | 40 +- src/modules/graphics/opengl/Font.h | 3 +- src/modules/graphics/opengl/GLBuffer.cpp | 14 +- src/modules/graphics/opengl/GLBuffer.h | 11 +- src/modules/graphics/opengl/Graphics.cpp | 658 +++--------------- src/modules/graphics/opengl/Graphics.h | 361 ++-------- src/modules/graphics/opengl/Image.cpp | 23 - src/modules/graphics/opengl/Image.h | 8 - src/modules/graphics/opengl/Mesh.cpp | 48 +- src/modules/graphics/opengl/Mesh.h | 26 +- src/modules/graphics/opengl/OpenGL.cpp | 17 +- src/modules/graphics/opengl/OpenGL.h | 20 +- src/modules/graphics/opengl/Shader.cpp | 126 +--- src/modules/graphics/opengl/Shader.h | 159 +---- src/modules/graphics/opengl/SpriteBatch.cpp | 5 +- src/modules/graphics/opengl/SpriteBatch.h | 2 +- src/modules/graphics/opengl/Text.cpp | 2 +- src/modules/graphics/opengl/Video.cpp | 6 +- src/modules/graphics/opengl/wrap_Graphics.cpp | 36 +- src/modules/graphics/opengl/wrap_Graphics.h | 4 +- src/modules/graphics/vertex.cpp | 20 + src/modules/graphics/vertex.h | 31 + .../graphics/{opengl => }/wrap_Canvas.cpp | 3 - .../graphics/{opengl => }/wrap_Canvas.h | 10 +- .../graphics/{opengl => }/wrap_Shader.cpp | 6 +- .../graphics/{opengl => }/wrap_Shader.h | 8 +- 38 files changed, 1603 insertions(+), 1431 deletions(-) create mode 100644 src/modules/graphics/Canvas.cpp create mode 100644 src/modules/graphics/Canvas.h create mode 100644 src/modules/graphics/Shader.cpp create mode 100644 src/modules/graphics/Shader.h rename src/modules/graphics/{opengl => }/wrap_Canvas.cpp (99%) rename src/modules/graphics/{opengl => }/wrap_Canvas.h (85%) rename src/modules/graphics/{opengl => }/wrap_Shader.cpp (99%) rename src/modules/graphics/{opengl => }/wrap_Shader.h (90%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8d6b9c5d..9efce114f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,6 +465,8 @@ source_group("modules\\font\\freetype" FILES ${LOVE_SRC_MODULE_FONT_FREETYPE}) # set(LOVE_SRC_MODULE_GRAPHICS_ROOT + src/modules/graphics/Canvas.cpp + src/modules/graphics/Canvas.h src/modules/graphics/Color.h src/modules/graphics/Drawable.cpp src/modules/graphics/Drawable.h @@ -478,6 +480,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT src/modules/graphics/Polyline.h src/modules/graphics/Quad.cpp src/modules/graphics/Quad.h + src/modules/graphics/Shader.cpp + src/modules/graphics/Shader.h src/modules/graphics/StreamBuffer.cpp src/modules/graphics/StreamBuffer.h src/modules/graphics/Texture.cpp @@ -486,10 +490,14 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT src/modules/graphics/vertex.h src/modules/graphics/Volatile.cpp src/modules/graphics/Volatile.h + src/modules/graphics/wrap_Canvas.cpp + src/modules/graphics/wrap_Canvas.h src/modules/graphics/wrap_Font.cpp src/modules/graphics/wrap_Font.h src/modules/graphics/wrap_Quad.cpp src/modules/graphics/wrap_Quad.h + src/modules/graphics/wrap_Shader.cpp + src/modules/graphics/wrap_Shader.h src/modules/graphics/wrap_Texture.cpp src/modules/graphics/wrap_Texture.h ) @@ -519,8 +527,6 @@ set(LOVE_SRC_MODULE_GRAPHICS_OPENGL src/modules/graphics/opengl/Text.h src/modules/graphics/opengl/Video.cpp src/modules/graphics/opengl/Video.h - src/modules/graphics/opengl/wrap_Canvas.cpp - src/modules/graphics/opengl/wrap_Canvas.h src/modules/graphics/opengl/wrap_Graphics.cpp src/modules/graphics/opengl/wrap_Graphics.h src/modules/graphics/opengl/wrap_Image.cpp @@ -529,8 +535,6 @@ set(LOVE_SRC_MODULE_GRAPHICS_OPENGL src/modules/graphics/opengl/wrap_Mesh.h src/modules/graphics/opengl/wrap_ParticleSystem.cpp src/modules/graphics/opengl/wrap_ParticleSystem.h - src/modules/graphics/opengl/wrap_Shader.cpp - src/modules/graphics/opengl/wrap_Shader.h src/modules/graphics/opengl/wrap_SpriteBatch.cpp src/modules/graphics/opengl/wrap_SpriteBatch.h src/modules/graphics/opengl/wrap_Text.cpp diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index b8de5df40..c17790d2e 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -456,9 +456,6 @@ FA0B7D551A95902C000E1D17 /* GLBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */; }; FA0B7D561A95902C000E1D17 /* GLBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */; }; FA0B7D571A95902C000E1D17 /* GLBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BA51A95902C000E1D17 /* GLBuffer.h */; }; - FA0B7D581A95902C000E1D17 /* wrap_Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA61A95902C000E1D17 /* wrap_Canvas.cpp */; }; - FA0B7D591A95902C000E1D17 /* wrap_Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BA61A95902C000E1D17 /* wrap_Canvas.cpp */; }; - FA0B7D5A1A95902C000E1D17 /* wrap_Canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BA71A95902C000E1D17 /* wrap_Canvas.h */; }; FA0B7D5E1A95902C000E1D17 /* wrap_Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */; }; FA0B7D5F1A95902C000E1D17 /* wrap_Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */; }; FA0B7D601A95902C000E1D17 /* wrap_Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */; }; @@ -471,9 +468,6 @@ FA0B7D671A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */; }; FA0B7D681A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */; }; FA0B7D691A95902C000E1D17 /* wrap_ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BB11A95902C000E1D17 /* wrap_ParticleSystem.h */; }; - FA0B7D6D1A95902C000E1D17 /* wrap_Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB41A95902C000E1D17 /* wrap_Shader.cpp */; }; - FA0B7D6E1A95902C000E1D17 /* wrap_Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB41A95902C000E1D17 /* wrap_Shader.cpp */; }; - FA0B7D6F1A95902C000E1D17 /* wrap_Shader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BB51A95902C000E1D17 /* wrap_Shader.h */; }; FA0B7D701A95902C000E1D17 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */; }; FA0B7D711A95902C000E1D17 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */; }; FA0B7D721A95902C000E1D17 /* wrap_SpriteBatch.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BB71A95902C000E1D17 /* wrap_SpriteBatch.h */; }; @@ -851,6 +845,17 @@ FA1BA0A21E16D97500AA2803 /* wrap_Font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0A01E16D97500AA2803 /* wrap_Font.cpp */; }; FA1BA0A31E16D97500AA2803 /* wrap_Font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0A01E16D97500AA2803 /* wrap_Font.cpp */; }; FA1BA0A41E16D97500AA2803 /* wrap_Font.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0A11E16D97500AA2803 /* wrap_Font.h */; }; + FA1BA0A71E16F20600AA2803 /* Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0A51E16F20600AA2803 /* Canvas.cpp */; }; + FA1BA0A81E16F20600AA2803 /* Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0A51E16F20600AA2803 /* Canvas.cpp */; }; + FA1BA0A91E16F20600AA2803 /* Canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0A61E16F20600AA2803 /* Canvas.h */; }; + FA1BA0AC1E16F9EE00AA2803 /* wrap_Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0AA1E16F9EE00AA2803 /* wrap_Canvas.cpp */; }; + FA1BA0AD1E16F9EE00AA2803 /* wrap_Canvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0AA1E16F9EE00AA2803 /* wrap_Canvas.cpp */; }; + FA1BA0AE1E16F9EE00AA2803 /* wrap_Canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0AB1E16F9EE00AA2803 /* wrap_Canvas.h */; }; + FA1BA0B11E16FD0800AA2803 /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */; }; + FA1BA0B21E16FD0800AA2803 /* Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */; }; + FA1BA0B31E16FD0800AA2803 /* Shader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0B01E16FD0800AA2803 /* Shader.h */; }; + FA1BA0B71E17043400AA2803 /* wrap_Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0B51E17043400AA2803 /* wrap_Shader.cpp */; }; + FA1BA0B81E17043400AA2803 /* wrap_Shader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0B61E17043400AA2803 /* wrap_Shader.h */; }; FA1DC2631C5D9555008F99A0 /* HashFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2611C5D9555008F99A0 /* HashFunction.cpp */; }; FA1DC2641C5D9555008F99A0 /* HashFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1DC2621C5D9555008F99A0 /* HashFunction.h */; }; FA1E887E1DF363CD00E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E887C1DF363CD00E808AA /* Filter.cpp */; }; @@ -1344,8 +1349,6 @@ FA0B7BA21A95902C000E1D17 /* Text.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Text.h; sourceTree = ""; }; FA0B7BA41A95902C000E1D17 /* GLBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLBuffer.cpp; sourceTree = ""; }; FA0B7BA51A95902C000E1D17 /* GLBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLBuffer.h; sourceTree = ""; }; - FA0B7BA61A95902C000E1D17 /* wrap_Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Canvas.cpp; sourceTree = ""; }; - FA0B7BA71A95902C000E1D17 /* wrap_Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Canvas.h; sourceTree = ""; }; FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Graphics.cpp; sourceTree = ""; }; FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Graphics.h; sourceTree = ""; }; FA0B7BAC1A95902C000E1D17 /* wrap_Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Image.cpp; sourceTree = ""; }; @@ -1354,8 +1357,6 @@ FA0B7BAF1A95902C000E1D17 /* wrap_Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Mesh.h; sourceTree = ""; }; FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_ParticleSystem.cpp; sourceTree = ""; }; FA0B7BB11A95902C000E1D17 /* wrap_ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_ParticleSystem.h; sourceTree = ""; }; - FA0B7BB41A95902C000E1D17 /* wrap_Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Shader.cpp; sourceTree = ""; }; - FA0B7BB51A95902C000E1D17 /* wrap_Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Shader.h; sourceTree = ""; }; FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_SpriteBatch.cpp; sourceTree = ""; }; FA0B7BB71A95902C000E1D17 /* wrap_SpriteBatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_SpriteBatch.h; sourceTree = ""; }; FA0B7BB81A95902C000E1D17 /* wrap_Text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Text.cpp; sourceTree = ""; }; @@ -1613,6 +1614,14 @@ FA1BA09C1E16CFCE00AA2803 /* Font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Font.h; sourceTree = ""; }; FA1BA0A01E16D97500AA2803 /* wrap_Font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Font.cpp; sourceTree = ""; }; FA1BA0A11E16D97500AA2803 /* wrap_Font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Font.h; sourceTree = ""; }; + FA1BA0A51E16F20600AA2803 /* Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Canvas.cpp; sourceTree = ""; }; + FA1BA0A61E16F20600AA2803 /* Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Canvas.h; sourceTree = ""; }; + FA1BA0AA1E16F9EE00AA2803 /* wrap_Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Canvas.cpp; sourceTree = ""; }; + FA1BA0AB1E16F9EE00AA2803 /* wrap_Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Canvas.h; sourceTree = ""; }; + FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Shader.cpp; sourceTree = ""; }; + FA1BA0B01E16FD0800AA2803 /* Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shader.h; sourceTree = ""; }; + FA1BA0B51E17043400AA2803 /* wrap_Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Shader.cpp; sourceTree = ""; }; + FA1BA0B61E17043400AA2803 /* wrap_Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Shader.h; sourceTree = ""; }; FA1DC2611C5D9555008F99A0 /* HashFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashFunction.cpp; sourceTree = ""; }; FA1DC2621C5D9555008F99A0 /* HashFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashFunction.h; sourceTree = ""; }; FA1E887C1DF363CD00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = ""; }; @@ -2434,6 +2443,8 @@ FA0B7B871A95902C000E1D17 /* graphics */ = { isa = PBXGroup; children = ( + FA1BA0A51E16F20600AA2803 /* Canvas.cpp */, + FA1BA0A61E16F20600AA2803 /* Canvas.h */, FA0B7B881A95902C000E1D17 /* Color.h */, FA9D8DDC1DEF842A002CD881 /* Drawable.cpp */, FA0B7B891A95902C000E1D17 /* Drawable.h */, @@ -2448,6 +2459,8 @@ FA0B7B9C1A95902C000E1D17 /* Polyline.h */, FA0B7BBC1A95902C000E1D17 /* Quad.cpp */, FA0B7BBD1A95902C000E1D17 /* Quad.h */, + FA1BA0AF1E16FD0800AA2803 /* Shader.cpp */, + FA1BA0B01E16FD0800AA2803 /* Shader.h */, FA29C0041E12355B00268CD8 /* StreamBuffer.cpp */, FA2AF6721DAD62710032B62C /* StreamBuffer.h */, FA0B7BBE1A95902C000E1D17 /* Texture.cpp */, @@ -2456,10 +2469,14 @@ FA2AF6711DAC76FF0032B62C /* vertex.h */, FA0B7BC01A95902C000E1D17 /* Volatile.cpp */, FA0B7BC11A95902C000E1D17 /* Volatile.h */, + FA1BA0AA1E16F9EE00AA2803 /* wrap_Canvas.cpp */, + FA1BA0AB1E16F9EE00AA2803 /* wrap_Canvas.h */, FA1BA0A01E16D97500AA2803 /* wrap_Font.cpp */, FA1BA0A11E16D97500AA2803 /* wrap_Font.h */, FA620A2E1AA2F8DB005DB4C2 /* wrap_Quad.cpp */, FA620A2F1AA2F8DB005DB4C2 /* wrap_Quad.h */, + FA1BA0B51E17043400AA2803 /* wrap_Shader.cpp */, + FA1BA0B61E17043400AA2803 /* wrap_Shader.h */, FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */, FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */, ); @@ -2493,8 +2510,6 @@ FA0B7BA21A95902C000E1D17 /* Text.h */, FA27B3C31B4985D8008A9DCE /* Video.cpp */, FA27B3C41B4985D8008A9DCE /* Video.h */, - FA0B7BA61A95902C000E1D17 /* wrap_Canvas.cpp */, - FA0B7BA71A95902C000E1D17 /* wrap_Canvas.h */, FA0B7BAA1A95902C000E1D17 /* wrap_Graphics.cpp */, FA0B7BAB1A95902C000E1D17 /* wrap_Graphics.h */, FA6AE6041B3335EC00583D5C /* wrap_Graphics.lua */, @@ -2504,8 +2519,6 @@ FA0B7BAF1A95902C000E1D17 /* wrap_Mesh.h */, FA0B7BB01A95902C000E1D17 /* wrap_ParticleSystem.cpp */, FA0B7BB11A95902C000E1D17 /* wrap_ParticleSystem.h */, - FA0B7BB41A95902C000E1D17 /* wrap_Shader.cpp */, - FA0B7BB51A95902C000E1D17 /* wrap_Shader.h */, FA0B7BB61A95902C000E1D17 /* wrap_SpriteBatch.cpp */, FA0B7BB71A95902C000E1D17 /* wrap_SpriteBatch.h */, FA0B7BB81A95902C000E1D17 /* wrap_Text.cpp */, @@ -3134,6 +3147,7 @@ FA0B7D7E1A95902C000E1D17 /* Texture.h in Headers */, FA0B7E561A95902C000E1D17 /* wrap_GearJoint.h in Headers */, FA0B7E1D1A95902C000E1D17 /* MouseJoint.h in Headers */, + FA1BA0B81E17043400AA2803 /* wrap_Shader.h in Headers */, FA1557C41CE90BD200AFF582 /* EXRHandler.h in Headers */, FA0B7DC91A95902C000E1D17 /* Keyboard.h in Headers */, FA0B7D4A1A95902C000E1D17 /* Polyline.h in Headers */, @@ -3234,6 +3248,7 @@ FA0B7E441A95902C000E1D17 /* wrap_CircleShape.h in Headers */, FA0B7EB41A95902C000E1D17 /* System.h in Headers */, FA0B7CE11A95902C000E1D17 /* Source.h in Headers */, + FA1BA0AE1E16F9EE00AA2803 /* wrap_Canvas.h in Headers */, FA0B7E621A95902C000E1D17 /* wrap_Physics.h in Headers */, FA0B7DF01A95902C000E1D17 /* Mouse.h in Headers */, 217DFBDC1D9F6D490055D849 /* buffer.h in Headers */, @@ -3270,6 +3285,7 @@ FAB17BE81ABFAA9000F9BA27 /* lz4.h in Headers */, FA0B7E6B1A95902C000E1D17 /* wrap_PulleyJoint.h in Headers */, FA0B7E051A95902C000E1D17 /* Contact.h in Headers */, + FA1BA0A91E16F20600AA2803 /* Canvas.h in Headers */, FA0B7A691A958EA3000E1D17 /* b2Island.h in Headers */, FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */, FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */, @@ -3352,6 +3368,7 @@ FA0B7E651A95902C000E1D17 /* wrap_PolygonShape.h in Headers */, FA0B7AC91A958EA3000E1D17 /* win32.h in Headers */, FA0B7DFC1A95902C000E1D17 /* Body.h in Headers */, + FA1BA0B31E16FD0800AA2803 /* Shader.h in Headers */, 217DFC101D9F6D490055D849 /* url.lua.h in Headers */, FA0B7A941A958EA3000E1D17 /* b2GearJoint.h in Headers */, FA0B7DF31A95902C000E1D17 /* wrap_Cursor.h in Headers */, @@ -3427,7 +3444,6 @@ FA0B7A9A1A958EA3000E1D17 /* b2MotorJoint.h in Headers */, 217DFC081D9F6D490055D849 /* udp.h in Headers */, FA0B7DCF1A95902C000E1D17 /* wrap_Keyboard.h in Headers */, - FA0B7D6F1A95902C000E1D17 /* wrap_Shader.h in Headers */, FA0B7EA21A95902C000E1D17 /* Sound.h in Headers */, FA0B7B331A958EA3000E1D17 /* wuff_config.h in Headers */, FA0B7CF31A95902C000E1D17 /* DroppedFile.h in Headers */, @@ -3451,7 +3467,6 @@ FA0B79311A958E3B000E1D17 /* Module.h in Headers */, 217DFBF51D9F6D490055D849 /* mime.lua.h in Headers */, FA9D8DD31DEB56C3002CD881 /* pixelformat.h in Headers */, - FA0B7D5A1A95902C000E1D17 /* wrap_Canvas.h in Headers */, FA0B7E4A1A95902C000E1D17 /* wrap_DistanceJoint.h in Headers */, FA0B7D2E1A95902C000E1D17 /* Color.h in Headers */, FA0B7A6A1A958EA3000E1D17 /* b2TimeStep.h in Headers */, @@ -3574,7 +3589,6 @@ FA0B7DA91A95902C000E1D17 /* PVRHandler.cpp in Sources */, FA0B7EC61A95902C000E1D17 /* ThreadModule.cpp in Sources */, FA0B7D2C1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */, - FA0B7D591A95902C000E1D17 /* wrap_Canvas.cpp in Sources */, FA9D8DD81DEF8411002CD881 /* Data.cpp in Sources */, FA0B7E8F1A95902C000E1D17 /* GmeDecoder.cpp in Sources */, FA0B7CD71A95902C000E1D17 /* Audio.cpp in Sources */, @@ -3700,6 +3714,7 @@ FA2AF6751DAD64970032B62C /* vertex.cpp in Sources */, FA0B7D801A95902C000E1D17 /* Volatile.cpp in Sources */, FA0B792D1A958E3B000E1D17 /* Memoizer.cpp in Sources */, + FA1BA0B21E16FD0800AA2803 /* Shader.cpp in Sources */, FA0B7EBC1A95902C000E1D17 /* LuaThread.cpp in Sources */, FA0B7A871A958EA3000E1D17 /* b2PolygonAndCircleContact.cpp in Sources */, FA0B7EF21A959D2C000E1D17 /* ios.mm in Sources */, @@ -3786,7 +3801,6 @@ FA0B7DF81A95902C000E1D17 /* Body.cpp in Sources */, FA4F2BB41DE1E4BD00CA37D7 /* RecordingDevice.cpp in Sources */, FA0B7DF51A95902C000E1D17 /* wrap_Mouse.cpp in Sources */, - FA0B7D6E1A95902C000E1D17 /* wrap_Shader.cpp in Sources */, FA0B7E861A95902C000E1D17 /* CoreAudioDecoder.cpp in Sources */, FA0B7E761A95902C000E1D17 /* wrap_WeldJoint.cpp in Sources */, FA0B7D561A95902C000E1D17 /* GLBuffer.cpp in Sources */, @@ -3834,6 +3848,7 @@ FA0B7D4F1A95902C000E1D17 /* SpriteBatch.cpp in Sources */, FAB2D5AB1AABDD8A008224A4 /* TrueTypeRasterizer.cpp in Sources */, FA0B7A9F1A958EA3000E1D17 /* b2PrismaticJoint.cpp in Sources */, + FA1BA0AD1E16F9EE00AA2803 /* wrap_Canvas.cpp in Sources */, FA0B79331A958E3B000E1D17 /* Object.cpp in Sources */, FA0B7E5B1A95902C000E1D17 /* wrap_MotorJoint.cpp in Sources */, FA0B79441A958E3B000E1D17 /* Variant.cpp in Sources */, @@ -3852,6 +3867,7 @@ FA0B7E2E1A95902C000E1D17 /* RopeJoint.cpp in Sources */, FA0B7CE01A95902C000E1D17 /* Source.cpp in Sources */, FA0B7ECF1A95902C000E1D17 /* wrap_LuaThread.cpp in Sources */, + FA1BA0A81E16F20600AA2803 /* Canvas.cpp in Sources */, FA0B7AA51A958EA3000E1D17 /* b2RevoluteJoint.cpp in Sources */, FA0B7EA11A95902C000E1D17 /* Sound.cpp in Sources */, FA0B7DE61A95902C000E1D17 /* Cursor.cpp in Sources */, @@ -3894,7 +3910,6 @@ 217DFC031D9F6D490055D849 /* timeout.c in Sources */, FA9D8DD71DEF8411002CD881 /* Data.cpp in Sources */, FA0B7D2B1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */, - FA0B7D581A95902C000E1D17 /* wrap_Canvas.cpp in Sources */, FA0B7E8E1A95902C000E1D17 /* GmeDecoder.cpp in Sources */, FA0B7CD61A95902C000E1D17 /* Audio.cpp in Sources */, FA0B7A9E1A958EA3000E1D17 /* b2PrismaticJoint.cpp in Sources */, @@ -3999,6 +4014,7 @@ FA0B7E151A95902C000E1D17 /* Joint.cpp in Sources */, FA0B7EE81A95902D000E1D17 /* wrap_Window.cpp in Sources */, FA0B7E271A95902C000E1D17 /* PulleyJoint.cpp in Sources */, + FA1BA0B71E17043400AA2803 /* wrap_Shader.cpp in Sources */, FA0B7B301A958EA3000E1D17 /* wuff.c in Sources */, FA0B7E031A95902C000E1D17 /* Contact.cpp in Sources */, FA0B7D821A95902C000E1D17 /* CompressedImageData.cpp in Sources */, @@ -4017,6 +4033,7 @@ FA2AF6741DAD64970032B62C /* vertex.cpp in Sources */, FA0B7D7F1A95902C000E1D17 /* Volatile.cpp in Sources */, FA0B7A3B1A958EA3000E1D17 /* b2TimeOfImpact.cpp in Sources */, + FA1BA0B11E16FD0800AA2803 /* Shader.cpp in Sources */, 217DFBED1D9F6D490055D849 /* luasocket.c in Sources */, 217DFC011D9F6D490055D849 /* tcp.c in Sources */, FA0B7EBB1A95902C000E1D17 /* LuaThread.cpp in Sources */, @@ -4099,7 +4116,6 @@ FA0B7AAA1A958EA3000E1D17 /* b2WeldJoint.cpp in Sources */, FA0B7DF71A95902C000E1D17 /* Body.cpp in Sources */, FA0B7DF41A95902C000E1D17 /* wrap_Mouse.cpp in Sources */, - FA0B7D6D1A95902C000E1D17 /* wrap_Shader.cpp in Sources */, FA0B7E851A95902C000E1D17 /* CoreAudioDecoder.cpp in Sources */, FA0B7E751A95902C000E1D17 /* wrap_WeldJoint.cpp in Sources */, FA0B7D551A95902C000E1D17 /* GLBuffer.cpp in Sources */, @@ -4151,6 +4167,7 @@ FA0B7E5A1A95902C000E1D17 /* wrap_MotorJoint.cpp in Sources */, FA0B7AA71A958EA3000E1D17 /* b2RopeJoint.cpp in Sources */, FA0B7DD61A95902C000E1D17 /* MathModule.cpp in Sources */, + FA1BA0AC1E16F9EE00AA2803 /* wrap_Canvas.cpp in Sources */, FA0B7D0F1A95902C000E1D17 /* BMFontRasterizer.cpp in Sources */, FA0B7E9A1A95902C000E1D17 /* VorbisDecoder.cpp in Sources */, FA0B7E4B1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */, @@ -4169,6 +4186,7 @@ FA0B7EA01A95902C000E1D17 /* Sound.cpp in Sources */, FA0B7DE51A95902C000E1D17 /* Cursor.cpp in Sources */, FA0B7EDB1A95902D000E1D17 /* Touch.cpp in Sources */, + FA1BA0A71E16F20600AA2803 /* Canvas.cpp in Sources */, FA0B7CE81A95902C000E1D17 /* Event.cpp in Sources */, FA0B7ACF1A958EA3000E1D17 /* peer.c in Sources */, FA0B7ADE1A958EA3000E1D17 /* lodepng.cpp in Sources */, diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp new file mode 100644 index 000000000..142dad29c --- /dev/null +++ b/src/modules/graphics/Canvas.cpp @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2006-2016 LOVE Development Team + * + * 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 "Canvas.h" +#include "Graphics.h" + +namespace love +{ +namespace graphics +{ + +love::Type Canvas::type("Canvas", &Texture::type); +int Canvas::canvasCount = 0; + +Canvas::Canvas() +{ + canvasCount++; +} + +Canvas::~Canvas() +{ + canvasCount--; +} + +void Canvas::drawv(love::graphics::Graphics *gfx, const love::Matrix4 &t, const Vertex *v) +{ + if (gfx->isCanvasActive(this)) + throw love::Exception("Cannot render a Canvas to itself!"); + + Texture::drawv(gfx, t, v); +} + +} // graphics +} // love + diff --git a/src/modules/graphics/Canvas.h b/src/modules/graphics/Canvas.h new file mode 100644 index 000000000..b89b47e4a --- /dev/null +++ b/src/modules/graphics/Canvas.h @@ -0,0 +1,65 @@ +/** +* Copyright (c) 2006-2016 LOVE Development Team +* +* 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. +**/ + +#pragma once + +#include "image/Image.h" +#include "image/ImageData.h" +#include "Texture.h" + +namespace love +{ +namespace graphics +{ + +class Graphics; + +class Canvas : public Texture +{ +public: + + static love::Type type; + + struct Settings + { + PixelFormat format = PIXELFORMAT_NORMAL; + float pixeldensity = 1.0f; + int msaa = 0; + }; + + Canvas(); + virtual ~Canvas(); + + virtual love::image::ImageData *newImageData(love::image::Image *module, int x, int y, int w, int h) = 0; + + virtual int getMSAA() const = 0; + virtual int getRequestedMSAA() const = 0; + virtual ptrdiff_t getMSAAHandle() const = 0; + + static int canvasCount; + +private: + + void drawv(Graphics *gfx, const Matrix4 &t, const Vertex *v) override; + +}; // Canvas + +} // graphics +} // love diff --git a/src/modules/graphics/Font.h b/src/modules/graphics/Font.h index f6c4c1f17..cb30ccc5f 100644 --- a/src/modules/graphics/Font.h +++ b/src/modules/graphics/Font.h @@ -34,7 +34,6 @@ #include "font/Rasterizer.h" #include "Texture.h" -#include "Volatile.h" #include "vertex.h" namespace love @@ -44,7 +43,7 @@ namespace graphics class Graphics; -class Font : public Object, public Volatile +class Font : public Object { public: diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index e42bd5239..c06df8d31 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -22,6 +22,8 @@ #include "Graphics.h" #include "math/MathModule.h" #include "Polyline.h" +#include "font/Font.h" +#include "window/Window.h" // C++ #include @@ -79,9 +81,20 @@ Colorf unGammaCorrectColor(const Colorf &c) love::Type Graphics::type("graphics", &Module::type); +Shader::ShaderSource Graphics::defaultShaderCode[Graphics::RENDERER_MAX_ENUM][2]; +Shader::ShaderSource Graphics::defaultVideoShaderCode[Graphics::RENDERER_MAX_ENUM][2]; + Graphics::Graphics() - : streamBufferState() + : width(0) + , height(0) + , pixelWidth(0) + , pixelHeight(0) + , created(false) + , active(true) + , writingToStencil(false) + , streamBufferState() , projectionMatrix() + , canvasSwitchCount(0) { transformStack.reserve(16); transformStack.push_back(Matrix4()); @@ -89,11 +102,426 @@ Graphics::Graphics() Graphics::~Graphics() { + states.clear(); + + defaultFont.set(nullptr); + + if (Shader::defaultShader) + { + Shader::defaultShader->release(); + Shader::defaultShader = nullptr; + } + + if (Shader::defaultVideoShader) + { + Shader::defaultVideoShader->release(); + Shader::defaultVideoShader = nullptr; + } + delete streamBufferState.vb[0]; delete streamBufferState.vb[1]; delete streamBufferState.indexBuffer; } +Quad *Graphics::newQuad(Quad::Viewport v, double sw, double sh) +{ + return new Quad(v, sw, sh); +} + +int Graphics::getWidth() const +{ + return width; +} + +int Graphics::getHeight() const +{ + return height; +} + +int Graphics::getPixelWidth() const +{ + return pixelWidth; +} + +int Graphics::getPixelHeight() const +{ + return pixelHeight; +} + +double Graphics::getCurrentPixelDensity() const +{ + if (states.back().canvases.size() > 0) + { + love::graphics::Canvas *c = states.back().canvases[0]; + return (double) c->getPixelHeight() / (double) c->getHeight(); + } + + return getScreenPixelDensity(); +} + +double Graphics::getScreenPixelDensity() const +{ + return (double) getPixelHeight() / (double) getHeight(); +} + +bool Graphics::isCreated() const +{ + return created; +} + +bool Graphics::isActive() const +{ + // The graphics module is only completely 'active' if there's a window, a + // context, and the active variable is set. + auto window = getInstance(M_WINDOW); + return active && isCreated() && window != nullptr && window->isOpen(); +} + +void Graphics::reset() +{ + DisplayState s; + stopDrawToStencilBuffer(); + restoreState(s); + origin(); +} + +/** + * State functions. + **/ + +void Graphics::restoreState(const DisplayState &s) +{ + setColor(s.color); + setBackgroundColor(s.backgroundColor); + + setBlendMode(s.blendMode, s.blendAlphaMode); + + setLineWidth(s.lineWidth); + setLineStyle(s.lineStyle); + setLineJoin(s.lineJoin); + + setPointSize(s.pointSize); + + if (s.scissor) + setScissor(s.scissorRect); + else + setScissor(); + + setStencilTest(s.stencilCompare, s.stencilTestValue); + + setFont(s.font.get()); + setShader(s.shader.get()); + setCanvas(s.canvases); + + setColorMask(s.colorMask); + setWireframe(s.wireframe); + + setDefaultFilter(s.defaultFilter); + setDefaultMipmapFilter(s.defaultMipmapFilter, s.defaultMipmapSharpness); +} + +void Graphics::restoreStateChecked(const DisplayState &s) +{ + const DisplayState &cur = states.back(); + + if (s.color != cur.color) + setColor(s.color); + + setBackgroundColor(s.backgroundColor); + + if (s.blendMode != cur.blendMode || s.blendAlphaMode != cur.blendAlphaMode) + setBlendMode(s.blendMode, s.blendAlphaMode); + + // These are just simple assignments. + setLineWidth(s.lineWidth); + setLineStyle(s.lineStyle); + setLineJoin(s.lineJoin); + + if (s.pointSize != cur.pointSize) + setPointSize(s.pointSize); + + if (s.scissor != cur.scissor || (s.scissor && !(s.scissorRect == cur.scissorRect))) + { + if (s.scissor) + setScissor(s.scissorRect); + else + setScissor(); + } + + if (s.stencilCompare != cur.stencilCompare || s.stencilTestValue != cur.stencilTestValue) + setStencilTest(s.stencilCompare, s.stencilTestValue); + + setFont(s.font.get()); + setShader(s.shader.get()); + + bool canvaseschanged = s.canvases.size() != cur.canvases.size(); + if (!canvaseschanged) + { + for (size_t i = 0; i < s.canvases.size() && i < cur.canvases.size(); i++) + { + if (s.canvases[i].get() != cur.canvases[i].get()) + { + canvaseschanged = true; + break; + } + } + } + + if (canvaseschanged) + setCanvas(s.canvases); + + if (s.colorMask != cur.colorMask) + setColorMask(s.colorMask); + + if (s.wireframe != cur.wireframe) + setWireframe(s.wireframe); + + setDefaultFilter(s.defaultFilter); + setDefaultMipmapFilter(s.defaultMipmapFilter, s.defaultMipmapSharpness); +} + +Colorf Graphics::getColor() const +{ + return states.back().color; +} + +void Graphics::setBackgroundColor(Colorf c) +{ + states.back().backgroundColor = c; +} + +Colorf Graphics::getBackgroundColor() const +{ + return states.back().backgroundColor; +} + +void Graphics::checkSetDefaultFont() +{ + // We don't create or set the default Font if an existing font is in use. + if (states.back().font.get() != nullptr) + return; + + // Create a new default font if we don't have one yet. + if (!defaultFont.get()) + { + auto fontmodule = Module::getInstance(M_FONT); + if (!fontmodule) + throw love::Exception("Font module has not been loaded."); + + auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL; + StrongRef r(fontmodule->newTrueTypeRasterizer(12, hinting), Acquire::NORETAIN); + + defaultFont.set(newFont(r.get()), Acquire::NORETAIN); + } + + states.back().font.set(defaultFont.get()); +} + +void Graphics::setFont(love::graphics::Font *font) +{ + // We don't need to set a default font here if null is passed in, since we + // only care about the default font in getFont and print. + DisplayState &state = states.back(); + state.font.set(font); +} + +love::graphics::Font *Graphics::getFont() +{ + checkSetDefaultFont(); + return states.back().font.get(); +} + +void Graphics::setShader(love::graphics::Shader *shader) +{ + if (shader == nullptr) + return setShader(); + + flushStreamDraws(); + + shader->attach(); + + states.back().shader.set(shader); +} + +void Graphics::setShader() +{ + flushStreamDraws(); + + Shader::attachDefault(); + + states.back().shader.set(nullptr); +} + +love::graphics::Shader *Graphics::getShader() const +{ + return states.back().shader.get(); +} + +void Graphics::setCanvas(Canvas *canvas) +{ + if (canvas == nullptr) + return setCanvas(); + + std::vector canvases = {canvas}; + setCanvas(canvases); +} + +void Graphics::setCanvas(const std::vector> &canvases) +{ + std::vector canvaslist; + canvaslist.reserve(canvases.size()); + + for (const StrongRef &c : canvases) + canvaslist.push_back(c.get()); + + return setCanvas(canvaslist); +} + +std::vector Graphics::getCanvas() const +{ + std::vector canvases; + canvases.reserve(states.back().canvases.size()); + + for (const StrongRef &c : states.back().canvases) + canvases.push_back(c.get()); + + return canvases; +} + +bool Graphics::isCanvasActive() const +{ + return !states.back().canvases.empty(); +} + +bool Graphics::isCanvasActive(love::graphics::Canvas *canvas) const +{ + for (const auto &c : states.back().canvases) + { + if (c.get() == canvas) + return true; + } + + return false; +} + +void Graphics::intersectScissor(const Rect &rect) +{ + Rect currect = states.back().scissorRect; + + if (!states.back().scissor) + { + currect.x = 0; + currect.y = 0; + currect.w = std::numeric_limits::max(); + currect.h = std::numeric_limits::max(); + } + + int x1 = std::max(currect.x, rect.x); + int y1 = std::max(currect.y, rect.y); + + int x2 = std::min(currect.x + currect.w, rect.x + rect.w); + int y2 = std::min(currect.y + currect.h, rect.y + rect.h); + + Rect newrect = {x1, y1, std::max(0, x2 - x1), std::max(0, y2 - y1)}; + setScissor(newrect); +} + +bool Graphics::getScissor(Rect &rect) const +{ + const DisplayState &state = states.back(); + rect = state.scissorRect; + return state.scissor; +} + +void Graphics::getStencilTest(CompareMode &compare, int &value) +{ + const DisplayState &state = states.back(); + compare = state.stencilCompare; + value = state.stencilTestValue; +} + +Graphics::ColorMask Graphics::getColorMask() const +{ + return states.back().colorMask; +} + +Graphics::BlendMode Graphics::getBlendMode(BlendAlpha &alphamode) const +{ + alphamode = states.back().blendAlphaMode; + return states.back().blendMode; +} + +void Graphics::setDefaultFilter(const Texture::Filter &f) +{ + Texture::defaultFilter = f; + states.back().defaultFilter = f; +} + +const Texture::Filter &Graphics::getDefaultFilter() const +{ + return Texture::defaultFilter; +} + +void Graphics::setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness) +{ + Texture::defaultMipmapFilter = filter; + Texture::defaultMipmapSharpness = sharpness; + + states.back().defaultMipmapFilter = filter; + states.back().defaultMipmapSharpness = sharpness; +} + +void Graphics::getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const +{ + *filter = Texture::defaultMipmapFilter; + *sharpness = Texture::defaultMipmapSharpness; +} + +void Graphics::setLineWidth(float width) +{ + states.back().lineWidth = width; +} + +void Graphics::setLineStyle(Graphics::LineStyle style) +{ + states.back().lineStyle = style; +} + +void Graphics::setLineJoin(Graphics::LineJoin join) +{ + states.back().lineJoin = join; +} + +float Graphics::getLineWidth() const +{ + return states.back().lineWidth; +} + +Graphics::LineStyle Graphics::getLineStyle() const +{ + return states.back().lineStyle; +} + +Graphics::LineJoin Graphics::getLineJoin() const +{ + return states.back().lineJoin; +} + +float Graphics::getPointSize() const +{ + return states.back().pointSize; +} + +bool Graphics::isWireframe() const +{ + return states.back().wireframe; +} + +void Graphics::captureScreenshot(const ScreenshotInfo &info) +{ + pendingScreenshotCallbacks.push_back(info); +} + Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &req) { using namespace vertex; @@ -205,6 +633,30 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest & return d; } +/** + * Drawing + **/ + +void Graphics::print(const std::vector &str, const Matrix4 &m) +{ + checkSetDefaultFont(); + + DisplayState &state = states.back(); + + if (state.font.get() != nullptr) + state.font->print(this, str, m, state.color); +} + +void Graphics::printf(const std::vector &str, float wrap, Font::AlignMode align, const Matrix4 &m) +{ + checkSetDefaultFont(); + + DisplayState &state = states.back(); + + if (state.font.get() != nullptr) + state.font->printf(this, str, wrap, align, m, state.color); +} + void Graphics::draw(Drawable *drawable, const Matrix4 &m) { drawable->draw(this, m); @@ -216,7 +668,7 @@ void Graphics::draw(Texture *texture, Quad *quad, const Matrix4 &m) } /** - * Primitives + * Primitives (points, shapes, lines). **/ void Graphics::points(const float *coords, const Colorf *colors, size_t numpoints) @@ -524,6 +976,46 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count) } } +void Graphics::push(StackType type) +{ + if (stackTypeStack.size() == MAX_USER_STACK_DEPTH) + throw Exception("Maximum stack depth reached (more pushes than pops?)"); + + pushTransform(); + + pixelScaleStack.push_back(pixelScaleStack.back()); + + if (type == STACK_ALL) + states.push_back(states.back()); + + stackTypeStack.push_back(type); +} + +void Graphics::pop() +{ + if (stackTypeStack.size() < 1) + throw Exception("Minimum stack depth reached (more pops than pushes?)"); + + popTransform(); + pixelScaleStack.pop_back(); + + if (stackTypeStack.back() == STACK_ALL) + { + DisplayState &newstate = states[states.size() - 2]; + + restoreStateChecked(newstate); + + // The last two states in the stack should be equal now. + states.pop_back(); + } + + stackTypeStack.pop_back(); +} + +/** + * Transform and stack functions. + **/ + const Matrix4 &Graphics::getTransform() const { return transformStack.back(); @@ -612,6 +1104,10 @@ Vector Graphics::inverseTransformPoint(Vector point) return p; } +/** + * Constants. + **/ + bool Graphics::getConstant(const char *in, DrawMode &out) { return drawModes.find(in, out); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 1aa8bb69e..cb8477516 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -30,7 +30,12 @@ #include "vertex.h" #include "Color.h" #include "Texture.h" +#include "Canvas.h" +#include "Font.h" +#include "Shader.h" +#include "Quad.h" #include "math/Transform.h" +#include "font/Rasterizer.h" // C++ #include @@ -38,6 +43,9 @@ namespace love { + +class Reference; + namespace graphics { @@ -283,12 +291,43 @@ public: Graphics *gfx; }; + typedef void (*ScreenshotCallback)(love::image::ImageData *i, Reference *ref, void *ud); + + struct ScreenshotInfo + { + ScreenshotCallback callback; + Reference *ref; + }; + Graphics(); virtual ~Graphics(); // Implements Module. virtual ModuleType getModuleType() const { return M_GRAPHICS; } + Quad *newQuad(Quad::Viewport v, double sw, double sh); + + virtual Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter) = 0; + + virtual Canvas *newCanvas(int width, int height, const Canvas::Settings &settings) = 0; + + virtual Shader *newShader(const Shader::ShaderSource &source) = 0; + + /** + * Resets the current color, background color, line style, and so forth. + **/ + void reset(); + + virtual void clear(Colorf color) = 0; + virtual void clear(const std::vector &colors) = 0; + + virtual void discard(const std::vector &colorbuffers, bool depthstencil) = 0; + + /** + * Flips buffers. (Rendered geometry is presented on screen). + **/ + virtual void present(void *screenshotCallbackData) = 0; + /** * Sets the current graphics display viewport dimensions. **/ @@ -319,25 +358,190 @@ public: * Normally the module will always be active as long as a window exists, it * may be different on some platforms (especially mobile ones.) **/ - virtual bool isActive() const = 0; + bool isActive() const; - virtual int getWidth() const = 0; - virtual int getHeight() const = 0; + /** + * True if a graphics viewport is set. + **/ + bool isCreated() const; - virtual bool isCanvasActive() const = 0; + int getWidth() const; + int getHeight() const; + int getPixelWidth() const; + int getPixelHeight() const; - virtual void flushStreamDraws() = 0; - StreamVertexData requestStreamDraw(const StreamDrawRequest &request); + double getCurrentPixelDensity() const; + double getScreenPixelDensity() const; - virtual Colorf getColor() const = 0; + /** + * Sets the current constant color. + **/ + virtual void setColor(Colorf c) = 0; - virtual float getLineWidth() const = 0; - virtual LineStyle getLineStyle() const = 0; - virtual LineJoin getLineJoin() const = 0; + /** + * Gets current color. + **/ + Colorf getColor() const; + + /** + * Sets the background Color. + **/ + void setBackgroundColor(Colorf c); + + /** + * Gets the current background color. + **/ + Colorf getBackgroundColor() const; + + void setFont(Font *font); + Font *getFont(); + + void setShader(Shader *shader); + void setShader(); + + Shader *getShader() const; + + void setCanvas(Canvas *canvas); + virtual void setCanvas(const std::vector &canvases) = 0; + void setCanvas(const std::vector> &canvases); + virtual void setCanvas() = 0; + + std::vector getCanvas() const; + bool isCanvasActive() const; + bool isCanvasActive(Canvas *canvas) const; + + /** + * Scissor defines a box such that everything outside that box is discarded + * and not drawn. Scissoring is automatically enabled. + * @param rect The rectangle defining the scissor area. + **/ + virtual void setScissor(const Rect &rect) = 0; + void intersectScissor(const Rect &rect); + + /** + * Clears any scissor that has been created. + **/ + virtual void setScissor() = 0; + + /** + * Gets the current scissor box. + * @return Whether the scissor is enabled. + */ + bool getScissor(Rect &rect) const; + + /** + * Enables or disables drawing to the stencil buffer. When enabled, the + * color buffer is disabled. + **/ + virtual void drawToStencilBuffer(StencilAction action, int value) = 0; + virtual void stopDrawToStencilBuffer() = 0; + + /** + * Sets whether stencil testing is enabled. + **/ + virtual void setStencilTest(CompareMode compare, int value) = 0; + virtual void setStencilTest() = 0; + void getStencilTest(CompareMode &compare, int &value); + + /** + * Clear the stencil buffer in the active Canvas(es.) + **/ + virtual void clearStencil() = 0; + + /** + * Sets the enabled color components when rendering. + **/ + virtual void setColorMask(ColorMask mask) = 0; + + /** + * Gets the current color mask. + **/ + ColorMask getColorMask() const; + + /** + * Sets the current blend mode. + **/ + virtual void setBlendMode(BlendMode mode, BlendAlpha alphamode) = 0; + + /** + * Gets the current blend mode. + **/ + BlendMode getBlendMode(BlendAlpha &alphamode) const; + + /** + * Sets the default filter for images, canvases, and fonts. + **/ + void setDefaultFilter(const Texture::Filter &f); + + /** + * Gets the default filter for images, canvases, and fonts. + **/ + const Texture::Filter &getDefaultFilter() const; + + /** + * Default Image mipmap filter mode and sharpness values. + **/ + void setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness); + void getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const; + + /** + * Sets the line width. + * @param width The new width of the line. + **/ + void setLineWidth(float width); + float getLineWidth() const; + + /** + * Sets the line style. + * @param style LINE_ROUGH or LINE_SMOOTH. + **/ + void setLineStyle(LineStyle style); + LineStyle getLineStyle() const; + + /** + * Sets the line join mode. + **/ + void setLineJoin(LineJoin style); + LineJoin getLineJoin() const; + + /** + * Sets the size of points. + **/ + virtual void setPointSize(float size) = 0; + + /** + * Gets the point size. + **/ + float getPointSize() const; + + /** + * Sets whether graphics will be drawn as wireframe lines instead of filled + * triangles (has no effect for drawn points.) + * This should only be used as a debugging tool. The wireframe lines do not + * behave the same as regular love.graphics lines. + **/ + virtual void setWireframe(bool enable) = 0; + + /** + * Gets whether wireframe drawing mode is enabled. + **/ + bool isWireframe() const; + + void captureScreenshot(const ScreenshotInfo &info); void draw(Drawable *drawable, const Matrix4 &m); void draw(Texture *texture, Quad *quad, const Matrix4 &m); + /** + * Draws text at the specified coordinates + **/ + void print(const std::vector &str, const Matrix4 &m); + + /** + * Draws formatted text on screen at the specified coordinates. + **/ + void printf(const std::vector &str, float wrap, Font::AlignMode align, const Matrix4 &m); + /** * Draws a point at (x,y). * @param x Point along x-axis. @@ -420,11 +624,31 @@ public: **/ void polygon(DrawMode mode, const float *coords, size_t count); + /** + * Gets whether a graphics feature is supported on this system. + **/ + virtual bool isSupported(Feature feature) const = 0; + /** * Gets the system-dependent numeric limit for the specified parameter. **/ virtual double getSystemLimit(SystemLimit limittype) const = 0; + /** + * Returns system-dependent renderer information. + * Returned strings can vary greatly between systems! Do not rely on it for + * anything! + **/ + virtual RendererInfo getRendererInfo() const = 0; + + /** + * Returns performance-related statistics. + **/ + virtual Stats getStats() const = 0; + + void push(StackType type = STACK_TRANSFORM); + void pop(); + const Matrix4 &getTransform() const; const Matrix4 &getProjection() const; @@ -440,6 +664,9 @@ public: Vector transformPoint(Vector point); Vector inverseTransformPoint(Vector point); + virtual void flushStreamDraws() = 0; + StreamVertexData requestStreamDraw(const StreamDrawRequest &request); + template T *getScratchBuffer(size_t count) { @@ -484,8 +711,48 @@ public: static bool getConstant(const char *in, StackType &out); static bool getConstant(StackType in, const char *&out); + // Default shader code (a shader is always required internally.) + static Shader::ShaderSource defaultShaderCode[RENDERER_MAX_ENUM][2]; + static Shader::ShaderSource defaultVideoShaderCode[RENDERER_MAX_ENUM][2]; + protected: + struct DisplayState + { + Colorf color = Colorf(1.0, 1.0, 1.0, 1.0); + Colorf gammaCorrectedColor = Colorf(1.0f, 1.0f, 1.0f, 1.0f); + Colorf backgroundColor = Colorf(0.0, 0.0, 0.0, 1.0); + + BlendMode blendMode = BLEND_ALPHA; + BlendAlpha blendAlphaMode = BLENDALPHA_MULTIPLY; + + float lineWidth = 1.0f; + LineStyle lineStyle = LINE_SMOOTH; + LineJoin lineJoin = LINE_JOIN_MITER; + + float pointSize = 1.0f; + + bool scissor = false; + Rect scissorRect = Rect(); + + CompareMode stencilCompare = COMPARE_ALWAYS; + int stencilTestValue = 0; + + StrongRef font; + StrongRef shader; + + std::vector> canvases; + + ColorMask colorMask = ColorMask(true, true, true, true); + + bool wireframe = false; + + Texture::Filter defaultFilter = Texture::Filter(); + + Texture::FilterMode defaultMipmapFilter = Texture::FILTER_NEAREST; + float defaultMipmapSharpness = 0.0f; + }; + struct StreamBufferState { StreamBuffer *vb[2]; @@ -498,10 +765,27 @@ protected: int indexCount; }; + void restoreState(const DisplayState &s); + void restoreStateChecked(const DisplayState &s); + void pushTransform(); void pushIdentityTransform(); void popTransform(); + int width; + int height; + int pixelWidth; + int pixelHeight; + + bool created; + bool active; + + bool writingToStencil; + + StrongRef defaultFont; + + std::vector pendingScreenshotCallbacks; + StreamBufferState streamBufferState; std::vector transformStack; @@ -509,8 +793,16 @@ protected: std::vector pixelScaleStack; + std::vector states; + std::vector stackTypeStack; + + int canvasSwitchCount; + + static const size_t MAX_USER_STACK_DEPTH = 64; + private: + void checkSetDefaultFont(); int calculateEllipsePoints(float rx, float ry) const; std::vector scratchBuffer; diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp new file mode 100644 index 000000000..b448071c1 --- /dev/null +++ b/src/modules/graphics/Shader.cpp @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2006-2016 LOVE Development Team + * + * 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. +**/ + +// LOVE +#include "Shader.h" + +namespace love +{ +namespace graphics +{ + +love::Type Shader::type("Shader", &Object::type); +Shader *Shader::current = nullptr; +Shader *Shader::defaultShader = nullptr; +Shader *Shader::defaultVideoShader = nullptr; + +Shader::~Shader() +{ + if (defaultShader == this) + defaultShader = nullptr; + + if (defaultVideoShader == this) + defaultVideoShader = nullptr; + + if (current == this) + attachDefault(); +} + +void Shader::attachDefault() +{ + if (defaultShader) + { + if (current != defaultShader) + defaultShader->attach(); + + return; + } + + current = nullptr; +} + +bool Shader::getConstant(const char *in, ShaderStage &out) +{ + return stageNames.find(in, out); +} + +bool Shader::getConstant(ShaderStage in, const char *&out) +{ + return stageNames.find(in, out); +} + +bool Shader::getConstant(const char *in, UniformType &out) +{ + return uniformTypes.find(in, out); +} + +bool Shader::getConstant(UniformType in, const char *&out) +{ + return uniformTypes.find(in, out); +} + +bool Shader::getConstant(const char *in, VertexAttribID &out) +{ + return attribNames.find(in, out); +} + +bool Shader::getConstant(VertexAttribID in, const char *&out) +{ + return attribNames.find(in, out); +} + +bool Shader::getConstant(const char *in, BuiltinUniform &out) +{ + return builtinNames.find(in, out); +} + +bool Shader::getConstant(BuiltinUniform in, const char *&out) +{ + return builtinNames.find(in, out); +} + +StringMap::Entry Shader::stageNameEntries[] = +{ + {"vertex", Shader::STAGE_VERTEX}, + {"pixel", Shader::STAGE_PIXEL}, +}; + +StringMap Shader::stageNames(Shader::stageNameEntries, sizeof(Shader::stageNameEntries)); + +StringMap::Entry Shader::uniformTypeEntries[] = +{ + {"float", Shader::UNIFORM_FLOAT}, + {"matrix", Shader::UNIFORM_MATRIX}, + {"int", Shader::UNIFORM_INT}, + {"bool", Shader::UNIFORM_BOOL}, + {"image", Shader::UNIFORM_SAMPLER}, + {"unknown", Shader::UNIFORM_UNKNOWN}, +}; + +StringMap Shader::uniformTypes(Shader::uniformTypeEntries, sizeof(Shader::uniformTypeEntries)); + +StringMap::Entry Shader::attribNameEntries[] = +{ + {"VertexPosition", ATTRIB_POS}, + {"VertexTexCoord", ATTRIB_TEXCOORD}, + {"VertexColor", ATTRIB_COLOR}, + {"ConstantColor", ATTRIB_CONSTANTCOLOR}, +}; + +StringMap Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries)); + +StringMap::Entry Shader::builtinNameEntries[] = +{ + {"TransformMatrix", Shader::BUILTIN_TRANSFORM_MATRIX}, + {"ProjectionMatrix", Shader::BUILTIN_PROJECTION_MATRIX}, + {"TransformProjectionMatrix", Shader::BUILTIN_TRANSFORM_PROJECTION_MATRIX}, + {"NormalMatrix", Shader::BUILTIN_NORMAL_MATRIX}, + {"love_PointSize", Shader::BUILTIN_POINT_SIZE}, + {"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE}, + {"love_VideoYChannel", Shader::BUILTIN_VIDEO_Y_CHANNEL}, + {"love_VideoCbChannel", Shader::BUILTIN_VIDEO_CB_CHANNEL}, + {"love_VideoCrChannel", Shader::BUILTIN_VIDEO_CR_CHANNEL}, +}; + +StringMap Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries)); + +} // graphics +} // love diff --git a/src/modules/graphics/Shader.h b/src/modules/graphics/Shader.h new file mode 100644 index 000000000..7aded00ae --- /dev/null +++ b/src/modules/graphics/Shader.h @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2006-2016 LOVE Development Team + * + * 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. + **/ + +#pragma once + +// LOVE +#include "common/Object.h" +#include "common/StringMap.h" +#include "Texture.h" + +// STL +#include +#include +#include + +namespace love +{ +namespace graphics +{ + +// A GLSL shader +class Shader : public Object +{ +public: + + static love::Type type; + + enum ShaderStage + { + STAGE_VERTEX, + STAGE_PIXEL, + STAGE_MAX_ENUM + }; + + // Built-in uniform variables. + enum BuiltinUniform + { + BUILTIN_TRANSFORM_MATRIX = 0, + BUILTIN_PROJECTION_MATRIX, + BUILTIN_TRANSFORM_PROJECTION_MATRIX, + BUILTIN_NORMAL_MATRIX, + BUILTIN_POINT_SIZE, + BUILTIN_SCREEN_SIZE, + BUILTIN_VIDEO_Y_CHANNEL, + BUILTIN_VIDEO_CB_CHANNEL, + BUILTIN_VIDEO_CR_CHANNEL, + BUILTIN_MAX_ENUM + }; + + // Types of potential uniform variables used in love's shaders. + enum UniformType + { + UNIFORM_FLOAT, + UNIFORM_MATRIX, + UNIFORM_INT, + UNIFORM_BOOL, + UNIFORM_SAMPLER, + UNIFORM_UNKNOWN, + UNIFORM_MAX_ENUM + }; + + struct ShaderSource + { + std::string vertex; + std::string pixel; + }; + + struct MatrixSize + { + short columns; + short rows; + }; + + struct UniformInfo + { + int location; + int count; + + union + { + int components; + MatrixSize matrix; + }; + + UniformType baseType; + std::string name; + + union + { + void *data; + float *floats; + int *ints; + }; + + Texture **textures; + }; + + // Pointer to currently active Shader. + static Shader *current; + + // Pointer to the default Shader. + static Shader *defaultShader; + static Shader *defaultVideoShader; + + virtual ~Shader(); + + /** + * Binds this Shader's program to be used when rendering. + * + * @param temporary True if we just want to send values to the shader with + * no intention of rendering. + **/ + virtual void attach(bool temporary = false) = 0; + + /** + * Attach the default shader. + **/ + static void attachDefault(); + + /** + * Returns any warnings this Shader may have generated. + **/ + virtual std::string getWarnings() const = 0; + + virtual const UniformInfo *getUniformInfo(const std::string &name) const = 0; + virtual void updateUniform(const UniformInfo *info, int count, bool internalUpdate = false) = 0; + + virtual void sendTextures(const UniformInfo *info, Texture **textures, int count, bool internalUpdate = false) = 0; + + /** + * Gets whether a uniform with the specified name exists and is actively + * used in the shader. + **/ + virtual bool hasUniform(const std::string &name) const = 0; + + static bool getConstant(const char *in, ShaderStage &out); + static bool getConstant(ShaderStage in, const char *&out); + + static bool getConstant(const char *in, UniformType &out); + static bool getConstant(UniformType in, const char *&out); + + static bool getConstant(const char *in, VertexAttribID &out); + static bool getConstant(VertexAttribID in, const char *&out); + + static bool getConstant(const char *in, BuiltinUniform &out); + static bool getConstant(BuiltinUniform in, const char *&out); + +private: + + static StringMap::Entry stageNameEntries[]; + static StringMap stageNames; + + static StringMap::Entry uniformTypeEntries[]; + static StringMap uniformTypes; + + // Names for the generic vertex attributes used by love. + static StringMap::Entry attribNameEntries[]; + static StringMap attribNames; + + // Names for the built-in uniform variables. + static StringMap::Entry builtinNameEntries[]; + static StringMap builtinNames; + +}; // Shader + +} // graphics +} // love diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index d3daa3d65..e992c6f3d 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -27,7 +27,10 @@ namespace graphics { love::Type Texture::type("Texture", &Drawable::type); + Texture::Filter Texture::defaultFilter; +Texture::FilterMode Texture::defaultMipmapFilter = Texture::FILTER_LINEAR; +float Texture::defaultMipmapSharpness = 0.0f; Texture::Texture() : format(PIXELFORMAT_UNKNOWN) @@ -35,7 +38,7 @@ Texture::Texture() , height(0) , pixelWidth(0) , pixelHeight(0) - , filter(getDefaultFilter()) + , filter(defaultFilter) , wrap() , vertices() { @@ -122,16 +125,6 @@ const Vertex *Texture::getVertices() const return vertices; } -void Texture::setDefaultFilter(const Filter &f) -{ - defaultFilter = f; -} - -const Texture::Filter &Texture::getDefaultFilter() -{ - return defaultFilter; -} - bool Texture::validateFilter(const Filter &f, bool mipmapsAllowed) { if (!mipmapsAllowed && f.mipmap != FILTER_NONE) diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index 4e771110e..7d1900cc1 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -81,6 +81,10 @@ public: Texture(); virtual ~Texture(); + static Filter defaultFilter; + static FilterMode defaultMipmapFilter; + static float defaultMipmapSharpness; + // Drawable. void draw(Graphics *gfx, const Matrix4 &m) override; @@ -109,10 +113,6 @@ public: virtual ptrdiff_t getHandle() const = 0; - // The default filter. - static void setDefaultFilter(const Filter &f); - static const Filter &getDefaultFilter(); - static bool validateFilter(const Filter &f, bool mipmapsAllowed); static bool getConstant(const char *in, FilterMode &out); @@ -140,9 +140,6 @@ protected: private: - // The default texture filter. - static Filter defaultFilter; - static StringMap::Entry filterModeEntries[]; static StringMap filterModes; diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index e682b901a..dcdfc4d71 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -19,8 +19,7 @@ **/ #include "Canvas.h" -#include "Image.h" -#include "Graphics.h" +#include "graphics/Graphics.h" #include // For min/max @@ -97,9 +96,6 @@ static bool createMSAABuffer(int width, int height, int &samples, PixelFormat pi return status == GL_FRAMEBUFFER_COMPLETE && samples > 1; } -love::Type Canvas::type("Canvas", &Texture::type); -int Canvas::canvasCount = 0; - Canvas::Canvas(int width, int height, const Settings &settings) : settings(settings) , fbo(0) @@ -140,13 +136,10 @@ Canvas::Canvas(int width, int height, const Settings &settings) this->format = getSizedFormat(settings.format); loadVolatile(); - - ++canvasCount; } Canvas::~Canvas() { - --canvasCount; unloadVolatile(); } @@ -247,16 +240,6 @@ void Canvas::unloadVolatile() texture_memory = 0; } -void Canvas::drawv(love::graphics::Graphics *gfx, const Matrix4 &localTransform, const Vertex *v) -{ - Graphics *glgfx = (Graphics *) gfx; - - if (glgfx != nullptr && glgfx->isCanvasActive(this)) - throw love::Exception("Cannot render a Canvas to itself!"); - - Texture::drawv(gfx, localTransform, v); -} - void Canvas::setFilter(const Texture::Filter &f) { if (!validateFilter(f, false)) @@ -307,15 +290,8 @@ love::image::ImageData *Canvas::newImageData(love::image::Image *module, int x, throw love::Exception("Invalid rectangle dimensions."); Graphics *gfx = Module::getInstance(Module::M_GRAPHICS); - - if (gfx != nullptr) - { - for (const auto &c : gfx->getCanvas()) - { - if (c == this) - throw love::Exception("Canvas:newImageData cannot be called while that Canvas is currently active."); - } - } + if (gfx != nullptr && gfx->isCanvasActive(this)) + throw love::Exception("Canvas:newImageData cannot be called while that Canvas is currently active."); PixelFormat dataformat; switch (getPixelFormat()) diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index 9e1389bd0..80f1baa01 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -23,12 +23,8 @@ #include "common/config.h" #include "graphics/Color.h" -#include "image/Image.h" -#include "image/ImageData.h" -#include "common/Matrix.h" -#include "common/StringMap.h" #include "common/int.h" -#include "graphics/Texture.h" +#include "graphics/Canvas.h" #include "graphics/Volatile.h" #include "OpenGL.h" @@ -39,19 +35,10 @@ namespace graphics namespace opengl { -class Canvas : public Texture, public Volatile +class Canvas final : public love::graphics::Canvas, public Volatile { public: - static love::Type type; - - struct Settings - { - PixelFormat format = PIXELFORMAT_NORMAL; - float pixeldensity = 1.0f; - int msaa = 0; - }; - Canvas(int width, int height, const Settings &settings); virtual ~Canvas(); @@ -64,28 +51,29 @@ public: bool setWrap(const Texture::Wrap &w) override; ptrdiff_t getHandle() const override; - love::image::ImageData *newImageData(love::image::Image *module, int x, int y, int w, int h); + love::image::ImageData *newImageData(love::image::Image *module, int x, int y, int w, int h) override; - inline GLenum getStatus() const - { - return status; - } - - inline int getMSAA() const + int getMSAA() const override { return actual_samples; } - inline int getRequestedMSAA() const + int getRequestedMSAA() const override { return settings.msaa; } - inline ptrdiff_t getMSAAHandle() const + ptrdiff_t getMSAAHandle() const override { return msaa_buffer; } + + inline GLenum getStatus() const + { + return status; + } + inline GLuint getFBO() const { return fbo; @@ -96,12 +84,8 @@ public: static bool isMultiFormatMultiCanvasSupported(); static bool isFormatSupported(PixelFormat format); - static int canvasCount; - private: - void drawv(Graphics *gfx, const Matrix4 &t, const Vertex *v) override; - Settings settings; GLuint fbo; diff --git a/src/modules/graphics/opengl/Font.h b/src/modules/graphics/opengl/Font.h index 6fe6f695d..149c5445e 100644 --- a/src/modules/graphics/opengl/Font.h +++ b/src/modules/graphics/opengl/Font.h @@ -22,6 +22,7 @@ // LOVE #include "graphics/Font.h" +#include "graphics/Volatile.h" #include "OpenGL.h" namespace love @@ -31,7 +32,7 @@ namespace graphics namespace opengl { -class Font : public love::graphics::Font +class Font final : public love::graphics::Font, public Volatile { public: diff --git a/src/modules/graphics/opengl/GLBuffer.cpp b/src/modules/graphics/opengl/GLBuffer.cpp index bf19e19af..17ae9f1a7 100644 --- a/src/modules/graphics/opengl/GLBuffer.cpp +++ b/src/modules/graphics/opengl/GLBuffer.cpp @@ -35,7 +35,7 @@ namespace graphics namespace opengl { -GLBuffer::GLBuffer(size_t size, const void *data, BufferType type, GLenum usage, uint32 mapflags) +GLBuffer::GLBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) : is_mapped(false) , size(size) , type(type) @@ -100,11 +100,13 @@ void GLBuffer::unmapStatic(size_t offset, size_t size) void GLBuffer::unmapStream() { + GLenum glusage = OpenGL::getGLBufferUsage(getUsage()); + // "orphan" current buffer to avoid implicit synchronisation on the GPU: // http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf gl.bindBuffer(type, vbo); - glBufferData(target, (GLsizeiptr) getSize(), nullptr, getUsage()); - glBufferData(target, (GLsizeiptr) getSize(), memory_map, getUsage()); + glBufferData(target, (GLsizeiptr) getSize(), nullptr, glusage); + glBufferData(target, (GLsizeiptr) getSize(), memory_map, glusage); } void GLBuffer::unmap() @@ -125,7 +127,7 @@ void GLBuffer::unmap() if (modified_size > 0) { - switch (getUsage()) + switch (OpenGL::getGLBufferUsage(getUsage())) { case GL_STATIC_DRAW: unmapStatic(modified_offset, modified_size); @@ -213,7 +215,7 @@ bool GLBuffer::load(bool restore) const GLvoid *src = restore ? memory_map : nullptr; // Note that if 'src' is '0', no data will be copied. - glBufferData(target, (GLsizeiptr) getSize(), src, getUsage()); + glBufferData(target, (GLsizeiptr) getSize(), src, OpenGL::getGLBufferUsage(getUsage())); return (glGetError() == GL_NO_ERROR); } @@ -260,7 +262,7 @@ QuadIndices::QuadIndices(size_t size) // QuadIndices will propagate the exception and keep the old GLBuffer. try { - newbuffer = new GLBuffer(buffersize, nullptr, BUFFER_INDEX, GL_STATIC_DRAW); + newbuffer = new GLBuffer(buffersize, nullptr, BUFFER_INDEX, vertex::USAGE_STATIC); newindices = new char[buffersize]; } catch (std::bad_alloc &) diff --git a/src/modules/graphics/opengl/GLBuffer.h b/src/modules/graphics/opengl/GLBuffer.h index 665cfd435..dc75d853b 100644 --- a/src/modules/graphics/opengl/GLBuffer.h +++ b/src/modules/graphics/opengl/GLBuffer.h @@ -25,6 +25,7 @@ // LOVE #include "common/config.h" #include "graphics/Volatile.h" +#include "graphics/vertex.h" // OpenGL #include "OpenGL.h" @@ -57,9 +58,9 @@ public: * * @param size The size of the GLBuffer in bytes. * @param type The type of the buffer object. - * @param usage Usage hint, e.g. GL_DYNAMIC_DRAW. + * @param usage Usage hint. */ - GLBuffer(size_t size, const void *data, BufferType type, GLenum usage, uint32 mapflags = 0); + GLBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags = 0); /** * Destructor. @@ -86,10 +87,8 @@ public: /** * Get the usage hint for this GLBuffer. - * - * @return The usage hint, e.g. GL_DYNAMIC_DRAW. */ - GLenum getUsage() const + vertex::Usage getUsage() const { return usage; } @@ -214,7 +213,7 @@ private: GLenum target; // Usage hint. GL_[DYNAMIC, STATIC, STREAM]_DRAW. - GLenum usage; + vertex::Usage usage; // The VBO identifier. Assigned by OpenGL. GLuint vbo; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index e7aa5494f..c1029b9c6 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -55,14 +55,6 @@ namespace opengl Graphics::Graphics() : quadIndices(nullptr) - , width(0) - , height(0) - , pixelWidth(0) - , pixelHeight(0) - , created(false) - , active(true) - , writingToStencil(false) - , canvasSwitchCount(0) { gl = OpenGL(); @@ -88,21 +80,6 @@ Graphics::Graphics() Graphics::~Graphics() { - // We do this manually so the graphics objects are released before the window. - states.clear(); - defaultFont.set(nullptr); - - if (Shader::defaultShader) - { - Shader::defaultShader->release(); - Shader::defaultShader = nullptr; - } - if (Shader::defaultVideoShader) - { - Shader::defaultVideoShader->release(); - Shader::defaultVideoShader = nullptr; - } - if (quadIndices) delete quadIndices; } @@ -112,133 +89,93 @@ const char *Graphics::getName() const return "love.graphics.opengl"; } -void Graphics::restoreState(const DisplayState &s) +Image *Graphics::newImage(const std::vector &data, const Image::Settings &settings) { - setColor(s.color); - setBackgroundColor(s.backgroundColor); - - setBlendMode(s.blendMode, s.blendAlphaMode); - - setLineWidth(s.lineWidth); - setLineStyle(s.lineStyle); - setLineJoin(s.lineJoin); - - setPointSize(s.pointSize); - - if (s.scissor) - setScissor(s.scissorRect); - else - setScissor(); - - setStencilTest(s.stencilCompare, s.stencilTestValue); - - setFont(s.font.get()); - setShader(s.shader.get()); - setCanvas(s.canvases); - - setColorMask(s.colorMask); - setWireframe(s.wireframe); - - setDefaultFilter(s.defaultFilter); - setDefaultMipmapFilter(s.defaultMipmapFilter, s.defaultMipmapSharpness); + return new Image(data, settings); } -void Graphics::restoreStateChecked(const DisplayState &s) +Image *Graphics::newImage(const std::vector &cdata, const Image::Settings &settings) { - const DisplayState &cur = states.back(); - - if (s.color != cur.color) - setColor(s.color); - - setBackgroundColor(s.backgroundColor); - - if (s.blendMode != cur.blendMode || s.blendAlphaMode != cur.blendAlphaMode) - setBlendMode(s.blendMode, s.blendAlphaMode); - - // These are just simple assignments. - setLineWidth(s.lineWidth); - setLineStyle(s.lineStyle); - setLineJoin(s.lineJoin); - - if (s.pointSize != cur.pointSize) - setPointSize(s.pointSize); - - if (s.scissor != cur.scissor || (s.scissor && !(s.scissorRect == cur.scissorRect))) - { - if (s.scissor) - setScissor(s.scissorRect); - else - setScissor(); - } - - if (s.stencilCompare != cur.stencilCompare || s.stencilTestValue != cur.stencilTestValue) - setStencilTest(s.stencilCompare, s.stencilTestValue); - - setFont(s.font.get()); - setShader(s.shader.get()); - - bool canvaseschanged = s.canvases.size() != cur.canvases.size(); - if (!canvaseschanged) - { - for (size_t i = 0; i < s.canvases.size() && i < cur.canvases.size(); i++) - { - if (s.canvases[i].get() != cur.canvases[i].get()) - { - canvaseschanged = true; - break; - } - } - } - - if (canvaseschanged) - setCanvas(s.canvases); - - if (s.colorMask != cur.colorMask) - setColorMask(s.colorMask); - - if (s.wireframe != cur.wireframe) - setWireframe(s.wireframe); - - setDefaultFilter(s.defaultFilter); - setDefaultMipmapFilter(s.defaultMipmapFilter, s.defaultMipmapSharpness); + return new Image(cdata, settings); } -void Graphics::checkSetDefaultFont() +graphics::Font *Graphics::newFont(love::font::Rasterizer *r, const Texture::Filter &filter) { - // We don't create or set the default Font if an existing font is in use. - if (states.back().font.get() != nullptr) - return; - - // Create a new default font if we don't have one yet. - if (!defaultFont.get()) - { - auto fontmodule = Module::getInstance(M_FONT); - if (!fontmodule) - throw love::Exception("Font module has not been loaded."); - - auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL; - StrongRef r(fontmodule->newTrueTypeRasterizer(12, hinting), Acquire::NORETAIN); - - defaultFont.set(newFont(r.get()), Acquire::NORETAIN); - } - - states.back().font.set(defaultFont.get()); + return new Font(r, filter); } -double Graphics::getCurrentPixelDensity() const +SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, vertex::Usage usage) { - if (states.back().canvases.size() > 0) - { - Canvas *c = states.back().canvases[0]; - return (double) c->getPixelHeight() / (double) c->getHeight(); - } - - return getScreenPixelDensity(); + return new SpriteBatch(texture, size, usage); } -double Graphics::getScreenPixelDensity() const +ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size) { - return (double) getPixelHeight() / (double) getHeight(); + return new ParticleSystem(texture, size); +} + +love::graphics::Canvas *Graphics::newCanvas(int width, int height, const Canvas::Settings &settings) +{ + if (!Canvas::isSupported()) + throw love::Exception("Canvases are not supported by your OpenGL drivers!"); + + if (!Canvas::isFormatSupported(settings.format)) + { + const char *fstr = "rgba8"; + love::getConstant(Canvas::getSizedFormat(settings.format), fstr); + throw love::Exception("The %s canvas format is not supported by your OpenGL drivers.", fstr); + } + + if (width > gl.getMaxTextureSize()) + throw Exception("Cannot create canvas: width of %d pixels is too large for this system.", width); + else if (height > gl.getMaxTextureSize()) + throw Exception("Cannot create canvas: height of %d pixels is too large for this system.", height); + + Canvas *canvas = new Canvas(width, height, settings); + GLenum err = canvas->getStatus(); + + // everything ok, return canvas (early out) + if (err == GL_FRAMEBUFFER_COMPLETE) + return canvas; + + canvas->release(); + throw love::Exception("Cannot create Canvas: %s", OpenGL::framebufferStatusString(err)); + return nullptr; // never reached +} + +love::graphics::Shader *Graphics::newShader(const Shader::ShaderSource &source) +{ + return new Shader(source); +} + +Mesh *Graphics::newMesh(const std::vector &vertices, Mesh::DrawMode drawmode, vertex::Usage usage) +{ + return new Mesh(vertices, drawmode, usage); +} + +Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage) +{ + return new Mesh(vertexcount, drawmode, usage); +} + +Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage) +{ + return new Mesh(vertexformat, vertexcount, drawmode, usage); +} + +Mesh *Graphics::newMesh(const std::vector &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage) +{ + return new Mesh(vertexformat, data, datasize, drawmode, usage); +} + +Text *Graphics::newText(graphics::Font *font, const std::vector &text) +{ + return new Text(font, text); +} + +Video *Graphics::newVideo(love::video::VideoStream *stream, float pixeldensity) +{ + return new Video(stream, pixeldensity); } void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) @@ -352,14 +289,14 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight) if (!Shader::defaultShader) { Renderer renderer = GLAD_ES_VERSION_2_0 ? RENDERER_OPENGLES : RENDERER_OPENGL; - Shader::defaultShader = newShader(Shader::defaultCode[renderer][gammacorrect]); + Shader::defaultShader = newShader(defaultShaderCode[renderer][gammacorrect]); } // and a default video shader. if (!Shader::defaultVideoShader) { Renderer renderer = GLAD_ES_VERSION_2_0 ? RENDERER_OPENGLES : RENDERER_OPENGL; - Shader::defaultVideoShader = newShader(Shader::defaultVideoCode[renderer][gammacorrect]); + Shader::defaultVideoShader = newShader(defaultVideoShaderCode[renderer][gammacorrect]); } // A shader should always be active, but the default shader shouldn't be @@ -407,14 +344,6 @@ void Graphics::setActive(bool enable) active = enable; } -bool Graphics::isActive() const -{ - // The graphics module is only completely 'active' if there's a window, a - // context, and the active variable is set. - auto window = getInstance(M_WINDOW); - return active && isCreated() && window != nullptr && window->isOpen(); -} - void Graphics::flushStreamDraws() { using namespace vertex; @@ -584,24 +513,7 @@ void Graphics::setDebug(bool enable) ::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n"); } -void Graphics::reset() -{ - DisplayState s; - stopDrawToStencilBuffer(); - restoreState(s); - origin(); -} - -void Graphics::setCanvas(Canvas *canvas) -{ - if (canvas == nullptr) - return setCanvas(); - - std::vector canvases = {canvas}; - setCanvas(canvases); -} - -void Graphics::setCanvas(const std::vector &canvases) +void Graphics::setCanvas(const std::vector &canvases) { DisplayState &state = states.back(); int ncanvases = (int) canvases.size(); @@ -629,7 +541,7 @@ void Graphics::setCanvas(const std::vector &canvases) if (ncanvases > gl.getMaxRenderTargets()) throw love::Exception("This system can't simultaneously render to %d canvases.", ncanvases); - Canvas *firstcanvas = canvases[0]; + love::graphics::Canvas *firstcanvas = canvases[0]; bool multiformatsupported = Canvas::isMultiFormatMultiCanvasSupported(); PixelFormat firstformat = firstcanvas->getPixelFormat(); @@ -640,7 +552,7 @@ void Graphics::setCanvas(const std::vector &canvases) for (int i = 1; i < ncanvases; i++) { - Canvas *c = canvases[i]; + love::graphics::Canvas *c = canvases[i]; if (c->getPixelWidth() != pixelwidth || c->getPixelHeight() != pixelheight) throw love::Exception("All canvases in must have the same pixel dimensions."); @@ -681,10 +593,10 @@ void Graphics::setCanvas(const std::vector &canvases) gl.setFramebufferSRGB(false); } - std::vector> canvasrefs; + std::vector> canvasrefs; canvasrefs.reserve(canvases.size()); - for (Canvas *c : canvases) + for (love::graphics::Canvas *c : canvases) canvasrefs.push_back(c); std::swap(state.canvases, canvasrefs); @@ -692,17 +604,6 @@ void Graphics::setCanvas(const std::vector &canvases) canvasSwitchCount++; } -void Graphics::setCanvas(const std::vector> &canvases) -{ - std::vector canvaslist; - canvaslist.reserve(canvases.size()); - - for (const StrongRef &c : canvases) - canvaslist.push_back(c.get()); - - return setCanvas(canvaslist); -} - void Graphics::setCanvas() { DisplayState &state = states.back(); @@ -740,17 +641,6 @@ void Graphics::setCanvas() canvasSwitchCount++; } -std::vector Graphics::getCanvas() const -{ - std::vector canvases; - canvases.reserve(states.back().canvases.size()); - - for (const StrongRef &c : states.back().canvases) - canvases.push_back(c.get()); - - return canvases; -} - void Graphics::endPass() { flushStreamDraws(); @@ -768,9 +658,11 @@ void Graphics::endPass() for (int i = 0; i < (int) canvases.size(); i++) { + Canvas *c = (Canvas *) canvases[i].get(); + glReadBuffer(GL_COLOR_ATTACHMENT0 + i); - gl.bindFramebuffer(OpenGL::FRAMEBUFFER_DRAW, canvases[i]->getFBO()); + gl.bindFramebuffer(OpenGL::FRAMEBUFFER_DRAW, c->getFBO()); if (GLAD_APPLE_framebuffer_multisample) glResolveMultisampleFramebufferAPPLE(); @@ -793,7 +685,7 @@ void Graphics::clear(Colorf c) // This seems to be enough to fix the bug for me. Other methods I've // tried (e.g. dummy draws) don't work in all cases. gl.useProgram(0); - gl.useProgram(Shader::current->getProgram()); + gl.useProgram(((Shader *)Shader::current)->getProgram()); } } @@ -859,26 +751,10 @@ void Graphics::clear(const std::vector &colors) // This seems to be enough to fix the bug for me. Other methods I've // tried (e.g. dummy draws) don't work in all cases. gl.useProgram(0); - gl.useProgram(Shader::current->getProgram()); + gl.useProgram(((Shader *)Shader::current)->getProgram()); } } -bool Graphics::isCanvasActive() const -{ - return !states.back().canvases.empty(); -} - -bool Graphics::isCanvasActive(Canvas *canvas) const -{ - for (const auto &c : states.back().canvases) - { - if (c.get() == canvas) - return true; - } - - return false; -} - void Graphics::discard(const std::vector &colorbuffers, bool depthstencil) { flushStreamDraws(); @@ -935,11 +811,11 @@ void Graphics::discard(OpenGL::FramebufferTarget target, const std::vector glDiscardFramebufferEXT(gltarget, (GLint) attachments.size(), &attachments[0]); } -void Graphics::bindCachedFBO(const std::vector &canvases) +void Graphics::bindCachedFBO(const std::vector &canvases) { int ncanvases = (int) canvases.size(); - uint32 hash = XXH32(&canvases[0], sizeof(Canvas *) * ncanvases, 0); + uint32 hash = XXH32(&canvases[0], sizeof(love::graphics::Canvas *) * ncanvases, 0); GLuint fbo = framebufferObjects[hash]; @@ -1075,11 +951,6 @@ GLuint Graphics::attachCachedStencilBuffer(int w, int h, int samples) return rb.renderbuffer; } -void Graphics::captureScreenshot(const ScreenshotInfo &info) -{ - pendingScreenshotCallbacks.push_back(info); -} - void Graphics::present(void *screenshotCallbackData) { if (!isActive()) @@ -1200,31 +1071,6 @@ void Graphics::present(void *screenshotCallbackData) canvasSwitchCount = 0; } -int Graphics::getWidth() const -{ - return width; -} - -int Graphics::getHeight() const -{ - return height; -} - -int Graphics::getPixelWidth() const -{ - return pixelWidth; -} - -int Graphics::getPixelHeight() const -{ - return pixelHeight; -} - -bool Graphics::isCreated() const -{ - return created; -} - void Graphics::setScissor(const Rect &rect) { flushStreamDraws(); @@ -1248,28 +1094,6 @@ void Graphics::setScissor(const Rect &rect) state.scissorRect = rect; } -void Graphics::intersectScissor(const Rect &rect) -{ - Rect currect = states.back().scissorRect; - - if (!states.back().scissor) - { - currect.x = 0; - currect.y = 0; - currect.w = std::numeric_limits::max(); - currect.h = std::numeric_limits::max(); - } - - int x1 = std::max(currect.x, rect.x); - int y1 = std::max(currect.y, rect.y); - - int x2 = std::min(currect.x + currect.w, rect.x + rect.w); - int y2 = std::min(currect.y + currect.h, rect.y + rect.h); - - Rect newrect = {x1, y1, std::max(0, x2 - x1), std::max(0, y2 - y1)}; - setScissor(newrect); -} - void Graphics::setScissor() { flushStreamDraws(); @@ -1277,13 +1101,6 @@ void Graphics::setScissor() glDisable(GL_SCISSOR_TEST); } -bool Graphics::getScissor(Rect &rect) const -{ - const DisplayState &state = states.back(); - rect = state.scissorRect; - return state.scissor; -} - void Graphics::drawToStencilBuffer(StencilAction action, int value) { writingToStencil = true; @@ -1405,117 +1222,11 @@ void Graphics::setStencilTest() setStencilTest(COMPARE_ALWAYS, 0); } -void Graphics::getStencilTest(CompareMode &compare, int &value) -{ - const DisplayState &state = states.back(); - compare = state.stencilCompare; - value = state.stencilTestValue; -} - void Graphics::clearStencil() { glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -Image *Graphics::newImage(const std::vector &data, const Image::Settings &settings) -{ - return new Image(data, settings); -} - -Image *Graphics::newImage(const std::vector &cdata, const Image::Settings &settings) -{ - return new Image(cdata, settings); -} - -Quad *Graphics::newQuad(Quad::Viewport v, double sw, double sh) -{ - return new Quad(v, sw, sh); -} - -graphics::Font *Graphics::newFont(love::font::Rasterizer *r, const Texture::Filter &filter) -{ - return new Font(r, filter); -} - -SpriteBatch *Graphics::newSpriteBatch(Texture *texture, int size, Mesh::Usage usage) -{ - return new SpriteBatch(texture, size, usage); -} - -ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size) -{ - return new ParticleSystem(texture, size); -} - -Canvas *Graphics::newCanvas(int width, int height, const Canvas::Settings &settings) -{ - if (!Canvas::isSupported()) - throw love::Exception("Canvases are not supported by your OpenGL drivers!"); - - if (!Canvas::isFormatSupported(settings.format)) - { - const char *fstr = "rgba8"; - love::getConstant(Canvas::getSizedFormat(settings.format), fstr); - throw love::Exception("The %s canvas format is not supported by your OpenGL drivers.", fstr); - } - - if (width > gl.getMaxTextureSize()) - throw Exception("Cannot create canvas: width of %d pixels is too large for this system.", width); - else if (height > gl.getMaxTextureSize()) - throw Exception("Cannot create canvas: height of %d pixels is too large for this system.", height); - - Canvas *canvas = new Canvas(width, height, settings); - GLenum err = canvas->getStatus(); - - // everything ok, return canvas (early out) - if (err == GL_FRAMEBUFFER_COMPLETE) - return canvas; - - canvas->release(); - throw love::Exception("Cannot create Canvas: %s", OpenGL::framebufferStatusString(err)); - return nullptr; // never reached -} - -Shader *Graphics::newShader(const Shader::ShaderSource &source) -{ - return new Shader(source); -} - -Mesh *Graphics::newMesh(const std::vector &vertices, Mesh::DrawMode drawmode, Mesh::Usage usage) -{ - return new Mesh(vertices, drawmode, usage); -} - -Mesh *Graphics::newMesh(int vertexcount, Mesh::DrawMode drawmode, Mesh::Usage usage) -{ - return new Mesh(vertexcount, drawmode, usage); -} - -Mesh *Graphics::newMesh(const std::vector &vertexformat, int vertexcount, Mesh::DrawMode drawmode, Mesh::Usage usage) -{ - return new Mesh(vertexformat, vertexcount, drawmode, usage); -} - -Mesh *Graphics::newMesh(const std::vector &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, Mesh::Usage usage) -{ - return new Mesh(vertexformat, data, datasize, drawmode, usage); -} - -Text *Graphics::newText(graphics::Font *font, const std::vector &text) -{ - return new Text(font, text); -} - -Video *Graphics::newVideo(love::video::VideoStream *stream, float pixeldensity) -{ - return new Video(stream, pixeldensity); -} - -bool Graphics::isGammaCorrect() const -{ - return love::graphics::isGammaCorrect(); -} - void Graphics::setColor(Colorf c) { c.r = std::min(std::max(c.r, 0.0f), 1.0f); @@ -1531,66 +1242,6 @@ void Graphics::setColor(Colorf c) states.back().gammaCorrectedColor = nc; } -Colorf Graphics::getColor() const -{ - return states.back().color; -} - -void Graphics::setBackgroundColor(Colorf c) -{ - states.back().backgroundColor = c; -} - -Colorf Graphics::getBackgroundColor() const -{ - return states.back().backgroundColor; -} - -void Graphics::setFont(love::graphics::Font *font) -{ - // We don't need to set a default font here if null is passed in, since we - // only care about the default font in getFont and print. - DisplayState &state = states.back(); - state.font.set(font); -} - -love::graphics::Font *Graphics::getFont() -{ - checkSetDefaultFont(); - return states.back().font.get(); -} - -void Graphics::setShader(Shader *shader) -{ - if (shader == nullptr) - return setShader(); - - flushStreamDraws(); - - DisplayState &state = states.back(); - - shader->attach(); - - state.shader.set(shader); -} - -void Graphics::setShader() -{ - flushStreamDraws(); - - DisplayState &state = states.back(); - - // This will activate the default shader. - Shader::detach(); - - state.shader.set(nullptr); -} - -Shader *Graphics::getShader() const -{ - return states.back().shader.get(); -} - void Graphics::setColorMask(ColorMask mask) { flushStreamDraws(); @@ -1599,11 +1250,6 @@ void Graphics::setColorMask(ColorMask mask) states.back().colorMask = mask; } -Graphics::ColorMask Graphics::getColorMask() const -{ - return states.back().colorMask; -} - void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode) { flushStreamDraws(); @@ -1682,68 +1328,6 @@ void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode) states.back().blendAlphaMode = alphamode; } -Graphics::BlendMode Graphics::getBlendMode(BlendAlpha &alphamode) const -{ - alphamode = states.back().blendAlphaMode; - return states.back().blendMode; -} - -void Graphics::setDefaultFilter(const Texture::Filter &f) -{ - Texture::setDefaultFilter(f); - states.back().defaultFilter = f; -} - -const Texture::Filter &Graphics::getDefaultFilter() const -{ - return Texture::getDefaultFilter(); -} - -void Graphics::setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness) -{ - Image::setDefaultMipmapFilter(filter); - Image::setDefaultMipmapSharpness(sharpness); - - states.back().defaultMipmapFilter = filter; - states.back().defaultMipmapSharpness = sharpness; -} - -void Graphics::getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const -{ - *filter = Image::getDefaultMipmapFilter(); - *sharpness = Image::getDefaultMipmapSharpness(); -} - -void Graphics::setLineWidth(float width) -{ - states.back().lineWidth = width; -} - -void Graphics::setLineStyle(Graphics::LineStyle style) -{ - states.back().lineStyle = style; -} - -void Graphics::setLineJoin(Graphics::LineJoin join) -{ - states.back().lineJoin = join; -} - -float Graphics::getLineWidth() const -{ - return states.back().lineWidth; -} - -Graphics::LineStyle Graphics::getLineStyle() const -{ - return states.back().lineStyle; -} - -Graphics::LineJoin Graphics::getLineJoin() const -{ - return states.back().lineJoin; -} - void Graphics::setPointSize(float size) { if (streamBufferState.primitiveMode == vertex::PrimitiveMode::POINTS) @@ -1753,11 +1337,6 @@ void Graphics::setPointSize(float size) states.back().pointSize = size; } -float Graphics::getPointSize() const -{ - return states.back().pointSize; -} - void Graphics::setWireframe(bool enable) { // Not supported in OpenGL ES. @@ -1770,31 +1349,6 @@ void Graphics::setWireframe(bool enable) states.back().wireframe = enable; } -bool Graphics::isWireframe() const -{ - return states.back().wireframe; -} - -void Graphics::print(const std::vector &str, const Matrix4 &m) -{ - checkSetDefaultFont(); - - DisplayState &state = states.back(); - - if (state.font.get() != nullptr) - state.font->print(this, str, m, state.color); -} - -void Graphics::printf(const std::vector &str, float wrap, Font::AlignMode align, const Matrix4 &m) -{ - checkSetDefaultFont(); - - DisplayState &state = states.back(); - - if (state.font.get() != nullptr) - state.font->printf(this, str, wrap, align, m, state.color); -} - Graphics::RendererInfo Graphics::getRendererInfo() const { RendererInfo info; @@ -1883,42 +1437,6 @@ bool Graphics::isSupported(Feature feature) const } } -void Graphics::push(StackType type) -{ - if (stackTypes.size() == MAX_USER_STACK_DEPTH) - throw Exception("Maximum stack depth reached (more pushes than pops?)"); - - pushTransform(); - - pixelScaleStack.push_back(pixelScaleStack.back()); - - if (type == STACK_ALL) - states.push_back(states.back()); - - stackTypes.push_back(type); -} - -void Graphics::pop() -{ - if (stackTypes.size() < 1) - throw Exception("Minimum stack depth reached (more pops than pushes?)"); - - popTransform(); - pixelScaleStack.pop_back(); - - if (stackTypes.back() == STACK_ALL) - { - DisplayState &newstate = states[states.size() - 2]; - - restoreStateChecked(newstate); - - // The last two states in the stack should be equal now. - states.pop_back(); - } - - stackTypes.pop_back(); -} - } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 9bfc01b5a..20fdd3d62 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -38,10 +38,7 @@ #include "video/VideoStream.h" -#include "graphics/Font.h" #include "Image.h" -#include "graphics/Quad.h" -#include "graphics/Texture.h" #include "SpriteBatch.h" #include "ParticleSystem.h" #include "Canvas.h" @@ -53,8 +50,6 @@ namespace love { -class Reference; - namespace graphics { namespace opengl @@ -64,321 +59,81 @@ class Graphics final : public love::graphics::Graphics { public: - typedef void (*ScreenshotCallback)(love::image::ImageData *i, Reference *ref, void *ud); - - struct ScreenshotInfo - { - ScreenshotCallback callback; - Reference *ref; - }; - Graphics(); virtual ~Graphics(); // Implements Module. const char *getName() const override; + Image *newImage(const std::vector &data, const Image::Settings &settings); + Image *newImage(const std::vector &cdata, const Image::Settings &settings); + + love::graphics::Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter) override; + + SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage); + + ParticleSystem *newParticleSystem(Texture *texture, int size); + + love::graphics::Canvas *newCanvas(int width, int height, const Canvas::Settings &settings) override; + + love::graphics::Shader *newShader(const Shader::ShaderSource &source) override; + + Mesh *newMesh(const std::vector &vertices, Mesh::DrawMode drawmode, vertex::Usage usage); + Mesh *newMesh(int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage); + + Mesh *newMesh(const std::vector &vertexformat, int vertexcount, Mesh::DrawMode drawmode, vertex::Usage usage); + Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, vertex::Usage usage); + + Text *newText(love::graphics::Font *font, const std::vector &text = {}); + + Video *newVideo(love::video::VideoStream *stream, float pixeldensity); + void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; bool setMode(int width, int height, int pixelwidth, int pixelheight) override; void unSetMode() override; void setActive(bool active) override; - bool isActive() const override; void flushStreamDraws() override; - /** - * Resets the current color, background color, - * line style, and so forth. (This will be called - * when the game reloads. - **/ - void reset(); + void clear(Colorf color) override; + void clear(const std::vector &colors) override; - void clear(Colorf color); - void clear(const std::vector &colors); + void discard(const std::vector &colorbuffers, bool depthstencil) override; - void discard(const std::vector &colorbuffers, bool depthstencil); + void present(void *screenshotCallbackData) override; - bool isCanvasActive() const override; - bool isCanvasActive(Canvas *canvas) const; + void setColor(Colorf c) override; - /** - * Flips buffers. (Rendered geometry is presented on screen). - **/ - void present(void *screenshotCallbackData); + void setCanvas(const std::vector &canvases) override; + void setCanvas() override; - int getWidth() const override; - int getHeight() const override; - int getPixelWidth() const; - int getPixelHeight() const; + void setScissor(const Rect &rect) override; + void setScissor() override; - double getCurrentPixelDensity() const; - double getScreenPixelDensity() const; + void drawToStencilBuffer(StencilAction action, int value) override; + void stopDrawToStencilBuffer() override; - /** - * True if a graphics viewport is set. - **/ - bool isCreated() const; + void setStencilTest(CompareMode compare, int value) override; + void setStencilTest() override; - void setCanvas(Canvas *canvas); - void setCanvas(const std::vector &canvases); - void setCanvas(const std::vector> &canvases); - void setCanvas(); + void clearStencil() override; - std::vector getCanvas() const; + void setColorMask(ColorMask mask) override; - /** - * Scissor defines a box such that everything outside that box is discarded and not drawn. - * Scissoring is automatically enabled. - * @param rect The rectangle defining the scissor area. - **/ - void setScissor(const Rect &rect); - void intersectScissor(const Rect &rect); + void setBlendMode(BlendMode mode, BlendAlpha alphamode) override; - /** - * Clears any scissor that has been created. - **/ - void setScissor(); + void setPointSize(float size) override; - /** - * Gets the current scissor box. - * @return Whether the scissor is enabled. - */ - bool getScissor(Rect &rect) const; - - /** - * Enables or disables drawing to the stencil buffer. When enabled, the - * color buffer is disabled. - **/ - void drawToStencilBuffer(StencilAction action, int value); - void stopDrawToStencilBuffer(); - - /** - * Sets whether stencil testing is enabled. - **/ - void setStencilTest(CompareMode compare, int value); - void setStencilTest(); - void getStencilTest(CompareMode &compare, int &value); - - /** - * Clear the stencil buffer in the active Canvas(es.) - **/ - void clearStencil(); - - /** - * Creates an Image object with padding and/or optimization. - **/ - Image *newImage(const std::vector &data, const Image::Settings &settings); - Image *newImage(const std::vector &cdata, const Image::Settings &settings); - - Quad *newQuad(Quad::Viewport v, double sw, double sh); - - /** - * Creates a Font object. - **/ - graphics::Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::getDefaultFilter()); - - SpriteBatch *newSpriteBatch(Texture *texture, int size, Mesh::Usage usage); - - ParticleSystem *newParticleSystem(Texture *texture, int size); - - Canvas *newCanvas(int width, int height, const Canvas::Settings &settings); - - Shader *newShader(const Shader::ShaderSource &source); - - Mesh *newMesh(const std::vector &vertices, Mesh::DrawMode drawmode, Mesh::Usage usage); - Mesh *newMesh(int vertexcount, Mesh::DrawMode drawmode, Mesh::Usage usage); - - Mesh *newMesh(const std::vector &vertexformat, int vertexcount, Mesh::DrawMode drawmode, Mesh::Usage usage); - Mesh *newMesh(const std::vector &vertexformat, const void *data, size_t datasize, Mesh::DrawMode drawmode, Mesh::Usage usage); - - Text *newText(graphics::Font *font, const std::vector &text = {}); - - Video *newVideo(love::video::VideoStream *stream, float pixeldensity); - - bool isGammaCorrect() const; - - /** - * Sets the current constant color. - **/ - void setColor(Colorf c); - - /** - * Gets current color. - **/ - Colorf getColor() const override; - - /** - * Sets the background Color. - **/ - void setBackgroundColor(Colorf c); - - /** - * Gets the current background color. - **/ - Colorf getBackgroundColor() const; - - void setFont(love::graphics::Font *font); - love::graphics::Font *getFont(); - - void setShader(Shader *shader); - void setShader(); - - Shader *getShader() const; - - /** - * Sets the enabled color components when rendering. - **/ - void setColorMask(ColorMask mask); - - /** - * Gets the current color mask. - **/ - ColorMask getColorMask() const; - - /** - * Sets the current blend mode. - **/ - void setBlendMode(BlendMode mode, BlendAlpha alphamode); - - /** - * Gets the current blend mode. - **/ - BlendMode getBlendMode(BlendAlpha &alphamode) const; - - /** - * Sets the default filter for images, canvases, and fonts. - **/ - void setDefaultFilter(const Texture::Filter &f); - - /** - * Gets the default filter for images, canvases, and fonts. - **/ - const Texture::Filter &getDefaultFilter() const; - - /** - * Default Image mipmap filter mode and sharpness values. - **/ - void setDefaultMipmapFilter(Texture::FilterMode filter, float sharpness); - void getDefaultMipmapFilter(Texture::FilterMode *filter, float *sharpness) const; - - /** - * Sets the line width. - * @param width The new width of the line. - **/ - void setLineWidth(float width); - - /** - * Sets the line style. - * @param style LINE_ROUGH or LINE_SMOOTH. - **/ - void setLineStyle(LineStyle style); - - /** - * Sets the line join mode. - **/ - void setLineJoin(LineJoin style); - - float getLineWidth() const override; - LineStyle getLineStyle() const override; - LineJoin getLineJoin() const override; - - /** - * Sets the size of points. - **/ - void setPointSize(float size); - - /** - * Gets the point size. - **/ - float getPointSize() const; - - /** - * Sets whether graphics will be drawn as wireframe lines instead of filled - * triangles (has no effect for drawn points.) - * This should only be used as a debugging tool. The wireframe lines do not - * behave the same as regular love.graphics lines. - **/ - void setWireframe(bool enable); - - /** - * Gets whether wireframe drawing mode is enabled. - **/ - bool isWireframe() const; - - /** - * Draws text at the specified coordinates - **/ - void print(const std::vector &str, const Matrix4 &m); - - /** - * Draws formatted text on screen at the specified coordinates. - **/ - void printf(const std::vector &str, float wrap, Font::AlignMode align, const Matrix4 &m); - - void captureScreenshot(const ScreenshotInfo &info); - - /** - * Returns system-dependent renderer information. - * Returned strings can vary greatly between systems! Do not rely on it for - * anything! - **/ - RendererInfo getRendererInfo() const; - - /** - * Returns performance-related statistics. - **/ - Stats getStats() const; + void setWireframe(bool enable) override; + bool isSupported(Feature feature) const override; double getSystemLimit(SystemLimit limittype) const override; - - /** - * Gets whether a graphics feature is supported on this system. - **/ - bool isSupported(Feature feature) const; - - void push(StackType type = STACK_TRANSFORM); - void pop(); + RendererInfo getRendererInfo() const override; + Stats getStats() const override; private: - struct DisplayState - { - Colorf color = Colorf(1.0, 1.0, 1.0, 1.0); - Colorf gammaCorrectedColor = Colorf(1.0f, 1.0f, 1.0f, 1.0f); - Colorf backgroundColor = Colorf(0.0, 0.0, 0.0, 1.0); - - BlendMode blendMode = BLEND_ALPHA; - BlendAlpha blendAlphaMode = BLENDALPHA_MULTIPLY; - - float lineWidth = 1.0f; - LineStyle lineStyle = LINE_SMOOTH; - LineJoin lineJoin = LINE_JOIN_MITER; - - float pointSize = 1.0f; - - bool scissor = false; - Rect scissorRect = Rect(); - - // Stencil. - CompareMode stencilCompare = COMPARE_ALWAYS; - int stencilTestValue = 0; - - StrongRef font; - StrongRef shader; - - std::vector> canvases; - - ColorMask colorMask = ColorMask(true, true, true, true); - - bool wireframe = false; - - Texture::Filter defaultFilter = Texture::Filter(); - - Texture::FilterMode defaultMipmapFilter = Texture::FILTER_NEAREST; - float defaultMipmapSharpness = 0.0f; - }; - struct CachedRenderbuffer { int w; @@ -388,44 +143,18 @@ private: GLuint renderbuffer; }; - void restoreState(const DisplayState &s); - void restoreStateChecked(const DisplayState &s); - void endPass(); - void bindCachedFBO(const std::vector &canvases); + void bindCachedFBO(const std::vector &canvases); void discard(OpenGL::FramebufferTarget target, const std::vector &colorbuffers, bool depthstencil); GLuint attachCachedStencilBuffer(int w, int h, int samples); void setDebug(bool enable); - void checkSetDefaultFont(); - - StrongRef defaultFont; - - std::vector pendingScreenshotCallbacks; - std::unordered_map framebufferObjects; std::vector stencilBuffers; QuadIndices *quadIndices; - int width; - int height; - int pixelWidth; - int pixelHeight; - - bool created; - bool active; - - bool writingToStencil; - - std::vector states; - std::vector stackTypes; // Keeps track of the pushed stack types. - - int canvasSwitchCount; - - static const size_t MAX_USER_STACK_DEPTH = 64; - }; // Graphics } // opengl diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index 689d5b868..6fa175f67 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -49,9 +49,6 @@ int Image::imageCount = 0; float Image::maxMipmapSharpness = 0.0f; -Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_LINEAR; -float Image::defaultMipmapSharpness = 0.0f; - static int getMipmapCount(int basewidth, int baseheight) { return (int) log2(std::max(basewidth, baseheight)) + 1; @@ -553,26 +550,6 @@ const Image::Settings &Image::getFlags() const return settings; } -void Image::setDefaultMipmapSharpness(float sharpness) -{ - defaultMipmapSharpness = sharpness; -} - -float Image::getDefaultMipmapSharpness() -{ - return defaultMipmapSharpness; -} - -void Image::setDefaultMipmapFilter(Texture::FilterMode f) -{ - defaultMipmapFilter = f; -} - -Texture::FilterMode Image::getDefaultMipmapFilter() -{ - return defaultMipmapFilter; -} - bool Image::isCompressed() const { return compressed; diff --git a/src/modules/graphics/opengl/Image.h b/src/modules/graphics/opengl/Image.h index 4a408d9a1..28fda2e0d 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -116,11 +116,6 @@ public: const Settings &getFlags() const; - static void setDefaultMipmapSharpness(float sharpness); - static float getDefaultMipmapSharpness(); - static void setDefaultMipmapFilter(FilterMode f); - static FilterMode getDefaultMipmapFilter(); - static bool isFormatSupported(PixelFormat pixelformat); static bool hasSRGBSupport(); @@ -169,9 +164,6 @@ private: static float maxMipmapSharpness; - static FilterMode defaultMipmapFilter; - static float defaultMipmapSharpness; - static StringMap::Entry settingTypeEntries[]; static StringMap settingTypes; diff --git a/src/modules/graphics/opengl/Mesh.cpp b/src/modules/graphics/opengl/Mesh.cpp index 1d0250777..7bf974ea8 100644 --- a/src/modules/graphics/opengl/Mesh.cpp +++ b/src/modules/graphics/opengl/Mesh.cpp @@ -61,7 +61,7 @@ static std::vector getDefaultVertexFormat() love::Type Mesh::type("Mesh", &Drawable::type); -Mesh::Mesh(const std::vector &vertexformat, const void *data, size_t datasize, DrawMode drawmode, Usage usage) +Mesh::Mesh(const std::vector &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage) : vertexFormat(vertexformat) , vbo(nullptr) , vertexCount(0) @@ -83,12 +83,12 @@ Mesh::Mesh(const std::vector &vertexformat, const void *data, size if (vertexCount == 0) throw love::Exception("Data size is too small for specified vertex attribute formats."); - vbo = new GLBuffer(datasize, data, BUFFER_VERTEX, getGLBufferUsage(usage), GLBuffer::MAP_EXPLICIT_RANGE_MODIFY); + vbo = new GLBuffer(datasize, data, BUFFER_VERTEX, usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY); vertexScratchBuffer = new char[vertexStride]; } -Mesh::Mesh(const std::vector &vertexformat, int vertexcount, DrawMode drawmode, Usage usage) +Mesh::Mesh(const std::vector &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage) : vertexFormat(vertexformat) , vbo(nullptr) , vertexCount((size_t) vertexcount) @@ -109,7 +109,7 @@ Mesh::Mesh(const std::vector &vertexformat, int vertexcount, DrawM size_t buffersize = vertexCount * vertexStride; - vbo = new GLBuffer(buffersize, nullptr, BUFFER_VERTEX, getGLBufferUsage(usage), GLBuffer::MAP_EXPLICIT_RANGE_MODIFY); + vbo = new GLBuffer(buffersize, nullptr, BUFFER_VERTEX, usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY); // Initialize the buffer's contents to 0. memset(vbo->map(), 0, buffersize); @@ -119,12 +119,12 @@ Mesh::Mesh(const std::vector &vertexformat, int vertexcount, DrawM vertexScratchBuffer = new char[vertexStride]; } -Mesh::Mesh(const std::vector &vertices, DrawMode drawmode, Usage usage) +Mesh::Mesh(const std::vector &vertices, DrawMode drawmode, vertex::Usage usage) : Mesh(getDefaultVertexFormat(), &vertices[0], vertices.size() * sizeof(Vertex), drawmode, usage) { } -Mesh::Mesh(int vertexcount, DrawMode drawmode, Usage usage) +Mesh::Mesh(int vertexcount, DrawMode drawmode, vertex::Usage usage) : Mesh(getDefaultVertexFormat(), vertexcount, drawmode, usage) { } @@ -554,7 +554,7 @@ int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inpu if (Shader::getConstant(inputname.c_str(), builtinattrib)) attriblocation = (GLint) builtinattrib; else if (Shader::current) - attriblocation = Shader::current->getAttribLocation(inputname); + attriblocation = ((Shader *) Shader::current)->getAttribLocation(inputname); // The active shader might not use this vertex attribute name. if (attriblocation < 0) @@ -713,31 +713,6 @@ size_t Mesh::getGLDataTypeSize(GLenum datatype) } } -GLenum Mesh::getGLBufferUsage(Usage usage) -{ - switch (usage) - { - case USAGE_STREAM: - return GL_STREAM_DRAW; - case USAGE_DYNAMIC: - return GL_DYNAMIC_DRAW; - case USAGE_STATIC: - return GL_STATIC_DRAW; - default: - return 0; - } -} - -bool Mesh::getConstant(const char *in, Usage &out) -{ - return usages.find(in, out); -} - -bool Mesh::getConstant(Usage in, const char *&out) -{ - return usages.find(in, out); -} - bool Mesh::getConstant(const char *in, Mesh::DrawMode &out) { return drawModes.find(in, out); @@ -758,15 +733,6 @@ bool Mesh::getConstant(DataType in, const char *&out) return dataTypes.find(in, out); } -StringMap::Entry Mesh::usageEntries[] = -{ - {"stream", USAGE_STREAM}, - {"dynamic", USAGE_DYNAMIC}, - {"static", USAGE_STATIC}, -}; - -StringMap Mesh::usages(Mesh::usageEntries, sizeof(Mesh::usageEntries)); - StringMap::Entry Mesh::drawModeEntries[] = { {"fan", DRAWMODE_FAN}, diff --git a/src/modules/graphics/opengl/Mesh.h b/src/modules/graphics/opengl/Mesh.h index 3c99f352a..d86214234 100644 --- a/src/modules/graphics/opengl/Mesh.h +++ b/src/modules/graphics/opengl/Mesh.h @@ -28,6 +28,7 @@ #include "common/StringMap.h" #include "graphics/Drawable.h" #include "graphics/Texture.h" +#include "graphics/vertex.h" #include "GLBuffer.h" // C++ @@ -52,15 +53,6 @@ public: static love::Type type; - // The expected usage pattern of the Mesh's vertex data. - enum Usage - { - USAGE_STREAM, - USAGE_DYNAMIC, - USAGE_STATIC, - USAGE_MAX_ENUM - }; - // How the Mesh's vertices are used when drawing. // http://escience.anu.edu.au/lecture/cg/surfaceModeling/image/surfaceModeling015.png enum DrawMode @@ -87,11 +79,11 @@ public: int components; // max 4 }; - Mesh(const std::vector &vertexformat, const void *data, size_t datasize, DrawMode drawmode, Usage usage); - Mesh(const std::vector &vertexformat, int vertexcount, DrawMode drawmode, Usage usage); + Mesh(const std::vector &vertexformat, const void *data, size_t datasize, DrawMode drawmode, vertex::Usage usage); + Mesh(const std::vector &vertexformat, int vertexcount, DrawMode drawmode, vertex::Usage usage); - Mesh(const std::vector &vertices, DrawMode drawmode, Usage usage); - Mesh(int vertexcount, DrawMode drawmode, Usage usage); + Mesh(const std::vector &vertices, DrawMode drawmode, vertex::Usage usage); + Mesh(int vertexcount, DrawMode drawmode, vertex::Usage usage); virtual ~Mesh(); @@ -202,11 +194,6 @@ public: // Implements Drawable. void draw(Graphics *gfx, const Matrix4 &m) override; - static GLenum getGLBufferUsage(Usage usage); - - static bool getConstant(const char *in, Usage &out); - static bool getConstant(Usage in, const char *&out); - static bool getConstant(const char *in, DrawMode &out); static bool getConstant(DrawMode in, const char *&out); @@ -260,9 +247,6 @@ private: StrongRef texture; - static StringMap::Entry usageEntries[]; - static StringMap usages; - static StringMap::Entry drawModeEntries[]; static StringMap drawModes; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 643adab02..f7d6f5c39 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -336,7 +336,7 @@ void OpenGL::prepareDraw() // Make sure the active shader's love-provided uniforms are up to date. if (Shader::current != nullptr) - Shader::current->checkSetBuiltinUniforms(); + ((Shader *)Shader::current)->checkSetBuiltinUniforms(); } GLenum OpenGL::getGLBufferType(BufferType type) @@ -352,6 +352,21 @@ GLenum OpenGL::getGLBufferType(BufferType type) } } +GLenum OpenGL::getGLBufferUsage(vertex::Usage usage) +{ + switch (usage) + { + case vertex::USAGE_STREAM: + return GL_STREAM_DRAW; + case vertex::USAGE_DYNAMIC: + return GL_DYNAMIC_DRAW; + case vertex::USAGE_STATIC: + return GL_STATIC_DRAW; + default: + return 0; + } +} + void OpenGL::bindBuffer(BufferType type, GLuint buffer) { if (state.boundBuffers[type] != buffer) diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 12911d759..c7bd197b0 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -52,25 +52,6 @@ namespace opengl // no clashes with other GL libraries when linking, etc. using namespace glad; -// Vertex attribute indices used in shaders by LOVE. The values map to OpenGL -// generic vertex attribute indices. -enum VertexAttribID -{ - ATTRIB_POS = 0, - ATTRIB_TEXCOORD, - ATTRIB_COLOR, - ATTRIB_CONSTANTCOLOR, - ATTRIB_MAX_ENUM -}; - -enum VertexAttribFlags -{ - ATTRIBFLAG_POS = 1 << ATTRIB_POS, - ATTRIBFLAG_TEXCOORD = 1 << ATTRIB_TEXCOORD, - ATTRIBFLAG_COLOR = 1 << ATTRIB_COLOR, - ATTRIBFLAG_CONSTANTCOLOR = 1 << ATTRIB_CONSTANTCOLOR -}; - /** * Thin layer between OpenGL and the rest of the program. * Internally shadows some OpenGL context state for improved efficiency and @@ -377,6 +358,7 @@ public: Vendor getVendor() const; static GLenum getGLBufferType(BufferType type); + static GLenum getGLBufferUsage(vertex::Usage usage); static GLint getGLWrapMode(Texture::WrapMode wmode); static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB); diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index 70c1b0754..469d5e56d 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -42,7 +42,7 @@ namespace // reattaches the originally active program when destroyed struct TemporaryAttacher { - TemporaryAttacher(Shader *shader, bool attachNow) + TemporaryAttacher(graphics::Shader *shader, bool attachNow) : curShader(shader) , prevShader(Shader::current) { @@ -55,7 +55,7 @@ namespace if (prevShader != nullptr) prevShader->attach(); else - curShader->detach(); + Shader::attachDefault(); } void attach() @@ -63,20 +63,11 @@ namespace curShader->attach(true); } - Shader *curShader; - Shader *prevShader; + graphics::Shader *curShader; + graphics::Shader *prevShader; }; } // anonymous namespace - -love::Type Shader::type("Shader", &Object::type); -Shader *Shader::current = nullptr; -Shader *Shader::defaultShader = nullptr; -Shader *Shader::defaultVideoShader = nullptr; - -Shader::ShaderSource Shader::defaultCode[Graphics::RENDERER_MAX_ENUM][2]; -Shader::ShaderSource Shader::defaultVideoCode[Graphics::RENDERER_MAX_ENUM][2]; - Shader::Shader(const ShaderSource &source) : shaderSource(source) , program(0) @@ -96,9 +87,6 @@ Shader::Shader(const ShaderSource &source) Shader::~Shader() { - if (current == this) - detach(); - unloadVolatile(); for (const auto &p : uniforms) @@ -125,7 +113,7 @@ GLuint Shader::compileCode(ShaderStage stage, const std::string &code) GLenum glstage; const char *typestr; - if (!stageNames.find(stage, typestr)) + if (!getConstant(stage, typestr)) typestr = ""; switch (stage) @@ -232,7 +220,7 @@ void Shader::mapActiveUniforms() // If this is a built-in (LOVE-created) uniform, store the location. BuiltinUniform builtin; - if (builtinNames.find(u.name.c_str(), builtin)) + if (getConstant(u.name.c_str(), builtin)) builtinUniforms[int(builtin)] = u.location; if (u.location == -1) @@ -397,9 +385,9 @@ bool Shader::loadVolatile() std::vector shaderids; bool gammacorrect = graphics::isGammaCorrect(); - const ShaderSource *defaults = &defaultCode[Graphics::RENDERER_OPENGL][gammacorrect ? 1 : 0]; + const ShaderSource *defaults = &Graphics::defaultShaderCode[Graphics::RENDERER_OPENGL][gammacorrect ? 1 : 0]; if (GLAD_ES_VERSION_2_0) - defaults = &defaultCode[Graphics::RENDERER_OPENGLES][gammacorrect ? 1 : 0]; + defaults = &Graphics::defaultShaderCode[Graphics::RENDERER_OPENGLES][gammacorrect ? 1 : 0]; // The shader program must have both vertex and pixel shader stages. const std::string &vertexcode = shaderSource.vertex.empty() ? defaults->vertex : shaderSource.vertex; @@ -433,7 +421,7 @@ bool Shader::loadVolatile() for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++) { const char *name = nullptr; - if (attribNames.find((VertexAttribID) i, name)) + if (getConstant((VertexAttribID) i, name)) glBindAttribLocation(program, i, (const GLchar *) name); } @@ -460,7 +448,7 @@ bool Shader::loadVolatile() for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++) { const char *name = nullptr; - if (attribNames.find(VertexAttribID(i), name)) + if (getConstant(VertexAttribID(i), name)) builtinAttributes[i] = glGetAttribLocation(program, name); else builtinAttributes[i] = -1; @@ -529,7 +517,7 @@ std::string Shader::getWarnings() const // Get the individual shader stage warnings for (const auto &warning : shaderWarnings) { - if (stageNames.find(warning.first, stagestr)) + if (getConstant(warning.first, stagestr)) warnings += std::string(stagestr) + std::string(" shader:\n") + warning.second; } @@ -565,22 +553,6 @@ void Shader::attach(bool temporary) } } -void Shader::detach() -{ - if (defaultShader) - { - if (current != defaultShader) - defaultShader->attach(); - - return; - } - - if (current != nullptr) - gl.useProgram(0); - - current = nullptr; -} - const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const { const auto it = uniforms.find(name); @@ -777,11 +749,6 @@ GLint Shader::getAttribLocation(const std::string &name) return location; } -bool Shader::hasVertexAttrib(VertexAttribID attrib) const -{ - return builtinAttributes[int(attrib)] != -1; -} - void Shader::setVideoTextures(GLuint ytexture, GLuint cbtexture, GLuint crtexture) { // Set up the texture units that will be used by the shader to sample from @@ -797,9 +764,9 @@ void Shader::setVideoTextures(GLuint ytexture, GLuint cbtexture, GLuint crtextur }; const char *names[3] = {nullptr, nullptr, nullptr}; - builtinNames.find(BUILTIN_VIDEO_Y_CHANNEL, names[0]); - builtinNames.find(BUILTIN_VIDEO_CB_CHANNEL, names[1]); - builtinNames.find(BUILTIN_VIDEO_CR_CHANNEL, names[2]); + getConstant(BUILTIN_VIDEO_Y_CHANNEL, names[0]); + getConstant(BUILTIN_VIDEO_CB_CHANNEL, names[1]); + getConstant(BUILTIN_VIDEO_CR_CHANNEL, names[2]); for (int i = 0; i < 3; i++) { @@ -1093,71 +1060,6 @@ Shader::UniformType Shader::getUniformBaseType(GLenum type) const } } -bool Shader::getConstant(const char *in, UniformType &out) -{ - return uniformTypes.find(in, out); -} - -bool Shader::getConstant(UniformType in, const char *&out) -{ - return uniformTypes.find(in, out); -} - -bool Shader::getConstant(const char *in, VertexAttribID &out) -{ - return attribNames.find(in, out); -} - -bool Shader::getConstant(VertexAttribID in, const char *&out) -{ - return attribNames.find(in, out); -} - -StringMap::Entry Shader::stageNameEntries[] = -{ - {"vertex", Shader::STAGE_VERTEX}, - {"pixel", Shader::STAGE_PIXEL}, -}; - -StringMap Shader::stageNames(Shader::stageNameEntries, sizeof(Shader::stageNameEntries)); - -StringMap::Entry Shader::uniformTypeEntries[] = -{ - {"float", Shader::UNIFORM_FLOAT}, - {"matrix", Shader::UNIFORM_MATRIX}, - {"int", Shader::UNIFORM_INT}, - {"bool", Shader::UNIFORM_BOOL}, - {"image", Shader::UNIFORM_SAMPLER}, - {"unknown", Shader::UNIFORM_UNKNOWN}, -}; - -StringMap Shader::uniformTypes(Shader::uniformTypeEntries, sizeof(Shader::uniformTypeEntries)); - -StringMap::Entry Shader::attribNameEntries[] = -{ - {"VertexPosition", ATTRIB_POS}, - {"VertexTexCoord", ATTRIB_TEXCOORD}, - {"VertexColor", ATTRIB_COLOR}, - {"ConstantColor", ATTRIB_CONSTANTCOLOR}, -}; - -StringMap Shader::attribNames(Shader::attribNameEntries, sizeof(Shader::attribNameEntries)); - -StringMap::Entry Shader::builtinNameEntries[] = -{ - {"TransformMatrix", Shader::BUILTIN_TRANSFORM_MATRIX}, - {"ProjectionMatrix", Shader::BUILTIN_PROJECTION_MATRIX}, - {"TransformProjectionMatrix", Shader::BUILTIN_TRANSFORM_PROJECTION_MATRIX}, - {"NormalMatrix", Shader::BUILTIN_NORMAL_MATRIX}, - {"love_PointSize", Shader::BUILTIN_POINT_SIZE}, - {"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE}, - {"love_VideoYChannel", Shader::BUILTIN_VIDEO_Y_CHANNEL}, - {"love_VideoCbChannel", Shader::BUILTIN_VIDEO_CB_CHANNEL}, - {"love_VideoCrChannel", Shader::BUILTIN_VIDEO_CR_CHANNEL}, -}; - -StringMap Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries)); - } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index d74be1c42..0df1a75f9 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -18,14 +18,11 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#ifndef LOVE_GRAPHICS_SHADER_H -#define LOVE_GRAPHICS_SHADER_H +#pragma once // LOVE -#include "common/Object.h" -#include "common/StringMap.h" +#include "graphics/Shader.h" #include "graphics/Graphics.h" -#include "graphics/Texture.h" #include "graphics/Volatile.h" #include "OpenGL.h" @@ -42,93 +39,10 @@ namespace opengl { // A GLSL shader -class Shader : public Object, public Volatile +class Shader final : public love::graphics::Shader, public Volatile { public: - static love::Type type; - - enum ShaderStage - { - STAGE_VERTEX, - STAGE_PIXEL, - STAGE_MAX_ENUM - }; - - // Built-in uniform variables. - enum BuiltinUniform - { - BUILTIN_TRANSFORM_MATRIX = 0, - BUILTIN_PROJECTION_MATRIX, - BUILTIN_TRANSFORM_PROJECTION_MATRIX, - BUILTIN_NORMAL_MATRIX, - BUILTIN_POINT_SIZE, - BUILTIN_SCREEN_SIZE, - BUILTIN_VIDEO_Y_CHANNEL, - BUILTIN_VIDEO_CB_CHANNEL, - BUILTIN_VIDEO_CR_CHANNEL, - BUILTIN_MAX_ENUM - }; - - // Types of potential uniform variables used in love's shaders. - enum UniformType - { - UNIFORM_FLOAT, - UNIFORM_MATRIX, - UNIFORM_INT, - UNIFORM_BOOL, - UNIFORM_SAMPLER, - UNIFORM_UNKNOWN, - UNIFORM_MAX_ENUM - }; - - struct ShaderSource - { - std::string vertex; - std::string pixel; - }; - - struct MatrixSize - { - short columns; - short rows; - }; - - struct UniformInfo - { - int location; - int count; - - union - { - int components; - MatrixSize matrix; - }; - - UniformType baseType; - std::string name; - - union - { - void *data; - float *floats; - int *ints; - }; - - Texture **textures; - }; - - // Pointer to currently active Shader. - static Shader *current; - - // Pointer to the default Shader. - static Shader *defaultShader; - static Shader *defaultVideoShader; - - // Default shader code (a shader is always required internally.) - static ShaderSource defaultCode[Graphics::RENDERER_MAX_ENUM][2]; - static ShaderSource defaultVideoCode[Graphics::RENDERER_MAX_ENUM][2]; - /** * Creates a new Shader using a list of source codes. * Source must contain either vertex or pixel shader code, or both. @@ -138,45 +52,19 @@ public: virtual ~Shader(); // Implements Volatile - virtual bool loadVolatile(); - virtual void unloadVolatile(); + bool loadVolatile() override; + void unloadVolatile() override; - /** - * Binds this Shader's program to be used when rendering. - * - * @param temporary True if we just want to send values to the shader with no intention of rendering. - **/ - void attach(bool temporary = false); - - /** - * Detach the currently bound Shader. - * Causes the GPU rendering pipeline to use fixed functionality in place of shader programs. - **/ - static void detach(); - - /** - * Returns any warnings this Shader may have generated. - **/ - std::string getWarnings() const; - - const UniformInfo *getUniformInfo(const std::string &name) const; - void updateUniform(const UniformInfo *info, int count, bool internalUpdate = false); - - void sendTextures(const UniformInfo *info, Texture **textures, int count, bool internalUpdate = false); - - /** - * Gets whether a uniform with the specified name exists and is actively - * used in the shader. - **/ - bool hasUniform(const std::string &name) const; + // Implements Shader. + void attach(bool temporary = false) override; + std::string getWarnings() const override; + const UniformInfo *getUniformInfo(const std::string &name) const override; + void updateUniform(const UniformInfo *info, int count, bool internalUpdate = false) override; + void sendTextures(const UniformInfo *info, Texture **textures, int count, bool internalUpdate = false) override; + bool hasUniform(const std::string &name) const override; GLint getAttribLocation(const std::string &name); - /** - * Internal use only. - **/ - bool hasVertexAttrib(VertexAttribID attrib) const; - void setVideoTextures(GLuint ytexture, GLuint cbtexture, GLuint crtexture); void checkSetScreenParams(); void checkSetPointSize(float size); @@ -190,12 +78,6 @@ public: static std::string getGLSLVersion(); static bool isSupported(); - static bool getConstant(const char *in, UniformType &out); - static bool getConstant(UniformType in, const char *&out); - - static bool getConstant(const char *in, VertexAttribID &out); - static bool getConstant(VertexAttribID in, const char *&out); - private: struct TextureUnit @@ -255,23 +137,8 @@ private: GLuint videoTextureUnits[3]; - static StringMap::Entry stageNameEntries[]; - static StringMap stageNames; - - static StringMap::Entry uniformTypeEntries[]; - static StringMap uniformTypes; - - // Names for the generic vertex attributes used by love. - static StringMap::Entry attribNameEntries[]; - static StringMap attribNames; - - // Names for the built-in uniform variables. - static StringMap::Entry builtinNameEntries[]; - static StringMap builtinNames; -}; +}; // Shader } // opengl } // graphics } // love - -#endif // LOVE_GRAPHICS_SHADER_H diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index 73b887831..ba50e63ee 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -44,7 +44,7 @@ namespace opengl love::Type SpriteBatch::type("SpriteBatch", &Drawable::type); -SpriteBatch::SpriteBatch(Texture *texture, int size, Mesh::Usage usage) +SpriteBatch::SpriteBatch(Texture *texture, int size, vertex::Usage usage) : texture(texture) , size(size) , next(0) @@ -57,10 +57,9 @@ SpriteBatch::SpriteBatch(Texture *texture, int size, Mesh::Usage usage) if (size <= 0) throw love::Exception("Invalid SpriteBatch size."); - GLenum gl_usage = Mesh::getGLBufferUsage(usage); size_t vertex_size = sizeof(Vertex) * 4 * size; - array_buf = new GLBuffer(vertex_size, nullptr, BUFFER_VERTEX, gl_usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY); + array_buf = new GLBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, GLBuffer::MAP_EXPLICIT_RANGE_MODIFY); } SpriteBatch::~SpriteBatch() diff --git a/src/modules/graphics/opengl/SpriteBatch.h b/src/modules/graphics/opengl/SpriteBatch.h index 98b53c9e6..a6c3a6488 100644 --- a/src/modules/graphics/opengl/SpriteBatch.h +++ b/src/modules/graphics/opengl/SpriteBatch.h @@ -54,7 +54,7 @@ public: static love::Type type; - SpriteBatch(Texture *texture, int size, Mesh::Usage usage); + SpriteBatch(Texture *texture, int size, vertex::Usage usage); virtual ~SpriteBatch(); int add(const Matrix4 &m, int index = -1); diff --git a/src/modules/graphics/opengl/Text.cpp b/src/modules/graphics/opengl/Text.cpp index d04d4af22..94df6cc26 100644 --- a/src/modules/graphics/opengl/Text.cpp +++ b/src/modules/graphics/opengl/Text.cpp @@ -62,7 +62,7 @@ void Text::uploadVertices(const std::vector &vertices, size_t if (vbo != nullptr) newsize = std::max(size_t(vbo->getSize() * 1.5), newsize); - GLBuffer *new_vbo = new GLBuffer(newsize, nullptr, BUFFER_VERTEX, GL_DYNAMIC_DRAW); + GLBuffer *new_vbo = new GLBuffer(newsize, nullptr, BUFFER_VERTEX, vertex::USAGE_DYNAMIC); if (vbo != nullptr) { diff --git a/src/modules/graphics/opengl/Video.cpp b/src/modules/graphics/opengl/Video.cpp index 57be2e92a..9d8e56bc8 100644 --- a/src/modules/graphics/opengl/Video.cpp +++ b/src/modules/graphics/opengl/Video.cpp @@ -37,7 +37,7 @@ Video::Video(love::video::VideoStream *stream, float pixeldensity) : stream(stream) , width(stream->getWidth() / pixeldensity) , height(stream->getHeight() / pixeldensity) - , filter(Texture::getDefaultFilter()) + , filter(Texture::defaultFilter) { filter.mipmap = Texture::FILTER_NONE; @@ -124,13 +124,13 @@ void Video::draw(Graphics *gfx, const Matrix4 &m) gfx->flushStreamDraws(); - Shader *shader = Shader::current; + Shader *shader = (Shader *) Shader::current; bool defaultShader = (shader == Shader::defaultShader); if (defaultShader) { // If we're still using the default shader, substitute the video version Shader::defaultVideoShader->attach(); - shader = Shader::defaultVideoShader; + shader = (Shader *) Shader::defaultVideoShader; } shader->setVideoTextures(textures[0], textures[1], textures[2]); diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 93dba6917..0077e1596 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -153,7 +153,7 @@ int w_isActive(lua_State *L) int w_isGammaCorrect(lua_State *L) { - luax_pushboolean(L, instance()->isGammaCorrect()); + luax_pushboolean(L, graphics::isGammaCorrect()); return 1; } @@ -214,7 +214,7 @@ int w_setCanvas(lua_State *L) } bool is_table = lua_istable(L, 1); - std::vector canvases; + std::vector canvases; if (is_table) { @@ -243,10 +243,10 @@ int w_setCanvas(lua_State *L) int w_getCanvas(lua_State *L) { - const std::vector canvases = instance()->getCanvas(); + const std::vector canvases = instance()->getCanvas(); int n = 0; - for (Canvas *c : canvases) + for (love::graphics::Canvas *c : canvases) { luax_pushtype(L, c); n++; @@ -644,12 +644,12 @@ int w_newSpriteBatch(lua_State *L) Texture *texture = luax_checktexture(L, 1); int size = (int) luaL_optnumber(L, 2, 1000); - Mesh::Usage usage = Mesh::USAGE_DYNAMIC; + vertex::Usage usage = vertex::USAGE_DYNAMIC; if (lua_gettop(L) > 2) { const char *usagestr = luaL_checkstring(L, 3); - if (!Mesh::getConstant(usagestr, usage)) - return luaL_error(L, "Invalid SpriteBatch usage hint: %s", usagestr); + if (!vertex::getConstant(usagestr, usage)) + return luaL_error(L, "Invalid usage hint: %s", usagestr); } SpriteBatch *t = nullptr; @@ -709,7 +709,7 @@ int w_newCanvas(lua_State *L) settings.msaa = luax_intflag(L, 3, "msaa", settings.msaa); } - Canvas *canvas = nullptr; + love::graphics::Canvas *canvas = nullptr; luax_catchexcept(L, [&](){ canvas = instance()->newCanvas(width, height, settings); }); if (canvas == nullptr) @@ -807,7 +807,7 @@ int w_newShader(lua_State *L) bool should_error = false; try { - Shader *shader = instance()->newShader(source); + love::graphics::Shader *shader = instance()->newShader(source); luax_pushtype(L, shader); shader->release(); } @@ -827,12 +827,12 @@ int w_newShader(lua_State *L) return 1; } -static Mesh::Usage luax_optmeshusage(lua_State *L, int idx, Mesh::Usage def) +static vertex::Usage luax_optmeshusage(lua_State *L, int idx, vertex::Usage def) { const char *usagestr = lua_isnoneornil(L, idx) ? nullptr : luaL_checkstring(L, idx); - if (usagestr && !Mesh::getConstant(usagestr, def)) - luaL_error(L, "Invalid mesh usage hint: %s", usagestr); + if (usagestr && !vertex::getConstant(usagestr, def)) + luaL_error(L, "Invalid usage hint: %s", usagestr); return def; } @@ -852,7 +852,7 @@ static Mesh *newStandardMesh(lua_State *L) Mesh *t = nullptr; Mesh::DrawMode drawmode = luax_optmeshdrawmode(L, 2, Mesh::DRAWMODE_FAN); - Mesh::Usage usage = luax_optmeshusage(L, 3, Mesh::USAGE_DYNAMIC); + vertex::Usage usage = luax_optmeshusage(L, 3, vertex::USAGE_DYNAMIC); // First argument is a table of standard vertices, or the number of // standard vertices. @@ -912,7 +912,7 @@ static Mesh *newCustomMesh(lua_State *L) std::vector vertexformat; Mesh::DrawMode drawmode = luax_optmeshdrawmode(L, 3, Mesh::DRAWMODE_FAN); - Mesh::Usage usage = luax_optmeshusage(L, 4, Mesh::USAGE_DYNAMIC); + vertex::Usage usage = luax_optmeshusage(L, 4, vertex::USAGE_DYNAMIC); lua_rawgeti(L, 1, 1); if (!lua_istable(L, -1)) @@ -1410,14 +1410,14 @@ int w_setShader(lua_State *L) return 0; } - Shader *shader = luax_checkshader(L, 1); + love::graphics::Shader *shader = luax_checkshader(L, 1); instance()->setShader(shader); return 0; } int w_getShader(lua_State *L) { - Shader *shader = instance()->getShader(); + love::graphics::Shader *shader = instance()->getShader(); if (shader) luax_pushtype(L, shader); else @@ -1453,8 +1453,8 @@ int w_setDefaultShaderCode(lua_State *L) lua_pop(L, 4); - Shader::defaultCode[renderer][i] = code; - Shader::defaultVideoCode[renderer][i] = videocode; + Graphics::defaultShaderCode[renderer][i] = code; + Graphics::defaultVideoShaderCode[renderer][i] = videocode; } } diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index 9795a6718..7ff9b73a0 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -28,8 +28,8 @@ #include "graphics/wrap_Quad.h" #include "wrap_SpriteBatch.h" #include "wrap_ParticleSystem.h" -#include "wrap_Canvas.h" -#include "wrap_Shader.h" +#include "graphics/wrap_Canvas.h" +#include "graphics/wrap_Shader.h" #include "wrap_Mesh.h" #include "wrap_Text.h" #include "wrap_Video.h" diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 8bd6b7003..02bab1501 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -19,6 +19,7 @@ **/ #include "vertex.h" +#include "common/StringMap.h" namespace love { @@ -129,6 +130,25 @@ void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, fillIndicesT(mode, vertexStart, vertexCount, indices); } +static StringMap::Entry usageEntries[] = +{ + { "stream", USAGE_STREAM }, + { "dynamic", USAGE_DYNAMIC }, + { "static", USAGE_STATIC }, +}; + +static StringMap usages(usageEntries, sizeof(usageEntries)); + +bool getConstant(const char *in, Usage &out) +{ + return usages.find(in, out); +} + +bool getConstant(Usage in, const char *&out) +{ + return usages.find(in, out); +} + } // vertex } // graphics } // love diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index ba9998870..621028bc5 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -32,6 +32,25 @@ namespace love namespace graphics { +// Vertex attribute indices used in shaders by LOVE. The values map to OpenGL +// generic vertex attribute indices. +enum VertexAttribID +{ + ATTRIB_POS = 0, + ATTRIB_TEXCOORD, + ATTRIB_COLOR, + ATTRIB_CONSTANTCOLOR, + ATTRIB_MAX_ENUM +}; + +enum VertexAttribFlags +{ + ATTRIBFLAG_POS = 1 << ATTRIB_POS, + ATTRIBFLAG_TEXCOORD = 1 << ATTRIB_TEXCOORD, + ATTRIBFLAG_COLOR = 1 << ATTRIB_COLOR, + ATTRIBFLAG_CONSTANTCOLOR = 1 << ATTRIB_CONSTANTCOLOR +}; + enum BufferType { BUFFER_VERTEX = 0, @@ -42,6 +61,15 @@ enum BufferType namespace vertex { +// The expected usage pattern of vertex data. +enum Usage +{ + USAGE_STREAM, + USAGE_DYNAMIC, + USAGE_STATIC, + USAGE_MAX_ENUM +}; + enum class PrimitiveMode { TRIANGLES, @@ -93,6 +121,9 @@ int getIndexCount(TriangleIndexMode mode, int vertexCount); void fillIndices(TriangleIndexMode mode, uint16 vertexStart, uint16 vertexCount, uint16 *indices); void fillIndices(TriangleIndexMode mode, uint32 vertexStart, uint32 vertexCount, uint32 *indices); +bool getConstant(const char *in, Usage &out); +bool getConstant(Usage in, const char *&out); + } // vertex typedef vertex::XYf_STf_RGBAub Vertex; diff --git a/src/modules/graphics/opengl/wrap_Canvas.cpp b/src/modules/graphics/wrap_Canvas.cpp similarity index 99% rename from src/modules/graphics/opengl/wrap_Canvas.cpp rename to src/modules/graphics/wrap_Canvas.cpp index bc4dfef83..3d9457a20 100644 --- a/src/modules/graphics/opengl/wrap_Canvas.cpp +++ b/src/modules/graphics/wrap_Canvas.cpp @@ -25,8 +25,6 @@ namespace love { namespace graphics { -namespace opengl -{ Canvas *luax_checkcanvas(lua_State *L, int idx) { @@ -115,6 +113,5 @@ extern "C" int luaopen_canvas(lua_State *L) return luax_register_type(L, &Canvas::type, w_Texture_functions, w_Canvas_functions, nullptr); } -} // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/wrap_Canvas.h b/src/modules/graphics/wrap_Canvas.h similarity index 85% rename from src/modules/graphics/opengl/wrap_Canvas.h rename to src/modules/graphics/wrap_Canvas.h index 806be0c34..951acef2e 100644 --- a/src/modules/graphics/opengl/wrap_Canvas.h +++ b/src/modules/graphics/wrap_Canvas.h @@ -18,27 +18,21 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#ifndef LOVE_GRAPHICS_OPENGL_WRAP_CANVAS_H -#define LOVE_GRAPHICS_OPENGL_WRAP_CANVAS_H +#pragma once // LOVE #include "common/runtime.h" #include "Canvas.h" -#include "graphics/wrap_Texture.h" +#include "wrap_Texture.h" namespace love { namespace graphics { -namespace opengl -{ //see Canvas.h Canvas *luax_checkcanvas(lua_State *L, int idx); extern "C" int luaopen_canvas(lua_State *L); -} // opengl } // graphics } // love - -#endif // LOVE_GRAPHICS_OPENGL_WRAP_CANVAS_H diff --git a/src/modules/graphics/opengl/wrap_Shader.cpp b/src/modules/graphics/wrap_Shader.cpp similarity index 99% rename from src/modules/graphics/opengl/wrap_Shader.cpp rename to src/modules/graphics/wrap_Shader.cpp index f15db4b35..b6d8638b1 100644 --- a/src/modules/graphics/opengl/wrap_Shader.cpp +++ b/src/modules/graphics/wrap_Shader.cpp @@ -19,9 +19,10 @@ **/ #include "wrap_Shader.h" -#include "graphics/wrap_Texture.h" +#include "wrap_Texture.h" #include "math/MathModule.h" #include "math/Transform.h" +#include "Graphics.h" #include #include @@ -31,8 +32,6 @@ namespace love { namespace graphics { -namespace opengl -{ Shader *luax_checkshader(lua_State *L, int idx) { @@ -331,7 +330,6 @@ extern "C" int luaopen_shader(lua_State *L) return luax_register_type(L, &Shader::type, w_Shader_functions, nullptr); } -} // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/wrap_Shader.h b/src/modules/graphics/wrap_Shader.h similarity index 90% rename from src/modules/graphics/opengl/wrap_Shader.h rename to src/modules/graphics/wrap_Shader.h index b26026fad..35656ca47 100644 --- a/src/modules/graphics/opengl/wrap_Shader.h +++ b/src/modules/graphics/wrap_Shader.h @@ -18,8 +18,7 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#ifndef LOVE_GRAPHICS_OPENGL_WRAP_PROGRAM_H -#define LOVE_GRAPHICS_OPENGL_WRAP_PROGRAM_H +#pragma once #include "common/runtime.h" #include "common/config.h" @@ -29,14 +28,9 @@ namespace love { namespace graphics { -namespace opengl -{ Shader *luax_checkshader(lua_State *L, int idx); extern "C" int luaopen_shader(lua_State *L); -} // opengl } // graphics } // love - -#endif