Merge "Allow multiple renderers per Actor and sharing renderers between actors" into...
[platform/core/uifw/dali-core.git] / dali / internal / update / rendering / scene-graph-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 // CLASS HEADER
18 #include "scene-graph-geometry.h"
19
20 // INTERNAL HEADERS
21 #include <dali/internal/update/controllers/scene-controller.h>
22 #include <dali/internal/render/renderers/render-geometry.h>
23 #include <dali/internal/update/controllers/render-message-dispatcher.h>
24
25 namespace Dali
26 {
27 namespace Internal
28 {
29 namespace SceneGraph
30 {
31
32 Geometry::Geometry()
33 : mIndexBuffer( NULL ),
34   mRenderGeometry(0),
35   mSceneController(0),
36   mRendererRefCount(0u),
37   mCenter(),
38   mGeometryType(Dali::Geometry::TRIANGLES),
39   mRequiresDepthTest(false)
40 {
41
42   // Observe our own PropertyOwner's uniform map
43   AddUniformMapObserver( *this );
44 }
45
46 Geometry::~Geometry()
47 {
48   mConnectionObservers.Destroy( *this );
49 }
50
51 void Geometry::AddVertexBuffer( PropertyBuffer* vertexBuffer )
52 {
53   mVertexBuffers.PushBack( vertexBuffer );
54   CalculateExtents( vertexBuffer );
55   vertexBuffer->AddUniformMapObserver(*this);
56   mConnectionObservers.ConnectionsChanged(*this);
57
58   if( mRenderGeometry )
59   {
60     mSceneController->GetRenderMessageDispatcher().AddPropertyBuffer( *mRenderGeometry, vertexBuffer, GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
61   }
62 }
63
64 void Geometry::RemoveVertexBuffer( PropertyBuffer* vertexBuffer )
65 {
66   DALI_ASSERT_DEBUG( NULL != vertexBuffer );
67
68   // Find the object and destroy it
69   Vector<PropertyBuffer*>::Iterator match = std::find(
70     mVertexBuffers.Begin(),
71     mVertexBuffers.End(),
72     vertexBuffer );
73
74   DALI_ASSERT_DEBUG( mVertexBuffers.End() != match );
75   if( mVertexBuffers.End() != match )
76   {
77     vertexBuffer->RemoveUniformMapObserver(*this);
78     mVertexBuffers.Erase( match );
79     mConnectionObservers.ConnectionsChanged(*this);
80
81     if( mRenderGeometry )
82     {
83       mSceneController->GetRenderMessageDispatcher().RemovePropertyBuffer( *mRenderGeometry, vertexBuffer );
84     }
85   }
86 }
87
88 void Geometry::SetIndexBuffer( PropertyBuffer* indexBuffer )
89 {
90   if( mIndexBuffer != indexBuffer )
91   {
92     mIndexBuffer = indexBuffer;
93     indexBuffer->AddUniformMapObserver(*this);
94     mConnectionObservers.ConnectionsChanged(*this);
95
96     if( mRenderGeometry )
97     {
98       mSceneController->GetRenderMessageDispatcher().AddPropertyBuffer( *mRenderGeometry, indexBuffer, GpuBuffer::ELEMENT_ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
99     }
100   }
101 }
102
103 void Geometry::ClearIndexBuffer()
104 {
105   if( mIndexBuffer )
106   {
107     mIndexBuffer->RemoveUniformMapObserver(*this);
108
109     if( mRenderGeometry )
110     {
111       mSceneController->GetRenderMessageDispatcher().RemovePropertyBuffer( *mRenderGeometry, mIndexBuffer );
112     }
113   }
114   mIndexBuffer = 0;
115   mConnectionObservers.ConnectionsChanged(*this);
116 }
117
118 void Geometry::SetGeometryType( BufferIndex bufferIndex, Geometry::GeometryType geometryType )
119 {
120   mGeometryType.Set( bufferIndex, geometryType);
121 }
122
123 Vector<PropertyBuffer*>& Geometry::GetVertexBuffers()
124 {
125   return mVertexBuffers;
126 }
127
128 PropertyBuffer* Geometry::GetIndexBuffer()
129 {
130   return mIndexBuffer;
131 }
132
133 Geometry::GeometryType Geometry::GetGeometryType( BufferIndex bufferIndex) const
134 {
135   int geometryType = mGeometryType[ bufferIndex ];
136   return static_cast< GeometryDataProvider::GeometryType > ( geometryType );
137 }
138
139 bool Geometry::GetRequiresDepthTesting( BufferIndex bufferIndex ) const
140 {
141   return mRequiresDepthTest.GetBoolean( bufferIndex );
142 }
143
144 void Geometry::ResetDefaultProperties( BufferIndex updateBufferIndex )
145 {
146   // Reset the animated properties
147   mCenter.ResetToBaseValue( updateBufferIndex );
148
149   // Age the double buffered properties
150   mGeometryType.CopyPrevious(updateBufferIndex);
151   mRequiresDepthTest.CopyPrevious(updateBufferIndex);
152 }
153
154 void Geometry::CalculateExtents( PropertyBuffer* vertexBuffer )
155 {
156   unsigned int elementIndex = 0;
157   unsigned int elementCount = vertexBuffer->GetElementCount( 0 );
158   unsigned int elementCount1 = vertexBuffer->GetElementCount( 1 );
159
160   // Select the double buffered element list that is the largest...
161   if ( elementCount < elementCount1 )
162   {
163     elementCount = elementCount1;
164     elementIndex = 1;
165   }
166
167   unsigned int attributeCount = vertexBuffer->GetAttributeCount( elementIndex );
168   unsigned int elementSize = vertexBuffer->GetElementSize( elementIndex );
169
170   std::string posName( "aPos" );
171   std::size_t found;
172
173   float left = 0.0f;
174   float right = 0.0f;
175   float top = 0.0f;
176   float bottom = 0.0f;
177
178   // Find the position attribute index
179   for ( unsigned int i = 0; i < attributeCount; ++i )
180   {
181     found = vertexBuffer->GetAttributeName( 0, i ).find( posName );
182     if ( found != std::string::npos )
183     {
184       unsigned int offset = vertexBuffer->GetAttributeOffset( elementIndex, i );
185       const PropertyBufferDataProvider::BufferType& data = vertexBuffer->GetData( elementIndex );
186
187       // Check attribute type to determine correct position type
188       Property::Type positionType = vertexBuffer->GetAttributeType( elementIndex, i );
189       Vector3 halfExtents;
190       Vector3 center;
191       switch ( positionType )
192       {
193         case Property::VECTOR2:
194         {
195           for ( unsigned int j = 0; j < elementCount; ++j )
196           {
197             const Vector2* position = reinterpret_cast< const Vector2* >( &data[ offset ] );
198             offset += elementSize;
199
200             if ( position->x < left )
201             {
202               left = position->x;
203             }
204             if ( position->x > right )
205             {
206               right = position->x;
207             }
208             if ( position->y < top )
209             {
210               top = position->y;
211             }
212             if ( position->y > bottom )
213             {
214               bottom = position->y;
215             }
216           }
217
218           halfExtents = Vector3( ( right - left ) * 0.5f, ( bottom - top ) * 0.5f, 0.0f );
219           center = Vector3( halfExtents.x + left , halfExtents.y + top, 0.0f );
220           break;
221         }
222         case Property::VECTOR3:
223         {
224           float near = 0.0f;
225           float far = 0.0f;
226           for ( unsigned int j = 0; j < elementCount; ++j )
227           {
228             const Vector3* position = reinterpret_cast< const Vector3* >( &data[ offset ] );
229             offset += elementSize;
230
231             if ( position->x < left )
232             {
233               left = position->x;
234             }
235             if ( position->x > right )
236             {
237               right = position->x;
238             }
239             if ( position->y < top )
240             {
241               top = position->y;
242             }
243             if ( position->y > bottom )
244             {
245               bottom = position->y;
246             }
247             if ( position->z > far )
248             {
249               far = position->z;
250             }
251             if ( position->z < near )
252             {
253               near = position->z;
254             }
255           }
256           halfExtents = Vector3( ( right - left ) * 0.5f, ( bottom - top ) * 0.5f, ( far - near ) * 0.5f );
257           center = Vector3( halfExtents.x + left , halfExtents.y + top, halfExtents.z + near );
258           break;
259         }
260         default:
261         {
262           break;
263         }
264       }
265       mCenter.Bake( 0, center );
266       mCenter.Bake( 1, center );
267     }
268   }
269 }
270
271 void Geometry::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
272 {
273 }
274
275 void Geometry::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
276 {
277 }
278
279 void Geometry::AddConnectionObserver( ConnectionChangePropagator::Observer& observer )
280 {
281   mConnectionObservers.Add(observer);
282 }
283
284 void Geometry::RemoveConnectionObserver( ConnectionChangePropagator::Observer& observer )
285 {
286   mConnectionObservers.Remove(observer);
287 }
288
289 void Geometry::UniformMappingsChanged( const UniformMap& mappings )
290 {
291   // Our uniform map, or that of one of the watched children has changed.
292   // Inform connected observers.
293   mConnectionObservers.ConnectedUniformMapChanged();
294 }
295
296 RenderGeometry* Geometry::GetRenderGeometry(SceneController* sceneController)
297 {
298   if(!mRenderGeometry)
299   {
300     //Create RenderGeometry
301     mSceneController = sceneController;
302     mRenderGeometry = new RenderGeometry( *this );
303
304     size_t vertexBufferCount( mVertexBuffers.Size() );
305     for( size_t i(0); i<vertexBufferCount; ++i )
306     {
307       mRenderGeometry->AddPropertyBuffer( mVertexBuffers[i], GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
308     }
309
310     if( mIndexBuffer )
311     {
312       mRenderGeometry->AddPropertyBuffer( mIndexBuffer, GpuBuffer::ELEMENT_ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
313     }
314
315     //Transfer ownership to RenderManager
316     sceneController->GetRenderMessageDispatcher().AddGeometry( *mRenderGeometry );
317   }
318
319   ++mRendererRefCount;
320   return mRenderGeometry;
321 }
322
323 void Geometry::OnRendererDisconnect()
324 {
325   --mRendererRefCount;
326   if( mRendererRefCount == 0 )
327   {
328     //Delete the corresponding RenderGeometry via message to RenderManager
329     mSceneController->GetRenderMessageDispatcher().RemoveGeometry( *mRenderGeometry );
330
331     mRenderGeometry = 0;
332     mSceneController = 0;
333   }
334 }
335
336
337 } // namespace SceneGraph
338 } // namespace Internal
339 } // namespace Dali