From d11ccd0e69514517d6bfd937d5add1960f1efaa4 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 5 Jul 2014 16:22:52 -0300 Subject: [PATCH 1/4] Added love.graphics.getCanvasFormats and love.graphics.getCompressedImageFormats, and removed love.graphics.hasCanvasFormat. The two new functions return tables containing the names of all relevant formats as keys, and boolean values indicating whether the formats are supported. --- changes.txt | 11 +- src/modules/graphics/Graphics.cpp | 1 - src/modules/graphics/Graphics.h | 1 - src/modules/graphics/opengl/Graphics.cpp | 31 ++++++ src/modules/graphics/opengl/Graphics.h | 5 + src/modules/graphics/opengl/wrap_Graphics.cpp | 105 ++++++++---------- src/modules/graphics/opengl/wrap_Graphics.h | 3 +- 7 files changed, 92 insertions(+), 65 deletions(-) diff --git a/changes.txt b/changes.txt index 7288795f5..862ba8149 100644 --- a/changes.txt +++ b/changes.txt @@ -5,13 +5,19 @@ LOVE 0.9.2 [Baby Inspector] * Added Shader:getExternVariable. * Added several new canvas texture formats. - * Added love.graphics.hasCanvasFormat. - * Added an optional duration argument to Joystick:setVibration. + * Added love.graphics.getCanvasFormats. + * Added love.graphics.getCompressedImageFormats. + * Added ParticleSystem:setQuads. + * Added SpriteBatch:flush. + * Added optional duration argument to Joystick:setVibration. * Added love.joystick.loadGamepadMappings and love.joystick.saveGamepadMappings. * Added Joint:setUserData and Joint:getUserData. * Added Body:getWorld. * Added love.window.getDisplayName. + * Deprecated SpriteBatch:bind and SpriteBatch:unbind. + * Deprecated all uses of the name 'FSAA'. + * Fixed shader:getWarnings returning unnecessary information. * Fixed love.filesystem.setIdentity breaking in some situations when called multiple times. * Fixed a potential crash when Shader objects are garbage collected. @@ -20,6 +26,7 @@ LOVE 0.9.2 [Baby Inspector] * Fixed Image:refresh generating mipmaps multiple times if mipmap filtering is enabled. * Fixed Mesh:setDrawRange when the Mesh has a vertex map set. * Fixed internal detection of the 'position' and 'effect' shader functions. + * Fixed Texture memory leak when Meshes are garbage collected. * Renamed all cases of FSAA to MSAA. The FSAA names still exist for backward-compatibility. diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 1b86bcdee..5688e5650 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -176,7 +176,6 @@ StringMap::Entry Graphics::suppor { "mipmap", Graphics::SUPPORT_MIPMAP }, { "dxt", Graphics::SUPPORT_DXT }, { "bc5", Graphics::SUPPORT_BC5 }, - { "instancing", Graphics::SUPPORT_INSTANCING }, { "srgb", Graphics::SUPPORT_SRGB }, }; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 715abe36b..9032b6c77 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -98,7 +98,6 @@ public: SUPPORT_MIPMAP, SUPPORT_DXT, SUPPORT_BC5, - SUPPORT_INSTANCING, SUPPORT_SRGB, SUPPORT_MAX_ENUM }; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 728a0c195..e92fee095 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1123,6 +1123,37 @@ double Graphics::getSystemLimit(SystemLimit limittype) const return limit; } +bool Graphics::isSupported(Support feature) const +{ + switch (feature) + { + case SUPPORT_CANVAS: + return Canvas::isSupported(); + case SUPPORT_HDR_CANVAS: + return Canvas::isFormatSupported(Canvas::FORMAT_HDR); + case SUPPORT_MULTI_CANVAS: + return Canvas::isMultiCanvasSupported(); + case SUPPORT_SHADER: + return Shader::isSupported(); + case SUPPORT_NPOT: + return Image::hasNpot(); + case SUPPORT_SUBTRACTIVE: + return (GLEE_VERSION_1_4 || GLEE_ARB_imaging) || (GLEE_EXT_blend_minmax && GLEE_EXT_blend_subtract); + case SUPPORT_MIPMAP: + return Image::hasMipmapSupport(); + case SUPPORT_DXT: + return Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_DXT5); + case SUPPORT_BC5: + return Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_BC5); + case SUPPORT_SRGB: + // sRGB support for the screen is guaranteed if it's supported as a + // Canvas format. + return Canvas::isFormatSupported(Canvas::FORMAT_SRGB); + default: + return false; + } +} + void Graphics::push() { if (userMatrices == matrixLimit) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index b2ba4dfe2..bad07f0d9 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -455,6 +455,11 @@ public: **/ double getSystemLimit(SystemLimit limittype) const; + /** + * Gets whether a graphics feature is supported on this system. + **/ + bool isSupported(Support feature) const; + void push(); void pop(); void rotate(float r); diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index d64f939d4..509933968 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -989,79 +989,63 @@ int w_getShader(lua_State *L) int w_isSupported(lua_State *L) { bool supported = true; - size_t len = lua_gettop(L); - Graphics::Support support; - for (unsigned int i = 1; i <= len; i++) + + for (int i = 1; i <= lua_gettop(L); i++) { const char *str = luaL_checkstring(L, i); - if (!Graphics::getConstant(str, support)) + Graphics::Support feature; + if (!Graphics::getConstant(str, feature)) return luaL_error(L, "Invalid graphics feature: %s", str); - switch (support) + if (!instance->isSupported(feature)) { - case Graphics::SUPPORT_CANVAS: - if (!Canvas::isSupported()) - supported = false; - break; - case Graphics::SUPPORT_HDR_CANVAS: - if (!Canvas::isFormatSupported(Canvas::FORMAT_HDR)) - supported = false; - break; - case Graphics::SUPPORT_MULTI_CANVAS: - if (!Canvas::isMultiCanvasSupported()) - supported = false; - break; - case Graphics::SUPPORT_SHADER: - if (!Shader::isSupported()) - supported = false; - break; - case Graphics::SUPPORT_NPOT: - if (!Image::hasNpot()) - supported = false; - break; - case Graphics::SUPPORT_SUBTRACTIVE: - if (!((GLEE_VERSION_1_4 || GLEE_ARB_imaging) || (GLEE_EXT_blend_minmax && GLEE_EXT_blend_subtract))) - supported = false; - break; - case Graphics::SUPPORT_MIPMAP: - if (!Image::hasMipmapSupport()) - supported = false; - break; - case Graphics::SUPPORT_DXT: - if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_DXT5)) - supported = false; - break; - case Graphics::SUPPORT_BC5: - if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_BC5)) - supported = false; - break; - case Graphics::SUPPORT_INSTANCING: - if (!GLEE_ARB_draw_instanced) - supported = false; - break; - case Graphics::SUPPORT_SRGB: - if (!Canvas::isFormatSupported(Canvas::FORMAT_SRGB)) - supported = false; - break; - default: supported = false; - } - if (!supported) break; + } } - lua_pushboolean(L, supported); + + luax_pushboolean(L, supported); return 1; } -int w_hasCanvasFormat(lua_State *L) +int w_getCanvasFormats(lua_State *L) { - const char *str = luaL_checkstring(L, 1); - Canvas::Format format; + lua_createtable(L, 0, (int) Canvas::FORMAT_MAX_ENUM); - if (!Canvas::getConstant(str, format)) - return luaL_error(L, "Invalid canvas format: %s", str); + for (int i = 0; i < (int) Canvas::FORMAT_MAX_ENUM; i++) + { + Canvas::Format format = (Canvas::Format) i; + const char *name = nullptr; + + if (!Canvas::getConstant(format, name)) + continue; + + luax_pushboolean(L, Canvas::isFormatSupported(format)); + lua_setfield(L, -2, name); + } + + return 1; +} + +int w_getCompressedImageFormats(lua_State *L) +{ + lua_createtable(L, 0, (int) image::CompressedData::FORMAT_MAX_ENUM); + + for (int i = 0; i < (int) image::CompressedData::FORMAT_MAX_ENUM; i++) + { + image::CompressedData::Format format = (image::CompressedData::Format) i; + const char *name = nullptr; + + if (format == image::CompressedData::FORMAT_UNKNOWN) + continue; + + if (!image::CompressedData::getConstant(format, name)) + continue; + + luax_pushboolean(L, Image::hasCompressedTextureSupport(format)); + lua_setfield(L, -2, name); + } - luax_pushboolean(L, Canvas::isFormatSupported(format)); return 1; } @@ -1440,7 +1424,8 @@ static const luaL_Reg functions[] = { "getShader", w_getShader }, { "isSupported", w_isSupported }, - { "hasCanvasFormat", w_hasCanvasFormat }, + { "getCanvasFormats", w_getCanvasFormats }, + { "getCompressedImageFormats", w_getCompressedImageFormats }, { "getRendererInfo", w_getRendererInfo }, { "getSystemLimit", w_getSystemLimit }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index 9a18bb7f3..7f98a44ea 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -93,7 +93,8 @@ int w_getCanvas(lua_State *L); int w_setShader(lua_State *L); int w_getShader(lua_State *L); int w_isSupported(lua_State *L); -int w_hasCanvasFormat(lua_State *L); +int w_getCanvasFormats(lua_State *L); +int w_getCompressedImageFormats(lua_State *L); int w_getRendererInfo(lua_State *L); int w_getSystemLimit(lua_State *L); int w_draw(lua_State *L); From d5ae557149c983f2c245372e7ba049758a85a19a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 5 Jul 2014 16:40:15 -0300 Subject: [PATCH 2/4] Updated changelog --- changes.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changes.txt b/changes.txt index 862ba8149..e62c7943b 100644 --- a/changes.txt +++ b/changes.txt @@ -16,7 +16,9 @@ LOVE 0.9.2 [Baby Inspector] * Added love.window.getDisplayName. * Deprecated SpriteBatch:bind and SpriteBatch:unbind. - * Deprecated all uses of the name 'FSAA'. + * Deprecated all uses of the name 'FSAA' in favor of 'MSAA'. + * Deprecated the 'hdrcanvas' graphics feature enum in favor of getCanvasFormats. + * Deprecated the 'dxt' and 'bc5' graphics feature enums in favor of getCompressedImageFormats. * Fixed shader:getWarnings returning unnecessary information. * Fixed love.filesystem.setIdentity breaking in some situations when called multiple times. From dac9f4eaaa3723edc36b7dc6f9a1d3da0a8e5464 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 5 Jul 2014 17:55:06 -0300 Subject: [PATCH 3/4] Added love.window.minimize (resolves issue #904). --- changes.txt | 1 + src/modules/window/Window.h | 2 ++ src/modules/window/sdl/Window.cpp | 6 ++++++ src/modules/window/sdl/Window.h | 2 ++ src/modules/window/wrap_Window.cpp | 7 +++++++ src/modules/window/wrap_Window.h | 1 + 6 files changed, 19 insertions(+) diff --git a/changes.txt b/changes.txt index e62c7943b..d0c4203b2 100644 --- a/changes.txt +++ b/changes.txt @@ -14,6 +14,7 @@ LOVE 0.9.2 [Baby Inspector] * Added Joint:setUserData and Joint:getUserData. * Added Body:getWorld. * Added love.window.getDisplayName. + * Added love.window.minimize. * Deprecated SpriteBatch:bind and SpriteBatch:unbind. * Deprecated all uses of the name 'FSAA' in favor of 'MSAA'. diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index 3cadb6d0d..e1afb25d2 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -104,6 +104,8 @@ public: virtual bool setIcon(love::image::ImageData *imgd) = 0; virtual love::image::ImageData *getIcon() = 0; + virtual void minimize() = 0; + // default no-op implementation virtual void swapBuffers(); diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index 6f2667166..c0e7461e6 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -601,6 +601,12 @@ love::image::ImageData *Window::getIcon() return curMode.icon; } +void Window::minimize() +{ + if (window != nullptr) + SDL_MinimizeWindow(window); +} + void Window::swapBuffers() { SDL_GL_SwapWindow(window); diff --git a/src/modules/window/sdl/Window.h b/src/modules/window/sdl/Window.h index f44aebf35..996e99c7d 100644 --- a/src/modules/window/sdl/Window.h +++ b/src/modules/window/sdl/Window.h @@ -68,6 +68,8 @@ public: bool setIcon(love::image::ImageData *imgd); love::image::ImageData *getIcon(); + void minimize(); + void swapBuffers(); bool hasFocus() const; diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index 6683c83e2..9a8a103a7 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -334,6 +334,12 @@ int w_getPixelScale(lua_State *L) return 1; } +int w_minimize(lua_State* /*L*/) +{ + instance->minimize(); + return 0; +} + static const luaL_Reg functions[] = { { "getDisplayCount", w_getDisplayCount }, @@ -356,6 +362,7 @@ static const luaL_Reg functions[] = { "hasMouseFocus", w_hasMouseFocus }, { "isVisible", w_isVisible }, { "getPixelScale", w_getPixelScale }, + { "minimize", w_minimize }, { 0, 0 } }; diff --git a/src/modules/window/wrap_Window.h b/src/modules/window/wrap_Window.h index 2739b8b9e..1b5277a11 100644 --- a/src/modules/window/wrap_Window.h +++ b/src/modules/window/wrap_Window.h @@ -49,6 +49,7 @@ int w_hasFocus(lua_State *L); int w_hasMouseFocus(lua_State *L); int w_isVisible(lua_State *L); int w_getPixelScale(lua_State *L); +int w_minimize(lua_State *L); extern "C" LOVE_EXPORT int luaopen_love_window(lua_State *L); } // window From 9ab9a393d5a3c246b61ccca7615fa9eb68aab48a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 7 Jul 2014 15:24:24 -0300 Subject: [PATCH 4/4] Added Contact:getFixtures and Body:getContactList (see issue #905). The list of Contacts associated with bodies changes during World:update (potentially multiple times), so you might miss collisions if you don't use the World callbacks at all. --- src/modules/physics/box2d/Body.cpp | 24 ++++++++++++++++++++++ src/modules/physics/box2d/Body.h | 7 +++++++ src/modules/physics/box2d/Contact.cpp | 9 ++++++++ src/modules/physics/box2d/Contact.h | 5 +++++ src/modules/physics/box2d/World.cpp | 4 +--- src/modules/physics/box2d/wrap_Body.cpp | 10 +++++++++ src/modules/physics/box2d/wrap_Body.h | 1 + src/modules/physics/box2d/wrap_Contact.cpp | 16 +++++++++++++++ src/modules/physics/box2d/wrap_Contact.h | 1 + 9 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index d43830d97..880e50b83 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -444,6 +444,30 @@ int Body::getFixtureList(lua_State *L) const return 1; } +int Body::getContactList(lua_State *L) const +{ + lua_newtable(L); + const b2ContactEdge *ce = body->GetContactList(); + int i = 1; + do + { + if (!ce) + break; + + Contact *contact = (Contact *) Memoizer::find(ce->contact); + if (!contact) + contact = new Contact(ce->contact); + else + contact->retain(); + + luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact); + lua_rawseti(L, -2, i); + i++; + } + while ((ce = ce->next)); + return 1; +} + b2Vec2 Body::getVector(lua_State *L) { love::luax_assert_argc(L, 2, 2); diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index cd4faf11b..83dd0c6b1 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -393,6 +393,13 @@ public: **/ int getFixtureList(lua_State *L) const; + /** + * Get an array of all active Contacts attached to this Body. + * This list changes during World:update and you may miss some collisions + * if you don't use the collision callbacks. + **/ + int getContactList(lua_State *L) const; + /** * Destroy this body. **/ diff --git a/src/modules/physics/box2d/Contact.cpp b/src/modules/physics/box2d/Contact.cpp index 2142bb487..b3a480029 100644 --- a/src/modules/physics/box2d/Contact.cpp +++ b/src/modules/physics/box2d/Contact.cpp @@ -142,6 +142,15 @@ void Contact::getChildren(int &childA, int &childB) childB = contact->GetChildIndexB(); } +void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB) +{ + fixtureA = (Fixture *) Memoizer::find(contact->GetFixtureA()); + fixtureB = (Fixture *) Memoizer::find(contact->GetFixtureB()); + + if (!fixtureA || !fixtureB) + throw love::Exception("A fixture has escaped Memoizer!"); +} + } // box2d } // physics } // love diff --git a/src/modules/physics/box2d/Contact.h b/src/modules/physics/box2d/Contact.h index 1222a3681..6068d3e6b 100644 --- a/src/modules/physics/box2d/Contact.h +++ b/src/modules/physics/box2d/Contact.h @@ -148,6 +148,11 @@ public: void getChildren(int &childA, int &childB); + /** + * Gets the Fixtures associated with this Contact. + **/ + void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB); + private: // The Box2D contact. diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 400772ffd..4f2177543 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -318,10 +318,8 @@ bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB) { // Fixtures should be memoized, if we created them Fixture *a = (Fixture *)Memoizer::find(fixtureA); - if (!a) - throw love::Exception("A fixture has escaped Memoizer!"); Fixture *b = (Fixture *)Memoizer::find(fixtureB); - if (!b) + if (!a || !b) throw love::Exception("A fixture has escaped Memoizer!"); return filter.process(a, b); } diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index 040438dc7..8e97138d0 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -540,6 +540,15 @@ int w_Body_getFixtureList(lua_State *L) return n; } +int w_Body_getContactList(lua_State *L) +{ + Body *t = luax_checkbody(L, 1); + lua_remove(L, 1); + int n = 0; + luax_catchexcept(L, [&](){ n = t->getContactList(L); }); + return n; +} + int w_Body_destroy(lua_State *L) { Body *t = luax_checkbody(L, 1); @@ -615,6 +624,7 @@ static const luaL_Reg functions[] = { "isFixedRotation", w_Body_isFixedRotation }, { "getWorld", w_Body_getWorld }, { "getFixtureList", w_Body_getFixtureList }, + { "getContactList", w_Body_getContactList }, { "destroy", w_Body_destroy }, { "setUserData", w_Body_setUserData }, { "getUserData", w_Body_getUserData }, diff --git a/src/modules/physics/box2d/wrap_Body.h b/src/modules/physics/box2d/wrap_Body.h index c702b5f56..f6e65f253 100644 --- a/src/modules/physics/box2d/wrap_Body.h +++ b/src/modules/physics/box2d/wrap_Body.h @@ -85,6 +85,7 @@ int w_Body_setFixedRotation(lua_State *L); int w_Body_isFixedRotation(lua_State *L); int w_Body_getWorld(lua_State *L); int w_Body_getFixtureList(lua_State *L); +int w_Body_getContactList(lua_State *L); int w_Body_destroy(lua_State *L); int w_Body_setUserData(lua_State *L); int w_Body_getUserData(lua_State *L); diff --git a/src/modules/physics/box2d/wrap_Contact.cpp b/src/modules/physics/box2d/wrap_Contact.cpp index f6856ddf1..7911c7ff2 100644 --- a/src/modules/physics/box2d/wrap_Contact.cpp +++ b/src/modules/physics/box2d/wrap_Contact.cpp @@ -19,6 +19,7 @@ **/ #include "wrap_Contact.h" +#include "Fixture.h" namespace love { @@ -138,6 +139,20 @@ int w_Contact_getChildren(lua_State *L) return 2; } +int w_Contact_getFixtures(lua_State *L) +{ + Contact *t = luax_checkcontact(L, 1); + Fixture *a = nullptr; + Fixture *b = nullptr; + luax_catchexcept(L, [&](){ t->getFixtures(a, b); }); + + a->retain(); + luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a); + b->retain(); + luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b); + return 2; +} + extern "C" int luaopen_contact(lua_State *L) { static const luaL_Reg functions[] = @@ -156,6 +171,7 @@ extern "C" int luaopen_contact(lua_State *L) { "setTangentSpeed", w_Contact_setTangentSpeed }, { "getTangentSpeed", w_Contact_getTangentSpeed }, { "getChildren", w_Contact_getChildren }, + { "getFixtures", w_Contact_getFixtures }, { 0, 0 } }; diff --git a/src/modules/physics/box2d/wrap_Contact.h b/src/modules/physics/box2d/wrap_Contact.h index c1c2e2e29..fd325c382 100644 --- a/src/modules/physics/box2d/wrap_Contact.h +++ b/src/modules/physics/box2d/wrap_Contact.h @@ -47,6 +47,7 @@ int w_Contact_resetRestitution(lua_State *L); int w_Contact_setTangentSpeed(lua_State *L); int w_Contact_getTangentSpeed(lua_State *L); int w_Contact_getChildren(lua_State *L); +int w_Contact_getFixtures(lua_State *L); extern "C" int luaopen_contact(lua_State *L); } // box2d