Browse Source

Decorators: Only allocate geometry strictly needed, reduce number of allocation calls.

Michael Ragazzon 6 years ago
parent
commit
2e0c0cad45

+ 2 - 0
Include/RmlUi/Core/Decorator.h

@@ -81,6 +81,8 @@ protected:
 	/// @param[in] texture The texture to add.
 	/// @return The index of the texture if it is successful, or -1 if it is invalid.
 	int AddTexture(const Texture& texture);
+	/// Get number of textures in use by the decorator.
+	int GetNumTextures() const;
 	/// Returns one of the decorator's previously loaded textures.
 	/// @param[in] index The index of the desired texture.
 	/// @return The texture at the appropriate index, or nullptr if the index was invalid.

+ 7 - 0
Source/Core/Decorator.cpp

@@ -81,6 +81,13 @@ int Decorator::AddTexture(const Texture& texture)
 	return (int)additional_textures.size();
 }
 
+int Decorator::GetNumTextures() const
+{
+	int result = (first_texture ? 1 : 0);
+	result += (int)additional_textures.size();
+	return result;
+}
+
 // Returns one of the decorator's previously loaded textures.
 const Texture* Decorator::GetTexture(int index) const
 {

+ 32 - 30
Source/Core/DecoratorTiledBox.cpp

@@ -36,19 +36,20 @@ namespace Core {
 
 struct DecoratorTiledBoxData
 {
-	DecoratorTiledBoxData(Element* host_element)
+	DecoratorTiledBoxData(Element* host_element, int num_textures) : num_textures(num_textures)
 	{
-		for (int i = 0; i < 9; ++i)
-			geometry[i] = new Geometry(host_element);
+		geometry = new Geometry[num_textures];
+		for (int i = 0; i < num_textures; i++)
+			geometry[i].SetHostElement(host_element);
 	}
 
 	~DecoratorTiledBoxData()
 	{
-		for (int i = 0; i < 9; ++i)
-			delete geometry[i];
+		delete[] geometry;
 	}
 
-	Geometry* geometry[9];
+	const int num_textures;
+	Geometry* geometry;
 };
 
 DecoratorTiledBox::DecoratorTiledBox()
@@ -110,8 +111,8 @@ DecoratorDataHandle DecoratorTiledBox::GenerateElementData(Element* element) con
 	// Initialise the tiles for this element.
 	for (int i = 0; i < 9; i++)
 	{
-		if (tiles[i].texture_index >= 0)
-			tiles[i].CalculateDimensions(element, *GetTexture(tiles[i].texture_index));
+		RMLUI_ASSERT(tiles[i].texture_index >= 0);
+		tiles[i].CalculateDimensions(element, *GetTexture(tiles[i].texture_index));
 	}
 
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
@@ -190,63 +191,64 @@ DecoratorDataHandle DecoratorTiledBox::GenerateElementData(Element* element) con
 			bottom_dimensions.y = bottom_right_dimensions.y;
 	}
 
-	DecoratorTiledBoxData* data = new DecoratorTiledBoxData(element);
+	const int num_textures = GetNumTextures();
+	DecoratorTiledBoxData* data = new DecoratorTiledBoxData(element, num_textures);
 
 	// Generate the geometry for the top-left tile.
-	tiles[TOP_LEFT_CORNER].GenerateGeometry(data->geometry[tiles[TOP_LEFT_CORNER].texture_index]->GetVertices(),
-											data->geometry[tiles[TOP_LEFT_CORNER].texture_index]->GetIndices(),
+	tiles[TOP_LEFT_CORNER].GenerateGeometry(data->geometry[tiles[TOP_LEFT_CORNER].texture_index].GetVertices(),
+											data->geometry[tiles[TOP_LEFT_CORNER].texture_index].GetIndices(),
 											element,
 											Vector2f(0, 0),
 											top_left_dimensions,
 											top_left_dimensions);
 	// Generate the geometry for the top edge tiles.
-	tiles[TOP_EDGE].GenerateGeometry(data->geometry[tiles[TOP_EDGE].texture_index]->GetVertices(),
-									 data->geometry[tiles[TOP_EDGE].texture_index]->GetIndices(),
+	tiles[TOP_EDGE].GenerateGeometry(data->geometry[tiles[TOP_EDGE].texture_index].GetVertices(),
+									 data->geometry[tiles[TOP_EDGE].texture_index].GetIndices(),
 									 element,
 									 Vector2f(top_left_dimensions.x, 0),
 									 Vector2f(padded_size.x - (top_left_dimensions.x + top_right_dimensions.x), top_dimensions.y),
 									 top_dimensions);
 	// Generate the geometry for the top-right tile.
-	tiles[TOP_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[TOP_RIGHT_CORNER].texture_index]->GetVertices(),
-											 data->geometry[tiles[TOP_RIGHT_CORNER].texture_index]->GetIndices(),
+	tiles[TOP_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[TOP_RIGHT_CORNER].texture_index].GetVertices(),
+											 data->geometry[tiles[TOP_RIGHT_CORNER].texture_index].GetIndices(),
 											 element,
 											 Vector2f(padded_size.x - top_right_dimensions.x, 0),
 											 top_right_dimensions,
 											 top_right_dimensions);
 
 	// Generate the geometry for the left side.
-	tiles[LEFT_EDGE].GenerateGeometry(data->geometry[tiles[LEFT_EDGE].texture_index]->GetVertices(),
-									  data->geometry[tiles[LEFT_EDGE].texture_index]->GetIndices(),
+	tiles[LEFT_EDGE].GenerateGeometry(data->geometry[tiles[LEFT_EDGE].texture_index].GetVertices(),
+									  data->geometry[tiles[LEFT_EDGE].texture_index].GetIndices(),
 									  element,
 									  Vector2f(0, top_left_dimensions.y),
 									  Vector2f(left_dimensions.x, padded_size.y - (top_left_dimensions.y + bottom_left_dimensions.y)),
 									  left_dimensions);
 
 	// Generate the geometry for the right side.
-	tiles[RIGHT_EDGE].GenerateGeometry(data->geometry[tiles[RIGHT_EDGE].texture_index]->GetVertices(),
-									   data->geometry[tiles[RIGHT_EDGE].texture_index]->GetIndices(),
+	tiles[RIGHT_EDGE].GenerateGeometry(data->geometry[tiles[RIGHT_EDGE].texture_index].GetVertices(),
+									   data->geometry[tiles[RIGHT_EDGE].texture_index].GetIndices(),
 									   element,
 									   Vector2f((padded_size.x - right_dimensions.x), top_right_dimensions.y),
 									   Vector2f(right_dimensions.x, padded_size.y - (top_right_dimensions.y + bottom_right_dimensions.y)),
 									   right_dimensions);
 
 	// Generate the geometry for the bottom-left tile.
-	tiles[BOTTOM_LEFT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index]->GetVertices(),
-											   data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index]->GetIndices(),
+	tiles[BOTTOM_LEFT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index].GetVertices(),
+											   data->geometry[tiles[BOTTOM_LEFT_CORNER].texture_index].GetIndices(),
 											   element,
 											   Vector2f(0, padded_size.y - bottom_left_dimensions.y),
 											   bottom_left_dimensions,
 											   bottom_left_dimensions);
 	// Generate the geometry for the bottom edge tiles.
-	tiles[BOTTOM_EDGE].GenerateGeometry(data->geometry[tiles[BOTTOM_EDGE].texture_index]->GetVertices(),
-										data->geometry[tiles[BOTTOM_EDGE].texture_index]->GetIndices(),
+	tiles[BOTTOM_EDGE].GenerateGeometry(data->geometry[tiles[BOTTOM_EDGE].texture_index].GetVertices(),
+										data->geometry[tiles[BOTTOM_EDGE].texture_index].GetIndices(),
 										element,
 										Vector2f(bottom_left_dimensions.x, padded_size.y - bottom_dimensions.y),
 										Vector2f(padded_size.x - (bottom_left_dimensions.x + bottom_right_dimensions.x), bottom_dimensions.y),
 										bottom_dimensions);
 	// Generate the geometry for the bottom-right tile.
-	tiles[BOTTOM_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index]->GetVertices(),
-												data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index]->GetIndices(),
+	tiles[BOTTOM_RIGHT_CORNER].GenerateGeometry(data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index].GetVertices(),
+												data->geometry[tiles[BOTTOM_RIGHT_CORNER].texture_index].GetIndices(),
 												element,
 												Vector2f(padded_size.x - bottom_right_dimensions.x, padded_size.y - bottom_right_dimensions.y),
 												bottom_right_dimensions,
@@ -259,8 +261,8 @@ DecoratorDataHandle DecoratorTiledBox::GenerateElementData(Element* element) con
 		Vector2f centre_surface_dimensions(padded_size.x - (left_dimensions.x + right_dimensions.x),
 											  padded_size.y - (top_dimensions.y + bottom_dimensions.y));
 
-		tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index]->GetVertices(),
-									   data->geometry[tiles[CENTRE].texture_index]->GetIndices(),
+		tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index].GetVertices(),
+									   data->geometry[tiles[CENTRE].texture_index].GetIndices(),
 									   element,
 									   Vector2f(left_dimensions.x, top_dimensions.y),
 									   centre_surface_dimensions,
