[dali_1.2.15] Merge branch 'devel/master'
[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   : batchParents(),
194     updateManager( NULL ),
195     currentFrame( 0 )
196   {
197   }
198
199   int GetBatchKeyIndex( size_t batchParentIndex, const BatchKey& key )
200   {
201     BatchParent& batchParent = batchParents[ batchParentIndex ];
202     for( size_t j = 0; j < batchParent.batches.size(); ++j )
203     {
204       if( batchParent.batches[j].batchKey == key )
205       {
206         return BATCH_INDEX_CREATE( batchParentIndex, j );
207       }
208     }
209     return -1;
210   }
211
212   std::vector<BatchParent>          batchParents; /// non-trivial type, hence std::vector
213   UpdateManager*                    updateManager;
214   size_t                            currentFrame;
215 };
216
217 GeometryBatcher::GeometryBatcher() :
218   mImpl( NULL )
219 {
220   mImpl = new Impl();
221 }
222
223 void GeometryBatcher::SetUpdateManager( UpdateManager* updateManager )
224 {
225   mImpl->updateManager = updateManager;
226 }
227
228 GeometryBatcher::~GeometryBatcher()
229 {
230   delete mImpl;
231 }
232
233 bool GeometryBatcher::CloneVertexFormat( const Render::Geometry* sourceGeometry, VertexDescriptor& vertexDescriptor )
234 {
235   const Render::Geometry* geometry = sourceGeometry;
236   const Render::PropertyBuffer::Format* format = geometry->GetPropertyBuffer( 0 )->GetFormat();
237
238   if( !format )
239   {
240     return false;
241   }
242
243   Render::PropertyBuffer::Format* clonedVertexFormat = new Render::PropertyBuffer::Format( *format );
244   Render::PropertyBuffer::Component& firstComponent = clonedVertexFormat->components[0];
245
246   vertexDescriptor.mVertexPositionType = firstComponent.type;
247   vertexDescriptor.mVertexComponentSize = clonedVertexFormat->size;
248   vertexDescriptor.mVertexFormat = clonedVertexFormat;
249
250   return true;
251 }
252
253 void GeometryBatcher::Update( BufferIndex bufferIndex )
254 {
255   if( !mImpl->batchParents.empty() )
256   {
257     std::vector<BatchParent>::iterator iter = mImpl->batchParents.begin();
258     std::vector<BatchParent>::iterator end = mImpl->batchParents.end();
259
260     // for each Batch Parent
261     for( size_t batchParentIndex = 0; iter != end; ++iter, ++batchParentIndex )
262     {
263       BatchParent& batchParentData = *iter;
264       // Skip update if batch parent doesn't need it
265       if( !batchParentData.needsUpdate )
266       {
267         continue;
268       }
269
270       Node* batchParentNode = batchParentData.node;
271
272       // Skip if batch parent doesn't have batched children
273       size_t size = batchParentData.batchedChildren.Size();
274       if( !size )
275       {
276         batchParentData.needsUpdate = false;
277         continue;
278       }
279
280       bool batchingFailed( false );
281       uint32_t batchKeyIndex( BATCH_NULL_HANDLE );
282
283       BatchKey oldKey;
284       BatchKey key;
285       VertexDescriptor vertexDescriptor;
286
287       // Destination vertex buffer per batch parent
288       Vector<char>& vertexBufferDest = *( new Vector<char>() );
289       Render::PropertyBuffer* batchVertexBuffer = new Render::PropertyBuffer();
290
291       size_t currentElementIndex = 0;
292
293       Matrix invWorldMatrix( batchParentNode->GetWorldMatrix( bufferIndex ) );
294       invWorldMatrix.Invert();
295
296       // For each batched child of this batch parent...
297       for( size_t i = 0; i < size; ++i )
298       {
299         Node* node = batchParentData.batchedChildren[i];
300
301         const SceneGraph::Renderer* renderer = node->GetRendererAt( 0 );
302
303         // Geometry
304         const Render::Geometry* geometry = &renderer->GetGeometry();
305
306         // Generate batch key
307         key.MakeFromNode( node );
308
309         // format of first property buffer
310         const Render::PropertyBuffer* vertexBuffer = geometry->GetPropertyBuffer( 0 );
311
312         // Geometry of the node may not be ready, in that case we discard whole batch
313         if( !vertexBuffer || ( !vertexDescriptor.mVertexFormat && !CloneVertexFormat( geometry, vertexDescriptor ) ) )
314         {
315           batchingFailed = true;
316           break;
317         }
318
319         // Instantiate new batch
320         if( oldKey != key )
321         {
322           oldKey = key;
323           batchKeyIndex = mImpl->GetBatchKeyIndex( batchParentIndex, key );
324
325           if( batchKeyIndex == BATCH_NULL_HANDLE )
326           {
327             // Create new batch geometry
328             Render::Geometry* newGeometry = new Render::Geometry();
329
330             Batch batch( key, newGeometry );
331
332             // push new batch
333             batchParentData.batches.push_back( batch );
334
335             // rebuild handle
336             batchKeyIndex = BATCH_INDEX_CREATE( batchParentIndex, batchParentData.batches.size()-1 );
337
338             // Vertex buffer may be set before it's filled with data
339             newGeometry->AddPropertyBuffer( batchVertexBuffer );
340
341             // Register geometry with update manager
342             mImpl->updateManager->AddGeometry( newGeometry );
343           }
344         }
345
346         // Tell node which batch it belongs to
347         node->mBatchIndex = batchKeyIndex;
348
349         uint32_t localIndex = BATCH_LOCAL_INDEX( batchKeyIndex );
350
351         if( !batchParentData.batches[ localIndex ].dirty )
352         {
353           continue;
354         }
355
356         const uint32_t vertexBufferSize = vertexBuffer->GetDataSize();
357         const char* vertexDataSource = &vertexBuffer->GetData()[ 0 ];
358
359         uint32_t currentSize = vertexBufferDest.Size();
360         vertexBufferDest.Resize( currentSize + vertexBufferSize );
361         char* vertexDataDest = &vertexBufferDest[ currentSize ];
362
363         // copy data as they are
364         std::copy( vertexDataSource, vertexDataSource + vertexBufferSize, vertexDataDest );
365
366         // transform node
367         const Matrix& worldMatrix = node->GetWorldMatrix( bufferIndex );
368
369         // vertex count
370         const unsigned int sourceVertexCount = vertexBufferSize / vertexDescriptor.mVertexComponentSize;
371
372         // compute transform for the node
373         TransformVertexBufferData transformParameters;
374         transformParameters.destinationPtr = vertexDataDest;
375         transformParameters.sourcePtr = vertexDataSource;
376
377         // perform transformation
378         Matrix transformMatrix;
379         Dali::Internal::MultiplyMatrices( transformMatrix.AsFloat(), worldMatrix.AsFloat(), invWorldMatrix.AsFloat() );
380         transformParameters.transform = transformMatrix.AsFloat();
381         transformParameters.componentSize = vertexDescriptor.mVertexComponentSize;
382         transformParameters.vertexCount = sourceVertexCount;
383         transformParameters.size = node->GetSize( bufferIndex ).AsFloat();
384
385         // Perform vertex transform based on the vertex format
386         switch( vertexDescriptor.mVertexPositionType )
387         {
388           case Dali::Property::VECTOR2:
389           {
390             TransformVertexBuffer<Vec2>( transformParameters );
391             break;
392           }
393           case Dali::Property::VECTOR3:
394           {
395             TransformVertexBuffer<Vec3>( transformParameters );
396             break;
397           }
398           case Dali::Property::VECTOR4:
399           {
400             TransformVertexBuffer<Vec4>( transformParameters );
401             break;
402           }
403           default:
404           {
405             DALI_ASSERT_ALWAYS( true && "Incorrect vertex format! Use Vector2, Vector3 or Vector4 as position!" );
406           }
407         }
408
409         // update index buffer
410         Batch& batch = batchParentData.batches[ localIndex ];
411         uint32_t currentIndexOffset = batch.indices.Size();
412         batch.indices.Resize( batch.indices.Size() + sourceVertexCount );
413         for( size_t k = 0; k < sourceVertexCount; ++k )
414         {
415           size_t index = currentElementIndex + k;
416           batch.indices[k + currentIndexOffset] = (unsigned short)index;
417         }
418
419         currentElementIndex += sourceVertexCount;
420       }
421
422       if( batchingFailed )
423       {
424         delete &vertexBufferDest;
425         delete batchVertexBuffer;
426         continue;
427       }
428
429       // Add shared property buffer
430       mImpl->updateManager->AddPropertyBuffer( batchVertexBuffer );
431       batchVertexBuffer->SetFormat( vertexDescriptor.mVertexFormat );
432       batchVertexBuffer->SetData( &vertexBufferDest, vertexBufferDest.Size()/vertexDescriptor.mVertexComponentSize );
433
434       batchParentData.needsUpdate = false;
435       batchParentData.vertexBuffer = batchVertexBuffer;
436
437       // Update index buffers for all batches own by that batch parent
438       std::vector<Batch>::iterator iter = batchParentData.batches.begin();
439       std::vector<Batch>::iterator end = batchParentData.batches.end();
440       for( ; iter != end; ++iter )
441       {
442         Batch& batch = (*iter);
443         batch.geometry->SetIndexBuffer( batch.indices );
444         batch.dirty = false;
445       }
446     }
447   }
448   ++mImpl->currentFrame;
449 }
450
451 void GeometryBatcher::AddBatchParent( Node* node )
452 {
453   BatchParent batchParent;
454   batchParent.node = node;
455   batchParent.needsUpdate = true;
456   batchParent.batchedChildren.Clear();
457
458   mImpl->batchParents.push_back( batchParent );
459 }
460
461 void GeometryBatcher::RemoveBatchParent( Node* node )
462 {
463   for( size_t i = 0; i < mImpl->batchParents.size(); ++i )
464   {
465     BatchParent& batchParent = mImpl->batchParents[i];
466     if( node == batchParent.node )
467     {
468       // tell children they're not batched anymore
469       Vector<Node*>::Iterator iter = batchParent.batchedChildren.Begin();
470       Vector<Node*>::Iterator end = batchParent.batchedChildren.End();
471       for( ; iter != end; ++iter )
472       {
473         Node* child = *iter;
474         child->mBatchIndex = BATCH_NULL_HANDLE;
475       }
476
477       // delete all resources that belongs to the batch parent
478       for( size_t j = 0; j < batchParent.batches.size(); ++j )
479       {
480         Batch& batch = batchParent.batches[j];
481         mImpl->updateManager->RemoveGeometry( batch.geometry );
482       }
483
484       // delete main vertex buffer
485       mImpl->updateManager->RemovePropertyBuffer( batchParent.vertexBuffer );
486
487       return;
488     }
489   }
490 }
491
492 void GeometryBatcher::AddNode( Node* node )
493 {
494   // look for batch parent
495   Node* currentNode = node->GetParent();
496   Node* batchParent = NULL;
497   while( currentNode )
498   {
499     if( currentNode->mIsBatchParent )
500     {
501       batchParent = currentNode;
502     }
503     currentNode = currentNode->GetParent();
504   }
505
506   if( batchParent )
507   {
508     // find batch parent
509     for( size_t i = 0; i < mImpl->batchParents.size(); ++i )
510     {
511       if( mImpl->batchParents[i].node == batchParent )
512       {
513         mImpl->batchParents[i].batchedChildren.PushBack( node );
514         node->SetBatchParent( batchParent );
515         mImpl->batchParents[i].needsUpdate = true;
516         break;
517       }
518     }
519   }
520 }
521
522 void GeometryBatcher::RemoveNode( Node* node )
523 {
524   if( node->mBatchIndex == BATCH_NULL_HANDLE )
525   {
526     return;
527   }
528
529   uint32_t parentIndex = BATCH_PARENT_INDEX( node->mBatchIndex );
530
531   BatchParent& batchParent = mImpl->batchParents[ parentIndex ];
532
533   // delete all batches from batch parent
534   for( size_t i = 0; i < batchParent.batches.size(); ++i )
535   {
536     Batch& batch = batchParent.batches[ i ];
537
538     // delete geometry
539     mImpl->updateManager->RemoveGeometry( batch.geometry );
540   }
541
542   batchParent.batches.clear();
543
544   // for all children reset batch index to BATCH_NULL_HANDLE
545   for( size_t i = 0; i < batchParent.batchedChildren.Size(); )
546   {
547     Node* child = batchParent.batchedChildren[i];
548
549     if( node == child )
550     {
551       batchParent.batchedChildren.Erase( batchParent.batchedChildren.Begin() + i );
552     }
553     else
554     {
555       child->mBatchIndex = BATCH_NULL_HANDLE;
556       ++i;
557     }
558   }
559
560   mImpl->updateManager->RemovePropertyBuffer( batchParent.vertexBuffer );
561   batchParent.needsUpdate = true;
562 }
563
564 bool GeometryBatcher::HasRendered( uint32_t batchIndex )
565 {
566   return mImpl->batchParents[ BATCH_PARENT_INDEX( batchIndex ) ].batches[ BATCH_LOCAL_INDEX( batchIndex ) ].renderedFrame == mImpl->currentFrame;
567 }
568
569 void GeometryBatcher::SetRendered( uint32_t batchIndex )
570 {
571   mImpl->batchParents[ BATCH_PARENT_INDEX( batchIndex ) ].batches[ BATCH_LOCAL_INDEX( batchIndex ) ].renderedFrame = mImpl->currentFrame;
572 }
573
574 Render::Geometry* GeometryBatcher::GetGeometry( uint32_t batchIndex )
575 {
576   return mImpl->batchParents[ BATCH_PARENT_INDEX( batchIndex) ].batches[ BATCH_LOCAL_INDEX( batchIndex ) ].geometry;
577 }
578
579 } // namespace SceneGraph
580
581 } // namespace Internal
582
583
584 } // namespace Dali