فهرست منبع

Fix font textures not released when calling Core::ReleaseTextures. See # 84.

Michael Ragazzon 5 سال پیش
والد
کامیت
a909b18fed

+ 0 - 3
Include/RmlUi/Core/Texture.h

@@ -80,9 +80,6 @@ public:
 	/// @return The texture's dimensions. This will be (0, 0) if the texture isn't loaded.
 	Vector2i GetDimensions(RenderInterface* render_interface) const;
 
-	/// Removes the underlying texture resource from the texture database, thereby releasing the texture once all references to it are removed.
-	void RemoveDatabaseCache() const;
-
 	/// Returns true if the texture points to the same underlying resource.
 	bool operator==(const Texture&) const;
 

+ 6 - 2
Include/RmlUi/Core/Types.h

@@ -139,18 +139,22 @@ using UnorderedMap = std::unordered_map< Key, Value >;
 template <typename Key, typename Value>
 using SmallUnorderedMap = UnorderedMap< Key, Value >;
 template <typename T>
-using SmallOrderedSet = std::set< T >;
+using UnorderedSet = std::unordered_set< T >;
 template <typename T>
 using SmallUnorderedSet = std::unordered_set< T >;
+template <typename T>
+using SmallOrderedSet = std::set< T >;
 #else
 template < typename Key, typename Value>
 using UnorderedMap = robin_hood::unordered_flat_map< Key, Value >;
 template <typename Key, typename Value>
 using SmallUnorderedMap = chobo::flat_map< Key, Value >;
 template <typename T>
-using SmallOrderedSet = chobo::flat_set< T >;
+using UnorderedSet = robin_hood::unordered_flat_set< T >;
 template <typename T>
 using SmallUnorderedSet = chobo::flat_set< T >;
+template <typename T>
+using SmallOrderedSet = chobo::flat_set< T >;
 #endif
 
 

+ 0 - 3
Source/Core/FontEngineDefault/FontFaceLayer.cpp

