[dali_1.0.30] Merge branch 'tizen'
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-algorithms.cpp
1 /*
2  * Copyright (c) 2014 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/update-algorithms.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/actors/draw-mode.h>
26 #include <dali/public-api/math/matrix.h>
27 #include <dali/public-api/math/vector3.h>
28 #include <dali/internal/update/resources/resource-manager.h>
29 #include <dali/internal/update/nodes/node.h>
30 #include <dali/internal/update/node-attachments/node-attachment.h>
31 #include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
32 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
33 #include <dali/internal/update/nodes/scene-graph-layer.h>
34 #include <dali/internal/render/renderers/scene-graph-renderer.h>
35
36 #include <dali/integration-api/debug.h>
37
38
39 namespace Dali
40 {
41
42 namespace Internal
43 {
44
45 namespace SceneGraph
46 {
47
48 #if defined(DEBUG_ENABLED)
49 Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UPDATE_ALGORITHMS");
50 #endif
51
52 /******************************************************************************
53  *********************** Apply Constraints ************************************
54  ******************************************************************************/
55
56
57 /**
58  * Constrain the local properties of the PropertyOwner.
59  * @param propertyOwner to constrain
60  * @param updateBufferIndex buffer index to use
61  * @return The number of constraints that are still being applied
62  */
63 unsigned int ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex )
64 {
65   unsigned int activeCount = 0;
66
67   ConstraintOwnerContainer& constraints = propertyOwner.GetConstraints();
68
69   const ConstraintIter endIter = constraints.End();
70   for( ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter )
71   {
72     ConstraintBase& constraint = **iter;
73     constraint.Apply( updateBufferIndex );
74
75     if( constraint.mWeight[updateBufferIndex] < 1.0f )
76     {
77       // this constraint is still being applied
78       ++activeCount;
79     }
80   }
81
82   return activeCount;
83 }
84
85 /**
86  * Recursively apply the constraints on the nodes
87  * @param node to constraint
88  * @param updateBufferIndex buffer index to use
89  * @return number of active constraints
90  */
91 unsigned int ConstrainNodes( Node& node, BufferIndex updateBufferIndex )
92 {
93   unsigned int activeCount = ConstrainPropertyOwner( node, updateBufferIndex );
94
95   /**
96    *  Constrain the children next
97    */
98   NodeContainer& children = node.GetChildren();
99   const NodeIter endIter = children.End();
100   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
101   {
102     Node& child = **iter;
103     activeCount += ConstrainNodes( child, updateBufferIndex );
104   }
105   return activeCount;
106 }
107
108 /******************************************************************************
109  ************************** Update node hierarchy *****************************
110  ******************************************************************************/
111
112 inline void UpdateRootNodeOpacity( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
113 {
114   if ( nodeDirtyFlags & ColorFlag )
115   {
116     rootNode.SetWorldColor( rootNode.GetColor( updateBufferIndex ), updateBufferIndex );
117   }
118   else
119   {
120     // Copy previous value, in case it changed in the previous frame
121     rootNode.CopyPreviousWorldColor( updateBufferIndex );
122   }
123 }
124
125 inline void UpdateNodeOpacity( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
126 {
127   // If opacity needs to be recalculated
128   if ( nodeDirtyFlags & ColorFlag )
129   {
130     node.InheritWorldColor( updateBufferIndex );
131   }
132   else
133   {
134     // Copy inherited value, if changed in the previous frame
135     node.CopyPreviousWorldColor( updateBufferIndex );
136   }
137 }
138
139 inline void UpdateNodeGeometry( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
140 {
141   if ( nodeDirtyFlags & SizeFlag )
142   {
143     Vector3 geometryScale( 1.0f, 1.0f, 1.0f );
144
145     if ( node.GetTransmitGeometryScaling() )
146     {
147       const Vector3& requiredSize = node.GetSize( updateBufferIndex );
148       geometryScale = FitKeepAspectRatio( requiredSize, node.GetInitialVolume() );
149     }
150
151     if ( node.GetGeometryScale() != geometryScale )
152     {
153       node.SetGeometryScale( geometryScale );
154     }
155   }
156 }
157
158 inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
159 {
160   // If the transform values need to be reinherited
161   if ( nodeDirtyFlags & TransformFlag )
162   {
163     rootNode.SetWorldPosition( updateBufferIndex, rootNode.GetPosition( updateBufferIndex ) );
164     rootNode.SetWorldRotation( updateBufferIndex, rootNode.GetRotation( updateBufferIndex ) );
165     rootNode.SetWorldScale   ( updateBufferIndex, rootNode.GetScale   ( updateBufferIndex ) );
166   }
167   else
168   {
169     // Copy previous value, in case they changed in the previous frame
170     rootNode.CopyPreviousWorldRotation( updateBufferIndex );
171     rootNode.CopyPreviousWorldScale( updateBufferIndex );
172     rootNode.CopyPreviousWorldPosition( updateBufferIndex );
173   }
174 }
175
176 inline void UpdateNodeTransformValues( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
177 {
178   // If the transform values need to be reinherited
179   if( nodeDirtyFlags & TransformFlag )
180   {
181     // Handle size relative to parent modes.
182     // This must be delt with before rotation/translation as otherwise anything
183     // anchored to a corner of this child would appear at the wrong position.
184     // Note: Switch is in order of use-case commonality.
185     switch( node.GetSizeMode() )
186     {
187       case USE_OWN_SIZE:
188       {
189         // Completely ignore the parents size.
190         break;
191       }
192
193       case SIZE_EQUAL_TO_PARENT:
194       {
195         // Set the nodes size to that of the parent.
196         node.SetSize( updateBufferIndex, node.GetParent()->GetSize( updateBufferIndex ) );
197         break;
198       }
199
200       case SIZE_RELATIVE_TO_PARENT:
201       {
202         // Set the nodes size to the parents multiplied by a user defined value.
203         node.SetSize( updateBufferIndex, node.GetSizeModeFactor() * node.GetParent()->GetSize( updateBufferIndex ) );
204         break;
205       }
206
207       case SIZE_FIXED_OFFSET_FROM_PARENT:
208       {
209         // Set the nodes size to the parents plus a user defined value.
210         node.SetSize( updateBufferIndex, node.GetSizeModeFactor() + node.GetParent()->GetSize( updateBufferIndex ) );
211         break;
212       }
213     }
214
215     // With a non-central anchor-point, the world rotation and scale affects the world position.
216     // Therefore the world rotation & scale must be updated before the world position.
217     if( node.IsRotationInherited() )
218     {
219       node.InheritWorldRotation( updateBufferIndex );
220     }
221     else
222     {
223       node.SetWorldRotation( updateBufferIndex, node.GetRotation( updateBufferIndex ) );
224     }
225
226     if( node.IsScaleInherited() )
227     {
228       node.InheritWorldScale( updateBufferIndex );
229     }
230     else
231     {
232       node.SetWorldScale( updateBufferIndex, node.GetScale( updateBufferIndex ) );
233     }
234
235     node.InheritWorldPosition( updateBufferIndex );
236   }
237   else
238   {
239     // Copy inherited values, if those changed in the previous frame
240     node.CopyPreviousWorldRotation( updateBufferIndex );
241     node.CopyPreviousWorldScale( updateBufferIndex );
242     node.CopyPreviousWorldPosition( updateBufferIndex );
243     node.CopyPreviousSize( updateBufferIndex );
244   }
245 }
246
247 inline void UpdateNodeWorldMatrix( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
248 {
249   // If world-matrix needs to be recalculated
250   if ( nodeDirtyFlags & TransformFlag )
251   {
252     if( node.GetInhibitLocalTransform() )
253     {
254       node.SetWorldMatrix( updateBufferIndex,
255                            node.GetWorldScale(updateBufferIndex),
256                            node.GetWorldRotation(updateBufferIndex) / node.GetRotation(updateBufferIndex),
257                            node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) );
258     }
259     else
260     {
261       node.SetWorldMatrix( updateBufferIndex,
262                            node.GetWorldScale(updateBufferIndex),
263                            node.GetWorldRotation(updateBufferIndex),
264                            node.GetWorldPosition(updateBufferIndex) );
265     }
266   }
267   else
268   {
269     node.CopyPreviousWorldMatrix( updateBufferIndex );
270   }
271 }
272
273 inline void UpdateNodeWorldMatrix( Node& node, RenderableAttachment& updatedRenderable, int nodeDirtyFlags, BufferIndex updateBufferIndex )
274 {
275   /**
276    * If world-matrix needs to be recalculated.
277    */
278   if ( ( nodeDirtyFlags & TransformFlag ) ||
279          updatedRenderable.IsScaleForSizeDirty() )
280   {
281     if( updatedRenderable.UsesGeometryScaling() )
282     {
283       // scaling, i.e. Text or Mesh
284       Vector3 scaling;
285       updatedRenderable.GetScaleForSize( node.GetSize( updateBufferIndex ), scaling );
286       if( node.GetInhibitLocalTransform() )
287       {
288         node.SetWorldMatrix( updateBufferIndex,
289                              node.GetWorldScale(updateBufferIndex) * scaling,
290                              node.GetWorldRotation(updateBufferIndex) / node.GetRotation(updateBufferIndex),
291                              node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) );
292       }
293       else
294       {
295         node.SetWorldMatrix( updateBufferIndex,
296                              node.GetWorldScale(updateBufferIndex) * scaling,
297                              node.GetWorldRotation(updateBufferIndex),
298                              node.GetWorldPosition(updateBufferIndex) );
299       }
300     }
301     else
302     {
303       // no scaling, i.e. Image
304       if( node.GetInhibitLocalTransform() )
305       {
306         node.SetWorldMatrix( updateBufferIndex,
307                              node.GetWorldScale(updateBufferIndex),
308                              node.GetWorldRotation(updateBufferIndex) / node.GetRotation(updateBufferIndex),
309                              node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) );
310       }
311       else
312       {
313         node.SetWorldMatrix( updateBufferIndex,
314                              node.GetWorldScale(updateBufferIndex),
315                              node.GetWorldRotation(updateBufferIndex),
316                              node.GetWorldPosition(updateBufferIndex) );
317       }
318     }
319   }
320   else
321   {
322     node.CopyPreviousWorldMatrix( updateBufferIndex );
323   }
324 }
325
326 /**
327  * Update an attachment.
328  * @return An updated renderable attachment if one was ready.
329  */
330 inline RenderableAttachment* UpdateAttachment( NodeAttachment& attachment,
331                                                Node& node,
332                                                BufferIndex updateBufferIndex,
333                                                ResourceManager& resourceManager,
334                                                int nodeDirtyFlags )
335 {
336   // Allow attachments to do specialised processing during updates
337   attachment.Update( updateBufferIndex, node, nodeDirtyFlags );
338
339   RenderableAttachment* renderable = attachment.GetRenderable(); // not all scene objects render
340   if( renderable )
341   {
342     // Notify renderables when size has changed
343     // Size can change while node was invisible so we need to check size again if we were previously invisible
344     if( nodeDirtyFlags & (SizeFlag|VisibleFlag) )
345     {
346       renderable->SizeChanged( updateBufferIndex );
347     }
348
349     // check if node is visible
350     if( renderable->ResolveVisibility( updateBufferIndex ) )
351     {
352       renderable->PrepareResources( updateBufferIndex, resourceManager );
353     }
354   }
355   return renderable;
356 }
357
358 inline void AddRenderableToLayer( Layer& layer,
359                                   RenderableAttachment& renderable,
360                                   BufferIndex updateBufferIndex,
361                                   int inheritedDrawMode )
362 {
363   // The renderables are stored into the opaque list temporarily for PrepareRenderables()
364   // step. The list is cleared by ProcessRenderTasks().
365   layer.opaqueRenderables.push_back( &renderable );
366 }
367
368 /**
369  * This is called recursively for all children of the root Node
370  */
371 inline int UpdateNodesAndAttachments( Node& node,
372                                       int parentFlags,
373                                       BufferIndex updateBufferIndex,
374                                       ResourceManager& resourceManager,
375                                       RenderQueue& renderQueue,
376                                       Layer& currentLayer,
377                                       int inheritedDrawMode )
378 {
379   Layer* layer = &currentLayer;
380
381   // Short-circuit for invisible nodes
382   if ( !node.IsVisible( updateBufferIndex ) )
383   {
384     return 0;
385   }
386
387   // If the node was not previously visible
388   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
389   if ( !node.IsVisible( previousBuffer ) )
390   {
391     // The node was skipped in the previous update; it must recalculate everything
392     node.SetAllDirtyFlags();
393   }
394
395   // Some dirty flags are inherited from parent
396   int nodeDirtyFlags( node.GetDirtyFlags() | ( parentFlags & InheritedDirtyFlags ) );
397
398   int cumulativeDirtyFlags = nodeDirtyFlags;
399
400   if ( node.IsLayer() )
401   {
402     // all childs go to this layer
403     layer = node.GetLayer();
404
405     // assume layer is clean to begin with
406     layer->SetReuseRenderers( updateBufferIndex, true );
407
408     // Layers do not inherit the DrawMode from their parents
409     inheritedDrawMode = DrawMode::NORMAL;
410   }
411   DALI_ASSERT_DEBUG( NULL != layer );
412
413   UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex );
414
415   UpdateNodeGeometry( node, nodeDirtyFlags, updateBufferIndex );
416
417   UpdateNodeTransformValues( node, nodeDirtyFlags, updateBufferIndex );
418
419   // Setting STENCIL will override OVERLAY, if that would otherwise have been inherited.
420   inheritedDrawMode |= node.GetDrawMode();
421
422   if ( node.HasAttachment() )
423   {
424     /*
425      * Add renderables for the children into the current Layer
426      */
427     RenderableAttachment* renderable = UpdateAttachment( node.GetAttachment(),
428                                                          node,
429                                                          updateBufferIndex,
430                                                          resourceManager,
431                                                          nodeDirtyFlags );
432
433
434     if( NULL != renderable )
435     {
436       // Update the world matrix after renderable update; the ScaleForSize property should now be calculated
437       UpdateNodeWorldMatrix( node, *renderable, nodeDirtyFlags, updateBufferIndex );
438
439       // The attachment is ready to render, so it is added to a set of renderables.
440       AddRenderableToLayer( *layer, *renderable, updateBufferIndex, inheritedDrawMode );
441     }
442   }
443   else if( node.IsObserved() )
444   {
445     // This node is being used as a property input for an animation, constraint,
446     // camera or bone. Ensure it's matrix is updated
447     UpdateNodeWorldMatrix( node, nodeDirtyFlags, updateBufferIndex );
448   }
449
450   // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused
451   // also if node has been deleted, dont reuse old render items
452   if( nodeDirtyFlags & RenderableUpdateFlags )
453   {
454     layer->SetReuseRenderers( updateBufferIndex, false );
455   }
456
457   // recurse children
458   NodeContainer& children = node.GetChildren();
459   const NodeIter endIter = children.End();
460   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
461   {
462     Node& child = **iter;
463     cumulativeDirtyFlags |=UpdateNodesAndAttachments( child,
464                                                       nodeDirtyFlags,
465                                                       updateBufferIndex,
466                                                       resourceManager,
467                                                       renderQueue,
468                                                       *layer,
469                                                       inheritedDrawMode );
470   }
471
472   return cumulativeDirtyFlags;
473 }
474
475 /**
476  * The root node is treated separately; it cannot inherit values since it has no parent
477  */
478 int UpdateNodesAndAttachments( Layer& rootNode,
479                                BufferIndex updateBufferIndex,
480                                ResourceManager& resourceManager,
481                                RenderQueue& renderQueue )
482 {
483   DALI_ASSERT_DEBUG( rootNode.IsRoot() );
484
485   // Short-circuit for invisible nodes
486   if ( !rootNode.IsVisible( updateBufferIndex ) )
487   {
488     return 0;
489   }
490
491   // If the root node was not previously visible
492   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
493   if ( !rootNode.IsVisible( previousBuffer ) )
494   {
495     // The node was skipped in the previous update; it must recalculate everything
496     rootNode.SetAllDirtyFlags();
497   }
498
499   int nodeDirtyFlags( rootNode.GetDirtyFlags() );
500
501   int cumulativeDirtyFlags = nodeDirtyFlags;
502
503   UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex );
504
505   UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex );
506
507   DrawMode::Type drawMode( rootNode.GetDrawMode() );
508
509   // recurse children
510   NodeContainer& children = rootNode.GetChildren();
511   const NodeIter endIter = children.End();
512   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
513   {
514     Node& child = **iter;
515     cumulativeDirtyFlags |= UpdateNodesAndAttachments( child,
516                                                        nodeDirtyFlags,
517                                                        updateBufferIndex,
518                                                        resourceManager,
519                                                        renderQueue,
520                                                        rootNode,
521                                                        drawMode );
522   }
523
524   return cumulativeDirtyFlags;
525 }
526
527 } // namespace SceneGraph
528
529 } // namespace Internal
530
531 } // namespace Dali