Fix SVACE errors in Graphics Backend
[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/renderers/render-vertex-buffer.h>
23 #include <dali/internal/render/shaders/program.h>
24
25 namespace Dali
26 {
27 namespace Internal
28 {
29 namespace Render
30 {
31 Geometry::Geometry()
32 : mIndices(),
33   mIndexBuffer(nullptr),
34   mGeometryType(Dali::Geometry::TRIANGLES),
35   mIndicesChanged(false),
36   mHasBeenUpdated(false),
37   mAttributesChanged(true)
38 {
39 }
40
41 Geometry::~Geometry() = default;
42
43 void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer)
44 {
45   mVertexBuffers.PushBack(vertexBuffer);
46   mAttributesChanged = true;
47 }
48
49 const Vector<Render::VertexBuffer*>& Geometry::GetVertexBuffers() const
50 {
51   return mVertexBuffers;
52 }
53
54 void Geometry::SetIndexBuffer(Dali::Vector<uint16_t>& indices)
55 {
56   mIndices.Swap(indices);
57   mIndicesChanged = true;
58 }
59
60 void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
61 {
62   const auto&& end = mVertexBuffers.End();
63   for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
64   {
65     if(*iter == vertexBuffer)
66     {
67       //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
68       mVertexBuffers.Remove(iter);
69       mAttributesChanged = true;
70       break;
71     }
72   }
73 }
74
75 void Geometry::OnRenderFinished()
76 {
77   mHasBeenUpdated    = false;
78   mAttributesChanged = false;
79 }
80
81 void Geometry::Upload(Graphics::Controller& graphicsController)
82 {
83   if(!mHasBeenUpdated)
84   {
85     // Update buffers
86     if(mIndicesChanged)
87     {
88       if(mIndices.Empty())
89       {
90         mIndexBuffer = nullptr;
91       }
92       else
93       {
94         if(mIndexBuffer == nullptr)
95         {
96           mIndexBuffer = new GpuBuffer(graphicsController, 0 | Graphics::BufferUsage::INDEX_BUFFER);
97         }
98
99         uint32_t bufferSize = static_cast<uint32_t>(sizeof(uint16_t) * mIndices.Size());
100         mIndexBuffer->UpdateDataBuffer(graphicsController, bufferSize, &mIndices[0]);
101       }
102
103       mIndicesChanged = false;
104     }
105
106     for(auto&& buffer : mVertexBuffers)
107     {
108       if(!buffer->Update(graphicsController))
109       {
110         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
111         return;
112       }
113     }
114
115     mHasBeenUpdated = true;
116   }
117 }
118
119 bool Geometry::Draw(
120   Graphics::Controller&    graphicsController,
121   Graphics::CommandBuffer& commandBuffer,
122   uint32_t                 elementBufferOffset,
123   uint32_t                 elementBufferCount)
124 {
125   //Bind buffers to attribute locations
126   const auto vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
127
128   std::vector<const Graphics::Buffer*> buffers;
129   std::vector<uint32_t>                offsets;
130
131   for(uint32_t i = 0; i < vertexBufferCount; ++i)
132   {
133     const GpuBuffer* gpuBuffer = mVertexBuffers[i]->GetGpuBuffer();
134     if(gpuBuffer)
135     {
136       const Graphics::Buffer* buffer = gpuBuffer->GetGraphicsObject();
137
138       if(buffer)
139       {
140         buffers.push_back(buffer);
141         offsets.push_back(0u);
142       }
143     }
144     //@todo Figure out why this is being drawn without geometry having been uploaded
145   }
146   if(buffers.empty())
147   {
148     return false;
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    = intptr_t(elementBufferOffset * sizeof(uint16_t));
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     const 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     // Un-indexed draw call
187     uint32_t numVertices(0u);
188     if(vertexBufferCount > 0)
189     {
190       // truncated, no value loss happening in practice
191       numVertices = static_cast<uint32_t>(mVertexBuffers[0]->GetElementCount());
192     }
193
194     commandBuffer.Draw(numVertices, 1, 0, 0);
195   }
196   return true;
197 }
198
199 Graphics::PrimitiveTopology Geometry::GetTopology() const
200 {
201   Graphics::PrimitiveTopology topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
202
203   switch(mGeometryType)
204   {
205     case Dali::Geometry::TRIANGLES:
206     {
207       topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
208       break;
209     }
210     case Dali::Geometry::LINES:
211     {
212       topology = Graphics::PrimitiveTopology::LINE_LIST;
213       break;
214     }
215     case Dali::Geometry::POINTS:
216     {
217       topology = Graphics::PrimitiveTopology::POINT_LIST;
218       break;
219     }
220     case Dali::Geometry::TRIANGLE_STRIP:
221     {
222       topology = Graphics::PrimitiveTopology::TRIANGLE_STRIP;
223       break;
224     }
225     case Dali::Geometry::TRIANGLE_FAN:
226     {
227       topology = Graphics::PrimitiveTopology::TRIANGLE_FAN;
228       break;
229     }
230     case Dali::Geometry::LINE_LOOP:
231     {
232       topology = Graphics::PrimitiveTopology::LINE_LOOP;
233       break;
234     }
235     case Dali::Geometry::LINE_STRIP:
236     {
237       topology = Graphics::PrimitiveTopology::LINE_STRIP;
238       break;
239     }
240   }
241   return topology;
242 }
243
244 } // namespace Render
245 } // namespace Internal
246 } // namespace Dali