X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Frenderers%2Frender-geometry.cpp;h=03afcd7e2c780227570a1fcdde878ff93bd9655b;hb=b042388ebaef225c58c75e350d101ddda6f5f970;hp=808854c05ccf6e459dea346f29e4590b0260b370;hpb=c9765585735d7e5a957ea6afbea50af266827580;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/renderers/render-geometry.cpp b/dali/internal/render/renderers/render-geometry.cpp index 808854c..03afcd7 100644 --- a/dali/internal/render/renderers/render-geometry.cpp +++ b/dali/internal/render/renderers/render-geometry.cpp @@ -1,5 +1,5 @@ /* - * 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. @@ -14,223 +14,281 @@ * limitations under the License. */ +// CLASS HEADER #include +// INTERNAL INCLUDES #include -#include -#include -#include -#include -#include +#include #include namespace Dali { namespace Internal { -namespace SceneGraph +namespace Render { - -RenderGeometry::RenderGeometry() -: mDataNeedsUploading( true ), - mShaderChanged( true ) +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); + } + } } - -RenderGeometry::~RenderGeometry() +} // unnamed namespace +Geometry::Geometry() +: mIndices(), + mIndexBuffer(nullptr), + mIndexType(Dali::Graphics::Format::R16_UINT), + mGeometryType(Dali::Geometry::TRIANGLES), + mIndicesChanged(false), + mHasBeenUpdated(false), + mAttributesChanged(true) { } -void RenderGeometry::GlContextCreated( Context& context ) +Geometry::~Geometry() = default; + +void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer) { - mDataNeedsUploading = true; + mVertexBuffers.PushBack(vertexBuffer); + mAttributesChanged = true; } -void RenderGeometry::GlContextDestroyed() +const Vector& Geometry::GetVertexBuffers() const { + return mVertexBuffers; } -void RenderGeometry::UploadAndDraw( - Context& context, - Program& program, - BufferIndex bufferIndex, - const RenderDataProvider* dataProviders ) +void Geometry::SetIndexBuffer(Uint16ContainerType& indices) { - UploadVertexData( context, program, bufferIndex, dataProviders ); - - for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i ) - { - mVertexBuffers[i]->BindBuffer( context, program ); - mVertexBuffers[i]->EnableVertexAttributes( context, bufferIndex, program ); - } - - if( mIndexBuffer ) - { - mIndexBuffer->BindBuffer( context, program ); - } + mIndices.Swap(indices); + mIndicesChanged = true; + mIndexType = Graphics::Format::R16_UINT; +} - Draw( context, bufferIndex, dataProviders ); +void Geometry::SetIndexBuffer(Uint32ContainerType& indices) +{ + // 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; +} - for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i ) +void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer) +{ + const auto&& end = mVertexBuffers.End(); + // @todo if this buffer is the only instance buffer, reduce instance count to 1. + for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter) { - mVertexBuffers[i]->DisableVertexAttributes( context, bufferIndex, program ); + if(*iter == vertexBuffer) + { + //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one + mVertexBuffers.Remove(iter); + mAttributesChanged = true; + break; + } } } -void RenderGeometry::GeometryUpdated() +void Geometry::OnRenderFinished() { - mDataNeedsUploading = true; + mHasBeenUpdated = false; + mAttributesChanged = false; } -void RenderGeometry::UploadVertexData( - Context& context, - Program& program, - BufferIndex bufferIndex, - const RenderDataProvider* dataProviders ) +void Geometry::Upload(Graphics::Controller& graphicsController) { - if( mDataNeedsUploading ) + if(!mHasBeenUpdated) { - SetUpPropertyBuffers( context, bufferIndex, dataProviders ); - - for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i ) + // Update buffers + if(mIndicesChanged) { - mVertexBuffers[i]->Upload( context, bufferIndex ); - mVertexBuffers[i]->UpdateAttributeLocations( context, bufferIndex, program ); + if(mIndices.Empty()) + { + mIndexBuffer = nullptr; + } + else + { + if(mIndexBuffer == nullptr) + { + // Currently we are unable to reuse index buffer so the write policy is to preserve current content + mIndexBuffer = new GpuBuffer(graphicsController, 0 | Graphics::BufferUsage::INDEX_BUFFER, GpuBuffer::WritePolicy::RETAIN); + } + + uint32_t bufferSize = static_cast(sizeof(uint16_t) * mIndices.Size()); + mIndexBuffer->UpdateDataBuffer(graphicsController, bufferSize, &mIndices[0]); + } + + mIndicesChanged = false; } - if( mIndexBuffer ) + + for(auto&& buffer : mVertexBuffers) { - mIndexBuffer->Upload( context, bufferIndex ); + if(!buffer->Update(graphicsController)) + { + //Vertex buffer is not ready ( Size, data or format has not been specified yet ) + return; + } } - mDataNeedsUploading = false; + mHasBeenUpdated = true; } } -void RenderGeometry::SetUpPropertyBuffers( - Context& context, - BufferIndex bufferIndex, - const RenderDataProvider* dataProvider ) +bool Geometry::BindVertexAttributes(Graphics::CommandBuffer& commandBuffer) { - // Vertex buffer - RenderDataProvider::VertexBuffers vertexBuffers = dataProvider->GetVertexBuffers(); + //Bind buffers to attribute locations + const auto vertexBufferCount = static_cast(mVertexBuffers.Count()); - DALI_ASSERT_DEBUG( vertexBuffers.Count() > 0 && "Need vertex buffers to upload" ); + std::vector buffers; + std::vector offsets; - mVertexBuffers.Clear(); - for( unsigned int i=0; iGetDivisor() > 0) + { + mInstanceCount = mVertexBuffers[i]->GetElementCount(); + } - RenderPropertyBuffer* propertyBuffer = new RenderPropertyBuffer( - *vertexBuffer, - GpuBuffer::ARRAY_BUFFER, - GpuBuffer::STATIC_DRAW ); // TODO: MESH_REWORK: change this for animated meshes + const GpuBuffer* gpuBuffer = mVertexBuffers[i]->GetGpuBuffer(); + if(gpuBuffer) + { + const Graphics::Buffer* buffer = gpuBuffer->GetGraphicsObject(); - mVertexBuffers.PushBack( propertyBuffer ); + if(buffer) + { + buffers.push_back(buffer); + offsets.push_back(0u); + } + } + //@todo Figure out why this is being drawn without geometry having been uploaded } - - // Index buffer - const PropertyBufferDataProvider* indexBuffer = dataProvider->GetIndexBuffer(); - if( indexBuffer ) + if(buffers.empty()) { - mIndexBuffer = new RenderPropertyBuffer( - *indexBuffer, - GpuBuffer::ELEMENT_ARRAY_BUFFER, - GpuBuffer::STATIC_DRAW ); // TODO: MESH_REWORK: change this for animated meshes + return false; } + + commandBuffer.BindVertexBuffers(0, buffers, offsets); + + return true; } -void RenderGeometry::BindBuffers( Context& context, BufferIndex bufferIndex, Program& program ) +bool Geometry::Draw( + Graphics::Controller& graphicsController, + Graphics::CommandBuffer& commandBuffer, + uint32_t elementBufferOffset, + uint32_t elementBufferCount) { - for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i ) + uint32_t numIndices(0u); + intptr_t firstIndexOffset(0u); + if(mIndexBuffer) { - mVertexBuffers[i]->BindBuffer( context, program ); - } + std::size_t sizeOfIndex = GetSizeOfIndexFromIndexType(mIndexType); - if( mIndexBuffer ) - { - mIndexBuffer->BindBuffer( context, program ); + numIndices = static_cast(mIndices.Size() * sizeof(uint16_t) / sizeOfIndex); + + if(elementBufferOffset != 0u) + { + elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices - 1 : elementBufferOffset; + firstIndexOffset = intptr_t(elementBufferOffset * sizeOfIndex); + numIndices -= elementBufferOffset; + } + + if(elementBufferCount != 0u) + { + numIndices = std::min(elementBufferCount, numIndices); + } } -} -void RenderGeometry::EnableVertexAttributes( Context& context, BufferIndex bufferIndex, Program& program ) -{ - OwnerContainer< RenderPropertyBuffer* >::Iterator it = mVertexBuffers.Begin(); - OwnerContainer< RenderPropertyBuffer* >::ConstIterator end = mVertexBuffers.End(); - for( ; it != end; ++it ) + //Draw call + if(mIndexBuffer && mGeometryType != Dali::Geometry::POINTS) { - (*it)->EnableVertexAttributes( context, bufferIndex, program ); - } -} + //Indexed draw call + const Graphics::Buffer* ibo = mIndexBuffer->GetGraphicsObject(); + if(ibo) + { + commandBuffer.BindIndexBuffer(*ibo, 0, mIndexType); + } -void RenderGeometry::DisableVertexAttributes( Context& context, BufferIndex bufferIndex, Program& program ) -{ - OwnerContainer< RenderPropertyBuffer* >::Iterator it = mVertexBuffers.Begin(); - OwnerContainer< RenderPropertyBuffer* >::ConstIterator end = mVertexBuffers.End(); - for( ; it != end; ++it ) + commandBuffer.DrawIndexed(numIndices, mInstanceCount, firstIndexOffset, 0, 0); + } + else { - (*it)->DisableVertexAttributes( context, bufferIndex, program ); + // Un-indexed draw call + uint32_t numVertices(0u); + + if(mVertexBuffers.Count() > 0) + { + // truncated, no value loss happening in practice + numVertices = static_cast(mVertexBuffers[0]->GetElementCount()); + } + + commandBuffer.Draw(numVertices, mInstanceCount, 0, 0); } + return true; } -void RenderGeometry::Draw( Context& context, BufferIndex bufferIndex, const RenderDataProvider* dataProvider ) +Graphics::PrimitiveTopology Geometry::GetTopology() const { - const GeometryDataProvider& geometry = dataProvider->GetGeometry(); - const PropertyBufferDataProvider* indexBuffer = dataProvider->GetIndexBuffer(); + Graphics::PrimitiveTopology topology = Graphics::PrimitiveTopology::TRIANGLE_LIST; - GeometryDataProvider::GeometryType type = geometry.GetGeometryType( bufferIndex ); - - unsigned int numIndices = 0; - if( indexBuffer ) - { - numIndices = indexBuffer->GetDataSize(bufferIndex) / indexBuffer->GetElementSize(bufferIndex); - } - - switch(type) + switch(mGeometryType) { case Dali::Geometry::TRIANGLES: { - if( numIndices ) - { - context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0); - } - else - { - const PropertyBufferDataProvider* firstVertexBuffer = dataProvider->GetVertexBuffers()[0]; - 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 = dataProvider->GetVertexBuffers()[0]; - 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 = dataProvider->GetVertexBuffers()[0]; - unsigned int numVertices = firstVertexBuffer->GetElementCount( bufferIndex ); - context.DrawArrays(GL_POINTS, 0, numVertices ); + topology = Graphics::PrimitiveTopology::POINT_LIST; break; } - default: + case Dali::Geometry::TRIANGLE_STRIP: + { + topology = Graphics::PrimitiveTopology::TRIANGLE_STRIP; + break; + } + case Dali::Geometry::TRIANGLE_FAN: + { + topology = Graphics::PrimitiveTopology::TRIANGLE_FAN; + break; + } + case Dali::Geometry::LINE_LOOP: + { + topology = Graphics::PrimitiveTopology::LINE_LOOP; + break; + } + case Dali::Geometry::LINE_STRIP: { - DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" ); + topology = Graphics::PrimitiveTopology::LINE_STRIP; break; } } + return topology; } -} // namespace SceneGraph +} // namespace Render } // namespace Internal } // namespace Dali