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