From 472915a4bb0768fb05915eb23b896a60c4150cce Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 23 Feb 2013 15:52:03 -0400 Subject: [PATCH 1/6] Worked around ATI/AMD driver bugs when creating mipmaps for Images --- src/modules/graphics/opengl/Image.cpp | 94 +++++++++++++++------------ src/modules/graphics/opengl/Image.h | 13 ++-- 2 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index 776082642..8ba756341 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -37,7 +37,8 @@ Image::Image(love::image::ImageData *data) : width((float)(data->getWidth())) , height((float)(data->getHeight())) , texture(0) - , mipmapsharpness(0.0f) + , mipmapSharpness(0.0f) + , mipmapsCreated(false) { data->retain(); this->data = data; @@ -143,36 +144,55 @@ void Image::drawq(love::graphics::Quad *quad, float x, float y, float angle, flo drawv(t, v); } -void Image::checkMipmapsCreated() const +void Image::checkMipmapsCreated() { - if (filter.mipmap != FILTER_NEAREST && filter.mipmap != FILTER_LINEAR) + if (mipmapsCreated || (filter.mipmap != FILTER_NEAREST && filter.mipmap != FILTER_LINEAR)) return; if (!hasMipmapSupport()) - throw love::Exception("Mipmap filtering is not supported on this system!"); + throw love::Exception("Mipmap filtering is not supported on this system."); - // some old GPUs/systems claim support for NPOT textures, but fail when generating mipmaps - // we can't detect which systems will do this, so we fail gracefully for all NPOT images + // Some old drivers claim support for NPOT textures, but fail when creating mipmaps. + // we can't detect which systems will do this, so we fail gracefully for all NPOT images. int w = int(width), h = int(height); if (w != next_p2(w) || h != next_p2(h)) - throw love::Exception("Could not generate mipmaps: image does not have power of two dimensions!"); + throw love::Exception("Could not create mipmaps: image does not have power of two dimensions."); bind(); - GLint mipmapscreated; - glGetTexParameteriv(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, &mipmapscreated); + if (hasNpot() && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)) + { + // AMD/ATI drivers have several bugs when generating mipmaps, + // re-uploading the entire base image seems to be required. + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA8, + (GLsizei)width, + (GLsizei)height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + data->getData()); - // generate mipmaps for this image if we haven't already - if (!mipmapscreated) + // More bugs: http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation + glEnable(GL_TEXTURE_2D); + glGenerateMipmap(GL_TEXTURE_2D); + } + else { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - - if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object) - glGenerateMipmap(GL_TEXTURE_2D); - else - // modify single texel to trigger mipmap chain generation - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data->getData()); + glTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, + 0, + (GLsizei)width, + (GLsizei)height, + GL_RGBA, + GL_UNSIGNED_BYTE, + data->getData()); } + + mipmapsCreated = true; } void Image::setFilter(const Image::Filter &f) @@ -180,8 +200,8 @@ void Image::setFilter(const Image::Filter &f) filter = f; bind(); - checkMipmapsCreated(); setTextureFilter(f); + checkMipmapsCreated(); } const Image::Filter &Image::getFilter() const @@ -208,15 +228,15 @@ void Image::setMipmapSharpness(float sharpness) return; // LOD bias has the range (-maxbias, maxbias) - mipmapsharpness = std::min(std::max(sharpness, -maxmipmapsharpness + 0.01f), maxmipmapsharpness - 0.01f); + mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f); bind(); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapsharpness); // negative bias is sharper + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness); // negative bias is sharper } float Image::getMipmapSharpness() const { - return mipmapsharpness; + return mipmapSharpness; } void Image::bind() const @@ -240,7 +260,7 @@ void Image::unload() bool Image::loadVolatile() { if (hasMipmapSharpnessSupport()) - glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &maxmipmapsharpness); + glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &maxMipmapSharpness); if (hasNpot()) return loadVolatileNPOT(); @@ -253,11 +273,8 @@ bool Image::loadVolatilePOT() glGenTextures(1,(GLuint *)&texture); bindTexture(texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + setTextureFilter(filter); + setTextureWrap(wrap); float p2width = next_p2(width); float p2height = next_p2(height); @@ -289,9 +306,9 @@ bool Image::loadVolatilePOT() GL_UNSIGNED_BYTE, data->getData()); - setMipmapSharpness(mipmapsharpness); - setFilter(filter); - setWrap(wrap); + mipmapsCreated = false; + checkMipmapsCreated(); + setMipmapSharpness(mipmapSharpness); return true; } @@ -301,11 +318,8 @@ bool Image::loadVolatileNPOT() glGenTextures(1,(GLuint *)&texture); bindTexture(texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + setTextureFilter(filter); + setTextureWrap(wrap); glTexImage2D(GL_TEXTURE_2D, 0, @@ -317,9 +331,9 @@ bool Image::loadVolatileNPOT() GL_UNSIGNED_BYTE, data->getData()); - setMipmapSharpness(mipmapsharpness); - setFilter(filter); - setWrap(wrap); + mipmapsCreated = false; + checkMipmapsCreated(); + setMipmapSharpness(mipmapSharpness); return true; } @@ -360,12 +374,12 @@ bool Image::hasNpot() bool Image::hasMipmapSupport() { - return (GLEE_VERSION_1_4 || GLEE_SGIS_generate_mipmap) != 0; + return GLEE_VERSION_1_4 || GLEE_SGIS_generate_mipmap; } bool Image::hasMipmapSharpnessSupport() { - return (GLEE_VERSION_1_4 || GLEE_EXT_texture_lod_bias) != 0; + return GLEE_VERSION_1_4 || GLEE_EXT_texture_lod_bias; } } // opengl diff --git a/src/modules/graphics/opengl/Image.h b/src/modules/graphics/opengl/Image.h index d09eb8954..ea4f05bfb 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -142,11 +142,14 @@ private: // The source vertices of the image. vertex vertices[4]; - // Mipmap texture LOD bias value - float mipmapsharpness; + // Mipmap texture LOD bias (sharpness) value. + float mipmapSharpness; - // Implementation-dependent maximum/minimum mipmap sharpness values - float maxmipmapsharpness; + // Implementation-dependent min/max mipmap sharpness values. + float maxMipmapSharpness; + + // True if mipmaps have been created for this Image. + bool mipmapsCreated; // The image's filter mode Image::Filter filter; @@ -157,7 +160,7 @@ private: bool loadVolatilePOT(); bool loadVolatileNPOT(); - void checkMipmapsCreated() const; + void checkMipmapsCreated(); }; // Image From 7d579308dc81d253d0a865a4fc7fb372e2f01012 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 24 Feb 2013 00:50:39 -0400 Subject: [PATCH 2/6] =?UTF-8?q?L=C3=96VE=20now=20errors=20when=20Image=20c?= =?UTF-8?q?reation=20fails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/graphics/opengl/Image.cpp | 97 ++++++++++++++++----------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index 8ba756341..b9cccc422 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -156,7 +156,7 @@ void Image::checkMipmapsCreated() // we can't detect which systems will do this, so we fail gracefully for all NPOT images. int w = int(width), h = int(height); if (w != next_p2(w) || h != next_p2(h)) - throw love::Exception("Could not create mipmaps: image does not have power of two dimensions."); + throw love::Exception("Cannot create mipmaps: image does not have power of two dimensions."); bind(); @@ -165,14 +165,14 @@ void Image::checkMipmapsCreated() // AMD/ATI drivers have several bugs when generating mipmaps, // re-uploading the entire base image seems to be required. glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA8, - (GLsizei)width, - (GLsizei)height, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - data->getData()); + 0, + GL_RGBA8, + (GLsizei)width, + (GLsizei)height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + data->getData()); // More bugs: http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation glEnable(GL_TEXTURE_2D); @@ -182,14 +182,14 @@ void Image::checkMipmapsCreated() { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexSubImage2D(GL_TEXTURE_2D, - 0, - 0, - 0, - (GLsizei)width, - (GLsizei)height, - GL_RGBA, - GL_UNSIGNED_BYTE, - data->getData()); + 0, + 0, + 0, + (GLsizei)width, + (GLsizei)height, + GL_RGBA, + GL_UNSIGNED_BYTE, + data->getData()); } mipmapsCreated = true; @@ -286,25 +286,35 @@ bool Image::loadVolatilePOT() vertices[2].s = s; vertices[3].s = s; + while (glGetError() != GL_NO_ERROR); // clear errors + glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA8, - (GLsizei)p2width, - (GLsizei)p2height, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - 0); + 0, + GL_RGBA8, + (GLsizei)p2width, + (GLsizei)p2height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + 0); glTexSubImage2D(GL_TEXTURE_2D, - 0, - 0, - 0, - (GLsizei)width, - (GLsizei)height, - GL_RGBA, - GL_UNSIGNED_BYTE, - data->getData()); + 0, + 0, + 0, + (GLsizei)width, + (GLsizei)height, + GL_RGBA, + GL_UNSIGNED_BYTE, + data->getData()); + + if (glGetError() != GL_NO_ERROR) + { + if (p2width > width || p2height > height) + throw love::Exception("Cannot create image: padded size may be larger than the maximum supported on this system."); + else + throw love::Exception("Cannot create image: size may be larger than the maximum supported on this system."); + } mipmapsCreated = false; checkMipmapsCreated(); @@ -321,15 +331,20 @@ bool Image::loadVolatileNPOT() setTextureFilter(filter); setTextureWrap(wrap); + while (glGetError() != GL_NO_ERROR); // clear errors + glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA8, - (GLsizei)width, - (GLsizei)height, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - data->getData()); + 0, + GL_RGBA8, + (GLsizei)width, + (GLsizei)height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + data->getData()); + + if (glGetError() != GL_NO_ERROR) + throw love::Exception("Cannot create image: size may be larger than the maximum supported on this system."); mipmapsCreated = false; checkMipmapsCreated(); From 1d34dda48b9a559ca7cc39046bbe2f07c615ee1b Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 24 Feb 2013 09:47:03 -0400 Subject: [PATCH 3/6] Removed SpriteBatch:remove(id) (reverted commit 2ca82dd) The implementation had issues with sprite draw order when SpriteBatch:add used indices in the vertex buffer previously freed with SpriteBatch:remove --- src/modules/graphics/opengl/SpriteBatch.cpp | 85 ++----------------- src/modules/graphics/opengl/SpriteBatch.h | 6 -- .../graphics/opengl/wrap_SpriteBatch.cpp | 9 -- .../graphics/opengl/wrap_SpriteBatch.h | 1 - 4 files changed, 8 insertions(+), 93 deletions(-) diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index fc2bfc6ad..e80c4b491 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -20,9 +20,6 @@ #include "SpriteBatch.h" -// STD -#include // std::find - // OpenGL #include "OpenGL.h" @@ -97,25 +94,9 @@ SpriteBatch::~SpriteBatch() int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index /*= -1*/) { // Only do this if there's a free slot. - if ((index == -1 && next >= size && gaps.size() == 0) || index < -1 || index >= size) + if ((index == -1 && next >= size) || index < -1 || index >= size) return -1; - // Determine where in the vertex buffer to insert into, using the gap list - // if possible. - int realindex; - if (index == -1 && gaps.size() > 0) - { - realindex = gaps.front(); - gaps.pop_front(); - } - else - { - realindex = (index == -1) ? next : index; - std::deque::iterator it = std::find(gaps.begin(), gaps.end(), realindex); - if (it != gaps.end()) - gaps.erase(it); // This index is no longer a gap. - } - // Needed for colors. memcpy(sprite, image->getVertices(), sizeof(vertex)*4); @@ -128,37 +109,21 @@ int SpriteBatch::add(float x, float y, float a, float sx, float sy, float ox, fl setColorv(sprite, *color); - addv(sprite, realindex); + addv(sprite, (index == -1) ? next : index); // Increment counter. - if (index == -1 && realindex == next) + if (index == -1) return next++; - return realindex; + return index; } int SpriteBatch::addq(Quad *quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index /*= -1*/) { // Only do this if there's a free slot. - if ((index == -1 && next >= size && gaps.size() == 0) || index < -1 || index >= next) + if ((index == -1 && next >= size) || index < -1 || index >= next) return -1; - // Determine where in the vertex buffer to insert into, using the gap list - // if possible. - int realindex; - if (index == -1 && gaps.size() > 0) - { - realindex = gaps.front(); - gaps.pop_front(); - } - else - { - realindex = (index == -1) ? next : index; - std::deque::iterator it = std::find(gaps.begin(), gaps.end(), realindex); - if (it != gaps.end()) - gaps.erase(it); // This index is no longer a gap. - } - // Needed for colors. memcpy(sprite, quad->getVertices(), sizeof(vertex)*4); @@ -170,53 +135,19 @@ int SpriteBatch::addq(Quad *quad, float x, float y, float a, float sx, float sy, if (color) setColorv(sprite, *color); - addv(sprite, realindex); + addv(sprite, (index == -1) ? next : index); // Increment counter. - if (index == -1 && realindex == next) + if (index == -1) return next++; - return realindex; -} - -void SpriteBatch::remove(int index) -{ - if (index < 0 || index >= next || next <= 0) - return; - - // If this is the last index in the sprite list, decrease the total sprite - // count instead of adding a dummy sprite. - if (index == next - 1) - { - int spritecount = index; - - // Remove all consecutive gaps at the end of the sprite list. - std::deque::iterator it; - while ((it = std::find(gaps.begin(), gaps.end(), --spritecount)) != gaps.end()) - gaps.erase(it); - - next = spritecount + 1; - return; - } - else if (std::find(gaps.begin(), gaps.end(), index) != gaps.end()) - return; // Don't add the same index to the gap list twice. - - - // OpenGL won't render any primitive whose vertices are all identical. - for (int i = 0; i < 4; i++) - sprite[i].x = sprite[i].y = 0; - - // Replace the existing sprite at this index with the dummy sprite. - addv(sprite, index); - - gaps.push_back(index); + return index; } void SpriteBatch::clear() { // Reset the position of the next index. next = 0; - gaps.clear(); } void *SpriteBatch::lock() diff --git a/src/modules/graphics/opengl/SpriteBatch.h b/src/modules/graphics/opengl/SpriteBatch.h index 43055dab1..5cf71b928 100644 --- a/src/modules/graphics/opengl/SpriteBatch.h +++ b/src/modules/graphics/opengl/SpriteBatch.h @@ -23,7 +23,6 @@ // C #include -#include // LOVE #include "common/math.h" @@ -64,7 +63,6 @@ public: int add(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1); int addq(Quad *quad, float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky, int index = -1); - void remove(int index); void clear(); void *lock(); @@ -127,10 +125,6 @@ private: VertexBuffer *array_buf; VertexIndex *element_buf; - // List of gaps in the SpriteBatch. Checked when adding sprites, and added - // to when removing them. - std::deque gaps; - }; // SpriteBatch } // opengl diff --git a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp index f29619991..6d9f501c1 100644 --- a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp +++ b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp @@ -101,14 +101,6 @@ int w_SpriteBatch_setq(lua_State *L) return 0; } -int w_SpriteBatch_remove(lua_State *L) -{ - SpriteBatch *t = luax_checkspritebatch(L, 1); - int id = luaL_checkinteger(L, 2); - t->remove(id); - return 0; -} - int w_SpriteBatch_clear(lua_State *L) { SpriteBatch *t = luax_checkspritebatch(L, 1); @@ -198,7 +190,6 @@ static const luaL_Reg functions[] = { "addq", w_SpriteBatch_addq }, { "set", w_SpriteBatch_set }, { "setq", w_SpriteBatch_setq }, - { "remove", w_SpriteBatch_remove }, { "clear", w_SpriteBatch_clear }, { "bind", w_SpriteBatch_bind }, { "unbind", w_SpriteBatch_unbind }, diff --git a/src/modules/graphics/opengl/wrap_SpriteBatch.h b/src/modules/graphics/opengl/wrap_SpriteBatch.h index ca397d715..aa737dcc9 100644 --- a/src/modules/graphics/opengl/wrap_SpriteBatch.h +++ b/src/modules/graphics/opengl/wrap_SpriteBatch.h @@ -36,7 +36,6 @@ int w_SpriteBatch_add(lua_State *L); int w_SpriteBatch_addq(lua_State *L); int w_SpriteBatch_set(lua_State *L); int w_SpriteBatch_setq(lua_State *L); -int w_SpriteBatch_remove(lua_State *L); int w_SpriteBatch_clear(lua_State *L); int w_SpriteBatch_lock(lua_State *L); int w_SpriteBatch_unlock(lua_State *L); From 4c2b1ea1040efc48b7c3ba0f174719e29ece7dcc Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Sun, 24 Feb 2013 14:54:25 +0100 Subject: [PATCH 4/6] Make visual studio produce love.dll instead of liblove.dll --- platform/msvc2010/liblove.vcxproj | 6 +++++- platform/msvc2010/love.rc | Bin 2786 -> 3492 bytes 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/msvc2010/liblove.vcxproj b/platform/msvc2010/liblove.vcxproj index 490cb667f..c72f9cdc1 100644 --- a/platform/msvc2010/liblove.vcxproj +++ b/platform/msvc2010/liblove.vcxproj @@ -112,11 +112,13 @@ $(SolutionDir)\bin\$(PlatformShortName)\Debug\MD\ $(ProjectName)\$(PlatformShortName)\Debug\ false + love $(SolutionDir)\bin\$(PlatformShortName)\Debug\MD\ $(ProjectName)\$(PlatformShortName)\Debug\ false + love $(SolutionDir)\bin\$(PlatformShortName)\Release\MT\ @@ -130,11 +132,13 @@ $(SolutionDir)\bin\$(PlatformShortName)\Release\MD\ $(ProjectName)\$(PlatformShortName)\Release\ false + love $(SolutionDir)\bin\$(PlatformShortName)\Release\MD\ $(ProjectName)\$(PlatformShortName)\Release\ false + love @@ -733,4 +737,4 @@ - + \ No newline at end of file diff --git a/platform/msvc2010/love.rc b/platform/msvc2010/love.rc index 665d87058471dd0cede5b872d203197d31db4134..1e91ecf7dd5583a5b41fcd56b9cec577b824980d 100644 GIT binary patch delta 796 zcmZ9KJ1<005Xa}@RpgN}v_zZaQ3l>Rz8mDj_uvomu-#GeDUZw^ti%ktx-aM%gX%1D0m)u=KJB2+ z&^~N{N*{Sq&Y&tys~S}@?d&2RY8FuQqbV#B%|g$V%Hip6@x_1Ac~k@nouVNen+Hk= z9apO*CHF1B+o15QOv3P<@<9!1A$CTRh8ouetfi@sUO>zmks F{RPxooEHE9 delta 178 zcmZ1?{YaGi|37^OEg9fyTIfo z76V3u$-6luCqH05FxiHSXYwYNKITk@q{+6dQzswb5CMv_@cS@0GWapLGlT+ZcLvwV z4_QUo%^7qU6c~&rpJjENti;wZ`2ZW&WI1-Z$*0(oz-$}#1(VY_qBdXP$YBIq<;G Date: Sun, 24 Feb 2013 15:11:14 +0100 Subject: [PATCH 5/6] Update changelog --- changes.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/changes.txt b/changes.txt index dc7752933..db7de7b74 100644 --- a/changes.txt +++ b/changes.txt @@ -10,6 +10,14 @@ LOVE 0.8.1 [Rubber Piggy] * Added love.mouse.setX/setY. * Added love.filesystem.getIdentity. * Added HDR canvas support. + * Added Source:isPlaying. + * Added mipmapping support (has isSupported test). + * Added Font:getAscent/getDescent/getBaseline. + * Added Canvas:getPixel. + * Added vertex shader support. + * Added boolean support to Shader:send. + * Added support for UTF-8 ImageFonts. + * Added SoundData:getDuration. * OPTIONAL: Added support for GME. * Fixed crashes with font drawing on some ATI cards. @@ -26,18 +34,26 @@ LOVE 0.8.1 [Rubber Piggy] * Fixed multiplicative blend mode. * Fixed Box2D exception in World:update. * Fixed spacing for the last character in an ImageFont. + * Fixed crash when locking SpriteBatches multiple times. + * Fixed File:read reading past end of file. + * Fixed keyrepeat settings being lost after (indirect) setMode. * Moved love's startup to modules/love. * Renamed love's boot script to 'love.boot', which can be required. + * Renamed PixelEffect to Shader (but now with vertex shaders). * Removed love.joystick.open and friends. + * Removed love.graphics.drawTest. * Updated allocation for SoundData, it's more efficient and less wasteful. * Updated Source:set* functions to default z to 0. * Updated the windows console, it now tries to re-use an active one first. * Updated love.image memory handling, improves errors and thread-safety. * Updated order of sleep/present in love.run (now draws, *then* sleeps). + * Updated the setFilter and setWrap methods, the second argument is now optional. + * Updated font rendering code, now more performant. + * Updated error handling, error handlers now get resolved when the error occurs. LOVE 0.8.0 [Rubber Piggy] ------------------------- From 86ced3c70e4866b65a5c2f8376faef9b1668a79a Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 24 Feb 2013 15:02:56 -0400 Subject: [PATCH 6/6] Simplified the error message on image creation failure --- src/modules/graphics/opengl/Image.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index b9cccc422..29c4deaf3 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -309,12 +309,7 @@ bool Image::loadVolatilePOT() data->getData()); if (glGetError() != GL_NO_ERROR) - { - if (p2width > width || p2height > height) - throw love::Exception("Cannot create image: padded size may be larger than the maximum supported on this system."); - else - throw love::Exception("Cannot create image: size may be larger than the maximum supported on this system."); - } + throw love::Exception("Cannot create image: size may be too large for this system."); mipmapsCreated = false; checkMipmapsCreated(); @@ -344,7 +339,7 @@ bool Image::loadVolatileNPOT() data->getData()); if (glGetError() != GL_NO_ERROR) - throw love::Exception("Cannot create image: size may be larger than the maximum supported on this system."); + throw love::Exception("Cannot create image: size may be too large for this system."); mipmapsCreated = false; checkMipmapsCreated();