@@ -271,7 +273,7 @@ DecoratorDataHandle DecoratorTiledBox::GenerateElementData(Element* element) con
 	const Texture* texture = nullptr;
 	int texture_index = 0;
 	while ((texture = GetTexture(texture_index)) != nullptr)
-		data->geometry[texture_index++]->SetTexture(texture);
+		data->geometry[texture_index++].SetTexture(texture);
 
 	return reinterpret_cast<DecoratorDataHandle>(data);
 }
@@ -288,8 +290,8 @@ void DecoratorTiledBox::RenderElement(Element* element, DecoratorDataHandle elem
 	Vector2f translation = element->GetAbsoluteOffset(Box::PADDING).Round();
 	DecoratorTiledBoxData* data = reinterpret_cast< DecoratorTiledBoxData* >(element_data);
 
-	for (int i = 0; i < 9; i++)
-		data->geometry[i]->Render(translation);
+	for (int i = 0; i < data->num_textures; i++)
+		data->geometry[i].Render(translation);
 }
 
 }

+ 15 - 13
Source/Core/DecoratorTiledHorizontal.cpp

@@ -37,19 +37,20 @@ namespace Core {
 
 struct DecoratorTiledHorizontalData
 {
-	DecoratorTiledHorizontalData(Element* host_element)
+	DecoratorTiledHorizontalData(Element* host_element, int num_textures) : num_textures(num_textures)
 	{
-		for (int i = 0; i < 3; ++i)
-			geometry[i] = new Geometry(host_element);
+		geometry = new Geometry[num_textures];
+		for (int i = 0; i < num_textures; i++)
+			geometry[i].SetHostElement(host_element);
 	}
 
 	~DecoratorTiledHorizontalData()
 	{
-		for (int i = 0; i < 3; ++i)
-			delete geometry[i];
+		delete[] geometry;
 	}
 
-	Geometry* geometry[3];
+	const int num_textures;
+	Geometry* geometry;
 };
 
 DecoratorTiledHorizontal::DecoratorTiledHorizontal()
@@ -97,7 +98,8 @@ DecoratorDataHandle DecoratorTiledHorizontal::GenerateElementData(Element* eleme
 	for (int i = 0; i < 3; i++)
 		tiles[i].CalculateDimensions(element, *(GetTexture(tiles[i].texture_index)));
 
-	DecoratorTiledHorizontalData* data = new DecoratorTiledHorizontalData(element);
+	const int num_textures = GetNumTextures();
+	DecoratorTiledHorizontalData* data = new DecoratorTiledHorizontalData(element, num_textures);
 
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 
@@ -123,17 +125,17 @@ DecoratorDataHandle DecoratorTiledHorizontal::GenerateElementData(Element* eleme
 	}
 
 	// Generate the geometry for the left tile.
-	tiles[LEFT].GenerateGeometry(data->geometry[tiles[LEFT].texture_index]->GetVertices(), data->geometry[tiles[LEFT].texture_index]->GetIndices(), element, Vector2f(0, 0), left_dimensions, left_dimensions);
+	tiles[LEFT].GenerateGeometry(data->geometry[tiles[LEFT].texture_index].GetVertices(), data->geometry[tiles[LEFT].texture_index].GetIndices(), element, Vector2f(0, 0), left_dimensions, left_dimensions);
 	// Generate the geometry for the centre tiles.
-	tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index]->GetVertices(), data->geometry[tiles[CENTRE].texture_index]->GetIndices(), element, Vector2f(left_dimensions.x, 0), Vector2f(padded_size.x - (left_dimensions.x + right_dimensions.x), centre_dimensions.y), centre_dimensions);
+	tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index].GetVertices(), data->geometry[tiles[CENTRE].texture_index].GetIndices(), element, Vector2f(left_dimensions.x, 0), Vector2f(padded_size.x - (left_dimensions.x + right_dimensions.x), centre_dimensions.y), centre_dimensions);
 	// Generate the geometry for the right tile.
