Implemented Draw and basic pipeline for vertex format and topology
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-geometry.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include <dali/internal/render/renderers/render-geometry.h>
19
20 // INTERNAL INCLUDES
21 #include <dali/internal/common/buffer-index.h>
22 #include <dali/internal/render/gl-resources/context.h>
23 #include <dali/internal/render/gl-resources/gpu-buffer.h>
24 #include <dali/internal/render/renderers/render-vertex-buffer.h>
25 #include <dali/internal/render/shaders/program.h>
26
27 namespace Dali
28 {
29 namespace Internal
30 {
31 namespace Render
32 {
33 Geometry::Geometry()
34 : mIndices(),
35   mIndexBuffer(nullptr),
36   mGeometryType(Dali::Geometry::TRIANGLES),
37   mIndicesChanged(false),
38   mHasBeenUpdated(false),
39   mAttributesChanged(true)
40 {
41 }
42
43 Geometry::~Geometry() = default;
44
45 void Geometry::GlContextCreated(Context& context)
46 {
47 }
48
49 void Geometry::GlContextDestroyed()
50 {
51 }
52
53 void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer)
54 {
55   mVertexBuffers.PushBack(vertexBuffer);
56   mAttributesChanged = true;
57 }
58
59 const Vector<Render::VertexBuffer*>& Geometry::GetVertexBuffers() const
60 {
61   return mVertexBuffers;
62 }
63
64 void Geometry::SetIndexBuffer(Dali::Vector<uint16_t>& indices)
65 {
66   mIndices.Swap(indices);
67   mIndicesChanged = true;
68 }
69
70 void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
71 {
72   const auto&& end = mVertexBuffers.End();
73   for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
74   {
75     if(*iter == vertexBuffer)
76     {
77       //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
78       mVertexBuffers.Remove(iter);
79       mAttributesChanged = true;
80       break;
81     }
82   }
83 }
84
85 void Geometry::OnRenderFinished()
86 {
87   mHasBeenUpdated    = false;
88   mAttributesChanged = false;
89 }
90
91 void Geometry::Upload(Graphics::Controller& graphicsController)
92 {
93   if(!mHasBeenUpdated)
94   {
95     // Update buffers
96     if(mIndicesChanged)
97     {
98       if(mIndices.Empty())
99       {
100         mIndexBuffer = nullptr;
101       }
102       else
103       {
104         if(mIndexBuffer == nullptr)
105         {
106           mIndexBuffer = new GpuBuffer(graphicsController, 0 | Graphics::BufferUsage::INDEX_BUFFER);
107         }
108
109         uint32_t bufferSize = static_cast<uint32_t>(sizeof(uint16_t) * mIndices.Size());
110         mIndexBuffer->UpdateDataBuffer(graphicsController, bufferSize, &mIndices[0]);
111       }
112
113       mIndicesChanged = false;
114     }
115
116     for(auto&& buffer : mVertexBuffers)
117     {
118       if(!buffer->Update(graphicsController))
119       {
120         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
121         return;
122       }
123     }
124
125     mHasBeenUpdated = true;
126   }
127 }
128
129 void Geometry::Draw(
130   Graphics::Controller&    graphicsController,
131   Graphics::CommandBuffer& commandBuffer,
132   uint32_t                 elementBufferOffset,
133   uint32_t                 elementBufferCount)
134 {
135   //Bind buffers to attribute locations
136   const uint32_t vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
137
138   std::vector<const Graphics::Buffer*> buffers;
139   std::vector<uint32_t>                offsets;
140
141   for(uint32_t i = 0; i < vertexBufferCount; ++i)
142   {
143     Graphics::Buffer* buffer = mVertexBuffers[i]->GetGpuBuffer().GetGraphicsObject();
144
145     if(buffer)
146     {
147       buffers.push_back(buffer);
148       offsets.push_back(0u);
149     }
150   }
151   commandBuffer.BindVertexBuffers(0, buffers, offsets);
152
153   uint32_t numIndices(0u);
154   intptr_t firstIndexOffset(0u);
155   if(mIndexBuffer)
156   {
157     numIndices = static_cast<uint32_t>(mIndices.Size());
158
159     if(elementBufferOffset != 0u)
160     {
161       elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices - 1 : elementBufferOffset;
162       firstIndexOffset    = elementBufferOffset * sizeof(GLushort);
163       numIndices -= elementBufferOffset;
164     }
165
166     if(elementBufferCount != 0u)
167     {
168       numIndices = std::min(elementBufferCount, numIndices);
169     }
170   }
171
172   //Draw call
173   if(mIndexBuffer && mGeometryType != Dali::Geometry::POINTS)
174   {
175     //Indexed draw call
176     Graphics::Buffer* ibo = mIndexBuffer->GetGraphicsObject();
177     if(ibo)
178     {
179       commandBuffer.BindIndexBuffer(*ibo, 0, Graphics::Format::R16_UINT);
180     }
181
182     commandBuffer.DrawIndexed(numIndices, 1, firstIndexOffset, 0, 0);
183   }
184   else
185   {
186     //Unindex draw call
187     GLsizei numVertices(0u);
188     if(vertexBufferCount > 0)
189     {
190       // truncated, no value loss happening in practice
191       numVertices = static_cast<GLsizei>(mVertexBuffers[0]->GetElementCount());
192     }
193
194     commandBuffer.Draw(numVertices, 1, 0, 0);
195   }
196 }
197
198 Graphics::PrimitiveTopology Geometry::GetTopology() const
199 {
200   Graphics::PrimitiveTopology topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
201
202   switch(mGeometryType)
203   {
204     case Dali::Geometry::TRIANGLES:
205     {
206       topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
207       break;
208     }
209     case Dali::Geometry::LINES:
210     {
211       topology = Graphics::PrimitiveTopology::LINE_LIST;
212       break;
213     }
214     case Dali::Geometry::POINTS:
215     {
216       topology = Graphics::PrimitiveTopology::POINT_LIST;
217       break;
218     }
219     case Dali::Geometry::TRIANGLE_STRIP:
220     {
221       topology = Graphics::PrimitiveTopology::TRIANGLE_STRIP;
222       break;
223     }
224     case Dali::Geometry::TRIANGLE_FAN:
225     {
226       topology = Graphics::PrimitiveTopology::TRIANGLE_FAN;
227       break;
228     }
229     case Dali::Geometry::LINE_LOOP:
230     {
231       topology = Graphics::PrimitiveTopology::LINE_LOOP;
232       break;
233     }
234     case Dali::Geometry::LINE_STRIP:
235     {
236       topology = Graphics::PrimitiveTopology::LINE_STRIP;
237       break;
238     }
239   }
240   return topology;
241 }
242
243 } // namespace Render
244 } // namespace Internal
245 } // namespace Dali