[dali_2.3.31] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-algorithms.cpp
1 /*
2  * Copyright (c) 2024 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/internal/render/renderers/render-renderer.h>
26 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
27 #include <dali/internal/update/nodes/node.h>
28 #include <dali/internal/update/nodes/scene-graph-layer.h>
29 #include <dali/public-api/actors/draw-mode.h>
30 #include <dali/public-api/math/matrix.h>
31 #include <dali/public-api/math/vector3.h>
32
33 #include <dali/integration-api/debug.h>
34
35 namespace Dali
36 {
37 namespace Internal
38 {
39 namespace SceneGraph
40 {
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UPDATE_ALGORITHMS");
43 #endif
44
45 /******************************************************************************
46  *********************** Apply Constraints ************************************
47  ******************************************************************************/
48
49 /**
50  * Constrain the local properties of the PropertyOwner.
51  * @param propertyOwner to constrain
52  * @param updateBufferIndex buffer index to use
53  */
54 void ConstrainPropertyOwner(PropertyOwner& propertyOwner, BufferIndex updateBufferIndex, bool isPreConstraint)
55 {
56   ConstraintOwnerContainer& constraints = (isPreConstraint) ? propertyOwner.GetConstraints() : propertyOwner.GetPostConstraints();
57
58   const ConstraintIter endIter = constraints.End();
59   for(ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter)
60   {
61     ConstraintBase& constraint = **iter;
62     constraint.Apply(updateBufferIndex);
63   }
64 }
65
66 /******************************************************************************
67  ************************** Update node hierarchy *****************************
68  ******************************************************************************/
69
70 inline void UpdateRootNodeOpacity(Layer& rootNode, NodePropertyFlags nodeDirtyFlags, BufferIndex updateBufferIndex)
71 {
72   if(nodeDirtyFlags & NodePropertyFlags::COLOR)
73   {
74     rootNode.SetWorldColor(rootNode.GetColor(updateBufferIndex), updateBufferIndex);
75   }
76   else
77   {
78     // Copy previous value, in case it changed in the previous frame
79     rootNode.CopyPreviousWorldColor(updateBufferIndex);
80   }
81 }
82
83 inline void UpdateNodeOpacity(Node& node, NodePropertyFlags nodeDirtyFlags, BufferIndex updateBufferIndex)
84 {
85   // If opacity needs to be recalculated
86   if(nodeDirtyFlags & NodePropertyFlags::COLOR)
87   {
88     node.InheritWorldColor(updateBufferIndex);
89   }
90   else
91   {
92     // Copy inherited value, if changed in the previous frame
93     node.CopyPreviousWorldColor(updateBufferIndex);
94   }
95 }
96
97 /**
98  * This is called recursively for all children of the root Node
99  */
100 inline NodePropertyFlags UpdateNodes(Node&                   node,
101                                      NodePropertyFlags       parentFlags,
102                                      BufferIndex             updateBufferIndex,
103                                      RenderQueue&            renderQueue,
104                                      PropertyOwnerContainer& postPropertyOwners,
105                                      bool                    updated)
106 {
107   // Apply constraints to the node
108   ConstrainPropertyOwner(node, updateBufferIndex);
109   if(!node.GetPostConstraints().Empty())
110   {
111     postPropertyOwners.PushBack(&node);
112   }
113
114   // Some dirty flags are inherited from parent
115   NodePropertyFlags nodeDirtyFlags = node.GetDirtyFlags() | node.GetInheritedDirtyFlags(parentFlags);
116
117   NodePropertyFlags cumulativeDirtyFlags = nodeDirtyFlags;
118
119   UpdateNodeOpacity(node, nodeDirtyFlags, updateBufferIndex);
120
121   // Age down partial update data
122   node.GetPartialRenderingData().Aging();
123
124   // For partial update, mark all children of an animating node as updated.
125   if(updated) // Only set to updated if parent was updated.
126   {
127     node.SetUpdated(true);
128   }
129   else if(node.Updated()) // Only propagate updated==true downwards.
130   {
131     updated = true;
132   }
133
134   // recurse children
135   NodeContainer& children = node.GetChildren();
136   const NodeIter endIter  = children.End();
137   for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
138   {
139     Node& child = **iter;
140     cumulativeDirtyFlags |= UpdateNodes(child,
141                                         nodeDirtyFlags,
142                                         updateBufferIndex,
143                                         renderQueue,
144                                         postPropertyOwners,
145                                         updated);
146   }
147
148   return cumulativeDirtyFlags;
149 }
150
151 /**
152  * The root node is treated separately; it cannot inherit values since it has no parent
153  */
154 NodePropertyFlags UpdateNodeTree(Layer&                  rootNode,
155                                  BufferIndex             updateBufferIndex,
156                                  RenderQueue&            renderQueue,
157                                  PropertyOwnerContainer& postPropertyOwners)
158 {
159   DALI_ASSERT_DEBUG(rootNode.IsRoot());
160
161   // Short-circuit for invisible nodes
162   if(DALI_UNLIKELY(!rootNode.IsVisible(updateBufferIndex))) // almost never ever true
163   {
164     return NodePropertyFlags::NOTHING;
165   }
166
167   // If the root node was not previously visible
168   BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
169   if(DALI_UNLIKELY(!rootNode.IsVisible(previousBuffer))) // almost never ever true
170   {
171     // The node was skipped in the previous update; it must recalculate everything
172     rootNode.SetAllDirtyFlags();
173   }
174
175   NodePropertyFlags nodeDirtyFlags(rootNode.GetDirtyFlags());
176
177   NodePropertyFlags cumulativeDirtyFlags = nodeDirtyFlags;
178
179   UpdateRootNodeOpacity(rootNode, nodeDirtyFlags, updateBufferIndex);
180
181   // Age down partial update data
182   rootNode.GetPartialRenderingData().Aging();
183
184   bool updated = rootNode.Updated();
185
186   // recurse children
187   NodeContainer& children = rootNode.GetChildren();
188   const NodeIter endIter  = children.End();
189   for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
190   {
191     Node& child = **iter;
192     cumulativeDirtyFlags |= UpdateNodes(child,
193                                         nodeDirtyFlags,
194                                         updateBufferIndex,
195                                         renderQueue,
196                                         postPropertyOwners,
197                                         updated);
198   }
199
200   return cumulativeDirtyFlags;
201 }
202
203 inline void UpdateLayers(Node&             node,
204                          NodePropertyFlags parentFlags,
205                          BufferIndex       updateBufferIndex,
206                          Layer&            currentLayer)
207 {
208   // Some dirty flags are inherited from parent
209   NodePropertyFlags nodeDirtyFlags = node.GetDirtyFlags() | node.GetInheritedDirtyFlags(parentFlags);
210   nodeDirtyFlags |= (node.IsLocalMatrixDirty() ? NodePropertyFlags::TRANSFORM : NodePropertyFlags::NOTHING);
211
212   Layer* nodeIsLayer(node.GetLayer());
213   Layer* layer = nodeIsLayer ? nodeIsLayer : &currentLayer;
214   if(nodeIsLayer)
215   {
216     layer->SetReuseRenderers(updateBufferIndex, true);
217   }
218   DALI_ASSERT_DEBUG(nullptr != layer);
219
220   // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused
221   // also if node has been deleted, dont reuse old render items
222   if(layer->GetReuseRenderers(updateBufferIndex))
223   {
224     if(nodeDirtyFlags != NodePropertyFlags::NOTHING)
225     {
226       layer->SetReuseRenderers(updateBufferIndex, false);
227     }
228     else
229     {
230       // If the node is not dirty, then check renderers
231       const uint32_t count = node.GetRendererCount();
232       for(uint32_t i = 0; i < count; ++i)
233       {
234         SceneGraph::RendererKey renderer = node.GetRendererAt(i);
235         if(renderer->IsDirty())
236         {
237           layer->SetReuseRenderers(updateBufferIndex, false);
238           break;
239         }
240       }
241     }
242   }
243
244   // recurse children
245   NodeContainer& children = node.GetChildren();
246   const NodeIter endIter  = children.End();
247   for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
248   {
249     Node& child = **iter;
250     UpdateLayers(child, nodeDirtyFlags, updateBufferIndex, *layer);
251   }
252 }
253
254 void UpdateLayerTree(Layer&      layer,
255                      BufferIndex updateBufferIndex)
256 {
257   NodePropertyFlags nodeDirtyFlags = layer.GetDirtyFlags();
258   nodeDirtyFlags |= (layer.IsLocalMatrixDirty() ? NodePropertyFlags::TRANSFORM : NodePropertyFlags::NOTHING);
259
260   layer.SetReuseRenderers(updateBufferIndex, nodeDirtyFlags == NodePropertyFlags::NOTHING);
261
262   // recurse children
263   NodeContainer& children = layer.GetChildren();
264   const NodeIter endIter  = children.End();
265   for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
266   {
267     Node& child = **iter;
268     UpdateLayers(child, nodeDirtyFlags, updateBufferIndex, layer);
269   }
270 }
271
272 } // namespace SceneGraph
273
274 } // namespace Internal
275
276 } // namespace Dali