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