2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali/internal/render/renderers/render-geometry.h>
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>
35 mIndexBuffer(nullptr),
36 mGeometryType(Dali::Geometry::TRIANGLES),
37 mIndicesChanged(false),
38 mHasBeenUpdated(false),
39 mAttributesChanged(true)
43 Geometry::~Geometry() = default;
45 void Geometry::GlContextCreated(Context& context)
49 void Geometry::GlContextDestroyed()
53 void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer)
55 mVertexBuffers.PushBack(vertexBuffer);
56 mAttributesChanged = true;
59 void Geometry::SetIndexBuffer(Dali::Vector<uint16_t>& indices)
61 mIndices.Swap(indices);
62 mIndicesChanged = true;
65 void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
67 const auto&& end = mVertexBuffers.End();
68 for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
70 if(*iter == vertexBuffer)
72 //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
73 mVertexBuffers.Remove(iter);
74 mAttributesChanged = true;
80 void Geometry::GetAttributeLocationFromProgram(Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex) const
82 attributeLocation.Clear();
84 for(auto&& vertexBuffer : mVertexBuffers)
86 const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
87 for(uint32_t j = 0; j < attributeCount; ++j)
89 auto attributeName = vertexBuffer->GetAttributeName(j);
90 uint32_t index = program.RegisterCustomAttribute(attributeName);
91 GLint location = program.GetCustomAttributeLocation(index);
95 DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
98 attributeLocation.PushBack(location);
103 void Geometry::OnRenderFinished()
105 mHasBeenUpdated = false;
106 mAttributesChanged = false;
109 void Geometry::Upload(Graphics::Controller& graphicsController)
118 mIndexBuffer = nullptr;
122 if(mIndexBuffer == nullptr)
124 mIndexBuffer = new GpuBuffer(graphicsController, 0 | Graphics::BufferUsage::INDEX_BUFFER);
127 uint32_t bufferSize = static_cast<uint32_t>(sizeof(uint16_t) * mIndices.Size());
128 mIndexBuffer->UpdateDataBuffer(graphicsController, bufferSize, &mIndices[0]);
131 mIndicesChanged = false;
134 for(auto&& buffer : mVertexBuffers)
136 if(!buffer->Update(graphicsController))
138 //Vertex buffer is not ready ( Size, data or format has not been specified yet )
143 mHasBeenUpdated = true;
149 Graphics::Controller& graphicsController,
150 Graphics::CommandBuffer& commandBuffer,
151 BufferIndex bufferIndex,
152 Vector<GLint>& attributeLocation,
153 uint32_t elementBufferOffset,
154 uint32_t elementBufferCount)
156 //Bind buffers to attribute locations
158 const uint32_t vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
160 std::vector<const Graphics::Buffer*> buffers;
161 std::vector<uint32_t> offsets;
163 for(uint32_t i = 0; i < vertexBufferCount; ++i)
165 Graphics::Buffer* buffer = mVertexBuffers[i]->GetGpuBuffer().GetGraphicsObject();
169 buffers.push_back(buffer);
170 offsets.push_back(0u);
173 commandBuffer.BindVertexBuffers(0, buffers, offsets);
175 uint32_t numIndices(0u);
176 intptr_t firstIndexOffset(0u);
179 numIndices = static_cast<uint32_t>(mIndices.Size());
181 if(elementBufferOffset != 0u)
183 elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices - 1 : elementBufferOffset;
184 firstIndexOffset = elementBufferOffset * sizeof(GLushort);
185 numIndices -= elementBufferOffset;
188 if(elementBufferCount != 0u)
190 numIndices = std::min(elementBufferCount, numIndices);
194 GLenum geometryGLType(GL_NONE);
195 switch(mGeometryType)
197 case Dali::Geometry::TRIANGLES:
199 geometryGLType = GL_TRIANGLES;
202 case Dali::Geometry::LINES:
204 geometryGLType = GL_LINES;
207 case Dali::Geometry::POINTS:
209 geometryGLType = GL_POINTS;
212 case Dali::Geometry::TRIANGLE_STRIP:
214 geometryGLType = GL_TRIANGLE_STRIP;
217 case Dali::Geometry::TRIANGLE_FAN:
219 geometryGLType = GL_TRIANGLE_FAN;
222 case Dali::Geometry::LINE_LOOP:
224 geometryGLType = GL_LINE_LOOP;
227 case Dali::Geometry::LINE_STRIP:
229 geometryGLType = GL_LINE_STRIP;
235 if(mIndexBuffer && geometryGLType != GL_POINTS)
238 Graphics::Buffer* ibo = mIndexBuffer->GetGraphicsObject();
241 commandBuffer.BindIndexBuffer(*ibo, 0, Graphics::Format::R16_UINT);
244 // Command buffer contains Texture bindings, vertex bindings and index buffer binding.
245 Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
246 submitInfo.cmdBuffer.push_back(&commandBuffer);
247 graphicsController.SubmitCommandBuffers(submitInfo);
249 //@todo This should all be done from inside Pipeline implementation.
250 //If there is only 1 vertex buffer, it should have been bound by SubmitCommandBuffers,
251 //and the single GL call from this will work on that bound buffer.
252 for(uint32_t i = 0; i < vertexBufferCount; ++i)
254 base += mVertexBuffers[i]->EnableVertexAttributes(context, attributeLocation, base);
257 // numIndices truncated, no value loss happening in practice
258 context.DrawElements(geometryGLType, static_cast<GLsizei>(numIndices), GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset));
263 GLsizei numVertices(0u);
264 if(vertexBufferCount > 0)
266 // truncated, no value loss happening in practice
267 numVertices = static_cast<GLsizei>(mVertexBuffers[0]->GetElementCount());
270 // Command buffer contains Texture bindings & vertex bindings
271 Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
272 submitInfo.cmdBuffer.push_back(&commandBuffer);
273 graphicsController.SubmitCommandBuffers(submitInfo);
275 //@todo This should all be done from inside Pipeline implementation.
276 //If there is only 1 vertex buffer, it should have been bound by SubmitCommandBuffers,
277 //and the single GL call from this will work on that bound buffer.
278 for(uint32_t i = 0; i < vertexBufferCount; ++i)
280 base += mVertexBuffers[i]->EnableVertexAttributes(context, attributeLocation, base);
283 context.DrawArrays(geometryGLType, 0, numVertices);
287 for(auto&& attribute : attributeLocation)
291 context.DisableVertexAttributeArray(static_cast<GLuint>(attribute));
296 } // namespace Render
297 } // namespace Internal