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