2 * Copyright (c) 2020 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>
36 mIndexBuffer(nullptr),
37 mGeometryType( Dali::Geometry::TRIANGLES ),
38 mIndicesChanged(false),
39 mHasBeenUpdated(false),
40 mAttributesChanged(true)
44 Geometry::~Geometry() = default;
46 void Geometry::GlContextCreated( Context& context )
50 void Geometry::GlContextDestroyed()
54 void Geometry::AddVertexBuffer( Render::VertexBuffer* vertexBuffer )
56 mVertexBuffers.PushBack( vertexBuffer );
57 mAttributesChanged = true;
60 void Geometry::SetIndexBuffer( Dali::Vector<uint16_t>& indices )
62 mIndices.Swap( indices );
63 mIndicesChanged = true;
66 void Geometry::RemoveVertexBuffer( const Render::VertexBuffer* vertexBuffer )
68 const auto&& end = mVertexBuffers.End();
69 for( auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter )
71 if( *iter == vertexBuffer )
73 //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
74 mVertexBuffers.Remove( iter );
75 mAttributesChanged = true;
81 void Geometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
83 attributeLocation.Clear();
85 for( auto&& vertexBuffer : mVertexBuffers )
87 const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
88 for( uint32_t j = 0; j < attributeCount; ++j )
90 auto attributeName = vertexBuffer->GetAttributeName( j );
91 uint32_t index = program.RegisterCustomAttribute( attributeName );
92 GLint location = program.GetCustomAttributeLocation( index );
96 DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.GetCString() );
99 attributeLocation.PushBack( location );
104 void Geometry::OnRenderFinished()
106 mHasBeenUpdated = false;
107 mAttributesChanged = false;
110 void Geometry::Upload( Context& context )
112 if( !mHasBeenUpdated )
115 if( mIndicesChanged )
117 if( mIndices.Empty() )
119 mIndexBuffer = nullptr;
123 if ( mIndexBuffer == nullptr )
125 mIndexBuffer = new GpuBuffer( context );
128 uint32_t bufferSize = static_cast<uint32_t>( sizeof( uint16_t ) * mIndices.Size() );
129 mIndexBuffer->UpdateDataBuffer( context, bufferSize, &mIndices[0], GpuBuffer::STATIC_DRAW, GpuBuffer::ELEMENT_ARRAY_BUFFER );
132 mIndicesChanged = false;
135 for( auto&& buffer : mVertexBuffers )
137 if( !buffer->Update( context ) )
139 //Vertex buffer is not ready ( Size, data or format has not been specified yet )
144 mHasBeenUpdated = true;
150 BufferIndex bufferIndex,
151 Vector<GLint>& attributeLocation,
152 uint32_t elementBufferOffset,
153 uint32_t elementBufferCount )
155 //Bind buffers to attribute locations
157 const uint32_t vertexBufferCount = static_cast<uint32_t>( mVertexBuffers.Count() );
158 for( uint32_t i = 0; i < vertexBufferCount; ++i )
160 mVertexBuffers[i]->BindBuffer( context, GpuBuffer::ARRAY_BUFFER );
161 base += mVertexBuffers[i]->EnableVertexAttributes( context, attributeLocation, base );
164 uint32_t numIndices(0u);
165 intptr_t firstIndexOffset(0u);
168 numIndices = static_cast<uint32_t>( mIndices.Size() );
170 if( elementBufferOffset != 0u )
172 elementBufferOffset = (elementBufferOffset >= numIndices ) ? numIndices - 1 : elementBufferOffset;
173 firstIndexOffset = elementBufferOffset * sizeof(GLushort);
174 numIndices -= elementBufferOffset;
177 if( elementBufferCount != 0u )
179 numIndices = std::min( elementBufferCount, numIndices );
183 GLenum geometryGLType(GL_NONE);
184 switch(mGeometryType)
186 case Dali::Geometry::TRIANGLES:
188 geometryGLType = GL_TRIANGLES;
191 case Dali::Geometry::LINES:
193 geometryGLType = GL_LINES;
196 case Dali::Geometry::POINTS:
198 geometryGLType = GL_POINTS;
201 case Dali::Geometry::TRIANGLE_STRIP:
203 geometryGLType = GL_TRIANGLE_STRIP;
206 case Dali::Geometry::TRIANGLE_FAN:
208 geometryGLType = GL_TRIANGLE_FAN;
211 case Dali::Geometry::LINE_LOOP:
213 geometryGLType = GL_LINE_LOOP;
216 case Dali::Geometry::LINE_STRIP:
218 geometryGLType = GL_LINE_STRIP;
224 if( mIndexBuffer && geometryGLType != GL_POINTS )
227 mIndexBuffer->Bind( context, GpuBuffer::ELEMENT_ARRAY_BUFFER );
228 // numIndices truncated, no value loss happening in practice
229 context.DrawElements( geometryGLType, static_cast<GLsizei>( numIndices ), GL_UNSIGNED_SHORT, reinterpret_cast<void*>( firstIndexOffset ) );
234 GLsizei numVertices(0u);
235 if( vertexBufferCount > 0 )
237 // truncated, no value loss happening in practice
238 numVertices = static_cast<GLsizei>( mVertexBuffers[0]->GetElementCount() );
241 context.DrawArrays( geometryGLType, 0, numVertices );
245 for( auto&& attribute : attributeLocation )
247 if( attribute != -1 )
249 context.DisableVertexAttributeArray( static_cast<GLuint>( attribute ) );
254 } // namespace SceneGraph
255 } // namespace Internal