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