-	tiles[RIGHT].GenerateGeometry(data->geometry[tiles[RIGHT].texture_index]->GetVertices(), data->geometry[tiles[RIGHT].texture_index]->GetIndices(), element, Vector2f(padded_size.x - right_dimensions.x, 0), right_dimensions, right_dimensions);
+	tiles[RIGHT].GenerateGeometry(data->geometry[tiles[RIGHT].texture_index].GetVertices(), data->geometry[tiles[RIGHT].texture_index].GetIndices(), element, Vector2f(padded_size.x - right_dimensions.x, 0), right_dimensions, right_dimensions);
 
 	// Set the textures on the geometry.
 	const Texture* texture = nullptr;
 	int texture_index = 0;
 	while ((texture = GetTexture(texture_index)) != nullptr)
-		data->geometry[texture_index++]->SetTexture(texture);
+		data->geometry[texture_index++].SetTexture(texture);
 
 	return reinterpret_cast<DecoratorDataHandle>(data);
 }
@@ -150,8 +152,8 @@ void DecoratorTiledHorizontal::RenderElement(Element* element, DecoratorDataHand
 	Vector2f translation = element->GetAbsoluteOffset(Box::PADDING).Round();
 	DecoratorTiledHorizontalData* data = reinterpret_cast< DecoratorTiledHorizontalData* >(element_data);
 
-	for (int i = 0; i < 3; i++)
-		data->geometry[i]->Render(translation);
+	for (int i = 0; i < data->num_textures; i++)
+		data->geometry[i].Render(translation);
 }
 
 }

