Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[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/geometry/scene-graph-geometry.h>
21 #include <dali/internal/update/common/scene-graph-property-buffer.h>
22 #include <dali/internal/render/data-providers/render-data-provider.h>
23 #include <dali/internal/render/gl-resources/context.h>
24 #include <dali/internal/render/gl-resources/gpu-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()
35 : mDataNeedsUploading( true ),
36   mShaderChanged( true )
37 {
38 }
39
40 RenderGeometry::~RenderGeometry()
41 {
42 }
43
44 void RenderGeometry::GlContextCreated( Context& context )
45 {
46   mDataNeedsUploading = true;
47 }
48
49 void RenderGeometry::GlContextDestroyed()
50 {
51 }
52
53 void RenderGeometry::UploadAndDraw(
54   Context& context,
55   Program& program,
56   BufferIndex bufferIndex,
57   const RenderDataProvider* dataProviders )
58 {
59   UploadVertexData( context, bufferIndex, dataProviders );
60
61   for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
62   {
63     mVertexBuffers[i]->BindBuffer( context, program );
64     mVertexBuffers[i]->EnableVertexAttributes( context, bufferIndex, program );
65   }
66
67   if( mIndexBuffer )
68   {
69     mIndexBuffer->BindBuffer( context, program );
70   }
71
72   Draw( context, bufferIndex, dataProviders );
73
74   for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
75   {
76     mVertexBuffers[i]->DisableVertexAttributes( context, bufferIndex, program );
77   }
78 }
79
80 void RenderGeometry::GeometryUpdated()
81 {
82   mDataNeedsUploading = true;
83 }
84
85 void RenderGeometry::UploadVertexData(
86   Context& context,
87   BufferIndex bufferIndex,
88   const RenderDataProvider* dataProviders )
89 {
90   if( mDataNeedsUploading ) // @todo Or if any of the property buffers are dirty
91   {
92     DoUpload( context, bufferIndex, dataProviders );
93
94     mDataNeedsUploading = false;
95   }
96 }
97
98 void RenderGeometry::DoUpload(
99   Context& context,
100   BufferIndex bufferIndex,
101   const RenderDataProvider* dataProvider )
102 {
103   // Vertex buffer
104   RenderDataProvider::VertexBuffers vertexBuffers = dataProvider->GetVertexBuffers();
105
106   DALI_ASSERT_DEBUG( vertexBuffers.Count() > 0 && "Need vertex buffers to upload" );
107
108   for( unsigned int i=0; i<vertexBuffers.Count(); ++i)
109   {
110     const PropertyBufferDataProvider* vertexBuffer = vertexBuffers[i];
111
112     RenderPropertyBuffer* propertyBuffer = new RenderPropertyBuffer(
113       *vertexBuffer,
114       GpuBuffer::ARRAY_BUFFER,
115       GpuBuffer::STATIC_DRAW ); // TODO: MESH_REWORK: change this for animated meshes
116
117     propertyBuffer->Upload( context, bufferIndex );
118
119     mVertexBuffers.PushBack( propertyBuffer );
120   }
121
122   // Index buffer
123   const PropertyBufferDataProvider* indexBuffer = dataProvider->GetIndexBuffer();
124   if( indexBuffer )
125   {
126     mIndexBuffer = new RenderPropertyBuffer(
127       *indexBuffer,
128       GpuBuffer::ELEMENT_ARRAY_BUFFER,
129       GpuBuffer::STATIC_DRAW ); // TODO: MESH_REWORK: change this for animated meshes
130
131     mIndexBuffer->Upload( context, bufferIndex );
132   }
133 }
134
135 void RenderGeometry::BindBuffers( Context& context, BufferIndex bufferIndex, Program& program )
136 {
137   for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
138   {
139     mVertexBuffers[i]->BindBuffer( context, program );
140   }
141
142   if( mIndexBuffer )
143   {
144     mIndexBuffer->BindBuffer( context, program );
145   }
146 }
147
148 void RenderGeometry::EnableVertexAttributes( Context& context, BufferIndex bufferIndex, Program& program )
149 {
150   OwnerContainer< RenderPropertyBuffer* >::Iterator it = mVertexBuffers.Begin();
151   OwnerContainer< RenderPropertyBuffer* >::ConstIterator end = mVertexBuffers.End();
152   for( ; it != end; ++it )
153   {
154     (*it)->EnableVertexAttributes( context, bufferIndex, program );
155   }
156 }
157
158 void RenderGeometry::DisableVertexAttributes( Context& context, BufferIndex bufferIndex, Program& program )
159 {
160   OwnerContainer< RenderPropertyBuffer* >::Iterator it = mVertexBuffers.Begin();
161   OwnerContainer< RenderPropertyBuffer* >::ConstIterator end = mVertexBuffers.End();
162   for( ; it != end; ++it )
163   {
164     (*it)->DisableVertexAttributes( context, bufferIndex, program );
165   }
166 }
167
168 void RenderGeometry::Draw( Context& context, BufferIndex bufferIndex, const RenderDataProvider* dataProvider )
169 {
170   const GeometryDataProvider& geometry = dataProvider->GetGeometry();
171   const PropertyBufferDataProvider* indexBuffer = dataProvider->GetIndexBuffer();
172
173   GeometryDataProvider::GeometryType type = geometry.GetGeometryType( bufferIndex );
174
175   unsigned int numIndices = 0;
176   if( indexBuffer )
177   {
178     numIndices = /* TODO: MESH_REWORK remove this 2, should implement unsigned short properties  */ 2 * indexBuffer->GetDataSize(bufferIndex) / indexBuffer->GetElementSize(bufferIndex);
179   }
180
181   switch(type)
182   {
183     case Dali::Geometry::TRIANGLES:
184     {
185       if( numIndices )
186       {
187         context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
188       }
189       else
190       {
191         const PropertyBufferDataProvider* firstVertexBuffer = dataProvider->GetVertexBuffers()[0];
192         unsigned int numVertices = firstVertexBuffer->GetElementCount( bufferIndex );
193         context.DrawArrays( GL_TRIANGLES, 0, numVertices );
194       }
195       break;
196     }
197     case Dali::Geometry::LINES:
198     {
199       if( numIndices )
200       {
201         context.DrawElements(GL_LINES, numIndices, GL_UNSIGNED_SHORT, 0);
202       }
203       else
204       {
205         const PropertyBufferDataProvider* firstVertexBuffer = dataProvider->GetVertexBuffers()[0];
206         unsigned int numVertices = firstVertexBuffer->GetElementCount( bufferIndex );
207         context.DrawArrays( GL_LINES, 0, numVertices );
208       }
209       break;
210     }
211     case Dali::Geometry::POINTS:
212     {
213       const PropertyBufferDataProvider* firstVertexBuffer = dataProvider->GetVertexBuffers()[0];
214       unsigned int numVertices = firstVertexBuffer->GetElementCount( bufferIndex );
215       context.DrawArrays(GL_POINTS, 0, numVertices );
216       break;
217     }
218     default:
219     {
220       DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" );
221       break;
222     }
223   }
224 }
225
226 } // namespace SceneGraph
227 } // namespace Internal
228 } // namespace Dali