diff --git a/src/common/Object.h b/src/common/Object.h index 78a84484c..705623291 100644 --- a/src/common/Object.h +++ b/src/common/Object.h @@ -59,14 +59,14 @@ public: * Retains the Object, i.e. increases the * reference count by one. **/ - virtual void retain(); + void retain(); /** * Releases one reference to the Object, i.e. decrements the * reference count by one, and potentially deletes the Object * if there are no more references. **/ - virtual void release(); + void release(); private: @@ -75,32 +75,41 @@ private: }; // Object -/** - * Partial re-implementation + specialization of std::shared_ptr. We can't - * use C++11's stdlib yet... - **/ + +enum class Acquire +{ + RETAIN, + NORETAIN, +}; + template class StrongRef { public: StrongRef() - : object(nullptr) + : object(nullptr) { } - StrongRef(T *obj) - : object(obj) + StrongRef(T *obj, Acquire acquire = Acquire::RETAIN) + : object(obj) { - if (object) object->retain(); + if (object && acquire == Acquire::RETAIN) object->retain(); } StrongRef(const StrongRef &other) - : object(other.get()) + : object(other.get()) { if (object) object->retain(); } + StrongRef(StrongRef &&other) + : object(other.object) + { + other.object = nullptr; + } + ~StrongRef() { if (object) object->release(); @@ -117,7 +126,7 @@ public: return object; } - operator bool() const + explicit operator bool() const { return object != nullptr; } @@ -127,9 +136,9 @@ public: return object; } - void set(T *obj) + void set(T *obj, Acquire acquire = Acquire::RETAIN) { - if (obj) obj->retain(); + if (obj && acquire == Acquire::RETAIN) obj->retain(); if (object) object->release(); object = obj; } diff --git a/src/common/Variant.cpp b/src/common/Variant.cpp index b26a368ef..7b33ee80b 100644 --- a/src/common/Variant.cpp +++ b/src/common/Variant.cpp @@ -111,6 +111,14 @@ Variant::Variant(const Variant &v) data.table->retain(); } +Variant::Variant(Variant &&v) + : type(std::move(v.type)) + , udatatype(std::move(v.udatatype)) + , data(std::move(v.data)) +{ + v.type = NIL; +} + Variant::~Variant() { switch (type) diff --git a/src/common/Variant.h b/src/common/Variant.h index 9a860a73c..3c4b9c5a3 100644 --- a/src/common/Variant.h +++ b/src/common/Variant.h @@ -43,6 +43,7 @@ public: Variant(love::Type udatatype, void *userdata); Variant(std::vector> *table); Variant(const Variant &v); + Variant(Variant &&v); ~Variant(); Variant &operator = (const Variant &v); diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index b9fb49a36..a58c1fe79 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -104,10 +104,7 @@ Source::Source(Pool *pool, love::sound::SoundData *soundData) if (fmt == 0) throw InvalidFormatException(soundData->getChannels(), soundData->getBitDepth()); - staticBuffer.set(new StaticDataBuffer(fmt, soundData->getData(), (ALsizei) soundData->getSize(), soundData->getSampleRate())); - - // The buffer has a +2 retain count right now, but we want it to have +1. - staticBuffer->release(); + staticBuffer.set(new StaticDataBuffer(fmt, soundData->getData(), (ALsizei) soundData->getSize(), sampleRate), Acquire::NORETAIN); float z[3] = {0, 0, 0}; @@ -179,11 +176,7 @@ Source::Source(const Source &s) if (type == TYPE_STREAM) { if (s.decoder.get()) - { - love::sound::Decoder *dec = s.decoder->clone(); - decoder.set(dec); - dec->release(); - } + decoder.set(s.decoder->clone(), Acquire::NORETAIN); alGenBuffers(MAX_BUFFERS, streamBuffers); } diff --git a/src/modules/event/wrap_Event.cpp b/src/modules/event/wrap_Event.cpp index efe8191df..de486bf61 100644 --- a/src/modules/event/wrap_Event.cpp +++ b/src/modules/event/wrap_Event.cpp @@ -74,16 +74,14 @@ int w_wait(lua_State *L) int w_push(lua_State *L) { - Message *m = Message::fromLua(L, 1); + StrongRef m(Message::fromLua(L, 1), Acquire::NORETAIN); - luax_pushboolean(L, m != nullptr); + luax_pushboolean(L, m.get() != nullptr); - if (m == nullptr) + if (m.get() == nullptr) return 1; instance()->push(m); - m->release(); - return 1; } @@ -101,9 +99,8 @@ int w_quit(lua_State *L) if (Variant::fromLua(L, 1, &v)) args.push_back(v); - Message *m = new Message("quit", args); + StrongRef m(new Message("quit", args), Acquire::NORETAIN); instance()->push(m); - m->release(); luax_pushboolean(L, true); return 1; diff --git a/src/modules/filesystem/FileData.cpp b/src/modules/filesystem/FileData.cpp index 35ceefda9..4e0f3972d 100644 --- a/src/modules/filesystem/FileData.cpp +++ b/src/modules/filesystem/FileData.cpp @@ -78,7 +78,7 @@ bool FileData::getConstant(const char *in, Decoder &out) return decoders.find(in, out); } -bool FileData::getConstant(Decoder in, const char *&out) +bool FileData::getConstant(Decoder in, const char *&out) { return decoders.find(in, out); } diff --git a/src/modules/filesystem/FileData.h b/src/modules/filesystem/FileData.h index d2909dd48..7106cdb7d 100644 --- a/src/modules/filesystem/FileData.h +++ b/src/modules/filesystem/FileData.h @@ -55,7 +55,7 @@ public: const std::string &getExtension() const; static bool getConstant(const char *in, Decoder &out); - static bool getConstant(Decoder in, const char *&out); + static bool getConstant(Decoder in, const char *&out); private: diff --git a/src/modules/filesystem/wrap_File.cpp b/src/modules/filesystem/wrap_File.cpp index b0209dff4..90e96c01e 100644 --- a/src/modules/filesystem/wrap_File.cpp +++ b/src/modules/filesystem/wrap_File.cpp @@ -108,13 +108,13 @@ int w_File_isOpen(lua_State *L) int w_File_read(lua_State *L) { File *file = luax_checkfile(L, 1); - Data *d = 0; + StrongRef d = nullptr; int64 size = (int64) luaL_optnumber(L, 2, (lua_Number) File::ALL); try { - d = file->read(size); + d.set(file->read(size), Acquire::NORETAIN); } catch (love::Exception &e) { @@ -123,7 +123,6 @@ int w_File_read(lua_State *L) lua_pushlstring(L, (const char *) d->getData(), d->getSize()); lua_pushnumber(L, d->getSize()); - d->release(); return 2; } diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp index 9edfa5a24..ed964b448 100644 --- a/src/modules/filesystem/wrap_Filesystem.cpp +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -223,17 +223,16 @@ int w_newFileData(lua_State *L) { File *file = luax_checkfile(L, 1); - FileData *data = 0; + StrongRef data; try { - data = file->read(); + data.set(file->read(), Acquire::NORETAIN); } catch (love::Exception &e) { return luax_ioError(L, "%s", e.what()); } luax_pushtype(L, FILESYSTEM_FILE_DATA_ID, data); - data->release(); return 1; } else diff --git a/src/modules/font/BMFontRasterizer.cpp b/src/modules/font/BMFontRasterizer.cpp index bda538d34..dd02634d7 100644 --- a/src/modules/font/BMFontRasterizer.cpp +++ b/src/modules/font/BMFontRasterizer.cpp @@ -198,12 +198,11 @@ void BMFontRasterizer::parseConfig(const std::string &configtext) if (!imagemodule) throw love::Exception("Image module not loaded!"); - // Release these variables right away since StrongRef retains. - StrongRef data = filesystem->read(filename.c_str()); - data->release(); + // read() returns a retained ref already. + StrongRef data(filesystem->read(filename.c_str()), Acquire::NORETAIN); - images[pageindex].set(imagemodule->newImageData(data.get())); - images[pageindex]->release(); + // Same with newImageData. + images[pageindex].set(imagemodule->newImageData(data.get()), Acquire::NORETAIN); } } else if (tag == "char") diff --git a/src/modules/font/Font.cpp b/src/modules/font/Font.cpp index c3a67dbcd..1aeb0eb29 100644 --- a/src/modules/font/Font.cpp +++ b/src/modules/font/Font.cpp @@ -43,9 +43,7 @@ public: Rasterizer *Font::newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting) { - StrongRef data(new DefaultFontData); - data->release(); - + StrongRef data(new DefaultFontData, Acquire::NORETAIN); return newTrueTypeRasterizer(data.get(), size, hinting); } diff --git a/src/modules/font/GlyphData.cpp b/src/modules/font/GlyphData.cpp index 485806bd2..7a7665224 100644 --- a/src/modules/font/GlyphData.cpp +++ b/src/modules/font/GlyphData.cpp @@ -40,18 +40,7 @@ GlyphData::GlyphData(uint32 glyph, GlyphMetrics glyphMetrics, GlyphData::Format , format(f) { if (metrics.width > 0 && metrics.height > 0) - { - switch (f) - { - case GlyphData::FORMAT_LUMINANCE_ALPHA: - data = new unsigned char[metrics.width * metrics.height * 2]; - break; - case GlyphData::FORMAT_RGBA: - default: - data = new unsigned char[metrics.width * metrics.height * 4]; - break; - } - } + data = new uint8[metrics.width * metrics.height * getPixelSize()]; } GlyphData::~GlyphData() @@ -61,22 +50,30 @@ GlyphData::~GlyphData() void *GlyphData::getData() const { - return (void *) data; + return data; +} + +size_t GlyphData::getPixelSize() const +{ + switch (format) + { + case FORMAT_LUMINANCE_ALPHA: + return 2; + case FORMAT_RGBA: + default: + return 4; + } +} + +void *GlyphData::getData(int x, int y) const +{ + size_t offset = (y * getWidth() + x) * getPixelSize(); + return data + offset; } size_t GlyphData::getSize() const { - switch (format) - { - case GlyphData::FORMAT_LUMINANCE_ALPHA: - return size_t(getWidth() * getHeight() * 2); - break; - case GlyphData::FORMAT_RGBA: - default: - return size_t(getWidth() * getHeight() * 4); - break; - } - + return size_t(getWidth() * getHeight()) * getPixelSize(); } int GlyphData::getHeight() const @@ -133,22 +130,22 @@ int GlyphData::getBearingY() const int GlyphData::getMinX() const { - return this->getBearingX(); + return getBearingX(); } int GlyphData::getMinY() const { - return this->getHeight() - this->getBearingY(); + return getHeight() - getBearingY(); } int GlyphData::getMaxX() const { - return this->getBearingX() + this->getWidth(); + return getBearingX() + getWidth(); } int GlyphData::getMaxY() const { - return this->getBearingY(); + return getBearingY(); } GlyphData::Format GlyphData::getFormat() const @@ -168,8 +165,8 @@ bool GlyphData::getConstant(GlyphData::Format in, const char *&out) StringMap::Entry GlyphData::formatEntries[] = { - {"luminancealpha", GlyphData::FORMAT_LUMINANCE_ALPHA}, - {"rgba", GlyphData::FORMAT_RGBA}, + {"luminancealpha", FORMAT_LUMINANCE_ALPHA}, + {"rgba", FORMAT_RGBA}, }; StringMap GlyphData::formats(GlyphData::formatEntries, sizeof(GlyphData::formatEntries)); diff --git a/src/modules/font/GlyphData.h b/src/modules/font/GlyphData.h index 5f8b188aa..a70118957 100644 --- a/src/modules/font/GlyphData.h +++ b/src/modules/font/GlyphData.h @@ -69,6 +69,16 @@ public: void *getData() const; size_t getSize() const; + /** + * Gets the data starting at a specific pixel in the glyph. + **/ + void *getData(int x, int y) const; + + /** + * Gets the size in bytes of each pixel in the glyph. + **/ + size_t getPixelSize() const; + /** * Gets the height of the glyph. **/ @@ -141,7 +151,7 @@ private: GlyphMetrics metrics; // Glyph texture data. - unsigned char *data; + uint8 *data; // The format the data's in. Format format; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 029e60391..464923120 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -203,11 +203,10 @@ void Graphics::checkSetDefaultFont() if (!fontmodule) throw love::Exception("Font module has not been loaded."); - StrongRef r(fontmodule->newTrueTypeRasterizer(12, font::TrueTypeRasterizer::HINTING_NORMAL)); - r->release(); + auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL; + StrongRef r(fontmodule->newTrueTypeRasterizer(12, hinting), Acquire::NORETAIN); - defaultFont.set(newFont(r.get())); - defaultFont->release(); + defaultFont.set(newFont(r.get()), Acquire::NORETAIN); } states.back().font.set(defaultFont.get()); diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index 0d41ccdbb..2fb3497e5 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -133,7 +133,11 @@ Image::Image(const std::vector &compressedda if (compresseddata[0]->getMipmapCount() == 1) this->flags.mipmaps = false; else - throw love::Exception("Image cannot have mipmaps: compressed image data does not have all required mipmap levels."); + { + throw love::Exception("Image cannot have mipmaps: compressed image data does not have all required mipmap levels (expected %d, got %d)", + getMipmapCount(width, height), + compresseddata[0]->getMipmapCount()); + } } for (const auto &cd : compresseddata) diff --git a/src/modules/image/magpie/ImageData.cpp b/src/modules/image/magpie/ImageData.cpp index 79fa26511..b4af00adf 100644 --- a/src/modules/image/magpie/ImageData.cpp +++ b/src/modules/image/magpie/ImageData.cpp @@ -124,10 +124,7 @@ void ImageData::decode(love::filesystem::FileData *data) // The decoder *must* output a 32 bits-per-pixel image. if (decodedimage.size != decodedimage.width*decodedimage.height*sizeof(pixel)) { - if (decodeHandler) - decodeHandler->free(decodedimage.data); - else - delete[] decodedimage.data; + decoder->free(decodedimage.data); throw love::Exception("Could not convert image!"); } diff --git a/src/modules/image/magpie/STBHandler.cpp b/src/modules/image/magpie/STBHandler.cpp index ac4ed76b4..72ea4aa78 100644 --- a/src/modules/image/magpie/STBHandler.cpp +++ b/src/modules/image/magpie/STBHandler.cpp @@ -75,7 +75,12 @@ FormatHandler::DecodedImage STBHandler::decode(love::filesystem::FileData *data) &comp, 4); if (img.data == nullptr || img.width <= 0 || img.height <= 0) - throw love::Exception("Could not decode image with stb_image."); + { + const char *err = stbi_failure_reason(); + if (err == nullptr) + err = "unknown error"; + throw love::Exception("Could not decode image with stb_image (%s).", err); + } img.size = img.width * img.height * 4; diff --git a/src/modules/physics/box2d/wrap_Fixture.cpp b/src/modules/physics/box2d/wrap_Fixture.cpp index da045c547..6074c256d 100644 --- a/src/modules/physics/box2d/wrap_Fixture.cpp +++ b/src/modules/physics/box2d/wrap_Fixture.cpp @@ -118,8 +118,8 @@ int w_Fixture_getBody(lua_State *L) int w_Fixture_getShape(lua_State *L) { Fixture *t = luax_checkfixture(L, 1); - Shape *shape = t->getShape(); - if (shape == 0) + StrongRef shape(t->getShape(), Acquire::NORETAIN); + if (shape.get() == nullptr) return 0; switch (shape->getType()) { @@ -139,7 +139,6 @@ int w_Fixture_getShape(lua_State *L) luax_pushtype(L, PHYSICS_SHAPE_ID, shape); break; } - shape->release(); return 1; } diff --git a/src/modules/thread/Channel.cpp b/src/modules/thread/Channel.cpp index e36e69db7..f85526eda 100644 --- a/src/modules/thread/Channel.cpp +++ b/src/modules/thread/Channel.cpp @@ -58,12 +58,17 @@ Channel *Channel::getChannel(const std::string &name) if (!namedChannelMutex) namedChannelMutex = newMutex(); - Lock l(namedChannelMutex); - if (!namedChannels.count(name)) - namedChannels[name] = new Channel(name); - else - namedChannels[name]->retain(); + Lock lock(namedChannelMutex); + auto it = namedChannels.find(name); + + if (it != namedChannels.end()) + { + it->second->retain(); + return it->second; + } + + namedChannels[name] = new Channel(name); return namedChannels[name]; } @@ -92,7 +97,10 @@ Channel::~Channel() delete cond; if (named) + { + Lock l(namedChannelMutex); namedChannels.erase(name); + } } unsigned long Channel::push(const Variant &var) @@ -196,22 +204,5 @@ void Channel::unlockMutex() mutex->unlock(); } -void Channel::retain() -{ - EmptyLock l; - if (named) - l.setLock(namedChannelMutex); - - Object::retain(); -} - -void Channel::release() -{ - EmptyLock l; - if (named) - l.setLock(namedChannelMutex); - - Object::release(); -} } // thread } // love diff --git a/src/modules/thread/Channel.h b/src/modules/thread/Channel.h index b7ddedc74..da98f9da9 100644 --- a/src/modules/thread/Channel.h +++ b/src/modules/thread/Channel.h @@ -54,9 +54,6 @@ public: int getCount(); void clear(); - void retain(); - void release(); - private: Channel(const std::string &name); diff --git a/src/modules/thread/LuaThread.cpp b/src/modules/thread/LuaThread.cpp index 0c5b096ae..4c463ecfe 100644 --- a/src/modules/thread/LuaThread.cpp +++ b/src/modules/thread/LuaThread.cpp @@ -116,9 +116,8 @@ void LuaThread::onError() Variant(error.c_str(), error.length()) }; - event::Message *msg = new event::Message("threaderror", vargs); + StrongRef msg(new event::Message("threaderror", vargs), Acquire::NORETAIN); eventmodule->push(msg); - msg->release(); } } // thread diff --git a/src/modules/thread/ThreadModule.cpp b/src/modules/thread/ThreadModule.cpp index c3b30277d..32a6c30ea 100644 --- a/src/modules/thread/ThreadModule.cpp +++ b/src/modules/thread/ThreadModule.cpp @@ -27,8 +27,7 @@ namespace thread LuaThread *ThreadModule::newThread(const std::string &name, love::Data *data) { - LuaThread *lt = new LuaThread(name, data); - return lt; + return new LuaThread(name, data); } Channel *ThreadModule::newChannel() diff --git a/src/modules/video/theora/VideoStream.cpp b/src/modules/video/theora/VideoStream.cpp index 0b6e91e3f..12dbca8bc 100644 --- a/src/modules/video/theora/VideoStream.cpp +++ b/src/modules/video/theora/VideoStream.cpp @@ -64,8 +64,7 @@ VideoStream::VideoStream(love::filesystem::File *file) throw ex; } - frameSync = new DeltaSync(); - frameSync->release(); + frameSync.set(new DeltaSync(), Acquire::NORETAIN); } VideoStream::~VideoStream()