/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
+// CLASS HEADER
#include <dali/internal/render/renderers/render-geometry.h>
+// INTERNAL INCLUDES
#include <dali/internal/common/buffer-index.h>
-#include <dali/internal/update/common/scene-graph-property-buffer.h>
-#include <dali/internal/update/rendering/scene-graph-geometry.h>
-#include <dali/internal/render/data-providers/render-data-provider.h>
-#include <dali/internal/render/gl-resources/context.h>
-#include <dali/internal/render/gl-resources/gpu-buffer.h>
+#include <dali/internal/render/renderers/render-vertex-buffer.h>
#include <dali/internal/render/shaders/program.h>
namespace Dali
{
namespace Internal
{
-namespace SceneGraph
+namespace Render
{
-
-RenderGeometry::RenderGeometry( const GeometryDataProvider& geometryDataProvider )
-: mGeometryDataProvider( geometryDataProvider ),
+namespace
+{
+inline constexpr size_t GetSizeOfIndexFromIndexType(Dali::Graphics::Format graphicsFormat)
+{
+ switch(graphicsFormat)
+ {
+ case Dali::Graphics::Format::R16_UINT:
+ {
+ return sizeof(uint16_t);
+ }
+ case Dali::Graphics::Format::R32_UINT:
+ {
+ return sizeof(uint32_t);
+ }
+ default:
+ {
+ // TODO : Not implmeneted.
+ return sizeof(uint16_t);
+ }
+ }
+}
+} // unnamed namespace
+Geometry::Geometry()
+: mIndices(),
+ mIndexBuffer(nullptr),
+ mIndexType(Dali::Graphics::Format::R16_UINT),
+ mGeometryType(Dali::Geometry::TRIANGLES),
+ mIndicesChanged(false),
mHasBeenUpdated(false),
mAttributesChanged(true)
{
}
-RenderGeometry::~RenderGeometry()
+Geometry::~Geometry() = default;
+
+void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer)
{
+ mVertexBuffers.PushBack(vertexBuffer);
+ mAttributesChanged = true;
}
-void RenderGeometry::GlContextCreated( Context& context )
+const Vector<Render::VertexBuffer*>& Geometry::GetVertexBuffers() const
{
+ return mVertexBuffers;
}
-void RenderGeometry::GlContextDestroyed()
+void Geometry::SetIndexBuffer(Uint16ContainerType& indices)
{
+ mIndices.Swap(indices);
+ mIndicesChanged = true;
+ mIndexType = Graphics::Format::R16_UINT;
}
-void RenderGeometry::AddPropertyBuffer( const PropertyBufferDataProvider* dataProvider, GpuBuffer::Target gpuBufferTarget, GpuBuffer::Usage gpuBufferUsage )
+void Geometry::SetIndexBuffer(Uint32ContainerType& indices)
{
- if( gpuBufferTarget == GpuBuffer::ELEMENT_ARRAY_BUFFER )
- {
- RenderPropertyBuffer* renderPropertyBuffer = new RenderPropertyBuffer( *dataProvider, gpuBufferTarget, gpuBufferUsage );
- mIndexBuffer = renderPropertyBuffer;
- }
- else if( gpuBufferTarget == GpuBuffer::ARRAY_BUFFER )
- {
- RenderPropertyBuffer* renderPropertyBuffer = new RenderPropertyBuffer( *dataProvider, gpuBufferTarget, gpuBufferUsage );
- mVertexBuffers.PushBack( renderPropertyBuffer );
- mAttributesChanged = true;
- }
+ // mIndices type is not matched with indices. Copy memory hardly.
+ mIndices.ResizeUninitialized(indices.Count() * 2);
+ memcpy(mIndices.Begin(), indices.Begin(), indices.Count() * sizeof(uint32_t));
+ mIndicesChanged = true;
+ mIndexType = Graphics::Format::R32_UINT;
}
-void RenderGeometry::RemovePropertyBuffer( const PropertyBufferDataProvider* dataProvider )
+void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
{
- if( dataProvider == &mIndexBuffer->GetDataProvider() )
+ const auto&& end = mVertexBuffers.End();
+ for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
{
- mIndexBuffer.Reset();
+ if(*iter == vertexBuffer)
+ {
+ //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
+ mVertexBuffers.Remove(iter);
+ mAttributesChanged = true;
+ break;
+ }
}
- else
+}
+
+void Geometry::OnRenderFinished()
+{
+ mHasBeenUpdated = false;
+ mAttributesChanged = false;
+}
+
+void Geometry::Upload(Graphics::Controller& graphicsController)
+{
+ if(!mHasBeenUpdated)
{
- for( RenderPropertyBufferIter iter( mVertexBuffers.Begin() ); iter != mVertexBuffers.End(); ++iter )
+ // Update buffers
+ if(mIndicesChanged)
{
- if( dataProvider == &(*iter)->GetDataProvider() )
+ if(mIndices.Empty())
{
- //This will delete the gpu buffer associated to the RenderPropertyBuffer if there is one
- mVertexBuffers.Remove( iter );
- mAttributesChanged = true;
- break;
+ mIndexBuffer = nullptr;
+ }
+ else
+ {
+ if(mIndexBuffer == nullptr)
+ {
+ mIndexBuffer = new GpuBuffer(graphicsController, 0 | Graphics::BufferUsage::INDEX_BUFFER);
+ }
+
+ uint32_t bufferSize = static_cast<uint32_t>(sizeof(uint16_t) * mIndices.Size());
+ mIndexBuffer->UpdateDataBuffer(graphicsController, bufferSize, &mIndices[0]);
+ }
+
+ mIndicesChanged = false;
+ }
+
+ for(auto&& buffer : mVertexBuffers)
+ {
+ if(!buffer->Update(graphicsController))
+ {
+ //Vertex buffer is not ready ( Size, data or format has not been specified yet )
+ return;
}
}
+
+ mHasBeenUpdated = true;
}
}
-void RenderGeometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
+bool Geometry::BindVertexAttributes(Graphics::CommandBuffer& commandBuffer)
{
- attributeLocation.Clear();
+ //Bind buffers to attribute locations
+ const auto vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
+
+ std::vector<const Graphics::Buffer*> buffers;
+ std::vector<uint32_t> offsets;
- for( size_t i(0); i< mVertexBuffers.Size(); ++i )
+ for(uint32_t i = 0; i < vertexBufferCount; ++i)
{
- unsigned int attributeCount = mVertexBuffers[i]->GetDataProvider().GetAttributeCount( bufferIndex );
- for( unsigned int j = 0; j < attributeCount; ++j )
+ const GpuBuffer* gpuBuffer = mVertexBuffers[i]->GetGpuBuffer();
+ if(gpuBuffer)
{
- const std::string& attributeName = mVertexBuffers[i]->GetDataProvider().GetAttributeName( bufferIndex, j );
- unsigned int index = program.RegisterCustomAttribute( attributeName );
- GLint location = program.GetCustomAttributeLocation( index );
+ const Graphics::Buffer* buffer = gpuBuffer->GetGraphicsObject();
- if( -1 == location )
+ if(buffer)
{
- DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
+ buffers.push_back(buffer);
+ offsets.push_back(0u);
}
-
- attributeLocation.PushBack( location );
}
+ //@todo Figure out why this is being drawn without geometry having been uploaded
+ }
+ if(buffers.empty())
+ {
+ return false;
}
-}
-void RenderGeometry::OnRenderFinished()
-{
- mHasBeenUpdated = false;
- mAttributesChanged = false;
+ commandBuffer.BindVertexBuffers(0, buffers, offsets);
+
+ return true;
}
-void RenderGeometry::UploadAndDraw(
- Context& context,
- BufferIndex bufferIndex,
- Vector<GLint>& attributeLocation )
+bool Geometry::Draw(
+ Graphics::Controller& graphicsController,
+ Graphics::CommandBuffer& commandBuffer,
+ uint32_t elementBufferOffset,
+ uint32_t elementBufferCount)
{
- if( !mHasBeenUpdated )
+ uint32_t numIndices(0u);
+ intptr_t firstIndexOffset(0u);
+ if(mIndexBuffer)
{
- //Update buffers
- if( mIndexBuffer )
+ std::size_t sizeOfIndex = GetSizeOfIndexFromIndexType(mIndexType);
+
+ numIndices = static_cast<uint32_t>(mIndices.Size() * sizeof(uint16_t) / sizeOfIndex);
+
+ if(elementBufferOffset != 0u)
{
- mIndexBuffer->Update( context, bufferIndex );
+ elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices - 1 : elementBufferOffset;
+ firstIndexOffset = intptr_t(elementBufferOffset * sizeOfIndex);
+ numIndices -= elementBufferOffset;
}
- for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
+
+ if(elementBufferCount != 0u)
{
- mVertexBuffers[i]->Update( context, bufferIndex );
+ numIndices = std::min(elementBufferCount, numIndices);
}
- mHasBeenUpdated = true;
}
- //Bind buffers to attribute locations
- unsigned int base = 0;
- for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
+ //Draw call
+ if(mIndexBuffer && mGeometryType != Dali::Geometry::POINTS)
{
- mVertexBuffers[i]->BindBuffer( context );
- base += mVertexBuffers[i]->EnableVertexAttributes( context, bufferIndex, attributeLocation, base );
- }
+ //Indexed draw call
+ const Graphics::Buffer* ibo = mIndexBuffer->GetGraphicsObject();
+ if(ibo)
+ {
+ commandBuffer.BindIndexBuffer(*ibo, 0, mIndexType);
+ }
- if( mIndexBuffer )
- {
- mIndexBuffer->BindBuffer( context );
+ commandBuffer.DrawIndexed(numIndices, 1, firstIndexOffset, 0, 0);
}
-
- //Bind index buffer
- unsigned int numIndices(0u);
- if( mIndexBuffer )
+ else
{
- const PropertyBufferDataProvider& indexBuffer = mIndexBuffer->GetDataProvider();
- numIndices = mIndexBuffer->GetDataProvider().GetDataSize(bufferIndex) / indexBuffer.GetElementSize(bufferIndex);
+ // Un-indexed draw call
+ uint32_t numVertices(0u);
+
+ if(mVertexBuffers.Count() > 0)
+ {
+ // truncated, no value loss happening in practice
+ numVertices = static_cast<uint32_t>(mVertexBuffers[0]->GetElementCount());
+ }
+
+ commandBuffer.Draw(numVertices, 1, 0, 0);
}
+ return true;
+}
- //Draw call
- GeometryDataProvider::GeometryType type = mGeometryDataProvider.GetGeometryType( bufferIndex );
- switch(type)
+Graphics::PrimitiveTopology Geometry::GetTopology() const
+{
+ Graphics::PrimitiveTopology topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
+
+ switch(mGeometryType)
{
case Dali::Geometry::TRIANGLES:
{
- if( numIndices )
- {
- context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
- }
- else
- {
- const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
- unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
- context.DrawArrays( GL_TRIANGLES, 0, numVertices );
- }
+ topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
break;
}
case Dali::Geometry::LINES:
{
- if( numIndices )
- {
- context.DrawElements(GL_LINES, numIndices, GL_UNSIGNED_SHORT, 0);
- }
- else
- {
- const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
- unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
- context.DrawArrays( GL_LINES, 0, numVertices );
- }
+ topology = Graphics::PrimitiveTopology::LINE_LIST;
break;
}
case Dali::Geometry::POINTS:
{
- const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
- unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
- context.DrawArrays(GL_POINTS, 0, numVertices );
+ topology = Graphics::PrimitiveTopology::POINT_LIST;
break;
}
case Dali::Geometry::TRIANGLE_STRIP:
{
- const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
- unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
- context.DrawArrays(GL_TRIANGLE_STRIP, 0, numVertices );
+ topology = Graphics::PrimitiveTopology::TRIANGLE_STRIP;
break;
}
case Dali::Geometry::TRIANGLE_FAN:
{
- const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
- unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
- context.DrawArrays(GL_TRIANGLE_FAN, 0, numVertices );
+ topology = Graphics::PrimitiveTopology::TRIANGLE_FAN;
break;
}
- default:
+ case Dali::Geometry::LINE_LOOP:
{
- DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" );
+ topology = Graphics::PrimitiveTopology::LINE_LOOP;
break;
}
- }
-
- //Disable atrributes
- for( unsigned int i = 0; i < attributeLocation.Count(); ++i )
- {
- if( attributeLocation[i] != -1 )
+ case Dali::Geometry::LINE_STRIP:
{
- context.DisableVertexAttributeArray( attributeLocation[i] );
+ topology = Graphics::PrimitiveTopology::LINE_STRIP;
+ break;
}
}
+ return topology;
}
-} // namespace SceneGraph
+} // namespace Render
} // namespace Internal
} // namespace Dali