Updated all code to new format
[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 void Geometry::SetIndexBuffer(Dali::Vector<uint16_t>& indices)
60 {
61   mIndices.Swap(indices);
62   mIndicesChanged = true;
63 }
64
65 void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
66 {
67   const auto&& end = mVertexBuffers.End();
68   for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
69   {
70     if(*iter == vertexBuffer)
71     {
72       //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
73       mVertexBuffers.Remove(iter);
74       mAttributesChanged = true;
75       break;
76     }
77   }
78 }
79
80 void Geometry::GetAttributeLocationFromProgram(Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex) const
81 {
82   attributeLocation.Clear();
83
84   for(auto&& vertexBuffer : mVertexBuffers)
85   {
86     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
87     for(uint32_t j = 0; j < attributeCount; ++j)
88     {
89       auto     attributeName = vertexBuffer->GetAttributeName(j);
90       uint32_t index         = program.RegisterCustomAttribute(attributeName);
91       GLint    location      = program.GetCustomAttributeLocation(index);
92
93       if(-1 == location)
94       {
95         DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
96       }
97
98       attributeLocation.PushBack(location);
99     }
100   }
101 }
102
103 void Geometry::OnRenderFinished()
104 {
105   mHasBeenUpdated    = false;
106   mAttributesChanged = false;
107 }
108
109 void Geometry::Upload(Context& context)
110 {
111   if(!mHasBeenUpdated)
112   {
113     // Update buffers
114     if(mIndicesChanged)
115     {
116       if(mIndices.Empty())
117       {
118         mIndexBuffer = nullptr;
119       }
120       else
121       {
122         if(mIndexBuffer == nullptr)
123         {
124           mIndexBuffer = new GpuBuffer(context);
125         }
126
127         uint32_t bufferSize = static_cast<uint32_t>(sizeof(uint16_t) * mIndices.Size());
128         mIndexBuffer->UpdateDataBuffer(context, bufferSize, &mIndices[0], GpuBuffer::STATIC_DRAW, GpuBuffer::ELEMENT_ARRAY_BUFFER);
129       }
130
131       mIndicesChanged = false;
132     }
133
134     for(auto&& buffer : mVertexBuffers)
135     {
136       if(!buffer->Update(context))
137       {
138         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
139         return;
140       }
141     }
142
143     mHasBeenUpdated = true;
144   }
145 }
146
147 void Geometry::Draw(
148   Context&       context,
149   BufferIndex    bufferIndex,
150   Vector<GLint>& attributeLocation,
151   uint32_t       elementBufferOffset,
152   uint32_t       elementBufferCount)
153 {
154   //Bind buffers to attribute locations
155   uint32_t       base              = 0u;
156   const uint32_t vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
157   for(uint32_t i = 0; i < vertexBufferCount; ++i)
158   {
159     mVertexBuffers[i]->BindBuffer(context, GpuBuffer::ARRAY_BUFFER);
160     base += mVertexBuffers[i]->EnableVertexAttributes(context, attributeLocation, base);
161   }
162
163   uint32_t numIndices(0u);
164   intptr_t firstIndexOffset(0u);
165   if(mIndexBuffer)
166   {
167     numIndices = static_cast<uint32_t>(mIndices.Size());
168
169     if(elementBufferOffset != 0u)
170     {
171       elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices - 1 : elementBufferOffset;
172       firstIndexOffset    = elementBufferOffset * sizeof(GLushort);
173       numIndices -= elementBufferOffset;
174     }
175
176     if(elementBufferCount != 0u)
177     {
178       numIndices = std::min(elementBufferCount, numIndices);
179     }
180   }
181
182   GLenum geometryGLType(GL_NONE);
183   switch(mGeometryType)
184   {
185     case Dali::Geometry::TRIANGLES:
186     {
187       geometryGLType = GL_TRIANGLES;
188       break;
189     }
190     case Dali::Geometry::LINES:
191     {
192       geometryGLType = GL_LINES;
193       break;
194     }
195     case Dali::Geometry::POINTS:
196     {
197       geometryGLType = GL_POINTS;
198       break;
199     }
200     case Dali::Geometry::TRIANGLE_STRIP:
201     {
202       geometryGLType = GL_TRIANGLE_STRIP;
203       break;
204     }
205     case Dali::Geometry::TRIANGLE_FAN:
206     {
207       geometryGLType = GL_TRIANGLE_FAN;
208       break;
209     }
210     case Dali::Geometry::LINE_LOOP:
211     {
212       geometryGLType = GL_LINE_LOOP;
213       break;
214     }
215     case Dali::Geometry::LINE_STRIP:
216     {
217       geometryGLType = GL_LINE_STRIP;
218       break;
219     }
220   }
221
222   //Draw call
223   if(mIndexBuffer && geometryGLType != GL_POINTS)
224   {
225     //Indexed draw call
226     mIndexBuffer->Bind(context, GpuBuffer::ELEMENT_ARRAY_BUFFER);
227     // numIndices truncated, no value loss happening in practice
228     context.DrawElements(geometryGLType, static_cast<GLsizei>(numIndices), GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset));
229   }
230   else
231   {
232     //Unindex draw call
233     GLsizei numVertices(0u);
234     if(vertexBufferCount > 0)
235     {
236       // truncated, no value loss happening in practice
237       numVertices = static_cast<GLsizei>(mVertexBuffers[0]->GetElementCount());
238     }
239
240     context.DrawArrays(geometryGLType, 0, numVertices);
241   }
242
243   //Disable attributes
244   for(auto&& attribute : attributeLocation)
245   {
246     if(attribute != -1)
247     {
248       context.DisableVertexAttributeArray(static_cast<GLuint>(attribute));
249     }
250   }
251 }
252
253 } // namespace Render
254 } // namespace Internal
255 } // namespace Dali