Merge "Add macros to provide branch prediction information" into devel/master
[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/animation/scene-graph-constraint-base.h>
32 #include <dali/internal/update/nodes/scene-graph-layer.h>
33 #include <dali/internal/render/renderers/render-renderer.h>
34
35 #include <dali/integration-api/debug.h>
36
37 namespace Dali
38 {
39
40 namespace Internal
41 {
42
43 namespace SceneGraph
44 {
45
46 #if defined(DEBUG_ENABLED)
47 Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UPDATE_ALGORITHMS");
48 #endif
49
50 /******************************************************************************
51  *********************** Apply Constraints ************************************
52  ******************************************************************************/
53
54
55 /**
56  * Constrain the local properties of the PropertyOwner.
57  * @param propertyOwner to constrain
58  * @param updateBufferIndex buffer index to use
59  * @return The number of constraints that are still being applied
60  */
61 void ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex )
62 {
63   ConstraintOwnerContainer& constraints = propertyOwner.GetConstraints();
64
65   const ConstraintIter endIter = constraints.End();
66   for( ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter )
67   {
68     ConstraintBase& constraint = **iter;
69     constraint.Apply( updateBufferIndex );
70   }
71 }
72
73 /**
74  * Recursively apply the constraints on the nodes
75  * @param node to constraint
76  * @param updateBufferIndex buffer index to use
77  * @return number of active constraints
78  */
79 void ConstrainNodes( Node& node, BufferIndex updateBufferIndex )
80 {
81   ConstrainPropertyOwner( node, updateBufferIndex );
82
83   if( node.HasAttachment() )
84   {
85     // @todo Remove dynamic cast.
86     NodeAttachment& attachment = node.GetAttachment();
87     PropertyOwner* propertyOwner = dynamic_cast< PropertyOwner* >( &attachment );
88     if( propertyOwner != NULL )
89     {
90       ConstrainPropertyOwner( *propertyOwner, updateBufferIndex );
91     }
92   }
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     ConstrainNodes( child, updateBufferIndex );
103   }
104 }
105
106 /******************************************************************************
107  ************************** Update node hierarchy *****************************
108  ******************************************************************************/
109
110 inline void UpdateRootNodeOpacity( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
111 {
112   if ( nodeDirtyFlags & ColorFlag )
113   {
114     rootNode.SetWorldColor( rootNode.GetColor( updateBufferIndex ), updateBufferIndex );
115   }
116   else
117   {
118     // Copy previous value, in case it changed in the previous frame
119     rootNode.CopyPreviousWorldColor( updateBufferIndex );
120   }
121 }
122
123 inline void UpdateNodeOpacity( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
124 {
125   // If opacity needs to be recalculated
126   if ( nodeDirtyFlags & ColorFlag )
127   {
128     node.InheritWorldColor( updateBufferIndex );
129   }
130   else
131   {
132     // Copy inherited value, if changed in the previous frame
133     node.CopyPreviousWorldColor( updateBufferIndex );
134   }
135 }
136
137 inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
138 {
139   // If the transform values need to be reinherited
140   if ( nodeDirtyFlags & TransformFlag )
141   {
142     rootNode.SetWorldPosition( updateBufferIndex, rootNode.GetPosition( updateBufferIndex ) );
143     rootNode.SetWorldOrientation( updateBufferIndex, rootNode.GetOrientation( updateBufferIndex ) );
144     rootNode.SetWorldScale   ( updateBufferIndex, rootNode.GetScale   ( updateBufferIndex ) );
145   }
146   else
147   {
148     // Copy previous value, in case they changed in the previous frame
149     rootNode.CopyPreviousWorldOrientation( updateBufferIndex );
150     rootNode.CopyPreviousWorldScale( updateBufferIndex );
151     rootNode.CopyPreviousWorldPosition( updateBufferIndex );
152   }
153 }
154
155 /**
156  * Updates transform values for the given node if the transform flag is dirty.
157   * Note that this will cause the size dirty flag to be set. This is why we pass
158  * the dirty flags in by reference.
159  * @param[in]     node The node to update
160  * @param[in,out] nodeDirtyFlags A reference to the dirty flags, these may be modified by this function
161  * @param[in]     updateBufferIndex The current index to use for this frame
162  */
163 inline void UpdateNodeTransformValues( Node& node, int& nodeDirtyFlags, BufferIndex updateBufferIndex )
164 {
165   // If the transform values need to be reinherited
166   if( nodeDirtyFlags & TransformFlag )
167   {
168     // With a non-central anchor-point, the world rotation and scale affects the world position.
169     // Therefore the world rotation & scale must be updated before the world position.
170     if( node.IsOrientationInherited() )
171     {
172       node.InheritWorldOrientation( updateBufferIndex );
173     }
174     else
175     {
176       node.SetWorldOrientation( updateBufferIndex, node.GetOrientation( updateBufferIndex ) );
177     }
178
179     if( node.IsScaleInherited() )
180     {
181       node.InheritWorldScale( updateBufferIndex );
182     }
183     else
184     {
185       node.SetWorldScale( updateBufferIndex, node.GetScale( updateBufferIndex ) );
186     }
187
188     node.InheritWorldPosition( updateBufferIndex );
189   }
190   else
191   {
192     // Copy inherited values, if those changed in the previous frame
193     node.CopyPreviousWorldOrientation( updateBufferIndex );
194     node.CopyPreviousWorldScale( updateBufferIndex );
195     node.CopyPreviousWorldPosition( updateBufferIndex );
196     node.CopyPreviousSize( updateBufferIndex );
197   }
198 }
199
200 inline void UpdateNodeWorldMatrix( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
201 {
202   // If world-matrix needs to be recalculated
203   if ( nodeDirtyFlags & TransformFlag )
204   {
205     node.SetWorldMatrix( updateBufferIndex,
206                          node.GetWorldScale(updateBufferIndex),
207                          node.GetWorldOrientation(updateBufferIndex),
208                          node.GetWorldPosition(updateBufferIndex) );
209   }
210   else
211   {
212     node.CopyPreviousWorldMatrix( updateBufferIndex );
213   }
214 }
215
216 /**
217  * This is called recursively for all children of the root Node
218  */
219 inline int UpdateNodesAndAttachments( Node& node,
220                                       int parentFlags,
221                                       BufferIndex updateBufferIndex,
222                                       ResourceManager& resourceManager,
223                                       RenderQueue& renderQueue,
224                                       Layer& currentLayer,
225                                       int inheritedDrawMode )
226 {
227   Layer* layer = &currentLayer;
228
229   // Short-circuit for invisible nodes
230   if ( !node.IsVisible( updateBufferIndex ) )
231   {
232     return 0;
233   }
234
235   // If the node was not previously visible
236   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
237   if ( !node.IsVisible( previousBuffer ) )
238   {
239     // The node was skipped in the previous update; it must recalculate everything
240     node.SetAllDirtyFlags();
241   }
242
243   // Some dirty flags are inherited from parent
244   int nodeDirtyFlags( node.GetDirtyFlags() | ( parentFlags & InheritedDirtyFlags ) );
245
246   int cumulativeDirtyFlags = nodeDirtyFlags;
247
248   Layer* nodeIsLayer( node.GetLayer() );
249   if ( nodeIsLayer )
250   {
251     // all childs go to this layer
252     layer = nodeIsLayer;
253
254     // assume layer is clean to begin with
255     layer->SetReuseRenderers( updateBufferIndex, true );
256
257     // Layers do not inherit the DrawMode from their parents
258     inheritedDrawMode = DrawMode::NORMAL;
259   }
260   DALI_ASSERT_DEBUG( NULL != layer );
261
262   UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex );
263
264   // Note: nodeDirtyFlags are passed in by reference and may be modified by the following function
265   UpdateNodeTransformValues( node, nodeDirtyFlags, updateBufferIndex );
266
267   // Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited.
268   inheritedDrawMode |= node.GetDrawMode();
269
270   if ( node.HasAttachment() )
271   {
272     node.GetAttachment().Update( updateBufferIndex, node, nodeDirtyFlags );
273   }
274   else if( node.IsObserved() || node.GetRendererCount() )
275   {
276     // This node is being used as a property input for an animation, constraint,
277     // camera or bone. Ensure it's matrix is updated
278     UpdateNodeWorldMatrix( node, nodeDirtyFlags, updateBufferIndex );
279   }
280
281   if( node.ResolveVisibility(updateBufferIndex) )
282   {
283     node.PrepareRender( updateBufferIndex );
284   }
285
286
287   // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused
288   // also if node has been deleted, dont reuse old render items
289   if( nodeDirtyFlags & RenderableUpdateFlags )
290   {
291     layer->SetReuseRenderers( updateBufferIndex, false );
292   }
293
294   // recurse children
295   NodeContainer& children = node.GetChildren();
296   const NodeIter endIter = children.End();
297   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
298   {
299     Node& child = **iter;
300     cumulativeDirtyFlags |=UpdateNodesAndAttachments( child,
301                                                       nodeDirtyFlags,
302                                                       updateBufferIndex,
303                                                       resourceManager,
304                                                       renderQueue,
305                                                       *layer,
306                                                       inheritedDrawMode );
307   }
308
309   return cumulativeDirtyFlags;
310 }
311
312 /**
313  * The root node is treated separately; it cannot inherit values since it has no parent
314  */
315 int UpdateNodesAndAttachments( Layer& rootNode,
316                                BufferIndex updateBufferIndex,
317                                ResourceManager& resourceManager,
318                                RenderQueue& renderQueue )
319 {
320   DALI_ASSERT_DEBUG( rootNode.IsRoot() );
321
322   // Short-circuit for invisible nodes
323   if ( DALI_UNLIKELY( !rootNode.IsVisible( updateBufferIndex ) ) ) // almost never ever true
324   {
325     return 0;
326   }
327
328   // If the root node was not previously visible
329   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
330   if ( DALI_UNLIKELY( !rootNode.IsVisible( previousBuffer ) ) ) // almost never ever true
331   {
332     // The node was skipped in the previous update; it must recalculate everything
333     rootNode.SetAllDirtyFlags();
334   }
335
336   int nodeDirtyFlags( rootNode.GetDirtyFlags() );
337
338   int cumulativeDirtyFlags = nodeDirtyFlags;
339
340   UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex );
341
342   UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex );
343
344   DrawMode::Type drawMode( rootNode.GetDrawMode() );
345
346   // recurse children
347   NodeContainer& children = rootNode.GetChildren();
348   const NodeIter endIter = children.End();
349   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
350   {
351     Node& child = **iter;
352     cumulativeDirtyFlags |= UpdateNodesAndAttachments( child,
353                                                        nodeDirtyFlags,
354                                                        updateBufferIndex,
355                                                        resourceManager,
356                                                        renderQueue,
357                                                        rootNode,
358                                                        drawMode );
359   }
360
361   return cumulativeDirtyFlags;
362 }
363
364 } // namespace SceneGraph
365
366 } // namespace Internal
367
368 } // namespace Dali