From 8556bda68cb9b3a9efdebf5a25d25a7f239857b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 19 Jul 2026 21:27:30 -0300 Subject: [PATCH] migrate texture consumers to shared ownership - return TexturePtr from texture creation and lookup APIs - retain texture handles in regions, atlases, fonts, framebuffers, sprites, UI, and maps - keep queued batch textures alive until rendering completes - preserve asynchronous atlas load results directly - replace TextureLoader unload semantics with reset - remove public texture deletion APIs and obsolete Sprite ownership flags - migrate bundled tools, examples, tests, ecode, and diagnostics - document Stage 2 completion and the temporary factory retention boundary --- .../resource_shared_ownership_architecture.md | 25 +++-- include/eepp/graphics/batchrenderer.hpp | 7 ++ include/eepp/graphics/font.hpp | 2 +- include/eepp/graphics/fontbmfont.hpp | 8 +- include/eepp/graphics/fontsprite.hpp | 6 +- include/eepp/graphics/fonttruetype.hpp | 12 +- include/eepp/graphics/framebuffer.hpp | 4 +- include/eepp/graphics/glyphdrawable.hpp | 8 +- include/eepp/graphics/ninepatch.hpp | 6 +- include/eepp/graphics/particlesystem.hpp | 3 +- include/eepp/graphics/sprite.hpp | 11 +- include/eepp/graphics/texture.hpp | 2 +- include/eepp/graphics/textureatlas.hpp | 14 +-- include/eepp/graphics/textureatlasloader.hpp | 5 +- include/eepp/graphics/texturefactory.hpp | 62 ++++------- include/eepp/graphics/textureloader.hpp | 12 +- include/eepp/graphics/textureregion.hpp | 24 ++-- include/eepp/ui/tools/uicolorpicker.hpp | 4 +- include/eepp/ui/uiicon.hpp | 2 +- include/eepp/ui/uiimage.hpp | 3 + include/eepp/ui/uinodedrawable.hpp | 4 + include/eepp/window/cursor.hpp | 1 + src/eepp/graphics/batchrenderer.cpp | 18 ++- src/eepp/graphics/drawablesearcher.cpp | 25 +++-- src/eepp/graphics/fontbmfont.cpp | 13 +-- src/eepp/graphics/fontsprite.cpp | 7 +- src/eepp/graphics/fonttruetype.cpp | 9 +- src/eepp/graphics/framebuffer.cpp | 7 +- src/eepp/graphics/framebufferfbo.cpp | 8 +- src/eepp/graphics/glyphdrawable.cpp | 10 +- src/eepp/graphics/ninepatch.cpp | 15 ++- src/eepp/graphics/particlesystem.cpp | 4 +- src/eepp/graphics/sprite.cpp | 86 +++++--------- src/eepp/graphics/text.cpp | 4 +- src/eepp/graphics/texture.cpp | 4 +- src/eepp/graphics/textureatlas.cpp | 22 ++-- src/eepp/graphics/textureatlasloader.cpp | 22 ++-- src/eepp/graphics/texturefactory.cpp | 105 +++++------------- src/eepp/graphics/textureloader.cpp | 23 ++-- src/eepp/graphics/textureregion.cpp | 40 +++---- src/eepp/ui/tools/uicolorpicker.cpp | 10 +- src/eepp/ui/tools/uidiffview.cpp | 1 - src/eepp/ui/tools/uiimageviewer.cpp | 2 - src/eepp/ui/uiicon.cpp | 6 +- src/eepp/ui/uiimage.cpp | 33 ++++-- src/eepp/ui/uinodedrawable.cpp | 19 +++- src/eepp/ui/uisvg.cpp | 5 +- src/examples/sprites/sprites.cpp | 4 +- .../maps/include/eepp/maps/tilemap.hpp | 4 +- .../maps/src/eepp/maps/mapobjectlayer.cpp | 2 +- src/modules/maps/src/eepp/maps/tilemap.cpp | 8 +- .../maps/src/eepp/maps/tilemaplayer.cpp | 2 +- src/tests/test_all/test.cpp | 31 ++++-- src/tests/test_all/test.hpp | 5 +- src/tests/unit_tests/fontrendering_tests.cpp | 2 +- .../resource_prerequisite_tests.cpp | 71 +++++++++--- src/tests/unit_tests/uihtml_tests.cpp | 17 +-- src/tools/ecode/settingsactions.cpp | 4 +- src/tools/uieditor/uieditor.cpp | 6 +- 59 files changed, 443 insertions(+), 436 deletions(-) diff --git a/.agent/plans/resource_shared_ownership_architecture.md b/.agent/plans/resource_shared_ownership_architecture.md index bdb69aca7..52190240d 100644 --- a/.agent/plans/resource_shared_ownership_architecture.md +++ b/.agent/plans/resource_shared_ownership_architecture.md @@ -1,7 +1,7 @@ # eepp shared-resource ownership architecture -Status: active implementation baseline; Stage 0, prerequisite fixes, and Stage 1 complete; -Stage 2 is next, 2026-07-15. +Status: active implementation baseline; Stage 0, prerequisite fixes, Stage 1, and Stage 2 complete; +Stage 3 is next, 2026-07-19. This document freezes the contracts that must be true before the public texture API is changed. The implementation may refine names and small mechanics, but changing an invariant below requires an @@ -576,6 +576,17 @@ Exit tests: ### Stage 2: one complete TexturePtr ownership cut +Status: complete, 2026-07-19. TextureFactory creation and acquisition APIs now return TexturePtr, +and TextureLoader exposes handle-based state with `reset()` replacing destructive `unload()` +semantics. TextureRegion, atlases/loaders, framebuffers, font pages and glyphs, nine-patches, +sprites, particle systems, SVG caches, UI image/background paths, maps, tools, tests, ecode, and +eeiv now retain texture handles. Atlas worker loads store their returned handles directly instead +of depending on later global lookup. BatchRenderer retains handle-aware submissions until flush; +its raw overload is limited to Texture's immediate draw path, whose queued object lifetime is +protected by display-time deferred destruction. Sprite's obsolete texture-owner flag and public +factory texture-removal APIs are removed. Factory-wide strong retention remains only as the +planned temporary bridge to Stage 3. + Change creation/acquisition APIs to return TexturePtr and migrate every required holder in the same repository-wide cut. During conversion, TextureFactory temporarily retains strong handles so an unclassified ignored result cannot silently expire. @@ -740,8 +751,8 @@ Remove raw-owning `ResourceManager` only when no subclass or consumer depends ## 12. Next implementation deliverable -Stage 1 is complete, including removal of the obsolete context-recovery APIs and TextureLoader -callback registry, weak UITextureViewer observation, and display/shutdown texture collection. The -next coding deliverable is the complete Stage 2 TexturePtr ownership cut described above: change -the public APIs and migrate every texture holder while temporary factory retention keeps the -repository behavior stable. +Stage 2 is complete with the repository-wide TexturePtr API and holder migration while temporary +factory retention preserves existing global lookup behavior. The next coding deliverable is Stage +3: introduce catalogs and Graphics scopes, migrate semantic name lookup out of TextureFactory, move +intentional persistence into catalogs/caches, and then remove the factory's temporary strong +retention. diff --git a/include/eepp/graphics/batchrenderer.hpp b/include/eepp/graphics/batchrenderer.hpp index b799f7b63..469b62a55 100644 --- a/include/eepp/graphics/batchrenderer.hpp +++ b/include/eepp/graphics/batchrenderer.hpp @@ -43,6 +43,10 @@ class EE_API BatchRenderer { void setTexture( const Texture* texture, Texture::CoordinateType coordinateType = Texture::CoordinateType::Normalized ); + /** Retains the texture until the currently queued batch has been rendered. */ + void setTexture( const TexturePtr& texture, + Texture::CoordinateType coordinateType = Texture::CoordinateType::Normalized ); + /** Set the predefined blending function to use on the batch */ void setBlendMode( const BlendMode& blend ); @@ -315,7 +319,10 @@ class EE_API BatchRenderer { VertexData* mTVertex{ nullptr }; unsigned int mNumVertex{ 0 }; + // Borrowed draw view. Handle-aware submissions retain mTextureOwner; Texture::draw() borrows + // under the contract that released textures are collected only after this batch is flushed. const Texture* mTexture{ nullptr }; + TexturePtr mTextureOwner; BlendMode mBlend{ BlendMode::Alpha() }; Vector2f mTexCoord[4]{ Vector2f::Zero, Vector2f::Zero, Vector2f::Zero, Vector2f::Zero }; diff --git a/include/eepp/graphics/font.hpp b/include/eepp/graphics/font.hpp index 92bd6b478..934c710c3 100644 --- a/include/eepp/graphics/font.hpp +++ b/include/eepp/graphics/font.hpp @@ -156,7 +156,7 @@ class EE_API Font { virtual Float getUnderlineThickness( unsigned int characterSize ) const = 0; - virtual Texture* getTexture( unsigned int characterSize ) const = 0; + virtual const TexturePtr& getTexture( unsigned int characterSize ) const = 0; virtual Uint32 getFontStyle() const; diff --git a/include/eepp/graphics/fontbmfont.hpp b/include/eepp/graphics/fontbmfont.hpp index 36489185c..1ebe751bb 100644 --- a/include/eepp/graphics/fontbmfont.hpp +++ b/include/eepp/graphics/fontbmfont.hpp @@ -37,7 +37,7 @@ class EE_API FontBMFont : public Font { const Font::Info& getInfo() const; Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic, - Float outlineThickness = 0 ) const; + Float outlineThickness = 0 ) const; GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize, bool bold = false, bool italic = false, @@ -54,7 +54,7 @@ class EE_API FontBMFont : public Font { Float getUnderlineThickness( unsigned int characterSize ) const; - Texture* getTexture( unsigned int characterSize ) const; + const TexturePtr& getTexture( unsigned int characterSize ) const; bool loaded() const; @@ -71,8 +71,8 @@ class EE_API FontBMFont : public Font { GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph GlyphDrawableTable - drawables; ///> Table mapping code points to their corresponding glyph drawables. - Texture* texture; ///< Texture containing the pixels of the glyphs + drawables; ///> Table mapping code points to their corresponding glyph drawables. + TexturePtr texture; ///< Texture containing the pixels of the glyphs }; void cleanup(); diff --git a/include/eepp/graphics/fontsprite.hpp b/include/eepp/graphics/fontsprite.hpp index 39cb8b06d..70cc1e53c 100644 --- a/include/eepp/graphics/fontsprite.hpp +++ b/include/eepp/graphics/fontsprite.hpp @@ -58,7 +58,7 @@ class EE_API FontSprite : public Font { Float getUnderlineThickness( unsigned int characterSize ) const; - Texture* getTexture( unsigned int characterSize ) const; + const TexturePtr& getTexture( unsigned int characterSize ) const; bool loaded() const; @@ -75,8 +75,8 @@ class EE_API FontSprite : public Font { GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph GlyphDrawableTable - drawables; ///> Table mapping code points to their corresponding glyph drawables. - Texture* texture; ///< Texture containing the pixels of the glyphs + drawables; ///> Table mapping code points to their corresponding glyph drawables. + TexturePtr texture; ///< Texture containing the pixels of the glyphs }; void cleanup(); diff --git a/include/eepp/graphics/fonttruetype.hpp b/include/eepp/graphics/fonttruetype.hpp index fc2f21f8e..518fc3442 100644 --- a/include/eepp/graphics/fonttruetype.hpp +++ b/include/eepp/graphics/fonttruetype.hpp @@ -77,7 +77,7 @@ class EE_API FontTrueType : public Font { Float getUnderlineThickness( unsigned int characterSize ) const; - Texture* getTexture( unsigned int characterSize ) const; + const TexturePtr& getTexture( unsigned int characterSize ) const; bool loaded() const; @@ -201,11 +201,11 @@ class EE_API FontTrueType : public Font { GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph GlyphDrawableTable - drawables; ///> Table mapping code points to their corresponding glyph drawables. - Texture* texture{ nullptr }; ///< Texture containing the pixels of the glyphs - std::vector rows; ///< List containing the position of all the existing rows - Uint32 fontInternalId{ 0 }; // The font internal id - unsigned int nextRow; ///< Y position of the next new row in the texture + drawables; ///> Table mapping code points to their corresponding glyph drawables. + TexturePtr texture; ///< Texture containing the pixels of the glyphs + std::vector rows; ///< List containing the position of all the existing rows + Uint32 fontInternalId{ 0 }; // The font internal id + unsigned int nextRow; ///< Y position of the next new row in the texture const FontTrueType* font{ nullptr }; }; diff --git a/include/eepp/graphics/framebuffer.hpp b/include/eepp/graphics/framebuffer.hpp index b2613c4f3..93bf9fa11 100644 --- a/include/eepp/graphics/framebuffer.hpp +++ b/include/eepp/graphics/framebuffer.hpp @@ -62,7 +62,7 @@ class EE_API FrameBuffer { ** The frame buffer must be unbinded before any rendering is done outside the frame buffer. ** For example MyFrameBufferPtr->getTexture()->Draw(0,0); */ - Texture* getTexture() const; + const TexturePtr& getTexture() const; /** @brief Sets the frame buffer clear color. */ void setClearColor( const ColorAf& color ); @@ -123,7 +123,7 @@ class EE_API FrameBuffer { bool mHasStencilBuffer{ false }; bool mAdjustCurrentClipping{ true }; bool mNeedsToRestoreScissorsClipping{ false }; - Texture* mTexture{ nullptr }; + TexturePtr mTexture; ColorAf mClearColor; View mView; float mProjMat[16]; diff --git a/include/eepp/graphics/glyphdrawable.hpp b/include/eepp/graphics/glyphdrawable.hpp index 6c72bcbce..c399fa893 100644 --- a/include/eepp/graphics/glyphdrawable.hpp +++ b/include/eepp/graphics/glyphdrawable.hpp @@ -11,7 +11,7 @@ class VertexBuffer; class EE_API GlyphDrawable : public DrawableResource { public: - static GlyphDrawable* New( Texture* texture, const Rect& srcRect, const Sizef& destSize = {}, + static GlyphDrawable* New( TexturePtr texture, const Rect& srcRect, const Sizef& destSize = {}, const std::string& resourceName = "" ); enum class DrawMode { @@ -21,7 +21,7 @@ class EE_API GlyphDrawable : public DrawableResource { ///< italic skew }; - GlyphDrawable( Texture* texture, const Rect& srcRect, const Sizef& destSize = {}, + GlyphDrawable( TexturePtr texture, const Rect& srcRect, const Sizef& destSize = {}, const std::string& resourceName = "" ); virtual void draw(); @@ -36,7 +36,7 @@ class EE_API GlyphDrawable : public DrawableResource { virtual bool isStateful(); /** @return The texture instance used by the GlyphDrawable. */ - Texture* getTexture(); + const TexturePtr& getTexture() const; /** @return The Texture sector that represents the GlyphDrawable */ const Rectf& getSrcRect() const; @@ -69,7 +69,7 @@ class EE_API GlyphDrawable : public DrawableResource { void setAdvance( Float advance ); protected: - Texture* mTexture; + TexturePtr mTexture; Rectf mSrcRect; Sizef mDestSize; Float mPixelDensity; diff --git a/include/eepp/graphics/ninepatch.hpp b/include/eepp/graphics/ninepatch.hpp index dd2ba9915..e81f0af1d 100644 --- a/include/eepp/graphics/ninepatch.hpp +++ b/include/eepp/graphics/ninepatch.hpp @@ -25,13 +25,13 @@ class EE_API NinePatch : public DrawableResource { static NinePatch* New( ResourceId textureId, int left, int top, int right, int bottom, const Float& pixelDensity = 1, const std::string& name = "" ); - static NinePatch* New( Texture* tex, int left, int top, int right, int bottom, + static NinePatch* New( TexturePtr tex, int left, int top, int right, int bottom, const Float& pixelDensity = 1, const std::string& name = "" ); static NinePatch* New( TextureRegion* textureRegion, int left, int top, int right, int bottom, const std::string& name = "" ); - NinePatch( Texture* tex, int left, int top, int right, int bottom, + NinePatch( TexturePtr tex, int left, int top, int right, int bottom, const Float& pixelDensity = 1, const std::string& name = "" ); NinePatch( TextureRegion* textureRegion, int left, int top, int right, int bottom, @@ -61,7 +61,7 @@ class EE_API NinePatch : public DrawableResource { Sizef mDestSize; Float mPixelDensity; - void createFromTexture( Texture* tex, int left, int top, int right, int bottom ); + void createFromTexture( const TexturePtr& tex, int left, int top, int right, int bottom ); virtual void onAlphaChange(); diff --git a/include/eepp/graphics/particlesystem.hpp b/include/eepp/graphics/particlesystem.hpp index 3d9dea7ed..9995cd1b5 100644 --- a/include/eepp/graphics/particlesystem.hpp +++ b/include/eepp/graphics/particlesystem.hpp @@ -12,6 +12,7 @@ using namespace EE::System; namespace EE { namespace Graphics { class Texture; +using TexturePtr = ResourcePtr; /** @enum EE::Graphics::ParticleEffect Predefined effects for the particle system. Use Callback when * wan't to create a new effect, o set the parameters using NoFx, but it's much more limited. */ @@ -157,7 +158,7 @@ class EE_API ParticleSystem { private: Particle* mParticle; Uint32 mPCount; - const Texture* mTexture; + TexturePtr mTexture; Uint32 mPLeft; Uint32 mLoops; diff --git a/include/eepp/graphics/sprite.hpp b/include/eepp/graphics/sprite.hpp index 9ce4d4f95..38dc9232d 100644 --- a/include/eepp/graphics/sprite.hpp +++ b/include/eepp/graphics/sprite.hpp @@ -211,7 +211,7 @@ class EE_API Sprite : public Drawable { * @param TexSector The texture sector to be rendered ( default all the texture ) * @return True if success */ - bool createStatic( Texture* tex, const Sizef& DestSize = Sizef( 0, 0 ), + bool createStatic( TexturePtr tex, const Sizef& DestSize = Sizef( 0, 0 ), const Vector2i& offset = Vector2i( 0, 0 ), const Rect& TexSector = Rect( 0, 0, 0, 0 ) ); @@ -238,7 +238,7 @@ class EE_API Sprite : public Drawable { * @param TexSector The texture sector to be rendered ( default all the texture ) * @return The frame position or 0 if fails */ - unsigned int addFrame( Texture* tex, const Sizef& DestSize = Sizef( 0, 0 ), + unsigned int addFrame( TexturePtr tex, const Sizef& DestSize = Sizef( 0, 0 ), const Vector2i& offset = Vector2i( 0, 0 ), const Rect& TexSector = Rect( 0, 0, 0, 0 ) ); @@ -269,7 +269,7 @@ class EE_API Sprite : public Drawable { * @param TexSector The texture sector to be rendered ( default all the texture ) * @return True if success */ - bool addSubFrame( Texture* tex, const unsigned int& NumFrame, const unsigned int& NumSubFrame, + bool addSubFrame( TexturePtr tex, const unsigned int& NumFrame, const unsigned int& NumSubFrame, const Sizef& DestSize = Sizef( 0, 0 ), const Vector2i& offset = Vector2i( 0, 0 ), const Rect& TexSector = Rect( 0, 0, 0, 0 ) ); @@ -395,10 +395,6 @@ class EE_API Sprite : public Drawable { bool isTextureRegionOwner() const; - Sprite& setAsTextureOwner( bool set ); - - bool isTextureOwner() const; - protected: enum SpriteFlags { SPRITE_FLAG_AUTO_ANIM = ( 1 << 0 ), @@ -406,7 +402,6 @@ class EE_API Sprite : public Drawable { SPRITE_FLAG_ANIM_PAUSED = ( 1 << 2 ), SPRITE_FLAG_ANIM_TO_FRAME_AND_STOP = ( 1 << 3 ), SPRITE_FLAG_EVENTS_ENABLED = ( 1 << 4 ), - SPRITE_FLAG_TEXTURE_OWNER = ( 1 << 5 ), SPRITE_FLAG_TEXTURE_REGION_OWNER = ( 1 << 6 ), }; diff --git a/include/eepp/graphics/texture.hpp b/include/eepp/graphics/texture.hpp index cd2f3bd1c..676a094b6 100644 --- a/include/eepp/graphics/texture.hpp +++ b/include/eepp/graphics/texture.hpp @@ -34,7 +34,7 @@ class EE_API Texture : public DrawableResource, public Image, private NonCopyabl static Uint32 getMaximumSize(); /* @return an array of Textures and the delay of the first frame */ - static std::pair, int> loadGif( IOStream& stream ); + static std::pair, int> loadGif( IOStream& stream ); /** Set the OpenGL Texture Id (texture handle) */ void setHandle( const int& texture ) { mTexture = texture; } diff --git a/include/eepp/graphics/textureatlas.hpp b/include/eepp/graphics/textureatlas.hpp index cda6c8002..2ca77e2b3 100644 --- a/include/eepp/graphics/textureatlas.hpp +++ b/include/eepp/graphics/textureatlas.hpp @@ -63,14 +63,14 @@ class EE_API TextureAtlas : public ResourceManager { * @param tex The texture * @param Name The texture name ( if any ) */ - TextureRegion* add( Texture* tex, const std::string& Name = "" ); + TextureRegion* add( TexturePtr tex, const std::string& Name = "" ); /** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture. * @param tex The texture * @param SrcRect The texture part that will be used as the TextureRegion. * @param Name The texture name ( if any ) */ - TextureRegion* add( Texture* tex, const Rect& SrcRect, const std::string& Name = "" ); + TextureRegion* add( TexturePtr tex, const Rect& SrcRect, const std::string& Name = "" ); /** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture. * @param tex The texture @@ -78,7 +78,7 @@ class EE_API TextureAtlas : public ResourceManager { * @param DestSize The destination size that the TextureRegion will have when rendered. * @param Name The texture name ( if any ) */ - TextureRegion* add( Texture* tex, const Rect& SrcRect, const Sizef& DestSize, + TextureRegion* add( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize, const std::string& Name = "" ); /** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture. @@ -89,7 +89,7 @@ class EE_API TextureAtlas : public ResourceManager { *used. * @param Name The texture name ( if any ) */ - TextureRegion* add( Texture* tex, const Rect& SrcRect, const Sizef& DestSize, + TextureRegion* add( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize, const Vector2i& Offset, const std::string& Name = "" ); /** @return The texture atlas name. */ @@ -119,7 +119,7 @@ class EE_API TextureAtlas : public ResourceManager { * linked to a texture. \n The Global Texture Atlas for example doesn't have any texture linked * to it. */ - Texture* getTexture( const Uint32& texnum = 0 ) const; + const TexturePtr& getTexture( const Uint32& texnum = 0 ) const; /** @return The number of textures linked to the texture atlas. */ Uint32 getTexturesCount(); @@ -130,9 +130,9 @@ class EE_API TextureAtlas : public ResourceManager { std::string mName; String::HashType mId; std::string mPath; - std::vector mTextures; + std::vector mTextures; - void setTextures( std::vector textures ); + void setTextures( std::vector textures ); }; }} // namespace EE::Graphics diff --git a/include/eepp/graphics/textureatlasloader.hpp b/include/eepp/graphics/textureatlasloader.hpp index 7a4dfd97e..451418fca 100644 --- a/include/eepp/graphics/textureatlasloader.hpp +++ b/include/eepp/graphics/textureatlasloader.hpp @@ -146,7 +146,7 @@ class EE_API TextureAtlasLoader { * 0 to GetTexturesLoadedCount(). Usually a texture atlas corresponds to only one texture, so * the texture index is 0. */ - Texture* getTexture( const Uint32& texnum = 0 ) const; + const TexturePtr& getTexture( const Uint32& texnum = 0 ) const; /** @return The number of textures linked to the texture atlas. */ Uint32 getTexturesLoadedCount(); @@ -170,11 +170,12 @@ class EE_API TextureAtlasLoader { std::atomic mIsLoading; TextureAtlas* mTextureAtlas; GLLoadCallback mLoadCallback; - std::vector mTexturesLoaded; + std::vector mTexturesLoaded; struct sTempTexAtlas { sTextureHdr Texture; std::vector TextureRegions; + TexturePtr LoadedTexture; }; sTextureAtlasHdr mTexGrHdr; diff --git a/include/eepp/graphics/texturefactory.hpp b/include/eepp/graphics/texturefactory.hpp index f2ba74cd5..71a9874c3 100644 --- a/include/eepp/graphics/texturefactory.hpp +++ b/include/eepp/graphics/texturefactory.hpp @@ -39,7 +39,7 @@ class EE_API TextureFactory : protected Mutex { * @param Filename A filename to recognize the texture. * @return The created texture */ - Texture* createEmptyTexture( + TexturePtr createEmptyTexture( const unsigned int& Width, const unsigned int& Height, const unsigned int& Channels = 4, const Color& DefaultColor = Color( 0, 0, 0, 255 ), const bool& Mipmap = false, const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, @@ -60,12 +60,13 @@ class EE_API TextureFactory : protected Mutex { * outside the texture factory ). * @return The texture loaded or null if error */ - Texture* loadFromPixels( const unsigned char* Pixels, const unsigned int& Width, - const unsigned int& Height, const unsigned int& Channels, - const bool& Mipmap = false, - const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, - const bool& CompressTexture = false, const bool& KeepLocalCopy = false, - const std::string& FileName = std::string( "" ) ); + TexturePtr + loadFromPixels( const unsigned char* Pixels, const unsigned int& Width, + const unsigned int& Height, const unsigned int& Channels, + const bool& Mipmap = false, + const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, + const bool& CompressTexture = false, const bool& KeepLocalCopy = false, + const std::string& FileName = std::string( "" ) ); /** Load a texture from Pack file * @param Pack Pointer to the pack instance @@ -79,7 +80,7 @@ class EE_API TextureFactory : protected Mutex { * the image. * @return The texture loaded or null if error */ - Texture* loadFromPack( + TexturePtr loadFromPack( Pack* Pack, const std::string& FilePackPath, const bool& Mipmap = false, const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, const bool& CompressTexture = false, const bool& KeepLocalCopy = false, @@ -97,7 +98,7 @@ class EE_API TextureFactory : protected Mutex { * the image. * @return The texture loaded or null if error */ - Texture* loadFromMemory( + TexturePtr loadFromMemory( const unsigned char* ImagePtr, const unsigned int& Size, const bool& Mipmap = false, const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, const bool& CompressTexture = false, const bool& KeepLocalCopy = false, @@ -114,7 +115,7 @@ class EE_API TextureFactory : protected Mutex { * the image. * @return The texture loaded or null if error */ - Texture* loadFromStream( + TexturePtr loadFromStream( IOStream& Stream, const bool& Mipmap = false, const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, const bool& CompressTexture = false, const bool& KeepLocalCopy = false, @@ -131,24 +132,12 @@ class EE_API TextureFactory : protected Mutex { * the image. * @return The texture loaded or null if error */ - Texture* loadFromFile( + TexturePtr loadFromFile( const std::string& Filepath, const bool& Mipmap = false, const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge, const bool& CompressTexture = false, const bool& KeepLocalCopy = false, const Image::FormatConfiguration& imageformatConfiguration = Image::FormatConfiguration() ); - /** Removes and unloads the texture identified by @p textureId. - * @param textureId The process-wide texture identity. - * @return True if was removed - */ - bool remove( ResourceId textureId ); - - /** Removes and Unload the Texture - * @param texture The texture pointer - * @return True if was removed - */ - bool remove( Texture* texture ); - /** Binds the texture identity indicated. This is useful if you are rendering a texture * outside this class. * @param textureId The process-wide texture identity. @@ -186,9 +175,6 @@ class EE_API TextureFactory : protected Mutex { /** Returns the number of textures loaded */ Uint32 getTextureCount(); - /** @return All the active textures */ - std::vector getTextures(); - /** @return A non-owning diagnostic snapshot of every currently live texture. */ TextureRegistrySnapshot snapshotTextures(); @@ -218,11 +204,8 @@ class EE_API TextureFactory : protected Mutex { /** Determines whether the texture identity exists in the factory. */ bool existsId( ResourceId textureId ); - /** Determines whether the texture is retained by the factory. */ - bool exists( const Texture* tex ); - /** @return The texture matching @p textureId, or null if it is not factory-retained. */ - Texture* getTexture( ResourceId textureId ); + TexturePtr getTexture( ResourceId textureId ); /** @return The memory used by the textures (in bytes) */ unsigned int getTextureMemorySize(); @@ -243,24 +226,24 @@ class EE_API TextureFactory : protected Mutex { * @param MemSize The size of the texture in memory ( just if you need to specify the real size * in memory, just useful to calculate the total texture memory ). */ - Texture* pushTexture( const std::string& Filepath, const Uint32& textureHandle, - const unsigned int& Width, const unsigned int& Height, - const unsigned int& ImgWidth, const unsigned int& ImgHeight, - const bool& Mipmap, const unsigned int& Channels, - const Texture::ClampMode& ClampMode, const bool& CompressTexture, - const bool& LocalCopy = false, const Uint32& MemSize = 0 ); + TexturePtr pushTexture( const std::string& Filepath, const Uint32& textureHandle, + const unsigned int& Width, const unsigned int& Height, + const unsigned int& ImgWidth, const unsigned int& ImgHeight, + const bool& Mipmap, const unsigned int& Channels, + const Texture::ClampMode& ClampMode, const bool& CompressTexture, + const bool& LocalCopy = false, const Uint32& MemSize = 0 ); /** Return a texture by it file path name * @param Name File path name * @return The texture, NULL if not exists. */ - Texture* getByName( const std::string& Name ); + TexturePtr getByName( const std::string& Name ); /** Return a texture by it hash path name * @param Hash The file path hash * @return The texture, NULL if not exists */ - Texture* getByHash( const String::HashType& hash ); + TexturePtr getByHash( const String::HashType& hash ); ~TextureFactory(); @@ -268,6 +251,7 @@ class EE_API TextureFactory : protected Mutex { protected: friend class Texture; + friend class TextureLoader; TextureFactory(); @@ -295,6 +279,8 @@ class EE_API TextureFactory : protected Mutex { void resetTextureBinding( const Texture* texture ); + bool releaseRetainedTexture( ResourceId textureId ); + void queueReleasedTexture( Texture* texture ); void diagnoseLiveTexturesAtShutdown(); diff --git a/include/eepp/graphics/textureloader.hpp b/include/eepp/graphics/textureloader.hpp index 2f5706ba6..00d59e2ef 100644 --- a/include/eepp/graphics/textureloader.hpp +++ b/include/eepp/graphics/textureloader.hpp @@ -89,9 +89,9 @@ class EE_API TextureLoader { * is done. */ void setColorKey( RGB Color ); - /** @brief Releases the texture loaded ( if was already loaded ), it will destroy the texture - * from memory. */ - void unload(); + /** Clears the loader state and releases its texture handle. Other texture owners remain valid. + */ + void reset(); /** @return The file path to the texture ( if any ) */ const std::string& getFilepath() const; @@ -100,7 +100,7 @@ class EE_API TextureLoader { ResourceId getId() const; /** @return The texture instance ( if it was loaded ). */ - Texture* getTexture() const; + const TexturePtr& getTexture() const; Image::FormatConfiguration getFormatConfiguration() const; @@ -112,7 +112,7 @@ class EE_API TextureLoader { protected: Uint32 mLoadType{ 0 }; // From memory, from path, from pack Uint8* mPixels{ nullptr }; // Texture Info - Texture* mTexture{ nullptr }; + TexturePtr mTexture; Int32 mImgWidth{ 0 }; Int32 mImgHeight{ 0 }; @@ -133,8 +133,6 @@ class EE_API TextureLoader { RGB* mColorKey{ nullptr }; Image::FormatConfiguration mFormatConfiguration; - void reset(); - private: bool mLoaded{ false }; bool mTexLoaded{ false }; diff --git a/include/eepp/graphics/textureregion.hpp b/include/eepp/graphics/textureregion.hpp index 177a7e892..7ac5f3941 100644 --- a/include/eepp/graphics/textureregion.hpp +++ b/include/eepp/graphics/textureregion.hpp @@ -24,14 +24,14 @@ class EE_API TextureRegion : public DrawableResource { static TextureRegion* New( ResourceId textureId, const Rect& srcRect, const Sizef& destSize, const Vector2i& offset, const std::string& name = "" ); - static TextureRegion* New( Texture* tex, const std::string& name = "" ); + static TextureRegion* New( TexturePtr tex, const std::string& name = "" ); - static TextureRegion* New( Texture* tex, const Rect& srcRect, const std::string& name = "" ); + static TextureRegion* New( TexturePtr tex, const Rect& srcRect, const std::string& name = "" ); - static TextureRegion* New( Texture* tex, const Rect& srcRect, const Sizef& destSize, + static TextureRegion* New( TexturePtr tex, const Rect& srcRect, const Sizef& destSize, const std::string& name = "" ); - static TextureRegion* New( Texture* tex, const Rect& srcRect, const Sizef& destSize, + static TextureRegion* New( TexturePtr tex, const Rect& srcRect, const Sizef& destSize, const Vector2i& offset, const std::string& name = "" ); /** Creates an empty TextureRegion */ @@ -41,14 +41,14 @@ class EE_API TextureRegion : public DrawableResource { * @param tex The texture * @param name The texture name ( if any ) */ - TextureRegion( Texture* tex, const std::string& name = "" ); + TextureRegion( TexturePtr tex, const std::string& name = "" ); /** Creates a TextureRegion of the indicated part of the texture. * @param tex The texture * @param srcRect The texture part that will be used as the TextureRegion. * @param name The texture name ( if any ) */ - TextureRegion( Texture* tex, const Rect& srcRect, const std::string& name = "" ); + TextureRegion( TexturePtr tex, const Rect& srcRect, const std::string& name = "" ); /** Creates a TextureRegion of the indicated part of the texture. * @param tex The texture @@ -56,7 +56,7 @@ class EE_API TextureRegion : public DrawableResource { * @param destSize The destination size that the TextureRegion will have when rendered. * @param name The texture name ( if any ) */ - TextureRegion( Texture* tex, const Rect& srcRect, const Sizef& destSize, + TextureRegion( TexturePtr tex, const Rect& srcRect, const Sizef& destSize, const std::string& name = "" ); /** Creates a TextureRegion of the indicated part of the texture. @@ -67,8 +67,8 @@ class EE_API TextureRegion : public DrawableResource { *used. * @param name The texture name ( if any ) */ - TextureRegion( Texture* tex, const Rect& srcRect, const Sizef& destSize, const Vector2i& offset, - const std::string& name = "" ); + TextureRegion( TexturePtr tex, const Rect& srcRect, const Sizef& destSize, + const Vector2i& offset, const std::string& name = "" ); virtual ~TextureRegion(); @@ -76,7 +76,7 @@ class EE_API TextureRegion : public DrawableResource { void setTextureId( ResourceId textureId ); /** Set the Texture that holds the TextureRegion. */ - void setTexture( Texture* texture ); + void setTexture( TexturePtr texture ); /** @return The Texture sector that represents the TextureRegion */ const Rect& getSrcRect() const; @@ -127,7 +127,7 @@ class EE_API TextureRegion : public DrawableResource { virtual bool isStateful() { return false; } /** @return The texture instance used by the TextureRegion. */ - Graphics::Texture* getTexture(); + const TexturePtr& getTexture() const; /** Replaces a color in the TextureRegion ( needs Lock() ) */ void replaceColor( Color ColorKey, Color NewColor ); @@ -204,7 +204,7 @@ class EE_API TextureRegion : public DrawableResource { protected: Uint8* mPixels; Uint8* mAlphaMask; - Graphics::Texture* mTexture; + TexturePtr mTexture; Rect mSrcRect; Sizef mOriDestSize; Sizef mDestSize; diff --git a/include/eepp/ui/tools/uicolorpicker.hpp b/include/eepp/ui/tools/uicolorpicker.hpp index 409757b65..4021eb7d3 100644 --- a/include/eepp/ui/tools/uicolorpicker.hpp +++ b/include/eepp/ui/tools/uicolorpicker.hpp @@ -78,9 +78,9 @@ class EE_API UIColorPicker { void windowClose( const Event* Event ); - Texture* createHueTexture( const Sizef& size ); + TexturePtr createHueTexture( const Sizef& size ); - Texture* createGridTexture(); + TexturePtr createGridTexture(); void updateColorPicker(); diff --git a/include/eepp/ui/uiicon.hpp b/include/eepp/ui/uiicon.hpp index f7f4c1821..f53fcb690 100644 --- a/include/eepp/ui/uiicon.hpp +++ b/include/eepp/ui/uiicon.hpp @@ -59,7 +59,7 @@ class EE_API UISVGIcon : public UIIcon { UISVGIcon( const std::string& name, const std::string& svgXML ); std::string mSVGXml; - mutable UnorderedMap mSVGs; + mutable UnorderedMap mSVGs; mutable Sizei mOriSize; mutable int mOriChannels{ 0 }; }; diff --git a/include/eepp/ui/uiimage.hpp b/include/eepp/ui/uiimage.hpp index 37569f65a..aa926d993 100644 --- a/include/eepp/ui/uiimage.hpp +++ b/include/eepp/ui/uiimage.hpp @@ -28,6 +28,8 @@ class EE_API UIImage : public UIWidget { UIImage* setDrawable( Drawable* drawable, bool ownIt = false ); + UIImage* setDrawable( TexturePtr texture ); + const Color& getColor() const; UIImage* setColor( const Color& col ); @@ -54,6 +56,7 @@ class EE_API UIImage : public UIWidget { protected: UIScaleType mScaleType; Drawable* mDrawable; + TexturePtr mTexture; Color mColor; Vector2f mAlignOffset; Vector2f mDestSize; diff --git a/include/eepp/ui/uinodedrawable.hpp b/include/eepp/ui/uinodedrawable.hpp index c9b7f47c8..f129580ff 100644 --- a/include/eepp/ui/uinodedrawable.hpp +++ b/include/eepp/ui/uinodedrawable.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -61,6 +62,8 @@ class EE_API UINodeDrawable : public Drawable { void setDrawable( Drawable* drawable, const bool& ownIt ); + void setDrawable( TexturePtr texture ); + void setDrawable( const std::string& drawableRef ); void setOffset( const Vector2f& offset ); @@ -131,6 +134,7 @@ class EE_API UINodeDrawable : public Drawable { bool mOwnsDrawable{ false }; bool mColorWasSet{ false }; Drawable* mDrawable; + TexturePtr mTexture; std::string mDrawableRef; Uint32 mResourceChangeCbId; RepeatX mRepeatX{ RepeatX::NoRepeat }; diff --git a/include/eepp/window/cursor.hpp b/include/eepp/window/cursor.hpp index dac650a5a..f8b99cb06 100644 --- a/include/eepp/window/cursor.hpp +++ b/include/eepp/window/cursor.hpp @@ -78,6 +78,7 @@ class EE_API Cursor { Vector2i mHotSpot; EE::Window::Window* mWindow; + // The texture pixels are copied synchronously; Cursor does not retain this borrow. Cursor( Texture* tex, const Vector2i& hotspot, const std::string& getName, EE::Window::Window* window ); diff --git a/src/eepp/graphics/batchrenderer.cpp b/src/eepp/graphics/batchrenderer.cpp index 781c98d96..0928d87eb 100644 --- a/src/eepp/graphics/batchrenderer.cpp +++ b/src/eepp/graphics/batchrenderer.cpp @@ -53,16 +53,26 @@ void BatchRenderer::discard() { mNumVertex = 0; mTVertex = nullptr; mTexture = nullptr; + mTextureOwner.reset(); } void BatchRenderer::setTexture( const Texture* texture, Texture::CoordinateType coordinateType ) { - if ( mTexture != texture || mCoordinateType != coordinateType ) + if ( mTexture != texture || mCoordinateType != coordinateType ) { flush(); + mTextureOwner.reset(); + } mTexture = texture; mCoordinateType = coordinateType; } +void BatchRenderer::setTexture( const TexturePtr& texture, + Texture::CoordinateType coordinateType ) { + setTexture( texture.get(), coordinateType ); + if ( mTextureOwner != texture ) + mTextureOwner = texture; +} + void BatchRenderer::setBlendMode( const BlendMode& blend ) { if ( blend != mBlend ) flush(); @@ -94,8 +104,10 @@ void BatchRenderer::setDrawMode( const PrimitiveType& Mode, const bool& Force ) } void BatchRenderer::flush() { - if ( mNumVertex == 0 ) + if ( mNumVertex == 0 ) { + mTextureOwner.reset(); return; + } if ( GlobalBatchRenderer::instance() != this ) GlobalBatchRenderer::instance()->draw(); @@ -163,6 +175,8 @@ void BatchRenderer::flush() { GLi->enable( GL_TEXTURE_2D ); GLi->enableClientState( GL_TEXTURE_COORD_ARRAY ); } + + mTextureOwner.reset(); } void BatchRenderer::batchQuad( const Float& x, const Float& y, const Float& width, diff --git a/src/eepp/graphics/drawablesearcher.cpp b/src/eepp/graphics/drawablesearcher.cpp index 7bb4ad7ba..3e84c3ef9 100644 --- a/src/eepp/graphics/drawablesearcher.cpp +++ b/src/eepp/graphics/drawablesearcher.cpp @@ -42,7 +42,7 @@ static Drawable* searchByNameInternal( const std::string& name ) { } if ( NULL == drawable ) { - drawable = TextureFactory::instance()->getByHash( id ); + drawable = TextureFactory::instance()->getByHash( id ).get(); } return drawable; @@ -50,7 +50,8 @@ static Drawable* searchByNameInternal( const std::string& name ) { static Drawable* parseDataURI( const std::string& name ) { auto hash = MD5::fromString( name ).toHexString(); - Drawable* drawable = TextureFactory::instance()->getByName( hash ); + TexturePtr texture = TextureFactory::instance()->getByName( hash ); + Drawable* drawable = texture.get(); std::string::size_type formatAndEncSep; if ( nullptr == drawable && ( formatAndEncSep = name.find_first_of( ',' ) ) != std::string::npos ) { @@ -72,7 +73,7 @@ static Drawable* parseDataURI( const std::string& name ) { } } - Texture* tex = nullptr; + TexturePtr tex; if ( !format.empty() && ( Image::isImageExtension( "." + format ) || format == "svg+xml" ) ) { Image::FormatConfiguration format; @@ -100,7 +101,7 @@ static Drawable* parseDataURI( const std::string& name ) { if ( tex ) { tex->setName( hash ); - drawable = tex; + drawable = tex.get(); } } return drawable; @@ -132,9 +133,9 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea drawable = TextureAtlasManager::instance()->getTextureRegionByName( name.substr( 12 ) ); } else if ( String::startsWith( name, "@image/" ) ) { - drawable = TextureFactory::instance()->getByName( name.substr( 7 ) ); + drawable = TextureFactory::instance()->getByName( name.substr( 7 ) ).get(); } else if ( String::startsWith( name, "@texture/" ) ) { - drawable = TextureFactory::instance()->getByName( name.substr( 9 ) ); + drawable = TextureFactory::instance()->getByName( name.substr( 9 ) ).get(); } else if ( String::startsWith( name, "@sprite/" ) && !searchedSprite ) { drawable = getSprite( name.substr( 8 ) ); } else if ( String::startsWith( name, "@drawable/" ) ) { @@ -156,17 +157,17 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea FileSystem::filePathRemoveProcessPath( filePath ); - drawable = TextureFactory::instance()->getByName( filePath ); + drawable = TextureFactory::instance()->getByName( filePath ).get(); if ( NULL == drawable ) { - Texture* tex = TextureFactory::instance()->loadFromFile( filePath ); + TexturePtr tex = TextureFactory::instance()->loadFromFile( filePath ); if ( tex ) - drawable = tex; + drawable = tex.get(); } } else if ( String::startsWith( name, "http://" ) || String::startsWith( name, "https://" ) ) { - Texture* texture = TextureFactory::instance()->getByName( name ); + TexturePtr texture = TextureFactory::instance()->getByName( name ); if ( NULL == texture && Engine::instance()->isSharedGLContextEnabled() ) { texture = TextureFactory::instance()->createEmptyTexture( @@ -194,7 +195,7 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea URI( name ), Seconds( 5 ), {}, headers ); } - drawable = texture; + drawable = texture.get(); } else if ( String::startsWith( name, "data:image/" ) ) { drawable = parseDataURI( name ); } else { @@ -212,7 +213,7 @@ Drawable* DrawableSearcher::searchById( const Uint32& id ) { Drawable* drawable = TextureAtlasManager::instance()->getTextureRegionById( id ); if ( NULL == drawable ) { - drawable = TextureFactory::instance()->getByHash( id ); + drawable = TextureFactory::instance()->getByHash( id ).get(); } if ( NULL == drawable && sPrintWarnings ) diff --git a/src/eepp/graphics/fontbmfont.cpp b/src/eepp/graphics/fontbmfont.cpp index 2763a8d03..40e503fc1 100644 --- a/src/eepp/graphics/fontbmfont.cpp +++ b/src/eepp/graphics/fontbmfont.cpp @@ -113,13 +113,13 @@ bool FontBMFont::loadFromStream( IOStream& stream ) { } } - Texture* tex = TF->loadFromPixels( rgbaImg.getPixelsPtr(), rgbaImg.getWidth(), - rgbaImg.getHeight(), rgbaImg.getChannels() ); + TexturePtr tex = TF->loadFromPixels( rgbaImg.getPixelsPtr(), rgbaImg.getWidth(), + rgbaImg.getHeight(), rgbaImg.getChannels() ); mPages[mFontSize].texture = tex; } else { - Texture* tex = TF->loadFromPixels( img.getPixelsPtr(), img.getWidth(), - img.getHeight(), img.getChannels() ); + TexturePtr tex = TF->loadFromPixels( img.getPixelsPtr(), img.getWidth(), + img.getHeight(), img.getChannels() ); mPages[mFontSize].texture = tex; } @@ -254,7 +254,7 @@ Float FontBMFont::getUnderlineThickness( unsigned int ) const { return 0.f; } -Texture* FontBMFont::getTexture( unsigned int ) const { +const TexturePtr& FontBMFont::getTexture( unsigned int ) const { return mPages[mFontSize].texture; } @@ -274,9 +274,6 @@ FontBMFont& FontBMFont::operator=( const FontBMFont& right ) { FontBMFont::Page::~Page() { for ( auto drawable : drawables ) eeDelete( drawable.second ); - - if ( NULL != texture && TextureFactory::existsSingleton() ) - TextureFactory::instance()->remove( texture->getTextureId() ); } }} // namespace EE::Graphics diff --git a/src/eepp/graphics/fontsprite.cpp b/src/eepp/graphics/fontsprite.cpp index fcd51031e..45d2e5337 100644 --- a/src/eepp/graphics/fontsprite.cpp +++ b/src/eepp/graphics/fontsprite.cpp @@ -136,7 +136,7 @@ bool FontSprite::loadFromStream( IOStream& stream, Color key, Uint32 firstChar, img.createMaskFromColor( Color::Fuchsia, 0 ); - Texture* texture = TextureFactory::instance()->loadFromPixels( + TexturePtr texture = TextureFactory::instance()->loadFromPixels( img.getPixelsPtr(), img.getWidth(), img.getHeight(), img.getChannels() ); mPages[mFontSize].texture = texture; if ( NULL != texture ) { @@ -232,7 +232,7 @@ Float FontSprite::getUnderlineThickness( unsigned int ) const { return 0.f; } -Texture* FontSprite::getTexture( unsigned int ) const { +const TexturePtr& FontSprite::getTexture( unsigned int ) const { return mPages[mFontSize].texture; } @@ -252,9 +252,6 @@ FontSprite& FontSprite::operator=( const FontSprite& right ) { FontSprite::Page::~Page() { for ( auto drawable : drawables ) eeDelete( drawable.second ); - - if ( NULL != texture && TextureFactory::existsSingleton() ) - TextureFactory::instance()->remove( texture->getTextureId() ); } }} // namespace EE::Graphics diff --git a/src/eepp/graphics/fonttruetype.cpp b/src/eepp/graphics/fonttruetype.cpp index 0518ab2a4..9f0d55703 100644 --- a/src/eepp/graphics/fonttruetype.cpp +++ b/src/eepp/graphics/fonttruetype.cpp @@ -1135,7 +1135,7 @@ Float FontTrueType::getUnderlineThickness( unsigned int characterSize ) const { } } -Texture* FontTrueType::getTexture( unsigned int characterSize ) const { +const TexturePtr& FontTrueType::getTexture( unsigned int characterSize ) const { return getPage( characterSize ).texture; } @@ -1621,7 +1621,7 @@ Rect FontTrueType::findGlyphRect( Page& page, unsigned int width, unsigned int h // Make the texture 2 times bigger Image newImage; newImage.create( textureWidth * 2, textureHeight * 2, 4 ); - newImage.copyImage( page.texture ); + newImage.copyImage( page.texture.get() ); page.texture->replace( &newImage ); } else { @@ -1958,7 +1958,7 @@ bool FontTrueType::hasColrGlyphs() const { FontTrueType::Page::Page( const Uint32 fontInternalId, const std::string& pageName, const FontTrueType* font ) : - texture( NULL ), fontInternalId( fontInternalId ), nextRow( 3 ), font( font ) { + texture(), fontInternalId( fontInternalId ), nextRow( 3 ), font( font ) { // Make sure that the texture is initialized by default Image image; image.create( 128, 128, 4 ); @@ -1979,9 +1979,6 @@ FontTrueType::Page::Page( const Uint32 fontInternalId, const std::string& pageNa FontTrueType::Page::~Page() { for ( auto drawable : drawables ) eeDelete( drawable.second ); - - if ( NULL != texture && TextureFactory::existsSingleton() ) - TextureFactory::instance()->remove( texture->getTextureId() ); } void FontTrueType::clearCache() { diff --git a/src/eepp/graphics/framebuffer.cpp b/src/eepp/graphics/framebuffer.cpp index 369f3e61d..ddd2642c6 100644 --- a/src/eepp/graphics/framebuffer.cpp +++ b/src/eepp/graphics/framebuffer.cpp @@ -32,7 +32,7 @@ FrameBuffer::FrameBuffer( EE::Window::Window* window ) : mHasColorBuffer( false ), mHasDepthBuffer( false ), mHasStencilBuffer( false ), - mTexture( NULL ), + mTexture(), mClearColor( 0, 0, 0, 0 ) { if ( NULL == mWindow ) { mWindow = Engine::instance()->getCurrentWindow(); @@ -42,13 +42,10 @@ FrameBuffer::FrameBuffer( EE::Window::Window* window ) : } FrameBuffer::~FrameBuffer() { - if ( mTexture && TextureFactory::existsSingleton() ) - TextureFactory::instance()->remove( mTexture ); - FrameBufferManager::instance()->remove( this ); } -Texture* FrameBuffer::getTexture() const { +const TexturePtr& FrameBuffer::getTexture() const { return mTexture; } diff --git a/src/eepp/graphics/framebufferfbo.cpp b/src/eepp/graphics/framebufferfbo.cpp index 3630877a5..dd8a7923f 100644 --- a/src/eepp/graphics/framebufferfbo.cpp +++ b/src/eepp/graphics/framebufferfbo.cpp @@ -163,11 +163,11 @@ bool FrameBufferFBO::create( const Uint32& Width, const Uint32& Height, bool Ste } else { if ( NULL == mTexture ) { - Texture* tex = TextureFactory::instance()->createEmptyTexture( Width, Height, channels, - Color::Transparent ); + TexturePtr texture = TextureFactory::instance()->createEmptyTexture( + Width, Height, channels, Color::Transparent ); - if ( tex ) { - mTexture = tex; + if ( texture ) { + mTexture = std::move( texture ); } else { Log::error( "FrameBufferFBO::create: failed to create texture" ); return false; diff --git a/src/eepp/graphics/glyphdrawable.cpp b/src/eepp/graphics/glyphdrawable.cpp index d5fd2eb79..f1d189749 100644 --- a/src/eepp/graphics/glyphdrawable.cpp +++ b/src/eepp/graphics/glyphdrawable.cpp @@ -5,15 +5,15 @@ namespace EE { namespace Graphics { -GlyphDrawable* GlyphDrawable::New( Texture* texture, const Rect& srcRect, const Sizef& destSize, +GlyphDrawable* GlyphDrawable::New( TexturePtr texture, const Rect& srcRect, const Sizef& destSize, const std::string& resourceName ) { - return eeNew( GlyphDrawable, ( texture, srcRect, destSize, resourceName ) ); + return eeNew( GlyphDrawable, ( std::move( texture ), srcRect, destSize, resourceName ) ); } -GlyphDrawable::GlyphDrawable( Texture* texture, const Rect& srcRect, const Sizef& destSize, +GlyphDrawable::GlyphDrawable( TexturePtr texture, const Rect& srcRect, const Sizef& destSize, const std::string& resourceName ) : DrawableResource( Drawable::GLYPH, resourceName ), - mTexture( texture ), + mTexture( std::move( texture ) ), mSrcRect( srcRect.asFloat() ), mDestSize( destSize ), mAdvance( destSize.getWidth() ) { @@ -80,7 +80,7 @@ bool GlyphDrawable::isStateful() { return false; } -Texture* GlyphDrawable::getTexture() { +const TexturePtr& GlyphDrawable::getTexture() const { return mTexture; } diff --git a/src/eepp/graphics/ninepatch.cpp b/src/eepp/graphics/ninepatch.cpp index e0136e7a7..6b1e511b4 100644 --- a/src/eepp/graphics/ninepatch.cpp +++ b/src/eepp/graphics/ninepatch.cpp @@ -10,9 +10,9 @@ NinePatch* NinePatch::New( ResourceId textureId, int left, int top, int right, i right, bottom, pixelDensity, name ) ); } -NinePatch* NinePatch::New( Texture* tex, int left, int top, int right, int bottom, +NinePatch* NinePatch::New( TexturePtr tex, int left, int top, int right, int bottom, const Float& pixelDensity, const std::string& name ) { - return eeNew( NinePatch, ( tex, left, top, right, bottom, pixelDensity, name ) ); + return eeNew( NinePatch, ( std::move( tex ), left, top, right, bottom, pixelDensity, name ) ); } NinePatch* NinePatch::New( TextureRegion* textureRegion, int left, int top, int right, int bottom, @@ -20,7 +20,7 @@ NinePatch* NinePatch::New( TextureRegion* textureRegion, int left, int top, int return eeNew( NinePatch, ( textureRegion, left, top, right, bottom, name ) ); } -NinePatch::NinePatch( Texture* tex, int left, int top, int right, int bottom, +NinePatch::NinePatch( TexturePtr tex, int left, int top, int right, int bottom, const Float& pixelDensity, const std::string& name ) : DrawableResource( Drawable::NINEPATCH, name ), mRect( left, top, right, bottom ), @@ -43,16 +43,14 @@ NinePatch::NinePatch( TextureRegion* textureRegion, int left, int top, int right for ( Int32 i = 0; i < SideCount; i++ ) mDrawable[i] = NULL; - Texture* tex; - - if ( NULL != textureRegion && ( tex = textureRegion->getTexture() ) != NULL ) { + if ( NULL != textureRegion && textureRegion->getTexture() != NULL ) { mPixelDensity = textureRegion->getPixelDensity(); Rectf r( textureRegion->getSrcRect().asFloat() ); mSize = r.getSize(); - createFromTexture( tex, left, top, right, bottom ); + createFromTexture( textureRegion->getTexture(), left, top, right, bottom ); for ( int i = 0; i < SideCount; i++ ) { TextureRegion* side = static_cast( mDrawable[i] ); @@ -121,7 +119,8 @@ TextureRegion* NinePatch::getTextureRegion( const int& side ) { return NULL; } -void NinePatch::createFromTexture( Texture* tex, int left, int top, int right, int bottom ) { +void NinePatch::createFromTexture( const TexturePtr& tex, int left, int top, int right, + int bottom ) { Rect r; r = Rect( 0, top, left, mSize.getHeight() - bottom ); mDrawable[Left] = TextureRegion::New( tex, r, r.getSize().asFloat() ); diff --git a/src/eepp/graphics/particlesystem.cpp b/src/eepp/graphics/particlesystem.cpp index c85da4698..7f531da6b 100644 --- a/src/eepp/graphics/particlesystem.cpp +++ b/src/eepp/graphics/particlesystem.cpp @@ -14,7 +14,7 @@ namespace EE { namespace Graphics { ParticleSystem::ParticleSystem() : mParticle( NULL ), mPCount( 0 ), - mTexture( 0 ), + mTexture(), mPLeft( 0 ), mLoops( 0 ), mEffect( ParticleEffect::Nofx ), @@ -324,7 +324,7 @@ void ParticleSystem::draw() { if ( mPointsSup ) { if ( NULL != mTexture ) { - const_cast( mTexture )->bind(); + mTexture->bind(); } else { GLi->disable( GL_TEXTURE_2D ); GLi->disableClientState( GL_TEXTURE_COORD_ARRAY ); diff --git a/src/eepp/graphics/sprite.cpp b/src/eepp/graphics/sprite.cpp index a073343fd..9517f2ad5 100644 --- a/src/eepp/graphics/sprite.cpp +++ b/src/eepp/graphics/sprite.cpp @@ -37,7 +37,6 @@ Sprite* Sprite::fromGif( IOStream& stream ) { sprite->setAnimationSpeed( 1000.f / (float)delay ); sprite->setAsTextureRegionOwner( true ); - sprite->setAsTextureOwner( true ); return sprite; } @@ -140,21 +139,13 @@ void Sprite::clearFrame() { } void Sprite::cleanUpResources() { - if ( isTextureRegionOwner() || isTextureOwner() ) { + if ( isTextureRegionOwner() ) { size_t frames = getNumFrames(); for ( size_t i = 0; i < frames; i++ ) { for ( size_t f = 0; f < mFrames[i].Spr.size(); f++ ) { TextureRegion* region = mFrames[i].Spr[f]; - Texture* texture = region->getTexture(); - - if ( isTextureOwner() && texture && - TextureFactory::instance()->exists( texture ) ) { - TextureFactory::instance()->remove( texture ); - } - - if ( isTextureRegionOwner() ) - GlobalTextureAtlas::instance()->remove( region ); + GlobalTextureAtlas::instance()->remove( region ); } } } @@ -338,12 +329,12 @@ bool Sprite::createStatic( ResourceId textureId, const Sizef& DestSize, const Ve return false; } -bool Sprite::createStatic( Texture* tex, const Sizef& DestSize, const Vector2i& offset, +bool Sprite::createStatic( TexturePtr tex, const Sizef& DestSize, const Vector2i& offset, const Rect& TexSector ) { if ( tex ) { reset(); - addFrame( tex->getTextureId(), DestSize, offset, TexSector ); + addFrame( std::move( tex ), DestSize, offset, TexSector ); return true; } @@ -453,22 +444,39 @@ unsigned int Sprite::addFrame( ResourceId textureId, const Sizef& DestSize, cons return 0; } -unsigned int Sprite::addFrame( Texture* tex, const Sizef& DestSize, const Vector2i& offset, +unsigned int Sprite::addFrame( TexturePtr tex, const Sizef& DestSize, const Vector2i& offset, const Rect& TexSector ) { unsigned int id = framePos(); - if ( addSubFrame( tex, id, mCurrentSubFrame, DestSize, offset, TexSector ) ) + if ( addSubFrame( std::move( tex ), id, mCurrentSubFrame, DestSize, offset, TexSector ) ) return id; return 0; } -bool Sprite::addSubFrame( Texture* tex, const unsigned int& NumFrame, +bool Sprite::addSubFrame( TexturePtr tex, const unsigned int& NumFrame, const unsigned int& NumSubFrame, const Sizef& DestSize, const Vector2i& Offset, const Rect& TexSector ) { - if ( tex ) - return addSubFrame( tex->getTextureId(), NumFrame, NumSubFrame, DestSize, Offset, - TexSector ); + if ( tex ) { + TextureRegion* region = GlobalTextureAtlas::instance()->add( TextureRegion::New() ); + region->setTexture( std::move( tex ) ); + + if ( TexSector.Right > 0 && TexSector.Bottom > 0 ) + region->setSrcRect( TexSector ); + else + region->setSrcRect( Rect( 0, 0, (Int32)region->getTexture()->getImageWidth(), + (Int32)region->getTexture()->getImageHeight() ) ); + + Sizef destSize( DestSize ); + if ( destSize.x <= 0 ) + destSize.x = static_cast( region->getSrcRect().getWidth() ); + if ( destSize.y <= 0 ) + destSize.y = static_cast( region->getSrcRect().getHeight() ); + + region->setDestSize( destSize ); + region->setOffset( Offset ); + return addSubFrame( region, NumFrame, NumSubFrame ); + } return false; } @@ -478,32 +486,8 @@ bool Sprite::addSubFrame( ResourceId textureId, const unsigned int& NumFrame, if ( !TextureFactory::instance()->existsId( textureId ) ) return false; - Texture* Tex = TextureFactory::instance()->getTexture( textureId ); - TextureRegion* S = GlobalTextureAtlas::instance()->add( TextureRegion::New() ); - - S->setTextureId( textureId ); - - if ( TexSector.Right > 0 && TexSector.Bottom > 0 ) - S->setSrcRect( TexSector ); - else - S->setSrcRect( Rect( 0, 0, (Int32)Tex->getImageWidth(), (Int32)Tex->getImageHeight() ) ); - - Sizef destSize( DestSize ); - - if ( destSize.x <= 0 ) { - destSize.x = static_cast( S->getSrcRect().Right - S->getSrcRect().Left ); - } - - if ( destSize.y <= 0 ) { - destSize.y = static_cast( S->getSrcRect().Bottom - S->getSrcRect().Top ); - } - - S->setDestSize( destSize ); - S->setOffset( Offset ); - - addSubFrame( S, NumFrame, NumSubFrame ); - - return true; + return addSubFrame( TextureFactory::instance()->getTexture( textureId ), NumFrame, NumSubFrame, + DestSize, Offset, TexSector ); } void Sprite::update() { @@ -925,18 +909,6 @@ bool Sprite::isTextureRegionOwner() const { return mFlags & SPRITE_FLAG_TEXTURE_REGION_OWNER; } -Sprite& Sprite::setAsTextureOwner( bool set ) { - if ( set ) - mFlags |= SPRITE_FLAG_TEXTURE_OWNER; - else - mFlags &= ~SPRITE_FLAG_TEXTURE_OWNER; - return *this; -} - -bool Sprite::isTextureOwner() const { - return mFlags & SPRITE_FLAG_TEXTURE_OWNER; -} - void Sprite::setOrigin( const OriginPoint& origin ) { mOrigin = origin; } diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index 5e253647b..3cd21972e 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -356,7 +356,7 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo Sizef size{ 0, height }; size_t ssize = string.size(); BatchRenderer* BR = GlobalBatchRenderer::instance(); - Texture* fontTexture = font->getTexture( fontSize ); + const TexturePtr& fontTexture = font->getTexture( fontSize ); Float tabAlign = 0; GlyphDrawable* spaceGlyph = nullptr; GlyphDrawable* tabGlyph = nullptr; @@ -1763,7 +1763,7 @@ void Text::draw( const Float& X, const Float& Y, const Vector2f& scale, const Fl if ( mColors.empty() ) return; - Texture* texture = mFontStyleConfig.Font->getTexture( mFontStyleConfig.CharacterSize ); + const TexturePtr& texture = mFontStyleConfig.Font->getTexture( mFontStyleConfig.CharacterSize ); if ( !texture ) return; texture->bind(); diff --git a/src/eepp/graphics/texture.cpp b/src/eepp/graphics/texture.cpp index af4cc6024..3304dde78 100644 --- a/src/eepp/graphics/texture.cpp +++ b/src/eepp/graphics/texture.cpp @@ -919,7 +919,7 @@ void Texture::draw( const Vector2f& position, const Sizef& size ) { size.y ); } -std::pair, int> Texture::loadGif( IOStream& stream ) { +std::pair, int> Texture::loadGif( IOStream& stream ) { stbi_io_callbacks callbacks; callbacks.read = &IOCb::read; callbacks.skip = &IOCb::skip; @@ -929,7 +929,7 @@ std::pair, int> Texture::loadGif( IOStream& stream ) { if ( type != STBI_gif ) return {}; stream.seek( 0 ); - std::vector gif; + std::vector gif; ScopedBuffer buf( stream.getSize() ); stream.read( (char*)buf.get(), buf.size() ); int width, height, frames, comp; diff --git a/src/eepp/graphics/textureatlas.cpp b/src/eepp/graphics/textureatlas.cpp index 09d4355e6..7605b3dd4 100644 --- a/src/eepp/graphics/textureatlas.cpp +++ b/src/eepp/graphics/textureatlas.cpp @@ -56,33 +56,33 @@ TextureRegion* TextureAtlas::add( ResourceId textureId, const Rect& SrcRect, con return add( TextureRegion::New( textureId, SrcRect, DestSize, Offset, Name ) ); } -TextureRegion* TextureAtlas::add( Texture* tex, const std::string& Name ) { - return add( TextureRegion::New( tex, Name ) ); +TextureRegion* TextureAtlas::add( TexturePtr tex, const std::string& Name ) { + return add( TextureRegion::New( std::move( tex ), Name ) ); } -TextureRegion* TextureAtlas::add( Texture* tex, const Rect& SrcRect, const std::string& Name ) { - return add( TextureRegion::New( tex, SrcRect, Name ) ); +TextureRegion* TextureAtlas::add( TexturePtr tex, const Rect& SrcRect, const std::string& Name ) { + return add( TextureRegion::New( std::move( tex ), SrcRect, Name ) ); } -TextureRegion* TextureAtlas::add( Texture* tex, const Rect& SrcRect, const Sizef& DestSize, +TextureRegion* TextureAtlas::add( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize, const std::string& Name ) { - return add( TextureRegion::New( tex, SrcRect, DestSize, Name ) ); + return add( TextureRegion::New( std::move( tex ), SrcRect, DestSize, Name ) ); } -TextureRegion* TextureAtlas::add( Texture* tex, const Rect& SrcRect, const Sizef& DestSize, +TextureRegion* TextureAtlas::add( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize, const Vector2i& Offset, const std::string& Name ) { - return add( TextureRegion::New( tex, SrcRect, DestSize, Offset, Name ) ); + return add( TextureRegion::New( std::move( tex ), SrcRect, DestSize, Offset, Name ) ); } Uint32 TextureAtlas::getCount() { return ResourceManager::getCount(); } -void TextureAtlas::setTextures( std::vector textures ) { - mTextures = textures; +void TextureAtlas::setTextures( std::vector textures ) { + mTextures = std::move( textures ); } -Texture* TextureAtlas::getTexture( const Uint32& texnum ) const { +const TexturePtr& TextureAtlas::getTexture( const Uint32& texnum ) const { eeASSERT( texnum < mTextures.size() ); return mTextures[texnum]; } diff --git a/src/eepp/graphics/textureatlasloader.cpp b/src/eepp/graphics/textureatlasloader.cpp index 7709f9201..03042a357 100644 --- a/src/eepp/graphics/textureatlasloader.cpp +++ b/src/eepp/graphics/textureatlasloader.cpp @@ -130,6 +130,8 @@ void TextureAtlasLoader::loadFromStream( IOStream& IOS ) { IOS.read( (char*)&mTexGrHdr, sizeof( sTextureAtlasHdr ) ); if ( mTexGrHdr.Magic == EE_TEXTURE_ATLAS_MAGIC ) { + // The complete entry vector is built before mRL starts. Each task below writes only the + // LoadedTexture member at its captured index, so worker execution cannot race a resize. for ( Uint32 i = 0; i < mTexGrHdr.TextureCount; i++ ) { sTextureHdr tTextureHdr; sTempTexAtlas tTexAtlas; @@ -143,16 +145,20 @@ void TextureAtlasLoader::loadFromStream( IOStream& IOS ) { std::string path( FileSystem::fileRemoveFileName( mTextureAtlasPath ) + name ); //! Checks if the texture is already loaded - Texture* tTex = TextureFactory::instance()->getByName( path ); + TexturePtr tTex = TextureFactory::instance()->getByName( path ); + tTexAtlas.LoadedTexture = tTex; if ( !mSkipResourceLoad && NULL == tTex ) { + const std::size_t textureIndex = mTempAtlass.size(); if ( NULL != mPack ) { - mRL.add( [this, path = std::move( path )] { - TextureFactory::instance()->loadFromPack( mPack, path ); + mRL.add( [this, textureIndex, path = std::move( path )] { + mTempAtlass[textureIndex].LoadedTexture = + TextureFactory::instance()->loadFromPack( mPack, path ); } ); } else { - mRL.add( [path = std::move( path )] { - TextureFactory::instance()->loadFromFile( path ); + mRL.add( [this, textureIndex, path = std::move( path )] { + mTempAtlass[textureIndex].LoadedTexture = + TextureFactory::instance()->loadFromFile( path ); } ); } } @@ -160,7 +166,7 @@ void TextureAtlasLoader::loadFromStream( IOStream& IOS ) { IOS.read( (char*)&tTexAtlas.TextureRegions[0], sizeof( sTextureRegionHdr ) * tTextureHdr.TextureRegionCount ); - mTempAtlass.push_back( tTexAtlas ); + mTempAtlass.push_back( std::move( tTexAtlas ) ); } } @@ -233,7 +239,7 @@ void TextureAtlasLoader::createTextureRegions() { FileSystem::filePathRemoveProcessPath( path ); - Texture* tTex = TextureFactory::instance()->getByName( path ); + TexturePtr tTex = tTexAtlas->LoadedTexture; if ( NULL != tTex ) mTexturesLoaded.push_back( tTex ); @@ -327,7 +333,7 @@ bool TextureAtlasLoader::isLoading() const { return mIsLoading.load(); } -Texture* TextureAtlasLoader::getTexture( const Uint32& texnum ) const { +const TexturePtr& TextureAtlasLoader::getTexture( const Uint32& texnum ) const { eeASSERT( texnum < mTexturesLoaded.size() ); return mTexturesLoaded[texnum]; } diff --git a/src/eepp/graphics/texturefactory.cpp b/src/eepp/graphics/texturefactory.cpp index 085ecf95c..db12b0c66 100644 --- a/src/eepp/graphics/texturefactory.cpp +++ b/src/eepp/graphics/texturefactory.cpp @@ -57,29 +57,27 @@ void TextureFactory::TextureDeleter::operator()( Texture* texture ) const noexce eeASSERTM( false, Texture_released_after_TextureFactory_destruction ); } -Texture* TextureFactory::createEmptyTexture( const unsigned int& Width, const unsigned int& Height, - const unsigned int& Channels, - const Color& DefaultColor, const bool& Mipmap, - const Texture::ClampMode& ClampMode, - const bool& CompressTexture, const bool& KeepLocalCopy, - const std::string& Filename ) { +TexturePtr TextureFactory::createEmptyTexture( + const unsigned int& Width, const unsigned int& Height, const unsigned int& Channels, + const Color& DefaultColor, const bool& Mipmap, const Texture::ClampMode& ClampMode, + const bool& CompressTexture, const bool& KeepLocalCopy, const std::string& Filename ) { Image TmpImg( Width, Height, Channels, DefaultColor ); return loadFromPixels( TmpImg.getPixelsPtr(), Width, Height, Channels, Mipmap, ClampMode, CompressTexture, KeepLocalCopy, Filename ); } -Texture* TextureFactory::loadFromPixels( const unsigned char* Pixels, const unsigned int& Width, - const unsigned int& Height, const unsigned int& Channels, - const bool& Mipmap, const Texture::ClampMode& ClampMode, - const bool& CompressTexture, const bool& KeepLocalCopy, - const std::string& FileName ) { +TexturePtr TextureFactory::loadFromPixels( const unsigned char* Pixels, const unsigned int& Width, + const unsigned int& Height, const unsigned int& Channels, + const bool& Mipmap, const Texture::ClampMode& ClampMode, + const bool& CompressTexture, const bool& KeepLocalCopy, + const std::string& FileName ) { TextureLoader myTex( Pixels, Width, Height, Channels, Mipmap, ClampMode, CompressTexture, KeepLocalCopy, FileName ); myTex.load(); return myTex.getTexture(); } -Texture* +TexturePtr TextureFactory::loadFromPack( Pack* Pack, const std::string& FilePackPath, const bool& Mipmap, const Texture::ClampMode& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, @@ -90,7 +88,7 @@ TextureFactory::loadFromPack( Pack* Pack, const std::string& FilePackPath, const return myTex.getTexture(); } -Texture* +TexturePtr TextureFactory::loadFromMemory( const unsigned char* ImagePtr, const unsigned int& Size, const bool& Mipmap, const Texture::ClampMode& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, @@ -101,7 +99,7 @@ TextureFactory::loadFromMemory( const unsigned char* ImagePtr, const unsigned in return myTex.getTexture(); } -Texture* +TexturePtr TextureFactory::loadFromStream( IOStream& Stream, const bool& Mipmap, const Texture::ClampMode& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, @@ -112,7 +110,7 @@ TextureFactory::loadFromStream( IOStream& Stream, const bool& Mipmap, return myTex.getTexture(); } -Texture* +TexturePtr TextureFactory::loadFromFile( const std::string& Filepath, const bool& Mipmap, const Texture::ClampMode& ClampMode, const bool& CompressTexture, const bool& KeepLocalCopy, @@ -123,13 +121,13 @@ TextureFactory::loadFromFile( const std::string& Filepath, const bool& Mipmap, return myTex.getTexture(); } -Texture* TextureFactory::pushTexture( const std::string& Filepath, const Uint32& textureHandle, - const unsigned int& Width, const unsigned int& Height, - const unsigned int& ImgWidth, const unsigned int& ImgHeight, - const bool& Mipmap, const unsigned int& Channels, - const Texture::ClampMode& ClampMode, - const bool& CompressTexture, const bool& LocalCopy, - const Uint32& MemSize ) { +TexturePtr TextureFactory::pushTexture( const std::string& Filepath, const Uint32& textureHandle, + const unsigned int& Width, const unsigned int& Height, + const unsigned int& ImgWidth, const unsigned int& ImgHeight, + const bool& Mipmap, const unsigned int& Channels, + const Texture::ClampMode& ClampMode, + const bool& CompressTexture, const bool& LocalCopy, + const Uint32& MemSize ) { Lock l( *this ); std::string FPath( Filepath ); @@ -144,7 +142,7 @@ Texture* TextureFactory::pushTexture( const std::string& Filepath, const Uint32& Tex->create( textureHandle, Width, Height, ImgWidth, ImgHeight, Mipmap, Channels, FPath, ClampMode, CompressTexture, MemSize ); TextureWeakPtr weakTexture( texture ); - mTextures.emplace( resourceId.value(), std::move( texture ) ); + mTextures.emplace( resourceId.value(), texture ); mLiveTextures.emplace( resourceId.value(), LiveTextureRecord{ resourceId, std::move( weakTexture ) } ); mLiveTextureGeneration.fetch_add( 1, std::memory_order_release ); @@ -154,7 +152,7 @@ Texture* TextureFactory::pushTexture( const std::string& Filepath, const Uint32& Tex->unlock( true, false ); } - return Tex; + return texture; } void TextureFactory::bind( const Texture* texture, Texture::CoordinateType coordinateType, @@ -202,7 +200,7 @@ void TextureFactory::bind( const Texture* texture, Texture::CoordinateType coord void TextureFactory::bind( ResourceId textureId, Texture::CoordinateType coordinateType, const Uint32& textureUnit, const bool& forceRebind ) { - bind( getTexture( textureId ), coordinateType, textureUnit, forceRebind ); + bind( getTexture( textureId ).get(), coordinateType, textureUnit, forceRebind ); } void TextureFactory::unloadTextures() { @@ -220,7 +218,7 @@ void TextureFactory::unloadTextures() { Log::debug( "Textures Unloaded." ); } -bool TextureFactory::remove( ResourceId textureId ) { +bool TextureFactory::releaseRetainedTexture( ResourceId textureId ) { TexturePtr texture; { Lock l( *this ); @@ -237,25 +235,6 @@ bool TextureFactory::remove( ResourceId textureId ) { return true; } -bool TextureFactory::remove( Texture* texture ) { - TexturePtr removed; - { - Lock l( *this ); - auto it = std::find_if( mTextures.begin(), mTextures.end(), [texture]( const auto& pair ) { - return pair.second.get() == texture; - } ); - if ( it == mTextures.end() ) - return false; - - removed = std::move( it->second ); - mTextures.erase( it ); - resetTextureBinding( removed.get() ); - } - - removed.reset(); - return true; -} - void TextureFactory::resetTextureBinding( const Texture* texture ) { if ( !texture ) return; @@ -277,22 +256,6 @@ void TextureFactory::setCurrentTexture( const int& textureHandle, const Uint32& mCurrentTexture[TextureUnit] = textureHandle; } -std::vector TextureFactory::getTextures() { - Lock l( *this ); - - std::vector textures; - textures.reserve( mTextures.size() ); - - for ( const auto& texture : mTextures ) { - Texture* Tex = texture.second.get(); - - if ( Tex ) - textures.push_back( Tex ); - } - - return textures; -} - TextureRegistrySnapshot TextureFactory::snapshotTextures() { struct LockedTextureRecord { LiveTextureRecord record; @@ -423,22 +386,14 @@ bool TextureFactory::existsId( ResourceId textureId ) { return mTextures.find( textureId.value() ) != mTextures.end(); } -bool TextureFactory::exists( const Texture* tex ) { - Lock l( *this ); - - return std::find_if( mTextures.begin(), mTextures.end(), [tex]( const auto& pair ) { - return pair.second.get() == tex; - } ) != mTextures.end(); -} - -Texture* TextureFactory::getTexture( ResourceId textureId ) { +TexturePtr TextureFactory::getTexture( ResourceId textureId ) { Lock l( *this ); auto it = mTextures.find( textureId.value() ); - return it != mTextures.end() ? it->second.get() : NULL; + return it != mTextures.end() ? it->second : TexturePtr{}; } -Texture* TextureFactory::getByName( const std::string& Name ) { +TexturePtr TextureFactory::getByName( const std::string& Name ) { return getByHash( String::hash( Name ) ); } @@ -459,13 +414,13 @@ unsigned int TextureFactory::getTextureMemorySize() { return static_cast( memorySize ); } -Texture* TextureFactory::getByHash( const String::HashType& hash ) { +TexturePtr TextureFactory::getByHash( const String::HashType& hash ) { Lock l( *this ); Uint64 latestId = 0; - Texture* latestTexture = NULL; + TexturePtr latestTexture; for ( const auto& texture : mTextures ) { - Texture* tTex = texture.second.get(); + const TexturePtr& tTex = texture.second; if ( NULL != tTex && texture.first > latestId && tTex->getHashName() == hash ) { latestId = texture.first; diff --git a/src/eepp/graphics/textureloader.cpp b/src/eepp/graphics/textureloader.cpp index c31615108..72ab35565 100644 --- a/src/eepp/graphics/textureloader.cpp +++ b/src/eepp/graphics/textureloader.cpp @@ -432,7 +432,7 @@ const std::string& TextureLoader::getFilepath() const { return mFilepath; } -Texture* TextureLoader::getTexture() const { +const TexturePtr& TextureLoader::getTexture() const { return mTexture; } @@ -445,17 +445,18 @@ void TextureLoader::setFormatConfiguration( mFormatConfiguration = formatConfiguration; } -void TextureLoader::unload() { - if ( mLoaded && mTexture != nullptr ) { - TextureFactory::instance()->remove( mTexture->getTextureId() ); - - reset(); - } -} - void TextureLoader::reset() { - mPixels = nullptr; - mTexture = nullptr; + if ( mTexture ) { + if ( TextureFactory* factory = TextureFactory::existsSingleton() ) + factory->releaseRetainedTexture( mTexture->getTextureId() ); + } + + if ( TEX_LT_PIXELS != mLoadType ) { + eeSAFE_FREE( mPixels ); + } else { + mPixels = nullptr; + } + mTexture.reset(); mImgWidth = 0; mImgHeight = 0; mWidth = 0; diff --git a/src/eepp/graphics/textureregion.cpp b/src/eepp/graphics/textureregion.cpp index 4137fb8b5..aa7305969 100644 --- a/src/eepp/graphics/textureregion.cpp +++ b/src/eepp/graphics/textureregion.cpp @@ -36,40 +36,40 @@ TextureRegion* TextureRegion::New( ResourceId textureId, const Rect& srcRect, co destSize, offset, name ) ); } -TextureRegion* TextureRegion::New( Texture* tex, const std::string& name ) { - return eeNew( TextureRegion, ( tex, name ) ); +TextureRegion* TextureRegion::New( TexturePtr tex, const std::string& name ) { + return eeNew( TextureRegion, ( std::move( tex ), name ) ); } -TextureRegion* TextureRegion::New( Texture* tex, const Rect& srcRect, const std::string& name ) { - return eeNew( TextureRegion, ( tex, srcRect, name ) ); +TextureRegion* TextureRegion::New( TexturePtr tex, const Rect& srcRect, const std::string& name ) { + return eeNew( TextureRegion, ( std::move( tex ), srcRect, name ) ); } -TextureRegion* TextureRegion::New( Texture* tex, const Rect& srcRect, const Sizef& destSize, +TextureRegion* TextureRegion::New( TexturePtr tex, const Rect& srcRect, const Sizef& destSize, const std::string& name ) { - return eeNew( TextureRegion, ( tex, srcRect, destSize, name ) ); + return eeNew( TextureRegion, ( std::move( tex ), srcRect, destSize, name ) ); } -TextureRegion* TextureRegion::New( Texture* tex, const Rect& srcRect, const Sizef& destSize, +TextureRegion* TextureRegion::New( TexturePtr tex, const Rect& srcRect, const Sizef& destSize, const Vector2i& offset, const std::string& name ) { - return eeNew( TextureRegion, ( tex, srcRect, destSize, offset, name ) ); + return eeNew( TextureRegion, ( std::move( tex ), srcRect, destSize, offset, name ) ); } TextureRegion::TextureRegion() : DrawableResource( Drawable::TEXTUREREGION ), mPixels( NULL ), mAlphaMask( NULL ), - mTexture( NULL ), + mTexture(), mSrcRect( Rect( 0, 0, 0, 0 ) ), mOriDestSize( 0, 0 ), mDestSize( 0, 0 ), mOffset( 0, 0 ), mPixelDensity( 1 ) {} -TextureRegion::TextureRegion( Texture* tex, const std::string& name ) : +TextureRegion::TextureRegion( TexturePtr tex, const std::string& name ) : DrawableResource( Drawable::TEXTUREREGION, name ), mPixels( NULL ), mAlphaMask( NULL ), - mTexture( tex ), + mTexture( std::move( tex ) ), mSrcRect( Rect( 0, 0, NULL != mTexture ? mTexture->getImageWidth() : 0, NULL != mTexture ? mTexture->getImageHeight() : 0 ) ), mOriDestSize( PixelDensity::dpToPx( mSrcRect.getSize().asFloat() ) ), @@ -77,11 +77,11 @@ TextureRegion::TextureRegion( Texture* tex, const std::string& name ) : mOffset( 0, 0 ), mPixelDensity( 1 ) {} -TextureRegion::TextureRegion( Texture* tex, const Rect& SrcRect, const std::string& name ) : +TextureRegion::TextureRegion( TexturePtr tex, const Rect& SrcRect, const std::string& name ) : DrawableResource( Drawable::TEXTUREREGION, name ), mPixels( NULL ), mAlphaMask( NULL ), - mTexture( tex ), + mTexture( std::move( tex ) ), mSrcRect( SrcRect ), mOriDestSize( PixelDensity::dpToPx( Sizef( (Float)( mSrcRect.Right - mSrcRect.Left ), (Float)( mSrcRect.Bottom - mSrcRect.Top ) ) ) ), @@ -89,24 +89,24 @@ TextureRegion::TextureRegion( Texture* tex, const Rect& SrcRect, const std::stri mOffset( 0, 0 ), mPixelDensity( 1 ) {} -TextureRegion::TextureRegion( Texture* tex, const Rect& SrcRect, const Sizef& DestSize, +TextureRegion::TextureRegion( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize, const std::string& name ) : DrawableResource( Drawable::TEXTUREREGION, name ), mPixels( NULL ), mAlphaMask( NULL ), - mTexture( tex ), + mTexture( std::move( tex ) ), mSrcRect( SrcRect ), mOriDestSize( DestSize ), mDestSize( DestSize ), mOffset( 0, 0 ), mPixelDensity( 1 ) {} -TextureRegion::TextureRegion( Texture* tex, const Rect& SrcRect, const Sizef& DestSize, +TextureRegion::TextureRegion( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize, const Vector2i& Offset, const std::string& name ) : DrawableResource( Drawable::TEXTUREREGION, name ), mPixels( NULL ), mAlphaMask( NULL ), - mTexture( tex ), + mTexture( std::move( tex ) ), mSrcRect( SrcRect ), mOriDestSize( DestSize ), mDestSize( DestSize ), @@ -121,8 +121,8 @@ void TextureRegion::setTextureId( ResourceId textureId ) { mTexture = TextureFactory::instance()->getTexture( textureId ); } -void TextureRegion::setTexture( Texture* texture ) { - mTexture = texture; +void TextureRegion::setTexture( TexturePtr texture ) { + mTexture = std::move( texture ); } const Rect& TextureRegion::getSrcRect() const { @@ -199,7 +199,7 @@ void TextureRegion::draw( const Vector2f& position, const Sizef& size ) { mDestSize = oldSize; } -Graphics::Texture* TextureRegion::getTexture() { +const TexturePtr& TextureRegion::getTexture() const { return mTexture; } diff --git a/src/eepp/ui/tools/uicolorpicker.cpp b/src/eepp/ui/tools/uicolorpicker.cpp index 4d1c0a778..8279e432b 100644 --- a/src/eepp/ui/tools/uicolorpicker.cpp +++ b/src/eepp/ui/tools/uicolorpicker.cpp @@ -287,8 +287,8 @@ UIColorPicker::UIColorPicker( UIWindow* attachTo, const UIColorPicker::ColorPick mRoot->on( Event::OnLayoutUpdate, [this]( const Event* ) { if ( mHuePicker->getDrawable() == nullptr ) { - mHuePicker->setDrawable( createHueTexture( mHuePicker->getPixelsSize() ), true ); - mCurrentColor->setBackgroundDrawable( createGridTexture(), true ); + mHuePicker->setDrawable( createHueTexture( mHuePicker->getPixelsSize() ) ); + mCurrentColor->setBackgroundDrawable( TextureRegion::New( createGridTexture() ), true ); mCurrentColor->setBackgroundRepeat( "repeat" ); updateAll(); } @@ -369,7 +369,7 @@ void UIColorPicker::windowClose( const Event* ) { eeDelete( this ); } -Texture* UIColorPicker::createHueTexture( const Sizef& size ) { +TexturePtr UIColorPicker::createHueTexture( const Sizef& size ) { Image image( 1, (Uint32)size.getHeight(), 3 ); for ( Uint32 y = 0; y < image.getHeight(); y++ ) { @@ -385,7 +385,7 @@ Texture* UIColorPicker::createHueTexture( const Sizef& size ) { image.getChannels() ); } -Texture* UIColorPicker::createGridTexture() { +TexturePtr UIColorPicker::createGridTexture() { Sizef size( PixelDensity::dpToPx( Sizef( 26, 24 ) ) ); Image image( size.getWidth(), size.getHeight(), 3, Color( 128, 128, 128, 255 ) ); Color highlightColor( 204, 204, 204, 255 ); @@ -573,7 +573,7 @@ void UIColorPicker::registerEvents() { ->setPosition( 0, 0 ) ->setSize( mRoot->getSceneNode()->getSize() ); mCoverWidget->setAnchors( UI_ANCHOR_LEFT | UI_ANCHOR_TOP | UI_ANCHOR_RIGHT | - UI_ANCHOR_BOTTOM ); + UI_ANCHOR_BOTTOM ); mCoverWidget->on( Event::MouseMove, [this]( const Event* event ) { Vector2i position = reinterpret_cast( event )->getPosition(); setColor( GLi->readPixel( position.x, diff --git a/src/eepp/ui/tools/uidiffview.cpp b/src/eepp/ui/tools/uidiffview.cpp index 47afee452..3fabb31ad 100644 --- a/src/eepp/ui/tools/uidiffview.cpp +++ b/src/eepp/ui/tools/uidiffview.cpp @@ -67,7 +67,6 @@ static Sprite* setImageViewerImage( UIImageViewer* viewer, Image* image ) { auto sprite = Sprite::New(); sprite->createStatic( texture ); - sprite->setAsTextureOwner( true ); sprite->setAsTextureRegionOwner( true ); viewer->reset(); diff --git a/src/eepp/ui/tools/uiimageviewer.cpp b/src/eepp/ui/tools/uiimageviewer.cpp index 866c82076..e6d0d7c37 100644 --- a/src/eepp/ui/tools/uiimageviewer.cpp +++ b/src/eepp/ui/tools/uiimageviewer.cpp @@ -167,7 +167,6 @@ void UIImageViewer::loadImageAsync( std::string_view path, bool isContents, bool : TextureFactory::instance()->loadFromFile( path ); Sprite* sprite = Sprite::New(); sprite->createStatic( tex ); - sprite->setAsTextureOwner( true ); sprite->setAsTextureRegionOwner( true ); image = sprite; } else { @@ -175,7 +174,6 @@ void UIImageViewer::loadImageAsync( std::string_view path, bool isContents, bool ? (IOStream*)new IOStreamMemory( path.c_str(), path.size() ) : (IOStream*)new IOStreamFile( path ); Sprite* sprite = Sprite::fromGif( *stream ); - sprite->setAsTextureOwner( true ); sprite->setAsTextureRegionOwner( true ); sprite->setAutoAnimate( false ); image = sprite; diff --git a/src/eepp/ui/uiicon.cpp b/src/eepp/ui/uiicon.cpp index 2e1745674..e3a95533c 100644 --- a/src/eepp/ui/uiicon.cpp +++ b/src/eepp/ui/uiicon.cpp @@ -77,7 +77,7 @@ UISVGIcon::~UISVGIcon() {} Drawable* UISVGIcon::getSize( const int& size ) const { auto it = mSVGs.find( size ); if ( it != mSVGs.end() ) - return it->second; + return it->second.get(); Image::FormatConfiguration format; if ( mOriSize == Sizei::Zero ) { @@ -91,12 +91,12 @@ Drawable* UISVGIcon::getSize( const int& size ) const { } } format.svgScale( size / (Float)eemax( mOriSize.x, mOriSize.y ) ); - Texture* texture = TextureFactory::instance()->loadFromMemory( + TexturePtr texture = TextureFactory::instance()->loadFromMemory( (const unsigned char*)&mSVGXml[0], mSVGXml.size(), false, Texture::ClampMode::ClampToEdge, false, false, format ); mSVGs[size] = texture; - return texture; + return texture.get(); } UISVGIcon::UISVGIcon( const std::string& name, const std::string& svgXML ) : diff --git a/src/eepp/ui/uiimage.cpp b/src/eepp/ui/uiimage.cpp index fb25d9510..72017f08c 100644 --- a/src/eepp/ui/uiimage.cpp +++ b/src/eepp/ui/uiimage.cpp @@ -38,11 +38,11 @@ std::string getTextureCacheName( const Network::URI& uri ) { return filePath; } -Texture* loadFileTextureCached( const std::string& filePath, const std::string& cacheName ) { +TexturePtr loadFileTextureCached( const std::string& filePath, const std::string& cacheName ) { static std::mutex loadMutex; std::lock_guard lock( loadMutex ); - if ( Texture* texture = TextureFactory::instance()->getByName( cacheName ) ) + if ( TexturePtr texture = TextureFactory::instance()->getByName( cacheName ) ) return texture; return TextureFactory::instance()->loadFromFile( @@ -136,6 +136,13 @@ UIImage* UIImage::setDrawable( Drawable* drawable, bool ownIt ) { return this; } +UIImage* UIImage::setDrawable( TexturePtr texture ) { + Texture* drawable = texture.get(); + setDrawable( drawable, false ); + mTexture = std::move( texture ); + return this; +} + void UIImage::onAutoSize() { if ( nullptr == mDrawable ) return; @@ -318,6 +325,8 @@ void UIImage::safeDeleteDrawable() { mDrawableOwner = false; } + + mTexture.reset(); } void UIImage::onDrawableResourceEvent( DrawableResource::Event event, DrawableResource* ) { @@ -344,8 +353,8 @@ bool UIImage::loadFileDrawable( const Network::URI& uri ) { Uint64 loadId = ++mRemoteImageLoadId; std::string filePath = uri.getFSPath(); std::string cacheName = getTextureCacheName( uri ); - if ( Texture* texture = TextureFactory::instance()->getByName( cacheName ) ) { - setDrawable( texture, false ); + if ( TexturePtr texture = TextureFactory::instance()->getByName( cacheName ) ) { + setDrawable( std::move( texture ) ); return true; } @@ -361,7 +370,7 @@ bool UIImage::loadFileDrawable( const Network::URI& uri ) { !alive || !alive->load( std::memory_order_acquire ) ) return; - Texture* texture = loadFileTextureCached( filePath, cacheName ); + TexturePtr texture = loadFileTextureCached( filePath, cacheName ); if ( texture == nullptr ) return; @@ -371,7 +380,7 @@ bool UIImage::loadFileDrawable( const Network::URI& uri ) { loadId != mRemoteImageLoadId ) return; - setDrawable( texture, false ); + setDrawable( std::move( texture ) ); } ); } ); @@ -384,10 +393,10 @@ void UIImage::loadRemoteDrawable( const Network::URI& uri ) { return; std::string url = uri.toString(); - if ( Texture* texture = TextureFactory::instance()->getByName( url ) ) { - if ( mDrawable != texture ) { + if ( TexturePtr texture = TextureFactory::instance()->getByName( url ) ) { + if ( mDrawable != texture.get() ) { ++mRemoteImageLoadId; - setDrawable( texture, false ); + setDrawable( std::move( texture ) ); } return; } @@ -397,10 +406,10 @@ void UIImage::loadRemoteDrawable( const Network::URI& uri ) { resourceState ? resourceState->generation.load( std::memory_order_acquire ) : 0; Uint64 loadId = ++mRemoteImageLoadId; auto alive = mAsyncImageAlive; - Texture* texture = TextureFactory::instance()->createEmptyTexture( + TexturePtr texture = TextureFactory::instance()->createEmptyTexture( 1, 1, 4, Color::Transparent, false, Texture::ClampMode::ClampToEdge, false, false, url ); if ( texture ) - setDrawable( texture, false ); + setDrawable( texture ); Http::Request::FieldTable headers; if ( !scene->getReferer().empty() ) @@ -419,7 +428,7 @@ void UIImage::loadRemoteDrawable( const Network::URI& uri ) { [alive, loadId, texture, imageData = std::move( imageData ), this]( UISceneNode* ) mutable { if ( !alive || !alive->load( std::memory_order_acquire ) || - loadId != mRemoteImageLoadId || mDrawable != texture ) + loadId != mRemoteImageLoadId || mDrawable != texture.get() ) return; Image image( reinterpret_cast( imageData.data() ), diff --git a/src/eepp/ui/uinodedrawable.cpp b/src/eepp/ui/uinodedrawable.cpp index bad00f63e..c9399343b 100644 --- a/src/eepp/ui/uinodedrawable.cpp +++ b/src/eepp/ui/uinodedrawable.cpp @@ -632,6 +632,7 @@ void UINodeDrawable::LayerDrawable::setDrawable( Drawable* drawable, const bool& eeSAFE_DELETE( mDrawable ); } } + mTexture.reset(); mDrawable = drawable; mDrawableRef = ""; @@ -653,6 +654,12 @@ void UINodeDrawable::LayerDrawable::setDrawable( Drawable* drawable, const bool& } } +void UINodeDrawable::LayerDrawable::setDrawable( TexturePtr texture ) { + Texture* drawable = texture.get(); + setDrawable( drawable, false ); + mTexture = std::move( texture ); +} + void UINodeDrawable::LayerDrawable::setDrawable( const std::string& drawableRef ) { if ( drawableRef == "none" ) { setDrawable( nullptr, false ); @@ -705,10 +712,10 @@ bool UINodeDrawable::LayerDrawable::loadRemoteDrawable( const std::string& value return true; std::string url = uri.toString(); - if ( Texture* texture = TextureFactory::instance()->getByName( url ) ) { - if ( mDrawable != texture ) { + if ( TexturePtr texture = TextureFactory::instance()->getByName( url ) ) { + if ( mDrawable != texture.get() ) { ++mRemoteDrawableLoadId; - setDrawable( texture, false ); + setDrawable( std::move( texture ) ); } return true; } @@ -718,10 +725,10 @@ bool UINodeDrawable::LayerDrawable::loadRemoteDrawable( const std::string& value resourceState ? resourceState->generation.load( std::memory_order_acquire ) : 0; Uint64 loadId = ++mRemoteDrawableLoadId; auto alive = mAsyncDrawableAlive; - Texture* texture = TextureFactory::instance()->createEmptyTexture( + TexturePtr texture = TextureFactory::instance()->createEmptyTexture( 1, 1, 4, Color::Transparent, false, Texture::ClampMode::ClampToEdge, false, false, url ); if ( texture ) - setDrawable( texture, false ); + setDrawable( texture ); Http::Request::FieldTable headers; if ( !scene->getReferer().empty() ) @@ -740,7 +747,7 @@ bool UINodeDrawable::LayerDrawable::loadRemoteDrawable( const std::string& value [alive, loadId, texture, imageData = std::move( imageData ), this]( UISceneNode* ) mutable { if ( !alive || !alive->load( std::memory_order_acquire ) || - loadId != mRemoteDrawableLoadId || mDrawable != texture ) + loadId != mRemoteDrawableLoadId || mDrawable != texture.get() ) return; Image image( reinterpret_cast( imageData.data() ), diff --git a/src/eepp/ui/uisvg.cpp b/src/eepp/ui/uisvg.cpp index c0705df91..03edcfafa 100644 --- a/src/eepp/ui/uisvg.cpp +++ b/src/eepp/ui/uisvg.cpp @@ -98,15 +98,14 @@ void UISvg::scheduleRasterize() { } void UISvg::rasterizeSvg( const std::string& svgXml ) { - Texture* texture = TextureFactory::instance()->loadFromMemory( + TexturePtr texture = TextureFactory::instance()->loadFromMemory( (const unsigned char*)svgXml.data(), svgXml.size() ); if ( !texture ) return; Sprite* sprite = Sprite::New(); - sprite->createStatic( texture ); - sprite->setAsTextureOwner( true ); + sprite->createStatic( std::move( texture ) ); sprite->setAsTextureRegionOwner( true ); auto spriteTransfer = std::make_shared( sprite ); diff --git a/src/examples/sprites/sprites.cpp b/src/examples/sprites/sprites.cpp index 5419aeb33..baa9b6a09 100644 --- a/src/examples/sprites/sprites.cpp +++ b/src/examples/sprites/sprites.cpp @@ -101,8 +101,8 @@ EE_MAIN_FUNC int main( int, char*[] ) { FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); // Load the rock texture - Texture* PlanetTex = TextureFactory::instance()->loadFromFile( "assets/sprites/7.png" ); - Texture* RockTex = TextureFactory::instance()->loadFromFile( "assets/sprites/5.png" ); + TexturePtr PlanetTex = TextureFactory::instance()->loadFromFile( "assets/sprites/7.png" ); + TexturePtr RockTex = TextureFactory::instance()->loadFromFile( "assets/sprites/5.png" ); // Load a previously generated texture atlas that contains the TextureRegions needed to load // an animated sprite diff --git a/src/modules/maps/include/eepp/maps/tilemap.hpp b/src/modules/maps/include/eepp/maps/tilemap.hpp index ed75446c4..d07791f68 100644 --- a/src/modules/maps/include/eepp/maps/tilemap.hpp +++ b/src/modules/maps/include/eepp/maps/tilemap.hpp @@ -194,7 +194,7 @@ class EE_MAPS_API TileMap { void setUpdateCallback( MapUpdateCb Cb ); - Texture* getBlankTileTexture(); + const TexturePtr& getBlankTileTexture() const; bool isTileBlocked( const Vector2i& TilePos ); @@ -269,7 +269,7 @@ class EE_MAPS_API TileMap { PropertiesMap mProperties; GOTypesList mObjTypes; CreateGOCb mCreateGOCb; - Texture* mTileTex; + TexturePtr mTileTex; Rectf mScreenAABB; MapLightManager* mLightManager; MapDrawCb mDrawCb; diff --git a/src/modules/maps/src/eepp/maps/mapobjectlayer.cpp b/src/modules/maps/src/eepp/maps/mapobjectlayer.cpp index 8cf969e06..08d2e6496 100644 --- a/src/modules/maps/src/eepp/maps/mapobjectlayer.cpp +++ b/src/modules/maps/src/eepp/maps/mapobjectlayer.cpp @@ -41,7 +41,7 @@ void MapObjectLayer::draw( const Vector2f& Offset ) { ( *it )->draw(); } - Texture* Tex = mMap->getBlankTileTexture(); + const TexturePtr& Tex = mMap->getBlankTileTexture(); if ( mMap->getShowBlocked() && NULL != Tex ) { Color Col( 255, 0, 0, 200 ); diff --git a/src/modules/maps/src/eepp/maps/tilemap.cpp b/src/modules/maps/src/eepp/maps/tilemap.cpp index 1b8b1ed5b..005b0c8b4 100644 --- a/src/modules/maps/src/eepp/maps/tilemap.cpp +++ b/src/modules/maps/src/eepp/maps/tilemap.cpp @@ -128,9 +128,9 @@ void TileMap::createEmptyTile() { std::string tileName( String::format( "maptile-%dx%d-%u", mTileSize.getWidth(), mTileSize.getHeight(), mGridLinesColor.getValue() ) ); - Texture* Tex = TF->getByName( tileName ); + TexturePtr texture = TF->getByName( tileName ); - if ( NULL == Tex ) { + if ( NULL == texture ) { Uint32 x, y; Color Col( mGridLinesColor ); @@ -152,7 +152,7 @@ void TileMap::createEmptyTile() { Img.getChannels(), true, Texture::ClampMode::ClampToEdge, false, false, tileName ); } else { - mTileTex = Tex; + mTileTex = std::move( texture ); } } @@ -1465,7 +1465,7 @@ void TileMap::setUpdateCallback( MapUpdateCb Cb ) { mUpdateCb = Cb; } -Texture* TileMap::getBlankTileTexture() { +const TexturePtr& TileMap::getBlankTileTexture() const { return mTileTex; } diff --git a/src/modules/maps/src/eepp/maps/tilemaplayer.cpp b/src/modules/maps/src/eepp/maps/tilemaplayer.cpp index 0be5447fa..272ebd330 100644 --- a/src/modules/maps/src/eepp/maps/tilemaplayer.cpp +++ b/src/modules/maps/src/eepp/maps/tilemaplayer.cpp @@ -38,7 +38,7 @@ void TileMapLayer::draw( const Vector2f& Offset ) { } } - Texture* Tex = mMap->getBlankTileTexture(); + const TexturePtr& Tex = mMap->getBlankTileTexture(); if ( mMap->getShowBlocked() && NULL != Tex ) { for ( Int32 x = start.x; x < end.x; x++ ) { diff --git a/src/tests/test_all/test.cpp b/src/tests/test_all/test.cpp index 49b26cb99..1ac2f1bbf 100644 --- a/src/tests/test_all/test.cpp +++ b/src/tests/test_all/test.cpp @@ -974,18 +974,21 @@ void EETest::createNewUI() { SceneManager::instance()->getUISceneNode()->bind( "gridlayout", gridLayout ); if ( NULL != gridLayout ) { - std::vector textures = TextureFactory::instance()->getTextures(); + TextureRegistrySnapshot textures = TextureFactory::instance()->snapshotTextures(); if ( textures.size() > 0 ) { for ( std::size_t i = 0; i < textures.size(); i++ ) { + TexturePtr texture = textures[i].texture.lock(); + if ( !texture ) + continue; UIImage* img = UIImage::New(); - img->setDrawable( textures[i] ) + img->setDrawable( texture ) ->setScaleType( UIScaleType::FitInside ) ->setGravity( UI_HALIGN_CENTER | UI_VALIGN_CENTER ) ->setEnabled( false ) ->setParent( gridLayout ); - img->setBackgroundColor( Color::fromPointer( textures[i] ) ); + img->setBackgroundColor( Color::fromPointer( texture.get() ) ); } } } @@ -1368,8 +1371,11 @@ void EETest::loadTextures() { std::string name( files[i] ); if ( "jpg" == FileSystem::fileExtension( name ) ) { - mResLoad.add( [this, name = std::move( name )] { - TextureFactory::instance()->loadFromPack( PakTest, name ); + const std::size_t textureIndex = mLoadedTextures.size(); + mLoadedTextures.emplace_back(); + mResLoad.add( [this, textureIndex, name = std::move( name )] { + mLoadedTextures[textureIndex] = + TextureFactory::instance()->loadFromPack( PakTest, name ); } ); } } @@ -1401,8 +1407,7 @@ void EETest::loadTextures() { Tiles[i] = SG->getByName( String::toString( i + 1 ) ); } - Tiles[6] = - SG->add( TF->loadFromFile( MyPath + "sprites/objects/1.png" )->getTextureId(), "7" ); + Tiles[6] = SG->add( TF->loadFromFile( MyPath + "sprites/objects/1.png" ), "7" ); #ifdef EE_GLES Image tImg( MyPath + "sprites/objects/2.png", 4 ); @@ -1431,7 +1436,7 @@ void EETest::loadTextures() { PS[3].create( ParticleEffect::Fire, 350, TN[5], Vector2f( -50.f, -50.f ), 32, true ); PS[4].create( ParticleEffect::Fire, 350, TN[5], Vector2f( -50.f, -50.f ), 32, true ); - Texture* Tex = TNP[2]; + Texture* Tex = TNP[2].get(); if ( NULL != Tex && Tex->lock() ) { int w = (int)Tex->getWidth(); @@ -1464,7 +1469,7 @@ void EETest::loadTextures() { CurMan->set( Cursor::SysHand ); CurMan->setGlobalCursor( Cursor::Arrow, - CurMan->add( CurMan->create( CursorP[0], Vector2i( 1, 1 ), "cursor_special" ) ) ); + CurMan->add( CurMan->create( CursorP[0].get(), Vector2i( 1, 1 ), "cursor_special" ) ) ); CurMan->set( Cursor::Arrow ); CL1.addFrame( TN[2] ); @@ -1522,7 +1527,13 @@ void EETest::screen1() { void EETest::screen2() { if ( mResLoad.isLoaded() ) { - Texture* TexLoaded = TF->getByName( "1.jpg" ); + TexturePtr TexLoaded; + for ( const TexturePtr& texture : mLoadedTextures ) { + if ( texture && texture->getName() == "1.jpg" ) { + TexLoaded = texture; + break; + } + } if ( NULL != TexLoaded ) TexLoaded->draw( 0, 0 ); diff --git a/src/tests/test_all/test.hpp b/src/tests/test_all/test.hpp index 162626033..86f159690 100644 --- a/src/tests/test_all/test.hpp +++ b/src/tests/test_all/test.hpp @@ -50,7 +50,7 @@ class EETest : private Thread { Uint32 lasttick; std::vector TN; - std::vector TNP; + std::vector TNP; std::vector Tiles; std::vector PS; @@ -97,7 +97,7 @@ class EETest : private Thread { Interpolation2d WP; Int32 PartsNum; ResourceId Cursor[1]; - Texture* CursorP[1]; + TexturePtr CursorP[1]; std::string mInfo; bool MultiViewportMode; @@ -123,6 +123,7 @@ class EETest : private Thread { String mBuddha; ResourceLoader mResLoad; + std::vector mLoadedTextures; void onTextureLoaded( ResourceLoader* ObjLoaded ); void createUI(); diff --git a/src/tests/unit_tests/fontrendering_tests.cpp b/src/tests/unit_tests/fontrendering_tests.cpp index 1e70616d5..eea02bcaf 100644 --- a/src/tests/unit_tests/fontrendering_tests.cpp +++ b/src/tests/unit_tests/fontrendering_tests.cpp @@ -1110,7 +1110,7 @@ UTEST( FontRendering, TextLayoutWrap ) { FontTrueType* font = static_cast( app.getUI()->getUIThemeManager()->getDefaultFont() ); auto fontSize = 16; - Texture* fontTexture = font->getTexture( fontSize ); + const TexturePtr& fontTexture = font->getTexture( fontSize ); BR->setBlendMode( BlendMode::Alpha() ); BR->quadsBegin(); BR->setTexture( fontTexture, fontTexture->getCoordinateType() ); diff --git a/src/tests/unit_tests/resource_prerequisite_tests.cpp b/src/tests/unit_tests/resource_prerequisite_tests.cpp index 69fe3f3cc..d99b31590 100644 --- a/src/tests/unit_tests/resource_prerequisite_tests.cpp +++ b/src/tests/unit_tests/resource_prerequisite_tests.cpp @@ -178,8 +178,8 @@ UTEST( ResourcePrerequisites, textureAtlasLoaderAppliesFilterToEveryTexture ) { ContextSettings( false, 0, 0, GLv_default, true, false ) ); { - Texture* first = TextureFactory::instance()->createEmptyTexture( 1, 1 ); - Texture* second = TextureFactory::instance()->createEmptyTexture( 1, 1 ); + TexturePtr first = TextureFactory::instance()->createEmptyTexture( 1, 1 ); + TexturePtr second = TextureFactory::instance()->createEmptyTexture( 1, 1 ); ASSERT_TRUE( first != NULL ); ASSERT_TRUE( second != NULL ); @@ -207,12 +207,14 @@ UTEST( ResourcePrerequisites, textureAtlasLoaderAcceptsFilterBeforeAtlasExists ) UTEST( ResourcePrerequisites, textureRegistryTracksStableIdentityAndMemoryWithoutOwning ) { createLifecycleTestWindow( "Texture registry identity test" ); TextureFactory* factory = TextureFactory::instance(); - Texture* first = factory->createEmptyTexture( 2, 3, 4, Color::Transparent, false, - Texture::ClampMode::ClampToEdge, false, false, - "registry-first" ); - Texture* second = factory->createEmptyTexture( 1, 1, 4, Color::Transparent, false, - Texture::ClampMode::ClampToEdge, false, false, - "registry-second" ); + Uint8 firstPixels[2 * 3 * 4]{}; + TextureLoader firstLoader( firstPixels, 2, 3, 4, false, Texture::ClampMode::ClampToEdge, false, + false, "registry-first" ); + firstLoader.load(); + TexturePtr first = firstLoader.getTexture(); + TexturePtr second = factory->createEmptyTexture( 1, 1, 4, Color::Transparent, false, + Texture::ClampMode::ClampToEdge, false, false, + "registry-second" ); ASSERT_TRUE( first != nullptr ); ASSERT_TRUE( second != nullptr ); @@ -242,7 +244,8 @@ UTEST( ResourcePrerequisites, textureRegistryTracksStableIdentityAndMemoryWithou TextureWeakPtr firstWeak = firstRecord->texture; TexturePtr retainedFirst = firstWeak.lock(); ASSERT_TRUE( retainedFirst != nullptr ); - ASSERT_TRUE( factory->remove( first ) ); + firstLoader.reset(); + first.reset(); EXPECT_FALSE( firstWeak.expired() ); EXPECT_EQ( factory->getTextureMemorySize(), 4u * 3u * 4u + 4u ); retainedFirst.reset(); @@ -253,19 +256,24 @@ UTEST( ResourcePrerequisites, textureRegistryTracksStableIdentityAndMemoryWithou [firstId]( const auto& record ) { return record.id == firstId; } ) ); EXPECT_EQ( factory->getTextureMemorySize(), 4u ); + second.reset(); Engine::destroySingleton(); createLifecycleTestWindow( "Texture registry identity restart test" ); - Texture* afterRestart = TextureFactory::instance()->createEmptyTexture( 1, 1 ); + TexturePtr afterRestart = TextureFactory::instance()->createEmptyTexture( 1, 1 ); ASSERT_TRUE( afterRestart != nullptr ); EXPECT_TRUE( secondId < afterRestart->getTextureId() ); + afterRestart.reset(); Engine::destroySingleton(); } -UTEST( ResourcePrerequisites, textureFinalReleaseWaitsForDisplayCollection ) { +UTEST( ResourcePrerequisites, pendingBatchRetainsTextureUntilDisplayCollection ) { EE::Window::Window* window = createLifecycleTestWindow( "Texture deferred release test" ); TextureFactory* factory = TextureFactory::instance(); - Texture* texture = factory->createEmptyTexture( 2, 2 ); + Uint8 pixels[2 * 2 * 4]{}; + TextureLoader loader( pixels, 2, 2, 4 ); + loader.load(); + TexturePtr texture = loader.getTexture(); ASSERT_TRUE( texture != nullptr ); bool unloaded = false; @@ -276,7 +284,7 @@ UTEST( ResourcePrerequisites, textureFinalReleaseWaitsForDisplayCollection ) { } ); TextureRegistrySnapshot snapshot = factory->snapshotTextures(); - auto record = std::find_if( snapshot.begin(), snapshot.end(), [texture]( const auto& entry ) { + auto record = std::find_if( snapshot.begin(), snapshot.end(), [&texture]( const auto& entry ) { return entry.id == texture->getTextureId(); } ); ASSERT_TRUE( record != snapshot.end() ); @@ -284,18 +292,46 @@ UTEST( ResourcePrerequisites, textureFinalReleaseWaitsForDisplayCollection ) { TexturePtr retainedTexture = weakTexture.lock(); ASSERT_TRUE( retainedTexture != nullptr ); - ASSERT_TRUE( factory->remove( texture ) ); + loader.reset(); GlobalBatchRenderer::instance()->setTexture( texture ); GlobalBatchRenderer::instance()->batchQuad( 0, 0, 2, 2 ); + texture.reset(); retainedTexture.reset(); - EXPECT_TRUE( weakTexture.expired() ); + EXPECT_FALSE( weakTexture.expired() ); EXPECT_FALSE( unloaded ); + EXPECT_EQ( factory->getPendingReleaseCount(), static_cast( 0 ) ); + + window->display( false ); + + EXPECT_TRUE( weakTexture.expired() ); + EXPECT_TRUE( unloaded ); + EXPECT_EQ( factory->getPendingReleaseCount(), static_cast( 0 ) ); + Engine::destroySingleton(); +} + +UTEST( ResourcePrerequisites, textureRegionRetainsItsTexture ) { + EE::Window::Window* window = createLifecycleTestWindow( "Texture region ownership test" ); + TextureFactory* factory = TextureFactory::instance(); + Uint8 pixels[2 * 2 * 4]{}; + TextureLoader loader( pixels, 2, 2, 4 ); + loader.load(); + TexturePtr texture = loader.getTexture(); + ASSERT_TRUE( texture != nullptr ); + TextureWeakPtr weakTexture = texture; + + { + TextureRegion region( texture ); + loader.reset(); + texture.reset(); + EXPECT_FALSE( weakTexture.expired() ); + } + + EXPECT_TRUE( weakTexture.expired() ); EXPECT_EQ( factory->getPendingReleaseCount(), static_cast( 1 ) ); window->display( false ); - EXPECT_TRUE( unloaded ); EXPECT_EQ( factory->getPendingReleaseCount(), static_cast( 0 ) ); Engine::destroySingleton(); } @@ -446,7 +482,7 @@ UTEST( ResourcePrerequisites, engineTeardownReleasesGraphicsBeforeContextsAcross for ( int cycle = 0; cycle < 2; ++cycle ) { createLifecycleTestWindow( "Engine teardown test" ); - Texture* texture = TextureFactory::instance()->createEmptyTexture( 4, 4 ); + TexturePtr texture = TextureFactory::instance()->createEmptyTexture( 4, 4 ); ASSERT_TRUE( texture != nullptr ); NinePatch* ninePatch = NinePatchManager::instance()->add( @@ -468,6 +504,7 @@ UTEST( ResourcePrerequisites, engineTeardownReleasesGraphicsBeforeContextsAcross auto* batch = GlobalBatchRenderer::instance(); batch->setTexture( texture ); batch->batchQuad( 0, 0, 4, 4 ); + texture.reset(); Engine::destroySingleton(); diff --git a/src/tests/unit_tests/uihtml_tests.cpp b/src/tests/unit_tests/uihtml_tests.cpp index 5a098206a..cad48def8 100644 --- a/src/tests/unit_tests/uihtml_tests.cpp +++ b/src/tests/unit_tests/uihtml_tests.cpp @@ -3822,7 +3822,7 @@ UTEST( UIBackground, RemoteImageReusesCachedTexture ) { ContextSettings( false, 0, 0, GLv_default, true, false ) ); UISceneNode* sceneNode = init_test_inline_block(); const std::string imageURL = "http://127.0.0.1:1/eepp-cached-background.png"; - Texture* cached = TextureFactory::instance()->createEmptyTexture( + TexturePtr cached = TextureFactory::instance()->createEmptyTexture( 8, 8, 4, Color::White, false, Texture::ClampMode::ClampToEdge, false, false, imageURL ); ASSERT_TRUE( cached != nullptr ); @@ -3842,9 +3842,10 @@ UTEST( UIBackground, RemoteImageReusesCachedTexture ) { ASSERT_TRUE( second->getBackground() != nullptr ); ASSERT_TRUE( first->getBackground()->getLayer( 0 ) != nullptr ); ASSERT_TRUE( second->getBackground()->getLayer( 0 ) != nullptr ); - EXPECT_EQ( cached, first->getBackground()->getLayer( 0 )->getDrawable() ); - EXPECT_EQ( cached, second->getBackground()->getLayer( 0 )->getDrawable() ); + EXPECT_EQ( cached.get(), first->getBackground()->getLayer( 0 )->getDrawable() ); + EXPECT_EQ( cached.get(), second->getBackground()->getLayer( 0 )->getDrawable() ); + cached.reset(); Engine::destroySingleton(); } @@ -5012,7 +5013,7 @@ UTEST( UIHTML, TextureReplaceInvalidatesRichTextAncestors ) { auto* img = images[0]->asType(); ASSERT_TRUE( img != nullptr ); - Texture* texture = + TexturePtr texture = TextureFactory::instance()->createEmptyTexture( 1, 1, 4, Color::Transparent ); ASSERT_TRUE( texture != nullptr ); img->setDrawable( texture ); @@ -5031,6 +5032,7 @@ UTEST( UIHTML, TextureReplaceInvalidatesRichTextAncestors ) { EXPECT_GT( body->getPixelsSize().getHeight(), bodyInitialHeight + 150.f ); EXPECT_GT( doc->getPixelsSize().getHeight(), docInitialHeight + 150.f ); + texture.reset(); Engine::destroySingleton(); } @@ -5155,7 +5157,7 @@ UTEST( UIHTML, RemoteImageReusesCachedTexture ) { const std::string imageURL = "http://127.0.0.1:1/eepp-cached-image.png"; UISceneNode* sceneNode = init_test_inline_block(); - Texture* cached = TextureFactory::instance()->createEmptyTexture( + TexturePtr cached = TextureFactory::instance()->createEmptyTexture( 8, 8, 4, Color::White, false, Texture::ClampMode::ClampToEdge, false, false, imageURL ); ASSERT_TRUE( cached != nullptr ); @@ -5182,9 +5184,10 @@ UTEST( UIHTML, RemoteImageReusesCachedTexture ) { auto* second = secondNode->asType(); ASSERT_TRUE( first != nullptr ); ASSERT_TRUE( second != nullptr ); - EXPECT_EQ( cached, first->getDrawable() ); - EXPECT_EQ( cached, second->getDrawable() ); + EXPECT_EQ( cached.get(), first->getDrawable() ); + EXPECT_EQ( cached.get(), second->getDrawable() ); + cached.reset(); Engine::destroySingleton(); } diff --git a/src/tools/ecode/settingsactions.cpp b/src/tools/ecode/settingsactions.cpp index 0a677a4db..5cb80197d 100644 --- a/src/tools/ecode/settingsactions.cpp +++ b/src/tools/ecode/settingsactions.cpp @@ -117,13 +117,13 @@ void SettingsActions::aboutEcode() { UIImage* image = UIImage::New(); image->setParent( msgBox->getContainer()->getFirstChild() ); auto tf = TextureFactory::instance(); - Texture* tex = tf->getByName( "ecode-logo" ); + TexturePtr tex = tf->getByName( "ecode-logo" ); if ( tex == nullptr ) { tex = tf->loadFromFile( mApp->resPath() + "icon/ecode.png" ); if ( tex ) tex->setName( "ecode-logo" ); } - image->setDrawable( tex ); + image->setDrawable( std::move( tex ) ); image->setLayoutGravity( UI_NODE_ALIGN_CENTER ); image->setGravity( UI_NODE_ALIGN_CENTER ); image->setScaleType( UIScaleType::FitInside ); diff --git a/src/tools/uieditor/uieditor.cpp b/src/tools/uieditor/uieditor.cpp index e2b039c02..9194c7f0e 100644 --- a/src/tools/uieditor/uieditor.cpp +++ b/src/tools/uieditor/uieditor.cpp @@ -136,7 +136,6 @@ void App::saveConfig() { void App::unloadImages() { for ( auto it = mImagesLoaded.begin(); it != mImagesLoaded.end(); ++it ) { GlobalTextureAtlas::instance()->remove( it->second ); - TextureFactory::instance()->remove( it->first ); } mImagesLoaded.clear(); } @@ -149,10 +148,11 @@ void App::unloadFonts() { void App::loadImage( std::string path ) { std::string filename( FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( path ) ) ); - Texture* tex = TextureFactory::instance()->loadFromFile( path ); + TexturePtr tex = TextureFactory::instance()->loadFromFile( path ); if ( tex ) { ResourceId texId = tex->getTextureId(); - TextureRegion* texRegion = GlobalTextureAtlas::instance()->add( texId, filename ); + TextureRegion* texRegion = + GlobalTextureAtlas::instance()->add( std::move( tex ), filename ); mImagesLoaded[texId] = texRegion; } }