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