[3.0] Temporary change to fix homescreen issue
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / geometry-batcher.cpp
1 /*
2  * Copyright (c) 2016 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
18 // CLASS HEADER
19 #include <dali/internal/update/manager/geometry-batcher.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/render/common/render-item.h>
23 #include <dali/internal/render/common/render-tracker.h>
24 #include <dali/internal/render/common/render-instruction.h>
25 #include <dali/internal/render/common/render-instruction-container.h>
26 #include <dali/internal/render/shaders/scene-graph-shader.h>
27 #include <dali/internal/render/renderers/render-renderer.h>
28 #include <dali/internal/render/renderers/render-property-buffer.h>
29 #include <dali/internal/render/renderers/render-geometry.h>
30 #include <dali/internal/update/rendering/scene-graph-renderer.h>
31 #include <dali/internal/update/controllers/scene-controller.h>
32 #include <dali/internal/update/manager/update-manager.h>
33 #include <dali/internal/common/math.h>
34
35 namespace
36 {
37
38 // helper macros to deal with handles
39 #define BATCH_LOCAL_INDEX(x) (x&0xFFFF)
40 #define BATCH_PARENT_INDEX(x) ((x>>16)&0xFFFF)
41 #define BATCH_INDEX_CREATE( batchParentIndex, batchIndex ) ( ( ( (batchParentIndex)&0xFFFF ) << 16 ) | ( (batchIndex)&0xFFFF ) )
42
43 /**
44  * The TransformVertexBufferInfo struct
45  * Must be filled before transforming vertices
46  */
47 struct TransformVertexBufferData
48 {
49   void*                         destinationPtr;       ///< pointer to the destination vertex buffer
50   const void*                   sourcePtr;            ///< pointer to the source vertex buffer
51   float*                        transform;            ///< transform relative to batch parent
52   const float*                  worldMatrix;          ///< model/world matrix of node being batched
53   const float*                  parentInvWorldMatrix; ///< inv world matrix of batch parent
54   unsigned                      componentSize;        ///< size of component
55   unsigned                      vertexCount;          ///< number of vertices to process
56   const float*                  size;                 ///< size of render item
57 };
58
59 /**
60  * @brief function transforms vertices from 'source' and writes into 'destination'
61  * @param[in,out] data Filled TransformVertexBufferInfo arguments structure
62  */
63 template <typename PositionType >
64 void TransformVertexBuffer( TransformVertexBufferData& data )
65 {
66   const PositionType* source = reinterpret_cast<const PositionType*>( data.sourcePtr );
67   PositionType* destination = reinterpret_cast<PositionType*>( data.destinationPtr );
68
69   size_t componentSize = data.componentSize ? data.componentSize : sizeof( PositionType );
70   const void* sourceEnd = (reinterpret_cast<const char*>( source ) + ( data.vertexCount*componentSize ));
71   for( ; source < sourceEnd;
72        *(reinterpret_cast<char**>( &destination )) += componentSize,
73        *(reinterpret_cast<const char**>( &source )) += componentSize
74        )
75   {
76     Dali::Internal::MultiplyVectorBySize( *destination, *source, data.size );
77     Dali::Internal::MultiplyVectorByMatrix4( *destination, data.transform, *destination );
78   }
79 }
80
81 } //Unnamed namespace
82
83 namespace Dali
84 {
85
86 namespace Internal
87 {
88
89 namespace SceneGraph
90 {
91
92 /**
93  * @brief The VertexDescriptor struct
94  * Holds details of vertex format used for batching
95  */
96 struct VertexDescriptor
97 {
98   VertexDescriptor()
99     : mVertexComponentSize( 0 ),
100       mVertexPositionType( Dali::Property::NONE ),
101       mVertexFormat( NULL )
102   {
103   }
104
105   unsigned int mVertexComponentSize; ///< Vertex component size in bytes
106   Dali::Property::Type mVertexPositionType;  ///< Vertex position type ( may be Vector2, Vector3, Vector4 )
107   Dali::Internal::Render::PropertyBuffer::Format* mVertexFormat; ///< Vertex format cloned from the very first batched item
108 };
109
110 struct BatchKey
111 {
112   BatchKey()
113   : batchParentNode( NULL ),
114     shader( NULL ),
115     textureSet( NULL ),
116     depthIndex( 0 )
117   {
118   }
119
120   ~BatchKey()
121   {
122   }
123
124   BatchKey( Node* node )
125   {
126     MakeFromNode( node );
127   }
128
129   inline void MakeFromNode( Node* node )
130   {
131     Renderer* renderer = node->GetRendererAt( 0 );
132     batchParentNode = node->GetBatchParent();
133     shader = &renderer->GetShader();
134     textureSet = renderer->GetTextures();
135     depthIndex = renderer->GetDepthIndex();
136   }
137
138   inline bool operator==( const BatchKey& key )
139   {
140     return batchParentNode == key.batchParentNode && shader == key.shader && textureSet == key.textureSet && depthIndex == key.depthIndex;
141   }
142
143   inline bool operator!=( const BatchKey& key )
144   {
145     return !( *this == key );
146   }
147
148   const Node*           batchParentNode;    /// batch parent node that owns batch
149   const Shader*         shader;             /// shader associated with the batch
150   const TextureSet*     textureSet;         /// texture set used by the batch
151   int                   depthIndex;         /// depth index of the batch
152 };
153
154 /**
155  * @brief The Batch struct
156  * Stores details of single batch
157  */
158 struct Batch
159 {
160   Batch( const BatchKey& key, Render::Geometry* batchGeometry = NULL )
161    : batchKey( key ),
162      geometry( batchGeometry ),
163      renderedFrame( 0 ),
164      dirty( true )
165   {}
166
167
168   BatchKey                batchKey;       /// Unique batch key
169   Vector<unsigned short>  indices;        /// index buffer per batch
170   Render::Geometry*       geometry;       /// Batch geometry
171   size_t                  renderedFrame;  /// Flag used to determine if batch has already rendered during a frame
172   bool                    dirty;          /// 'dirty' flag per batch
173 };
174
175 typedef std::vector<Batch> BatchList;
176
177 /**
178  * @brief The BatchParent struct
179  * Stores list of children of single batch parent
180  */
181 struct BatchParent
182 {
183   Node*                   node;             /// Pointer to a node which is a parent for batch(es)
184   Vector<Node*>           batchedChildren;  /// List of batchable children
185   BatchList               batches;          /// List of batches which belong to this parent
186   Render::PropertyBuffer* vertexBuffer;     /// Vertex buffer shared by all batches for this parent
187   bool                    needsUpdate;      /// Flag indicating if batches should be updated
188 };
189
190 struct Impl
191 {
192   Impl() :
193     currentFrame( 0 )
194   {}
195
196   int GetBatchKeyIndex( size_t batchParentIndex, const BatchKey& key )
197   {
198     BatchParent& batchParent = batchParents[ batchParentIndex ];
199     for( size_t j = 0; j < batchParent.batches.size(); ++j )
200     {
201       if( batchParent.batches[j].batchKey == key )
202       {
203         return BATCH_INDEX_CREATE( batchParentIndex, j );
204       }
205     }
206     return -1;
207   }
208
209   std::vector<BatchParent>          batchParents; /// non-trivial type, hence std::vector
210   UpdateManager*                    updateManager;
211   size_t                            currentFrame;
212 };
213
214 GeometryBatcher::GeometryBatcher() :
215   mImpl( NULL )
216 {
217   mImpl = new Impl();
218 }
219
220 void GeometryBatcher::SetUpdateManager( UpdateManager* updateManager )
221 {
222   mImpl->updateManager = updateManager;
223 }
224
225 GeometryBatcher::~GeometryBatcher()
226 {
227   delete mImpl;
228 }
229
230 bool GeometryBatcher::CloneVertexFormat( const Render::Geometry* sourceGeometry, VertexDescriptor& vertexDescriptor )
231 {
232   const Render::Geometry* geometry = sourceGeometry;
233   const Render::PropertyBuffer::Format* format = geometry->GetPropertyBuffer( 0 )->GetFormat();
234
235   if( !format )
236   {
237     return false;
238   }
239
240   Render::PropertyBuffer::Format* clonedVertexFormat = new Render::PropertyBuffer::Format( *format );
241   Render::PropertyBuffer::Component& firstComponent = clonedVertexFormat->components[0];
242
243   vertexDescriptor.mVertexPositionType = firstComponent.type;
244   vertexDescriptor.mVertexComponentSize = clonedVertexFormat->size;
245   vertexDescriptor.mVertexFormat = clonedVertexFormat;
246
247   return true;
248 }
249
250 void GeometryBatcher::Update( BufferIndex bufferIndex )
251 {
252   if( !mImpl->batchParents.empty() )
253   {
254     std::vector<BatchParent>::iterator iter = mImpl->batchParents.begin();
255     std::vector<BatchParent>::iterator end = mImpl->batchParents.end();
256
257     // for each Batch Parent
258     for( size_t batchParentIndex = 0; iter != end; ++iter, ++batchParentIndex )
259     {
260       BatchParent& batchParentData = *iter;
261       // Skip update if batch parent doesn't need it
262       if( !batchParentData.needsUpdate )
263       {
264         continue;
265       }
266
267       Node* batchParentNode = batchParentData.node;
268
269       // Skip if batch parent doesn't have batched children
270       size_t size = batchParentData.batchedChildren.Size();
271       if( !size )
272       {
273         batchParentData.needsUpdate = false;
274         continue;
275       }
276
277       bool batchingFailed( false );
278       uint32_t batchKeyIndex( BATCH_NULL_HANDLE );
279
280       BatchKey oldKey;
281       BatchKey key;
282       VertexDescriptor vertexDescriptor;
283
284       // Destination vertex buffer per batch parent
285       Vector<char>& vertexBufferDest = *( new Vector<char>() );
286       Render::PropertyBuffer* batchVertexBuffer = new Render::PropertyBuffer();
287
288       size_t currentElementIndex = 0;
289
290       Matrix invWorldMatrix( batchParentNode->GetWorldMatrix( bufferIndex ) );
291       invWorldMatrix.Invert();
292
293       // For each batched child of this batch parent...
294       for( size_t i = 0; i < size; ++i )
295       {
296         Node* node = batchParentData.batchedChildren[i];
297
298         const SceneGraph::Renderer* renderer = node->GetRendererAt( 0 );
299
300         // Geometry
301         const Render::Geometry* geometry = &renderer->GetGeometry();
302
303         // Generate batch key
304         key.MakeFromNode( node );
305
306         // format of first property buffer
307         const Render::PropertyBuffer* vertexBuffer = geometry->GetPropertyBuffer( 0 );
308
309         // Geometry of the node may not be ready, in that case we discard whole batch
310         if( !vertexBuffer || ( !vertexDescriptor.mVertexFormat && !CloneVertexFormat( geometry, vertexDescriptor ) ) )
311         {
312           batchingFailed = true;
313           break;
314         }
315
316         // Instantiate new batch
317         if( oldKey != key )
318         {
319           oldKey = key;
320           batchKeyIndex = mImpl->GetBatchKeyIndex( batchParentIndex, key );
321
322           if( batchKeyIndex == BATCH_NULL_HANDLE )
323           {
324             // Create new batch geometry
325             Render::Geometry* newGeometry = new Render::Geometry();
326
327             Batch batch( key, newGeometry );
328
329             // push new batch
330             batchParentData.batches.push_back( batch );
331
332             // rebuild handle
333             batchKeyIndex = BATCH_INDEX_CREATE( batchParentIndex, batchParentData.batches.size()-1 );
334
335             // Vertex buffer may be set before it's filled with data
336             newGeometry->AddPropertyBuffer( batchVertexBuffer );
337
338             // Register geometry with update manager
339             mImpl->updateManager->AddGeometry( newGeometry );
340           }
341         }
342
343         // Tell node which batch it belongs to
344         node->mBatchIndex = batchKeyIndex;
345
346         uint32_t localIndex = BATCH_LOCAL_INDEX( batchKeyIndex );
347
348         if( !batchParentData.batches[ localIndex ].dirty )
349         {
350           continue;
351         }
352
353         const uint32_t vertexBufferSize = vertexBuffer->GetDataSize();
354         const char* vertexDataSource = &vertexBuffer->GetData()[ 0 ];
355
356         uint32_t currentSize = vertexBufferDest.Size();
357         vertexBufferDest.Resize( currentSize + vertexBufferSize );
358         char* vertexDataDest = &vertexBufferDest[ currentSize ];
359
360         // copy data as they are
361         std::copy( vertexDataSource, vertexDataSource + vertexBufferSize, vertexDataDest );
362
363         // transform node
364         const Matrix& worldMatrix = node->GetWorldMatrix( bufferIndex );
365
366         // vertex count
367         const unsigned int sourceVertexCount = vertexBufferSize / vertexDescriptor.mVertexComponentSize;
368
369         // compute transform for the node
370         TransformVertexBufferData transformParameters;
371         transformParameters.destinationPtr = vertexDataDest;
372         transformParameters.sourcePtr = vertexDataSource;
373
374         // perform transformation
375         Matrix transformMatrix;
376         Dali::Internal::MultiplyMatrices( transformMatrix.AsFloat(), worldMatrix.AsFloat(), invWorldMatrix.AsFloat() );
377         transformParameters.transform = transformMatrix.AsFloat();
378         transformParameters.componentSize = vertexDescriptor.mVertexComponentSize;
379         transformParameters.vertexCount = sourceVertexCount;
380         transformParameters.size = node->GetSize( bufferIndex ).AsFloat();
381
382         // Perform vertex transform based on the vertex format
383         switch( vertexDescriptor.mVertexPositionType )
384         {
385           case Dali::Property::VECTOR2:
386           {
387             TransformVertexBuffer<Vec2>( transformParameters );
388             break;
389           }
390           case Dali::Property::VECTOR3:
391           {
392             TransformVertexBuffer<Vec3>( transformParameters );
393             break;
394           }
395           case Dali::Property::VECTOR4:
396           {
397             TransformVertexBuffer<Vec4>( transformParameters );
398             break;
399           }
400           default:
401           {
402             DALI_ASSERT_ALWAYS( true && "Incorrect vertex format! Use Vector2, Vector3 or Vector4 as position!" );
403           }
404         }
405
406         // update index buffer
407         Batch& batch = batchParentData.batches[ localIndex ];
408         uint32_t currentIndexOffset = batch.indices.Size();
409         batch.indices.Resize( batch.indices.Size() + sourceVertexCount );
410         for( size_t k = 0; k < sourceVertexCount; ++k )
411         {
412           size_t index = currentElementIndex + k;
413           batch.indices[k + currentIndexOffset] = (unsigned short)index;
414         }
415
416         currentElementIndex += sourceVertexCount;
417       }
418
419       if( batchingFailed )
420       {
421         delete &vertexBufferDest;
422         delete batchVertexBuffer;
423         continue;
424       }
425
426       // Add shared property buffer
427       mImpl->updateManager->AddPropertyBuffer( batchVertexBuffer );
428       batchVertexBuffer->SetFormat( vertexDescriptor.mVertexFormat );
429       batchVertexBuffer->SetData( &vertexBufferDest, vertexBufferDest.Size()/vertexDescriptor.mVertexComponentSize );
430
431       batchParentData.needsUpdate = false;
432       batchParentData.vertexBuffer = batchVertexBuffer;
433
434       // Update index buffers for all batches own by that batch parent
435       std::vector<Batch>::iterator iter = batchParentData.batches.begin();
436       std::vector<Batch>::iterator end = batchParentData.batches.end();
437       for( ; iter != end; ++iter )
438       {
439         Batch& batch = (*iter);
440         batch.geometry->SetIndexBuffer( batch.indices );
441         batch.dirty = false;
442       }
443     }
444   }
445   ++mImpl->currentFrame;
446 }
447
448 void GeometryBatcher::AddBatchParent( Node* node )
449 {
450   BatchParent batchParent;
451   batchParent.node = node;
452   batchParent.needsUpdate = true;
453   batchParent.batchedChildren.Clear();
454
455   mImpl->batchParents.push_back( batchParent );
456 }
457
458 void GeometryBatcher::RemoveBatchParent( Node* node )
459 {
460   for( size_t i = 0; i < mImpl->batchParents.size(); ++i )
461   {
462     BatchParent& batchParent = mImpl->batchParents[i];
463     if( node == batchParent.node )
464     {
465       // tell children they're not batched anymore
466       Vector<Node*>::Iterator iter = batchParent.batchedChildren.Begin();
467       Vector<Node*>::Iterator end = batchParent.batchedChildren.End();
468       for( ; iter != end; ++iter )
469       {
470         Node* child = *iter;
471         child->mBatchIndex = BATCH_NULL_HANDLE;
472       }
473
474       // delete all resources that belongs to the batch parent
475       for( size_t j = 0; j < batchParent.batches.size(); ++j )
476       {
477         Batch& batch = batchParent.batches[j];
478         mImpl->updateManager->RemoveGeometry( batch.geometry );
479       }
480
481       // delete main vertex buffer
482       mImpl->updateManager->RemovePropertyBuffer( batchParent.vertexBuffer );
483
484       return;
485     }
486   }
487 }
488
489 void GeometryBatcher::AddNode( Node* node )
490 {
491   // look for batch parent
492   Node* currentNode = node->GetParent();
493   Node* batchParent = NULL;
494   while( currentNode )
495   {
496     if( currentNode->mIsBatchParent )
497     {
498       batchParent = currentNode;
499     }
500     currentNode = currentNode->GetParent();
501   }
502
503   if( batchParent )
504   {
505     // find batch parent
506     for( size_t i = 0; i < mImpl->batchParents.size(); ++i )
507     {
508       if( mImpl->batchParents[i].node == batchParent )
509       {
510         mImpl->batchParents[i].batchedChildren.PushBack( node );
511         node->SetBatchParent( batchParent );
512         mImpl->batchParents[i].needsUpdate = true;
513         break;
514       }
515     }
516   }
517 }
518
519 void GeometryBatcher::RemoveNode( Node* node )
520 {
521   if( node->mBatchIndex == BATCH_NULL_HANDLE )
522   {
523     return;
524   }
525
526   uint32_t parentIndex = BATCH_PARENT_INDEX( node->mBatchIndex );
527
528   BatchParent& batchParent = mImpl->batchParents[ parentIndex ];
529
530   // delete all batches from batch parent
531   for( size_t i = 0; i < batchParent.batches.size(); ++i )
532   {
533     Batch& batch = batchParent.batches[ i ];
534
535     // delete geometry
536     mImpl->updateManager->RemoveGeometry( batch.geometry );
537   }
538
539   batchParent.batches.clear();
540
541   // for all children reset batch index to BATCH_NULL_HANDLE
542   for( size_t i = 0; i < batchParent.batchedChildren.Size(); )
543   {
544     Node* child = batchParent.batchedChildren[i];
545
546     if( node == child )
547     {
548       batchParent.batchedChildren.Erase( batchParent.batchedChildren.Begin() + i );
549     }
550     else
551     {
552       child->mBatchIndex = BATCH_NULL_HANDLE;
553       ++i;
554     }
555   }
556
557   mImpl->updateManager->RemovePropertyBuffer( batchParent.vertexBuffer );
558   batchParent.needsUpdate = true;
559 }
560
561 bool GeometryBatcher::HasRendered( uint32_t batchIndex )
562 {
563   return mImpl->batchParents[ BATCH_PARENT_INDEX( batchIndex ) ].batches[ BATCH_LOCAL_INDEX( batchIndex ) ].renderedFrame == mImpl->currentFrame;
564 }
565
566 void GeometryBatcher::SetRendered( uint32_t batchIndex )
567 {
568   mImpl->batchParents[ BATCH_PARENT_INDEX( batchIndex ) ].batches[ BATCH_LOCAL_INDEX( batchIndex ) ].renderedFrame = mImpl->currentFrame;
569 }
570
571 Render::Geometry* GeometryBatcher::GetGeometry( uint32_t batchIndex )
572 {
573   return mImpl->batchParents[ BATCH_PARENT_INDEX( batchIndex) ].batches[ BATCH_LOCAL_INDEX( batchIndex ) ].geometry;
574 }
575
576 } // namespace SceneGraph
577
578 } // namespace Internal
579
580
581 } // namespace Dali