+ 15 - 13
Source/Core/DecoratorTiledVertical.cpp

@@ -38,19 +38,20 @@ namespace Core {
 
 struct DecoratorTiledVerticalData
 {
-	DecoratorTiledVerticalData(Element* host_element)
+	DecoratorTiledVerticalData(Element* host_element, int num_textures) : num_textures(num_textures)
 	{
-		for (int i = 0; i < 3; ++i)
-			geometry[i] = new Geometry(host_element);
+		geometry = new Geometry[num_textures];
+		for (int i = 0; i < num_textures; i++)
+			geometry[i].SetHostElement(host_element);
 	}
 
 	~DecoratorTiledVerticalData()
 	{
-		for (int i = 0; i < 3; ++i)
-			delete geometry[i];
+		delete[] geometry;
 	}
 
-	Geometry* geometry[3];
+	const int num_textures;
+	Geometry* geometry;
 };
 
 DecoratorTiledVertical::DecoratorTiledVertical()
@@ -98,7 +99,8 @@ DecoratorDataHandle DecoratorTiledVertical::GenerateElementData(Element* element
 	for (int i = 0; i < 3; i++)
 		tiles[i].CalculateDimensions(element, *GetTexture(tiles[i].texture_index));
 
-	DecoratorTiledVerticalData* data = new DecoratorTiledVerticalData(element);
+	const int num_textures = GetNumTextures();
+	DecoratorTiledVerticalData* data = new DecoratorTiledVerticalData(element, num_textures);
 
 	Vector2f padded_size = element->GetBox().GetSize(Box::PADDING);
 
@@ -124,17 +126,17 @@ DecoratorDataHandle DecoratorTiledVertical::GenerateElementData(Element* element
 	}
 
 	// Generate the geometry for the left tile.
-	tiles[TOP].GenerateGeometry(data->geometry[tiles[TOP].texture_index]->GetVertices(), data->geometry[tiles[TOP].texture_index]->GetIndices(), element, Vector2f(0, 0), top_dimensions, top_dimensions);
+	tiles[TOP].GenerateGeometry(data->geometry[tiles[TOP].texture_index].GetVertices(), data->geometry[tiles[TOP].texture_index].GetIndices(), element, Vector2f(0, 0), top_dimensions, top_dimensions);
 	// Generate the geometry for the centre tiles.
-	tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index]->GetVertices(), data->geometry[tiles[CENTRE].texture_index]->GetIndices(), element, Vector2f(0, top_dimensions.y), Vector2f(centre_dimensions.x, padded_size.y - (top_dimensions.y + bottom_dimensions.y)), centre_dimensions);
+	tiles[CENTRE].GenerateGeometry(data->geometry[tiles[CENTRE].texture_index].GetVertices(), data->geometry[tiles[CENTRE].texture_index].GetIndices(), element, Vector2f(0, top_dimensions.y), Vector2f(centre_dimensions.x, padded_size.y - (top_dimensions.y + bottom_dimensions.y)), centre_dimensions);
 	// Generate the geometry for the right tile.
