diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 63064c01a..1d94be244 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -1453,7 +1453,7 @@ FA0B7B891A95902C000E1D17 /* Drawable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Drawable.h; sourceTree = ""; }; FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Graphics.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; FA0B7B8B1A95902C000E1D17 /* Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Graphics.h; sourceTree = ""; }; - FA0B7B8D1A95902C000E1D17 /* Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Canvas.cpp; sourceTree = ""; }; + FA0B7B8D1A95902C000E1D17 /* Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Canvas.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; FA0B7B8E1A95902C000E1D17 /* Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Canvas.h; sourceTree = ""; }; FA0B7B911A95902C000E1D17 /* Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Graphics.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; FA0B7B921A95902C000E1D17 /* Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Graphics.h; sourceTree = ""; }; @@ -1725,9 +1725,9 @@ 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 = ""; }; + FA1BA0A51E16F20600AA2803 /* Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Canvas.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + FA1BA0A61E16F20600AA2803 /* Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Canvas.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + FA1BA0AA1E16F9EE00AA2803 /* wrap_Canvas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = wrap_Canvas.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 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 = ""; }; diff --git a/src/common/Matrix.cpp b/src/common/Matrix.cpp index 32e4b4ff8..a9374765a 100644 --- a/src/common/Matrix.cpp +++ b/src/common/Matrix.cpp @@ -250,6 +250,12 @@ void Matrix4::shear(float kx, float ky) this->operator *=(t); } +bool Matrix4::isAffine2DTransform() const +{ + return fabsf(e[2] + e[3] + e[6] + e[7] + e[8] + e[9] + e[11] + e[14]) < 0.00001f + && fabsf(e[10] + e[15] - 2.0f) < 0.00001f; +} + Matrix4 Matrix4::inverse() const { Matrix4 inv; diff --git a/src/common/Matrix.h b/src/common/Matrix.h index 83f0edce6..07af79018 100644 --- a/src/common/Matrix.h +++ b/src/common/Matrix.h @@ -195,6 +195,13 @@ public: template void transform(Vdst *dst, const Vsrc *src, int size) const; + /** + * Gets whether this matrix is an affine 2D transform (if the only non- + * identity elements are the upper-left 4x4 and 2 translation values in the + * 4th column). + **/ + bool isAffine2DTransform() const; + /** * Computes and returns the inverse of the matrix. **/ diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp index f5446f268..7ec5d68ed 100644 --- a/src/modules/graphics/Canvas.cpp +++ b/src/modules/graphics/Canvas.cpp @@ -62,10 +62,10 @@ Canvas::Canvas(const Settings &settings) if (readable && isPixelFormatDepthStencil(format) && settings.msaa > 1) throw love::Exception("Readable depth/stencil Canvases with MSAA are not currently supported."); - if ((!readable || settings.msaa > 1) && settings.mipmaps != MIPMAP_NONE) + if ((!readable || settings.msaa > 1) && settings.mipmaps != MIPMAPS_NONE) throw love::Exception("Non-readable and MSAA textures cannot have mipmaps."); - mipmapCount = settings.mipmaps == MIPMAP_NONE ? 1 : getMipmapCount(pixelWidth, pixelHeight); + mipmapCount = settings.mipmaps == MIPMAPS_NONE ? 1 : getMipmapCount(pixelWidth, pixelHeight); canvasCount++; } @@ -111,14 +111,14 @@ bool Canvas::getConstant(MipmapMode in, const char *&out) return mipmapModes.find(in, out); } -StringMap::Entry Canvas::mipmapEntries[] = +StringMap::Entry Canvas::mipmapEntries[] = { - { "none", MIPMAP_NONE }, - { "manual", MIPMAP_MANUAL }, - { "auto", MIPMAP_AUTO }, + { "none", MIPMAPS_NONE }, + { "manual", MIPMAPS_MANUAL }, + { "auto", MIPMAPS_AUTO }, }; -StringMap Canvas::mipmapModes(Canvas::mipmapEntries, sizeof(Canvas::mipmapEntries)); +StringMap Canvas::mipmapModes(Canvas::mipmapEntries, sizeof(Canvas::mipmapEntries)); } // graphics } // love diff --git a/src/modules/graphics/Canvas.h b/src/modules/graphics/Canvas.h index 62e36d6e2..13aaae135 100644 --- a/src/modules/graphics/Canvas.h +++ b/src/modules/graphics/Canvas.h @@ -41,10 +41,10 @@ public: enum MipmapMode { - MIPMAP_NONE, - MIPMAP_MANUAL, - MIPMAP_AUTO, - MIPMAP_MAX_ENUM + MIPMAPS_NONE, + MIPMAPS_MANUAL, + MIPMAPS_AUTO, + MIPMAPS_MAX_ENUM }; struct Settings @@ -52,7 +52,7 @@ public: int width = 1; int height = 1; int layers = 1; // depth for 3D textures - MipmapMode mipmaps = MIPMAP_NONE; + MipmapMode mipmaps = MIPMAPS_NONE; PixelFormat format = PIXELFORMAT_NORMAL; TextureType type = TEXTURE_2D; float pixeldensity = 1.0f; @@ -86,8 +86,8 @@ protected: private: - static StringMap::Entry mipmapEntries[]; - static StringMap mipmapModes; + static StringMap::Entry mipmapEntries[]; + static StringMap mipmapModes; }; // Canvas diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 5c654204b..1542312e6 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -593,6 +593,16 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest & if (state.vertexCount == 0 && Shader::current != nullptr && req.texture != nullptr) Shader::current->checkMainTexture(req.texture); + if (!getTransform().isAffine2DTransform()) + { + for (CommonFormat fmt : req.formats) + { + int components = getFormatPositionComponents(fmt); + if (components > 0 && components < 3) + throw love::Exception("Obly affine 2D transforms are supported with auto-batched draws."); + } + } + bool shouldflush = false; bool shouldresize = false; diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 63af15c6d..b14d37ca1 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -523,7 +523,7 @@ love::image::ImageData *Canvas::newImageData(love::image::Image *module, int sli void Canvas::generateMipmaps() { - if (getMipmapCount() == 1 || getMipmapMode() == MIPMAP_NONE) + if (getMipmapCount() == 1 || getMipmapMode() == MIPMAPS_NONE) throw love::Exception("generateMipmaps can only be called on a Canvas which was created with mipmaps enabled."); gl.bindTextureToUnit(this, 0, false); diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 709a6a1b0..b35e45fd0 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -713,12 +713,12 @@ void Graphics::endPass() for (const auto &rt : rts.colors) { - if (rt.canvas->getMipmapMode() == Canvas::MIPMAP_AUTO && rt.mipmap == 0) + if (rt.canvas->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0) rt.canvas->generateMipmaps(); } int dsmipmap = rts.depthStencil.mipmap; - if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAP_AUTO && dsmipmap == 0) + if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAPS_AUTO && dsmipmap == 0) depthstencil->generateMipmaps(); } diff --git a/src/modules/graphics/vertex.cpp b/src/modules/graphics/vertex.cpp index 249bedac4..39fef1926 100644 --- a/src/modules/graphics/vertex.cpp +++ b/src/modules/graphics/vertex.cpp @@ -79,6 +79,23 @@ uint32 getFormatFlags(CommonFormat format) } } +int getFormatPositionComponents(CommonFormat format) +{ + switch (format) + { + case CommonFormat::NONE: + case CommonFormat::RGBAub: + return 0; + case CommonFormat::XYf: + case CommonFormat::XYf_STf: + case CommonFormat::XYf_STPf: + case CommonFormat::XYf_STf_RGBAub: + case CommonFormat::XYf_STus_RGBAub: + case CommonFormat::XYf_STPf_RGBAub: + return 2; + } +} + size_t getIndexDataSize(IndexDataType type) { switch (type) diff --git a/src/modules/graphics/vertex.h b/src/modules/graphics/vertex.h index a86ee34aa..061efd84d 100644 --- a/src/modules/graphics/vertex.h +++ b/src/modules/graphics/vertex.h @@ -137,8 +137,13 @@ struct XYf_STPf_RGBAub }; size_t getFormatStride(CommonFormat format); + uint32 getFormatFlags(CommonFormat format); + +int getFormatPositionComponents(CommonFormat format); + size_t getIndexDataSize(IndexDataType type); + IndexDataType getIndexDataTypeFromMax(size_t maxvalue); int getIndexCount(TriangleIndexMode mode, int vertexCount); diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 2f52fd619..d98d03bc5 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -2519,7 +2519,7 @@ int w_push(lua_State *L) if (luax_istype(L, 2, math::Transform::type)) { math::Transform *t = luax_totype(L, 2); - instance()->applyTransform(t); + luax_catchexcept(L, [&]() { instance()->applyTransform(t); }); } return 0; @@ -2571,14 +2571,14 @@ int w_origin(lua_State * /*L*/) int w_applyTransform(lua_State *L) { math::Transform *t = math::luax_checktransform(L, 1); - instance()->applyTransform(t); + luax_catchexcept(L, [&]() { instance()->applyTransform(t); }); return 0; } int w_replaceTransform(lua_State *L) { math::Transform *t = math::luax_checktransform(L, 1); - instance()->replaceTransform(t); + luax_catchexcept(L, [&]() { instance()->replaceTransform(t); }); return 0; } diff --git a/src/modules/graphics/wrap_Graphics.lua b/src/modules/graphics/wrap_Graphics.lua index bb9f3c64f..2ab58a6a3 100644 --- a/src/modules/graphics/wrap_Graphics.lua +++ b/src/modules/graphics/wrap_Graphics.lua @@ -204,7 +204,7 @@ GLSL.VERTEX = { #endif]], FUNCTIONS = [[ -void updatePointSize() { +void setPointSize() { #ifdef GL_ES gl_PointSize = love_PointSize; #endif @@ -224,7 +224,7 @@ vec4 position(mat4 transform_proj, vec4 vertpos); void main() { VaryingTexCoord = VertexTexCoord; VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor; - updatePointSize(); + setPointSize(); love_Position = position(TransformProjectionMatrix, VertexPosition); }]], } diff --git a/src/modules/math/wrap_Transform.cpp b/src/modules/math/wrap_Transform.cpp index 85dd19fbf..aea09f781 100644 --- a/src/modules/math/wrap_Transform.cpp +++ b/src/modules/math/wrap_Transform.cpp @@ -57,6 +57,13 @@ int w_Transform_apply(lua_State *L) return 1; } +int w_Transform_isAffine2DTransform(lua_State *L) +{ + Transform *t = luax_checktransform(L, 1); + luax_pushboolean(L, t->getMatrix().isAffine2DTransform()); + return 1; +} + int w_Transform_translate(lua_State *L) { Transform *t = luax_checktransform(L, 1); @@ -284,6 +291,7 @@ static const luaL_Reg functions[] = { "clone", w_Transform_clone }, { "inverse", w_Transform_inverse }, { "apply", w_Transform_apply }, + { "isAffine2DTransform", w_Transform_isAffine2DTransform }, { "translate", w_Transform_translate }, { "rotate", w_Transform_rotate }, { "scale", w_Transform_scale },