[Tizen] Revert "Support multiple window rendering"
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-geometry.cpp
1 /*
2  * Copyright (c) 2018 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-property-buffer.h>
25 #include <dali/internal/render/shaders/program.h>
26
27 namespace Dali
28 {
29 namespace Internal
30 {
31 namespace Render
32 {
33
34 Geometry::Geometry()
35 : mIndices(),
36   mIndexBuffer(NULL),
37   mGeometryType( Dali::Geometry::TRIANGLES ),
38   mIndicesChanged(false),
39   mHasBeenUpdated(false),
40   mAttributesChanged(true)
41 {
42 }
43
44 Geometry::~Geometry()
45 {
46 }
47
48 void Geometry::GlContextCreated( Context& context )
49 {
50 }
51
52 void Geometry::GlContextDestroyed()
53 {
54 }
55
56 void Geometry::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
57 {
58   mVertexBuffers.PushBack( propertyBuffer );
59   mAttributesChanged = true;
60 }
61
62 void Geometry::SetIndexBuffer( Dali::Vector<uint16_t>& indices )
63 {
64   mIndices.Swap( indices );
65   mIndicesChanged = true;
66 }
67
68 void Geometry::RemovePropertyBuffer( const Render::PropertyBuffer* propertyBuffer )
69 {
70   const auto&& end = mVertexBuffers.End();
71   for( auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter )
72   {
73     if( *iter == propertyBuffer )
74     {
75       //This will delete the gpu buffer associated to the RenderPropertyBuffer if there is one
76       mVertexBuffers.Remove( iter );
77       mAttributesChanged = true;
78       break;
79     }
80   }
81 }
82
83 void Geometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
84 {
85   attributeLocation.Clear();
86
87   for( auto&& vertexBuffer : mVertexBuffers )
88   {
89     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
90     for( uint32_t j = 0; j < attributeCount; ++j )
91     {
92       const std::string& attributeName = vertexBuffer->GetAttributeName( j );
93       uint32_t index = program.RegisterCustomAttribute( attributeName );
94       GLint location = program.GetCustomAttributeLocation( index );
95
96       if( -1 == location )
97       {
98         DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
99       }
100
101       attributeLocation.PushBack( location );
102     }
103   }
104 }
105
106 void Geometry::OnRenderFinished()
107 {
108   mHasBeenUpdated = false;
109   mAttributesChanged = false;
110 }
111
112 void Geometry::UploadAndDraw(
113     Context& context,
114     BufferIndex bufferIndex,
115     Vector<GLint>& attributeLocation,
116     uint32_t elementBufferOffset,
117     uint32_t elementBufferCount )
118 {
119   if( !mHasBeenUpdated )
120   {
121     // Update buffers
122     if( mIndicesChanged )
123     {
124       if( mIndices.Empty() )
125       {
126         mIndexBuffer = NULL;
127       }
128       else
129       {
130         if ( mIndexBuffer == NULL )
131         {
132           mIndexBuffer = new GpuBuffer( context );
133         }
134
135         uint32_t bufferSize = static_cast<uint32_t>( sizeof( uint16_t ) * mIndices.Size() );
136         mIndexBuffer->UpdateDataBuffer( bufferSize, &mIndices[0], GpuBuffer::STATIC_DRAW, GpuBuffer::ELEMENT_ARRAY_BUFFER );
137       }
138
139       mIndicesChanged = false;
140     }
141
142     for( auto&& buffer : mVertexBuffers )
143     {
144       if( !buffer->Update( context ) )
145       {
146         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
147         return;
148       }
149     }
150
151     mHasBeenUpdated = true;
152   }
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( 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( 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 SceneGraph
254 } // namespace Internal
255 } // namespace Dali