Browse Source

Sprite set use unique pointer directly for memory

Michael Ragazzon 4 months ago
parent
commit
ed487334b3

+ 51 - 71
Source/Core/FontEngineDefault/SpriteSet.cpp

@@ -1,8 +1,7 @@
-#include <algorithm>
-
-#include "../../../Include/RmlUi/Core/Types.h"
-
 #include "SpriteSet.h"
 #include "SpriteSet.h"
+#include "../../../Include/RmlUi/Core/Profiling.h"
+#include "../../../Include/RmlUi/Core/Types.h"
+#include <algorithm>
 
 
 namespace Rml {
 namespace Rml {
 
 
@@ -11,8 +10,8 @@ namespace {
 	constexpr unsigned int max_changed_pixels = 256 * 256;
 	constexpr unsigned int max_changed_pixels = 256 * 256;
 	constexpr unsigned int split_threshold = 8;
 	constexpr unsigned int split_threshold = 8;
 
 
-	template<typename T>
-	void InitializePool(Vector<T> &pool)
+	template <typename T>
+	void InitializePool(Vector<T>& pool)
 	{
 	{
 		const unsigned int pool_size = static_cast<unsigned int>(pool.size());
 		const unsigned int pool_size = static_cast<unsigned int>(pool.size());
 		const unsigned int last_pool_index = pool_size - 1;
 		const unsigned int last_pool_index = pool_size - 1;
@@ -21,7 +20,7 @@ namespace {
 		pool[last_pool_index].next_index = null_index;
 		pool[last_pool_index].next_index = null_index;
 	}
 	}
 
 
-	template<typename T>
+	template <typename T>
 	unsigned int AllocateEntry(Vector<T>& pool, unsigned int& next_free_index)
 	unsigned int AllocateEntry(Vector<T>& pool, unsigned int& next_free_index)
 	{
 	{
 		if (next_free_index == null_index)
 		if (next_free_index == null_index)
@@ -40,17 +39,16 @@ namespace {
 		return index;
 		return index;
 	}
 	}
 
 
-	template<typename T>
+	template <typename T>
 	void FreeEntry(Vector<T>& pool, unsigned int& next_free_index, const unsigned int index)
 	void FreeEntry(Vector<T>& pool, unsigned int& next_free_index, const unsigned int index)
 	{
 	{
 		pool[index].next_index = next_free_index;
 		pool[index].next_index = next_free_index;
 		next_free_index = index;
 		next_free_index = index;
 	}
 	}
-}
+} // namespace
 
 
-SpriteSet::SpriteSet(
-	const unsigned int bytes_per_pixel, const unsigned int page_size, const unsigned int sprite_padding
-) : bytes_per_pixel(bytes_per_pixel), page_size(page_size), sprite_padding(sprite_padding)
+SpriteSet::SpriteSet(const unsigned int bytes_per_pixel, const unsigned int page_size, const unsigned int sprite_padding) :
+	bytes_per_pixel(bytes_per_pixel), page_size(page_size), sprite_padding(sprite_padding)
 {
 {
 	InitializePool(page_pool);
 	InitializePool(page_pool);
 	InitializePool(shelf_pool);
 	InitializePool(shelf_pool);
@@ -72,9 +70,7 @@ void SpriteSet::Tick()
 		while (!slot_pool[source_slot_index].allocated)
 		while (!slot_pool[source_slot_index].allocated)
 			source_slot_index = slot_pool[source_slot_index].next_index;
 			source_slot_index = slot_pool[source_slot_index].next_index;
 		const Slot& source_slot = slot_pool[source_slot_index];
 		const Slot& source_slot = slot_pool[source_slot_index];
-		const unsigned int destination_slot_index = TryAllocateInPage(
-			first_page_index, source_slot.width, source_slot.height
-		);
+		const unsigned int destination_slot_index = TryAllocateInPage(first_page_index, source_slot.width, source_slot.height);
 		if (destination_slot_index == null_index)
 		if (destination_slot_index == null_index)
 			break;
 			break;
 		const Slot& destination_slot = slot_pool[destination_slot_index];
 		const Slot& destination_slot = slot_pool[destination_slot_index];
@@ -88,11 +84,8 @@ void SpriteSet::Tick()
 		const unsigned int height = source_slot.height;
 		const unsigned int height = source_slot.height;
 		for (unsigned int local_y = 0; local_y != height; ++local_y)
 		for (unsigned int local_y = 0; local_y != height; ++local_y)
 		{
 		{
-			const auto data_start = source_page.texture_data->begin() + ((source_y + local_y) * page_size + source_x);
-			std::copy(
-				data_start, data_start + width,
-				destination_page.texture_data->begin() + ((destination_y + local_y) * page_size + destination_x)
-			);
+			const auto data_start = source_page.texture_data.get() + ((source_y + local_y) * page_size + source_x);
+			std::copy(data_start, data_start + width, destination_page.texture_data.get() + ((destination_y + local_y) * page_size + destination_x));
 		}
 		}
 		destination_page.first_dirty_y = std::min(destination_page.first_dirty_y, destination_y);
 		destination_page.first_dirty_y = std::min(destination_page.first_dirty_y, destination_y);
 		destination_page.past_last_dirty_y = std::max(destination_page.past_last_dirty_y, destination_y + height);
 		destination_page.past_last_dirty_y = std::max(destination_page.past_last_dirty_y, destination_y + height);
@@ -104,9 +97,7 @@ void SpriteSet::Tick()
 	}
 	}
 }
 }
 
 
-SpriteSet::Handle SpriteSet::Add(
-	const unsigned int width, const unsigned int height, const unsigned char* const data, const unsigned int row_stride
-)
+SpriteSet::Handle SpriteSet::Add(const unsigned int width, const unsigned int height, const unsigned char* const data, const unsigned int row_stride)
 {
 {
 	const unsigned int padded_width = width + sprite_padding * 2;
 	const unsigned int padded_width = width + sprite_padding * 2;
 	const unsigned int padded_height = height + sprite_padding * 2;
 	const unsigned int padded_height = height + sprite_padding * 2;
@@ -114,27 +105,22 @@ SpriteSet::Handle SpriteSet::Add(
 	const Slot& slot = slot_pool[slot_index];
 	const Slot& slot = slot_pool[slot_index];
 	const Shelf& shelf = shelf_pool[slot.shelf_index];
 	const Shelf& shelf = shelf_pool[slot.shelf_index];
 	Page& page = page_pool[shelf.page_index];
 	Page& page = page_pool[shelf.page_index];
-	for (
-		unsigned int i = 0, top_padding_y = shelf.y, bottom_padding_y = shelf.y + padded_height - 1;
-		i < sprite_padding; ++i, ++top_padding_y, --bottom_padding_y
-	)
+	for (unsigned int i = 0, top_padding_y = shelf.y, bottom_padding_y = shelf.y + padded_height - 1; i < sprite_padding;
+		++i, ++top_padding_y, --bottom_padding_y)
 	{
 	{
-		auto texture_start = page.texture_data->begin() + (top_padding_y * page_size + slot.x) * bytes_per_pixel;
+		auto texture_start = page.texture_data.get() + (top_padding_y * page_size + slot.x) * bytes_per_pixel;
 		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, static_cast<unsigned char>(0));
 		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, static_cast<unsigned char>(0));
-		texture_start = page.texture_data->begin() + (bottom_padding_y * page_size + slot.x) * bytes_per_pixel;
+		texture_start = page.texture_data.get() + (bottom_padding_y * page_size + slot.x) * bytes_per_pixel;
 		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, static_cast<unsigned char>(0));
 		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, static_cast<unsigned char>(0));
 	}
 	}
 	const unsigned int texture_y = shelf.y + sprite_padding;
 	const unsigned int texture_y = shelf.y + sprite_padding;
 	for (unsigned int local_y = 0; local_y != height; ++local_y)
 	for (unsigned int local_y = 0; local_y != height; ++local_y)
 	{
 	{
 		const unsigned char* const data_start = data + local_y * row_stride * bytes_per_pixel;
 		const unsigned char* const data_start = data + local_y * row_stride * bytes_per_pixel;
-		const auto texture_start = page.texture_data->begin()
-			+ ((texture_y + local_y) * page_size + slot.x) * bytes_per_pixel;
+		const auto texture_start = page.texture_data.get() + ((texture_y + local_y) * page_size + slot.x) * bytes_per_pixel;
 		std::fill(texture_start, texture_start + sprite_padding * bytes_per_pixel, static_cast<unsigned char>(0));
 		std::fill(texture_start, texture_start + sprite_padding * bytes_per_pixel, static_cast<unsigned char>(0));
-		std::fill(
-			texture_start + (sprite_padding + width) * bytes_per_pixel, texture_start + padded_width * bytes_per_pixel,
-			static_cast<unsigned char>(0)
-		);
+		std::fill(texture_start + (sprite_padding + width) * bytes_per_pixel, texture_start + padded_width * bytes_per_pixel,
+			static_cast<unsigned char>(0));
 		std::copy(data_start, data_start + width * bytes_per_pixel, texture_start + sprite_padding * bytes_per_pixel);
 		std::copy(data_start, data_start + width * bytes_per_pixel, texture_start + sprite_padding * bytes_per_pixel);
 	}
 	}
 	page.first_dirty_y = std::min(page.first_dirty_y, shelf.y);
 	page.first_dirty_y = std::min(page.first_dirty_y, shelf.y);
