[dali_1.1.7] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-geometry.cpp
1 /*
2  * Copyright (c) 2015 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 #include <dali/internal/render/renderers/render-geometry.h>
18
19 #include <dali/internal/common/buffer-index.h>
20 #include <dali/internal/update/rendering/scene-graph-geometry.h>
21 #include <dali/internal/render/data-providers/render-data-provider.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 SceneGraph
32 {
33
34 RenderGeometry::RenderGeometry( const GeometryDataProvider& geometryDataProvider )
35 : mGeometryDataProvider( geometryDataProvider ),
36   mIndexBuffer(0),
37   mHasBeenUpdated(false),
38   mAttributesChanged(true)
39 {
40 }
41
42 RenderGeometry::~RenderGeometry()
43 {
44 }
45
46 void RenderGeometry::GlContextCreated( Context& context )
47 {
48 }
49
50 void RenderGeometry::GlContextDestroyed()
51 {
52 }
53
54 void RenderGeometry::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer, bool isIndexBuffer )
55 {
56   if( isIndexBuffer )
57   {
58     mIndexBuffer = propertyBuffer;
59   }
60   else
61   {
62     mVertexBuffers.PushBack( propertyBuffer );
63     mAttributesChanged = true;
64   }
65 }
66
67 void RenderGeometry::RemovePropertyBuffer( const Render::PropertyBuffer* propertyBuffer )
68 {
69   if( propertyBuffer == mIndexBuffer )
70   {
71     mIndexBuffer = 0;
72   }
73   else
74   {
75     size_t bufferCount = mVertexBuffers.Size();
76     for( size_t i(0); i<bufferCount; ++i )
77     {
78       if( propertyBuffer == mVertexBuffers[i] )
79       {
80         //This will delete the gpu buffer associated to the RenderPropertyBuffer if there is one
81         mVertexBuffers.Remove( mVertexBuffers.Begin()+i);
82         mAttributesChanged = true;
83         break;
84       }
85     }
86   }
87 }
88
89 void RenderGeometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
90 {
91   attributeLocation.Clear();
92
93   for( size_t i(0); i< mVertexBuffers.Size(); ++i )
94   {
95     unsigned int attributeCount = mVertexBuffers[i]->GetAttributeCount();
96     for( unsigned int j = 0; j < attributeCount; ++j )
97     {
98       const std::string& attributeName = mVertexBuffers[i]->GetAttributeName( j );
99       unsigned int index = program.RegisterCustomAttribute( attributeName );
100       GLint location = program.GetCustomAttributeLocation( index );
101
102       if( -1 == location )
103       {
104         DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
105       }
106
107       attributeLocation.PushBack( location );
108     }
109   }
110 }
111
112 void RenderGeometry::OnRenderFinished()
113 {
114   mHasBeenUpdated = false;
115   mAttributesChanged = false;
116 }
117
118 void RenderGeometry::UploadAndDraw(
119     Context& context,
120     BufferIndex bufferIndex,
121     Vector<GLint>& attributeLocation )
122 {
123   if( !mHasBeenUpdated )
124   {
125     //Update buffers
126     if( mIndexBuffer )
127     {
128       if(!mIndexBuffer->Update( context, true ) )
129       {
130         //Index buffer is not ready ( Size, data or format has not been specified yet )
131         return;
132       }
133     }
134     for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
135     {
136       if( !mVertexBuffers[i]->Update( context, false ) )
137       {
138         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
139         return;
140       }
141     }
142     mHasBeenUpdated = true;
143   }
144
145   //Bind buffers to attribute locations
146   unsigned int base = 0;
147   for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
148   {
149     mVertexBuffers[i]->BindBuffer( GpuBuffer::ARRAY_BUFFER );
150     base += mVertexBuffers[i]->EnableVertexAttributes( context, attributeLocation, base );
151   }
152
153   if( mIndexBuffer )
154   {
155     mIndexBuffer->BindBuffer( GpuBuffer::ELEMENT_ARRAY_BUFFER );
156   }
157
158   //Bind index buffer
159   unsigned int numIndices(0u);
160   if( mIndexBuffer )
161   {
162     numIndices = mIndexBuffer->GetDataSize() / mIndexBuffer->GetElementSize();
163   }
164
165   //Draw call
166   GeometryDataProvider::GeometryType type = mGeometryDataProvider.GetGeometryType( bufferIndex );
167   switch(type)
168   {
169     case Dali::Geometry::TRIANGLES:
170     {
171       if( numIndices )
172       {
173         context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
174       }
175       else
176       {
177         unsigned int numVertices = mVertexBuffers[0]->GetElementCount();
178         context.DrawArrays( GL_TRIANGLES, 0, numVertices );
179       }
180       break;
181     }
182     case Dali::Geometry::LINES:
183     {
184       if( numIndices )
185       {
186         context.DrawElements(GL_LINES, numIndices, GL_UNSIGNED_SHORT, 0);
187       }
188       else
189       {
190         unsigned int numVertices = mVertexBuffers[0]->GetElementCount();
191         context.DrawArrays( GL_LINES, 0, numVertices );
192       }
193       break;
194     }
195     case Dali::Geometry::POINTS:
196     {
197       unsigned int numVertices = mVertexBuffers[0]->GetElementCount();
198       context.DrawArrays(GL_POINTS, 0, numVertices );
199       break;
200     }
201     case Dali::Geometry::TRIANGLE_STRIP:
202     {
203       if( numIndices )
204       {
205         context.DrawElements(GL_TRIANGLE_STRIP, numIndices, GL_UNSIGNED_SHORT, 0);
206       }
207       else
208       {
209         unsigned int numVertices = mVertexBuffers[0]->GetElementCount();
210         context.DrawArrays(GL_TRIANGLE_STRIP, 0, numVertices );
211       }
212       break;
213     }
214     case Dali::Geometry::TRIANGLE_FAN:
215     {
216       if( numIndices )
217       {
218         context.DrawElements(GL_TRIANGLE_FAN, numIndices, GL_UNSIGNED_SHORT, 0);
219       }
220       else
221       {
222         unsigned int numVertices = mVertexBuffers[0]->GetElementCount();
223         context.DrawArrays(GL_TRIANGLE_FAN, 0, numVertices );
224       }
225       break;
226     }
227     default:
228     {
229       DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" );
230       break;
231     }
232   }
233
234   //Disable atrributes
235   for( unsigned int i = 0; i < attributeLocation.Count(); ++i )
236   {
237     if( attributeLocation[i] != -1 )
238     {
239       context.DisableVertexAttributeArray( attributeLocation[i] );
240     }
241   }
242 }
243
244 } // namespace SceneGraph
245 } // namespace Internal
246 } // namespace Dali