Browse Source

Fix file textures not being reloaded after release

Michael Ragazzon 1 year ago
parent
commit
011b3c17ef

+ 1 - 1
Source/Core/RenderManager.cpp

@@ -240,7 +240,7 @@ void RenderManager::Render(const Geometry& geometry, Vector2f translation, Textu
 	{
 		TextureHandle texture_handle = {};
 		if (texture.file_index != TextureFileIndex::Invalid)
-			texture_handle = texture_database->file_database.GetHandle(texture.file_index);
+			texture_handle = texture_database->file_database.GetHandle(render_interface, texture.file_index);
 		else if (texture.callback_index != StableVectorIndex::Invalid)
 			texture_handle = texture_database->callback_database.GetHandle(this, render_interface, texture.callback_index);
 

+ 1 - 1
Source/Core/RenderManagerAccess.cpp

@@ -34,7 +34,7 @@ namespace Rml {
 
 Vector2i RenderManagerAccess::GetDimensions(RenderManager* render_manager, TextureFileIndex texture)
 {
-	return render_manager->texture_database->file_database.GetDimensions(texture);
+	return render_manager->texture_database->file_database.GetDimensions(render_manager->render_interface, texture);
 }
 
 Vector2i RenderManagerAccess::GetDimensions(RenderManager* render_manager, StableVectorIndex callback_texture)

+ 31 - 12
Source/Core/TextureDatabase.cpp

@@ -122,28 +122,47 @@ TextureFileIndex FileTextureDatabase::LoadTexture(RenderInterface* render_interf
 	if (it != texture_map.end())
 		return it->second;
 
-	Vector2i dimensions;
-	if (TextureHandle handle = render_interface->LoadTexture(dimensions, source))
+	FileTextureEntry entry = LoadTextureEntry(render_interface, source);
+	if (!entry.texture_handle)
+		return TextureFileIndex::Invalid;
+
+	const auto index = TextureFileIndex(texture_list.size());
+	texture_map[source] = index;
+	texture_list.push_back(std::move(entry));
+
+	return index;
+}
+
+FileTextureDatabase::FileTextureEntry FileTextureDatabase::LoadTextureEntry(RenderInterface* render_interface, const String& source)
+{
+	FileTextureEntry result = {};
+	result.texture_handle = render_interface->LoadTexture(result.dimensions, source);
+	return result;
+}
+
+FileTextureDatabase::FileTextureEntry& FileTextureDatabase::EnsureLoaded(RenderInterface* render_interface, TextureFileIndex index)
+{
+	FileTextureEntry& entry = texture_list[size_t(index)];
+	if (!entry.texture_handle)
 	{
-		TextureFileIndex result = TextureFileIndex(texture_list.size());
-		texture_map[source] = result;
-		texture_list.push_back(FileTextureEntry{handle, dimensions});
-		return result;
+		auto it = std::find_if(texture_map.begin(), texture_map.end(), [index](const auto& pair) { return pair.second == index; });
+		RMLUI_ASSERT(it != texture_map.end());
+		const String& source = it->first;
+		entry = LoadTextureEntry(render_interface, source);
 	}
-
-	return TextureFileIndex::Invalid;
+	return entry;
 }
 
-TextureHandle FileTextureDatabase::GetHandle(TextureFileIndex index) const
+TextureHandle FileTextureDatabase::GetHandle(RenderInterface* render_interface, TextureFileIndex index)
 {
 	RMLUI_ASSERT(size_t(index) < texture_list.size());
-	return texture_list[size_t(index)].texture_handle;
+	return EnsureLoaded(render_interface, index).texture_handle;
 }
 
-Vector2i FileTextureDatabase::GetDimensions(TextureFileIndex index) const
+Vector2i FileTextureDatabase::GetDimensions(RenderInterface* render_interface, TextureFileIndex index)
 {
 	RMLUI_ASSERT(size_t(index) < texture_list.size());
-	return texture_list[size_t(index)].dimensions;
+	return EnsureLoaded(render_interface, index).dimensions;
 }
 
 void FileTextureDatabase::GetSourceList(StringList& source_list) const

+ 6 - 2
Source/Core/TextureDatabase.h

@@ -71,8 +71,8 @@ public:
 
 	TextureFileIndex LoadTexture(RenderInterface* render_interface, const String& source);
 
-	TextureHandle GetHandle(TextureFileIndex index) const;
-	Vector2i GetDimensions(TextureFileIndex index) const;
+	TextureHandle GetHandle(RenderInterface* render_interface, TextureFileIndex index);
+	Vector2i GetDimensions(RenderInterface* render_interface, TextureFileIndex index);
 
 	void GetSourceList(StringList& source_list) const;
 
@@ -83,6 +83,10 @@ private:
 		TextureHandle texture_handle = {};
 		Vector2i dimensions;
 	};
+
+	FileTextureEntry LoadTextureEntry(RenderInterface* render_interface, const String& source);
+	FileTextureEntry& EnsureLoaded(RenderInterface* render_interface, TextureFileIndex index);
+
 	Vector<FileTextureEntry> texture_list;
 	UnorderedMap<String, TextureFileIndex> texture_map; // key: source, value: index into 'texture_list'
 };

+ 19 - 3
Tests/Source/UnitTests/Core.cpp

@@ -61,7 +61,7 @@ static const String document_textures_rml = R"(
 			height: 100px;
 			decorator: image(alien3);
 		}
-		progress { 
+		progress {
 			display: block;
 			width: 50px;
 			height: 50px;
@@ -145,13 +145,29 @@ TEST_CASE("core.release_resources")
 
 	SUBCASE("ReleaseTextures")
 	{
+		const auto startup_counters = counters;
+		REQUIRE(counters.load_texture > 0);
+		REQUIRE(counters.generate_texture > 0);
+		REQUIRE(counters.release_texture == 0);
+
 		// Release all textures and verify that the render interface received the release call.
 		Rml::ReleaseTextures();
-		CHECK(counters.generate_texture + counters.load_texture == counters.release_texture);
+		CHECK(counters.load_texture == startup_counters.load_texture);
+		CHECK(counters.generate_texture == startup_counters.generate_texture);
+		CHECK(counters.release_texture == startup_counters.generate_texture + startup_counters.load_texture);
+		const int num_released_textures = counters.release_texture;
 
 		// By doing a new context Update+Render the textures should be loaded again.
 		TestsShell::RenderLoop();
-		CHECK(counters.generate_texture + counters.load_texture > counters.release_texture);
+		CHECK(counters.load_texture == 2 * startup_counters.load_texture);
+		CHECK(counters.generate_texture == 2 * startup_counters.generate_texture);
+		CHECK(counters.release_texture == num_released_textures);
+
+		// Another loop should not affect the texture calls.
+		TestsShell::RenderLoop();
+		CHECK(counters.load_texture == 2 * startup_counters.load_texture);
+		CHECK(counters.generate_texture == 2 * startup_counters.generate_texture);
+		CHECK(counters.release_texture == num_released_textures);
 	}
 
 	SUBCASE("ReleaseFontResources")