@@ -146,6 +132,8 @@ SpriteSet::Handle SpriteSet::Add(
 
 
 unsigned int SpriteSet::Allocate(const unsigned int width, const unsigned int height)
 unsigned int SpriteSet::Allocate(const unsigned int width, const unsigned int height)
 {
 {
+	ZoneScoped;
+
 	// Try to allocate in an existing page.
 	// Try to allocate in an existing page.
 	if (first_page_index != null_index)
 	if (first_page_index != null_index)
 	{
 	{
@@ -189,7 +177,9 @@ unsigned int SpriteSet::Allocate(const unsigned int width, const unsigned int he
 
 
 	Page& page = page_pool[last_page_index];
 	Page& page = page_pool[last_page_index];
 	page.texture_id = page_count;
 	page.texture_id = page_count;
-	page.texture_data = MakeUnique<Vector<unsigned char>>(page_size * page_size * bytes_per_pixel);
+	page.texture_data = UniquePtr<unsigned char[]>(new unsigned char[page_size * page_size * bytes_per_pixel]);
+	Log::Message(Log::LT_INFO, "SpriteSet - Allocating new page %u with size %u x %u", page_count, page_size, page_size);
+	memset(page.texture_data.get(), 0, page_size * page_size * bytes_per_pixel);
 	page.first_dirty_y = page_size;
 	page.first_dirty_y = page_size;
 	page.past_last_dirty_y = 0;
 	page.past_last_dirty_y = 0;
 	page.first_dirty_x = page_size;
 	page.first_dirty_x = page_size;
@@ -210,22 +200,13 @@ unsigned int SpriteSet::TryAllocateInPage(const unsigned int page_index, const u
 	unsigned int selected_shelf_index = null_index;
 	unsigned int selected_shelf_index = null_index;
 	unsigned int selected_slot_index = null_index;
 	unsigned int selected_slot_index = null_index;
 	unsigned int selected_shelf_height = static_cast<unsigned int>(-1);
 	unsigned int selected_shelf_height = static_cast<unsigned int>(-1);
-	for (
-		unsigned int shelf_index = page.first_shelf_index;
-		shelf_index != null_index; shelf_index = shelf_pool[shelf_index].next_index
-	)
+	for (unsigned int shelf_index = page.first_shelf_index; shelf_index != null_index; shelf_index = shelf_pool[shelf_index].next_index)
 	{
 	{
 		const Shelf& shelf = shelf_pool[shelf_index];
 		const Shelf& shelf = shelf_pool[shelf_index];
-		if (
-			shelf.height < height || shelf.height >= selected_shelf_height
-			|| (shelf.allocated && shelf.height > height * 3 / 2)
-		)
+		if (shelf.height < height || shelf.height >= selected_shelf_height || (shelf.allocated && shelf.height > height * 3 / 2))
 			continue;
 			continue;
 		bool found = false;
 		bool found = false;
-		for (
-			unsigned int slot_index = shelf.first_free_slot_index;
-			slot_index != null_index; slot_index = slot_pool[slot_index].next_free_index
-		)
+		for (unsigned int slot_index = shelf.first_free_slot_index; slot_index != null_index; slot_index = slot_pool[slot_index].next_free_index)
 		{
 		{
 			const Slot& slot = slot_pool[slot_index];
 			const Slot& slot = slot_pool[slot_index];
 			if (slot.width < width)
 			if (slot.width < width)
@@ -250,13 +231,10 @@ unsigned int SpriteSet::TryAllocateInPage(const unsigned int page_index, const u
 			const unsigned int new_shelf_index = AllocateEntry<Shelf>(shelf_pool, next_free_shelf_index);
 			const unsigned int new_shelf_index = AllocateEntry<Shelf>(shelf_pool, next_free_shelf_index);
 			const unsigned int new_slot_index = AllocateEntry<Slot>(slot_pool, next_free_slot_index);
 			const unsigned int new_slot_index = AllocateEntry<Slot>(slot_pool, next_free_slot_index);
 			shelf = &shelf_pool[selected_shelf_index];
 			shelf = &shelf_pool[selected_shelf_index];
-			slot_pool[new_slot_index] = {
-				new_shelf_index, page.texture_id, 0, shelf->y + height, page_size, 0, 0, null_index, null_index, null_index, null_index, 0, false
-			};
-			shelf_pool[new_shelf_index] = {
-				page_index, shelf->y + height, shelf->height - height,
-				selected_shelf_index, shelf->next_index,  new_slot_index, new_slot_index, false
-			};
+			slot_pool[new_slot_index] = {new_shelf_index, page.texture_id, 0, shelf->y + height, page_size, 0, 0, null_index, null_index, null_index,
+				null_index, 0, false};
+			shelf_pool[new_shelf_index] = {page_index, shelf->y + height, shelf->height - height, selected_shelf_index, shelf->next_index,
+				new_slot_index, new_slot_index, false};
 			if (shelf->next_index != null_index)
 			if (shelf->next_index != null_index)
 				shelf_pool[shelf->next_index].previous_index = new_shelf_index;
 				shelf_pool[shelf->next_index].previous_index = new_shelf_index;
 			shelf->next_index = new_shelf_index;
 			shelf->next_index = new_shelf_index;
@@ -268,10 +246,8 @@ unsigned int SpriteSet::TryAllocateInPage(const unsigned int page_index, const u
 	{
 	{
 		const unsigned int new_slot_index = AllocateEntry<Slot>(slot_pool, next_free_slot_index);
 		const unsigned int new_slot_index = AllocateEntry<Slot>(slot_pool, next_free_slot_index);
 		slot = &slot_pool[selected_slot_index];
 		slot = &slot_pool[selected_slot_index];
-		slot_pool[new_slot_index] = {
-			selected_shelf_index, page.texture_id, slot->x + width, shelf->y, slot->width - width, 0, 0,
-			selected_slot_index, slot->next_index, slot->previous_free_index, slot->next_free_index, 0, false
-		};
+		slot_pool[new_slot_index] = {selected_shelf_index, page.texture_id, slot->x + width, shelf->y, slot->width - width, 0, 0, selected_slot_index,
+			slot->next_index, slot->previous_free_index, slot->next_free_index, 0, false};
 		if (slot->next_index != null_index)
 		if (slot->next_index != null_index)
 			slot_pool[slot->next_index].previous_index = new_slot_index;
 			slot_pool[slot->next_index].previous_index = new_slot_index;
 		slot->next_index = new_slot_index;
 		slot->next_index = new_slot_index;
@@ -311,14 +287,14 @@ unsigned int SpriteSet::Remove(const unsigned int slot_index)
 	/* DEBUG: Fill the removed area with blue.
 	/* DEBUG: Fill the removed area with blue.
 	for (unsigned int offset_y = 0; offset_y < slot.height; ++offset_y)
 	for (unsigned int offset_y = 0; offset_y < slot.height; ++offset_y)
 	{
 	{
-		for (unsigned int offset_x = 0; offset_x < slot.width; ++offset_x)
-		{
-			const auto pixel = page.texture_data->begin() + ((slot.y + offset_y) * page_size + slot.x + offset_x) * 4;
-			pixel[0] = 0;
-			pixel[1] = 0;
-			pixel[2] = 255;
-			pixel[3] = 255;
-		}
+	    for (unsigned int offset_x = 0; offset_x < slot.width; ++offset_x)
+	    {
+	        const auto pixel = page.texture_data->begin() + ((slot.y + offset_y) * page_size + slot.x + offset_x) * 4;
+	        pixel[0] = 0;
+	        pixel[1] = 0;
+	        pixel[2] = 255;
+	        pixel[3] = 255;
+	    }
 	}
 	}
 	*/
 	*/
 
 
@@ -369,7 +345,8 @@ unsigned int SpriteSet::Remove(const unsigned int slot_index)
 			if (previous_slot.next_free_index != null_index)
 			if (previous_slot.next_free_index != null_index)
 				slot_pool[previous_slot.next_free_index].previous_free_index = previous_slot.previous_free_index;
 				slot_pool[previous_slot.next_free_index].previous_free_index = previous_slot.previous_free_index;
 			FreeEntry<Slot>(slot_pool, next_free_slot_index, previous_index);
 			FreeEntry<Slot>(slot_pool, next_free_slot_index, previous_index);
-			if (slot.previous_index == null_index) {
+			if (slot.previous_index == null_index)
+			{
 				shelf.first_slot_index = slot_index;
 				shelf.first_slot_index = slot_index;
 				if (slot.next_index == null_index)
 				if (slot.next_index == null_index)
 					shelf.allocated = false;
 					shelf.allocated = false;
@@ -447,8 +424,11 @@ SpriteSet::SpriteData SpriteSet::Get(const Handle handle) const
 {
 {
 	const Slot& slot = slot_pool[handle.slot_index];
 	const Slot& slot = slot_pool[handle.slot_index];
 	return {
 	return {
-		slot.texture_id, slot.x + sprite_padding, slot.y + sprite_padding,
-		slot.actual_width - sprite_padding * 2, slot.height - sprite_padding * 2
+		slot.texture_id,
+		slot.x + sprite_padding,
+		slot.y + sprite_padding,
+		slot.actual_width - sprite_padding * 2,
+		slot.height - sprite_padding * 2,
 	};
 	};
 }
 }
 
 
@@ -461,7 +441,7 @@ Vector<const unsigned char*> SpriteSet::GetTextures() const
 	while (true)
 	while (true)
 	{
 	{
 		const Page& page = page_pool[page_index];
 		const Page& page = page_pool[page_index];
-		textures.push_back(page.texture_data->data());
+		textures.push_back(page.texture_data.get());
 		if (page_index == last_page_index)
 		if (page_index == last_page_index)
 			break;
 			break;
 		page_index = page.next_index;
 		page_index = page.next_index;

+ 3 - 6
Source/Core/FontEngineDefault/SpriteSet.h

@@ -1,9 +1,8 @@
 #ifndef GRAPHICS_SPRITESET_H // TODO for PR: Change the header guard when the name and location are finalised.
 #ifndef GRAPHICS_SPRITESET_H // TODO for PR: Change the header guard when the name and location are finalised.
 #define GRAPHICS_SPRITESET_H
 #define GRAPHICS_SPRITESET_H
 
 
-#include <cstdlib>
-
 #include "../../../Include/RmlUi/Core/Types.h"
 #include "../../../Include/RmlUi/Core/Types.h"
+#include <cstdlib>
 
 
 namespace Rml {
 namespace Rml {
 
 
@@ -44,9 +43,7 @@ public:
 	/// @param[in] height The height of the image.
 	/// @param[in] height The height of the image.
 	/// @param[in] data The image data.
 	/// @param[in] data The image data.
 	/// @return The handle to the image.
 	/// @return The handle to the image.
-	Handle Add(const unsigned int width, const unsigned int height, const unsigned char* data) {
-		return Add(width, height, data, width);
-	}
+	Handle Add(const unsigned int width, const unsigned int height, const unsigned char* data) { return Add(width, height, data, width); }
 
 
 	/// Adds a subimage to the texture atlas.
 	/// Adds a subimage to the texture atlas.
 	/// @param[in] width The width of the subimage.
 	/// @param[in] width The width of the subimage.
@@ -78,7 +75,7 @@ private:
 		unsigned int past_last_dirty_y;
 		unsigned int past_last_dirty_y;
 		unsigned int first_dirty_x;
 		unsigned int first_dirty_x;
 		unsigned int past_last_dirty_x;
 		unsigned int past_last_dirty_x;
-		UniquePtr<std::vector<unsigned char>> texture_data;
+		UniquePtr<unsigned char[]> texture_data;
 	};
 	};
 	struct Shelf {
 	struct Shelf {
 		unsigned int page_index;
 		unsigned int page_index;