@@ -48,9 +48,6 @@ bool FontFaceLayer::Generate(const FontFaceHandleDefault* handle, const FontFace
 	{
 		// @performance: We could be much smarter about this, e.g. such as adding new glyphs to the existing texture layout and textures.
 		// Right now we re-generate the whole thing, including textures.
-		for (auto& texture : textures)
-			texture.RemoveDatabaseCache();
-
 		texture_layout = TextureLayout{};
 		character_boxes.clear();
 		textures.clear();

+ 0 - 5
Source/Core/Texture.cpp

@@ -73,11 +73,6 @@ Vector2i Texture::GetDimensions(RenderInterface* render_interface) const
 	return resource->GetDimensions(render_interface);
 }
 
-void Texture::RemoveDatabaseCache() const
-{
-	TextureDatabase::RemoveTexture(resource.get());
-}
-
 bool Texture::operator==(const Texture& other) const
 {
 	return resource == other.resource;

+ 21 - 25
Source/Core/TextureDatabase.cpp

@@ -35,18 +35,18 @@
 namespace Rml {
 namespace Core {
 
-static TextureDatabase* instance = nullptr;
+static TextureDatabase* texture_database = nullptr;
 
 TextureDatabase::TextureDatabase()
 {
-	RMLUI_ASSERT(instance == nullptr);
-	instance = this;
+	RMLUI_ASSERT(texture_database == nullptr);
+	texture_database = this;
 }
 
 TextureDatabase::~TextureDatabase()
 {
-	RMLUI_ASSERT(instance == this);
-	instance = nullptr;
+	RMLUI_ASSERT(texture_database == this);
+	texture_database = nullptr;
 }
 
 void TextureDatabase::Initialise()
@@ -56,7 +56,7 @@ void TextureDatabase::Initialise()
 
 void TextureDatabase::Shutdown()
 {
-	delete instance;
+	delete texture_database;
 }
 
 // If the requested texture is already in the database, it will be returned with an extra reference count. If not, it
@@ -69,8 +69,8 @@ SharedPtr<TextureResource> TextureDatabase::Fetch(const String& source, const St
 	else
 		GetSystemInterface()->JoinPath(path, StringUtilities::Replace(source_directory, '|', ':'), source);
 
-	TextureMap::iterator iterator = instance->textures.find(path);
-	if (iterator != instance->textures.end())
+	TextureMap::iterator iterator = texture_database->textures.find(path);
+	if (iterator != texture_database->textures.end())
 	{
 		return iterator->second;
 	}
@@ -78,35 +78,31 @@ SharedPtr<TextureResource> TextureDatabase::Fetch(const String& source, const St
 	auto resource = std::make_shared<TextureResource>();
 	resource->Set(path);
 
-	instance->textures[resource->GetSource()] = resource;
+	texture_database->textures[resource->GetSource()] = resource;
 	return resource;
 }
 
-// Releases all textures in the database.
-void TextureDatabase::ReleaseTextures()
+void TextureDatabase::AddCallbackTexture(TextureResource* texture)
 {
-	for (TextureMap::iterator i = instance->textures.begin(); i != instance->textures.end(); ++i)
-		i->second->Release();
+	if (texture_database)
+		texture_database->callback_textures.insert(texture);
 }
 
-// Removes a texture from the database.
-void TextureDatabase::RemoveTexture(TextureResource* texture)
+void TextureDatabase::RemoveCallbackTexture(TextureResource* texture)
 {
-	if (instance)
-	{
-		TextureMap::iterator iterator = instance->textures.find(texture->GetSource());
-		if (iterator != instance->textures.end())
-			instance->textures.erase(iterator);
-	}
+	if (texture_database)
+		texture_database->callback_textures.erase(texture);
 }
 
-// Release all textures bound through a render interface.
 void TextureDatabase::ReleaseTextures(RenderInterface* render_interface)
 {
-	if (instance)
+	if (texture_database)
 	{
-		for (TextureMap::iterator i = instance->textures.begin(); i != instance->textures.end(); ++i)
-			i->second->Release(render_interface);
+		for (const auto& texture : texture_database->textures)
+			texture.second->Release(render_interface);
+
+		for (const auto& texture : texture_database->callback_textures)
+			texture->Release(render_interface);
 	}
 }
 

+ 11 - 6
Source/Core/TextureDatabase.h

@@ -47,18 +47,20 @@ public:
 	static void Initialise();
 	static void Shutdown();
 
+    /// Fetch a texture resource from file.
 	/// If the requested texture is already in the database, it will be returned with an extra
 	/// reference count. If not, it will be loaded through the application's render interface.
 	static SharedPtr<TextureResource> Fetch(const String& source, const String& source_directory);
 
-	/// Releases all textures in the database.
-	static void ReleaseTextures();
+	/// Release all textures bound through a render interface.
+    /// Pass nullptr to release all textures in the database.
+	static void ReleaseTextures(RenderInterface* render_interface = nullptr);
 
-	/// Removes a texture from the database.
-	static void RemoveTexture(TextureResource* texture);
+    /// Adds a texture resource with a callback function and stores it as a weak (raw) pointer in the database.
+    static void AddCallbackTexture(TextureResource* texture);
 
-	/// Release all textures bound through a render interface.
-	static void ReleaseTextures(RenderInterface* render_interface);
+    /// Removes a callback texture from the database.
+    static void RemoveCallbackTexture(TextureResource* texture);
 
 private:
 	TextureDatabase();
@@ -66,6 +68,9 @@ private:
 
 	using TextureMap = UnorderedMap< String, SharedPtr<TextureResource> >;
 	TextureMap textures;
+
+    using CallbackTextureMap = UnorderedSet< TextureResource* >;
+    CallbackTextureMap callback_textures;
 };
 
 }

+ 17 - 5
Source/Core/TextureResource.cpp

@@ -41,22 +41,34 @@ TextureResource::TextureResource()
 
 TextureResource::~TextureResource()
 {
-	Release();
+	Reset();
 }
 
-// Attempts to load a texture from the application into the resource.
 void TextureResource::Set(const String& _source)
 {
-	Release();
-	texture_callback.reset();
+	Reset();
 	source = _source;
 }
 
 void TextureResource::Set(const String& name, const TextureCallback& callback)
 {
-	Release();
+	Reset();
 	source = name;
 	texture_callback = std::make_unique<TextureCallback>(callback);
+	TextureDatabase::AddCallbackTexture(this);
+}
+
+void TextureResource::Reset()
+{
+	Release();
+
+	if (texture_callback)
+	{
+		TextureDatabase::RemoveCallbackTexture(this);
+		texture_callback.reset();
+	}
+
+	source.clear();
 }
 
 // Returns the resource's underlying texture.

+ 7 - 6
Source/Core/TextureResource.h

@@ -48,12 +48,12 @@ public:
 	TextureResource();
 	~TextureResource();
 
-	/// Clear any existing data and set the source path. Texture loading is delayed until the texture is
-	/// accessed by a specific render interface.
+	/// Clear any existing data and set the source path.
+	/// Texture loading is delayed until the texture is accessed by a specific render interface.
 	void Set(const String& source);
 
-	/// Clear any existing data and set a callback function for loading the data. Texture loading is
-	/// delayed until the texture is accessed by a specific render interface.
+	/// Clear any existing data and set a callback function for loading the data.
+	/// Texture loading is delayed until the texture is accessed by a specific render interface.
 	void Set(const String& name, const TextureCallback& callback);
 
 	/// Returns the resource's underlying texture handle.
@@ -67,11 +67,12 @@ public:
 	/// Releases the texture's handle.
 	void Release(RenderInterface* render_interface = nullptr);
 
-protected:
+private:
+	void Reset();
+
 	/// Attempts to load the texture from the source, or the callback function if set.
 	bool Load(RenderInterface* render_interface);
 
-private:
 	String source;
 
 	using TextureData = std::pair< TextureHandle, Vector2i >;