-	tiles[BOTTOM].GenerateGeometry(data->geometry[tiles[BOTTOM].texture_index]->GetVertices(), data->geometry[tiles[BOTTOM].texture_index]->GetIndices(), element, Vector2f(0, padded_size.y - bottom_dimensions.y), bottom_dimensions, bottom_dimensions);
+	tiles[BOTTOM].GenerateGeometry(data->geometry[tiles[BOTTOM].texture_index].GetVertices(), data->geometry[tiles[BOTTOM].texture_index].GetIndices(), element, Vector2f(0, padded_size.y - bottom_dimensions.y), bottom_dimensions, bottom_dimensions);
 
 	// Set the textures on the geometry.
 	const Texture* texture = nullptr;
 	int texture_index = 0;
 	while ((texture = GetTexture(texture_index)) != nullptr)
-		data->geometry[texture_index++]->SetTexture(texture);
+		data->geometry[texture_index++].SetTexture(texture);
 
 	return reinterpret_cast<DecoratorDataHandle>(data);
 }
@@ -151,8 +153,8 @@ void DecoratorTiledVertical::RenderElement(Element* element, DecoratorDataHandle
 	Vector2f translation = element->GetAbsoluteOffset(Box::PADDING).Round();
 	DecoratorTiledVerticalData* data = reinterpret_cast< DecoratorTiledVerticalData* >(element_data);
 
-	for (int i = 0; i < 3; i++)
-		data->geometry[i]->Render(translation);
+	for (int i = 0; i < data->num_textures; i++)
+		data->geometry[i].Render(translation);
 }
 
 }