Memory pool key uses ptr in 32bit mode
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / render-task-processor.cpp
1 /*
2  * Copyright (c) 2022 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/render-task-processor.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/internal/render/common/render-instruction-container.h>
24 #include <dali/internal/render/common/render-instruction.h>
25 #include <dali/internal/render/common/render-item.h>
26 #include <dali/internal/render/common/render-tracker.h>
27 #include <dali/internal/render/renderers/render-renderer.h>
28 #include <dali/internal/update/manager/sorted-layers.h>
29 #include <dali/internal/update/nodes/scene-graph-layer.h>
30 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
31 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
32
33 #if defined(DEBUG_ENABLED)
34 extern Debug::Filter* gRenderTaskLogFilter;
35 #endif
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace SceneGraph
42 {
43 namespace // Unnamed namespace
44 {
45 // Return false if the node or it's parents are exclusive to another render-task.
46 bool CheckExclusivity(const Node& node, const RenderTask& task)
47 {
48   const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
49   if(exclusiveTo)
50   {
51     return (exclusiveTo == &task);
52   }
53
54   const Node* parent = node.GetParent();
55   if(parent)
56   {
57     return CheckExclusivity(*parent, task);
58   }
59
60   // No exclusive flags set.
61   return true;
62 }
63
64 Layer* FindLayer(Node& node)
65 {
66   Node*  currentNode(&node);
67   Layer* layer(nullptr);
68   while(currentNode)
69   {
70     if((layer = currentNode->GetLayer()) != nullptr)
71     {
72       return layer;
73     }
74
75     currentNode = currentNode->GetParent();
76   }
77
78   return nullptr;
79 }
80
81 /**
82  * Rebuild the Layer::colorRenderables and overlayRenderables members,
83  * including only renderers which are included in the current render-task.
84  *
85  * @param[in]  updateBufferIndex The current update buffer index.
86  * @param[in]  node The current node of the scene-graph.
87  * @param[in]  currentLayer The current layer containing lists of opaque/transparent renderables.
88  * @param[in]  renderTask The current render-task.
89  * @param[in]  inheritedDrawMode The draw mode of the parent
90  * @param[in]  parentDepthIndex The inherited parent node depth index
91  * @param[in]  currentClippingId The current Clipping Id
92  *               Note: ClippingId is passed by reference, so it is permanently modified when traversing back up the tree for uniqueness.
93  * @param[in]  clippingDepth The current stencil clipping depth
94  * @param[in]  clippingDepth The current scissor clipping depth
95  * @param[out] clippingUsed  Gets set to true if any clipping nodes have been found
96  * @return true if rendering should be kept, false otherwise.
97  */
98 bool AddRenderablesForTask(BufferIndex updateBufferIndex,
99                            Node&       node,
100                            Layer&      currentLayer,
101                            RenderTask& renderTask,
102                            int         inheritedDrawMode,
103                            uint32_t&   currentClippingId,
104                            uint32_t    clippingDepth,
105                            uint32_t    scissorDepth,
106                            bool&       clippingUsed)
107 {
108   bool keepRendering = false;
109
110   // Short-circuit for invisible nodes
111   if(!node.IsVisible(updateBufferIndex))
112   {
113     node.GetPartialRenderingData().mVisible = false;
114     return keepRendering;
115   }
116
117   // If the node was not previously visible
118   if(!node.GetPartialRenderingData().mVisible)
119   {
120     node.GetPartialRenderingData().mVisible = true;
121     node.SetUpdatedTree(true);
122   }
123
124   // Check whether node is exclusive to a different render-task
125   const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
126   if(exclusiveTo && (exclusiveTo != &renderTask))
127   {
128     return keepRendering;
129   }
130
131   // Assume all children go to this layer (if this node is a layer).
132   Layer* layer = node.GetLayer();
133   if(layer)
134   {
135     // Layers do not inherit the DrawMode from their parents
136     inheritedDrawMode = node.GetDrawMode();
137   }
138   else
139   {
140     // This node is not a layer.
141     layer = &currentLayer;
142     inheritedDrawMode |= node.GetDrawMode();
143   }
144
145   DALI_ASSERT_DEBUG(NULL != layer);
146
147   const uint32_t count = node.GetRendererCount();
148
149   // Update the clipping Id and depth for this node (if clipping is enabled).
150   const Dali::ClippingMode::Type clippingMode = node.GetClippingMode();
151   if(DALI_UNLIKELY(clippingMode != ClippingMode::DISABLED))
152   {
153     if(DALI_LIKELY(clippingMode == ClippingMode::CLIP_TO_BOUNDING_BOX))
154     {
155       ++scissorDepth; // This only modifies the local value (which is passed in when the method recurses).
156       // If we do not have any renderers, create one to house the scissor operation.
157       if(count == 0u)
158       {
159         layer->colorRenderables.PushBack(Renderable(&node, RendererKey{}));
160       }
161     }
162     else
163     {
164       // We only need clipping Id for stencil clips. This means we can deliberately avoid modifying it for bounding box clips,
165       // thus allowing bounding box clipping to still detect clip depth changes without turning on the stencil buffer for non-clipped nodes.
166       ++currentClippingId; // This modifies the reference passed in as well as the local value, causing the value to be global to the recursion.
167       ++clippingDepth;     // This only modifies the local value (which is passed in when the method recurses).
168     }
169     clippingUsed = true;
170   }
171   // Set the information in the node.
172   node.SetClippingInformation(currentClippingId, clippingDepth, scissorDepth);
173
174   RenderableContainer& target = DALI_LIKELY(inheritedDrawMode == DrawMode::NORMAL) ? layer->colorRenderables : layer->overlayRenderables;
175   for(uint32_t i = 0; i < count; ++i)
176   {
177     SceneGraph::RendererKey rendererKey = node.GetRendererAt(i);
178
179     target.PushBack(Renderable(&node, rendererKey));
180     keepRendering = keepRendering || (rendererKey->GetRenderingBehavior() == DevelRenderer::Rendering::CONTINUOUSLY);
181   }
182
183   // Recurse children.
184   NodeContainer& children = node.GetChildren();
185   const NodeIter endIter  = children.End();
186   for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
187   {
188     Node& child = **iter;
189     keepRendering |= AddRenderablesForTask(updateBufferIndex, child, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed);
190   }
191
192   return keepRendering;
193 }
194
195 /**
196  * Process the list of render-tasks; the output is a series of render instructions.
197  * @note When ProcessRenderTasks is called, the layers should already the transparent/opaque renderers which are ready to render.
198  * If there is only one default render-task, then no further processing is required.
199  * @param[in]  updateBufferIndex          The current update buffer index.
200  * @param[in]  taskContainer              The container of render-tasks.
201  * @param[in]  rootNode                   The root node of the scene-graph.
202  * @param[in]  sortedLayers               The layers containing lists of opaque / transparent renderables.
203  * @param[out] instructions               The instructions for rendering the next frame.
204  * @param[in]  renderInstructionProcessor An instance of the RenderInstructionProcessor used to sort and handle the renderers for each layer.
205  * @param[in]  renderToFboEnabled         Whether rendering into the Frame Buffer Object is enabled (used to measure FPS above 60)
206  * @param[in]  isRenderingToFbo           Whether this frame is being rendered into the Frame Buffer Object (used to measure FPS above 60)
207  * @param[in]  processOffscreen           Whether the offscreen render tasks are the ones processed. Otherwise it processes the onscreen tasks.
208  * @return true if rendering should be kept, false otherwise.
209  */
210 bool ProcessTasks(BufferIndex                          updateBufferIndex,
211                   RenderTaskList::RenderTaskContainer& taskContainer,
212                   Layer&                               rootNode,
213                   SortedLayerPointers&                 sortedLayers,
214                   RenderInstructionContainer&          instructions,
215                   RenderInstructionProcessor&          renderInstructionProcessor,
216                   bool                                 renderToFboEnabled,
217                   bool                                 isRenderingToFbo,
218                   bool                                 processOffscreen)
219 {
220   uint32_t clippingId       = 0u;
221   bool     hasClippingNodes = false;
222
223   bool isFirstRenderTask = true;
224   bool keepRendering     = false;
225
226   // Retrieve size of Scene and default camera position to update viewport of each RenderTask if the RenderTask uses ViewportGuideNode.
227   RenderTaskList::RenderTaskContainer::Iterator iter                  = taskContainer.Begin();
228   RenderTask&                                   defaultRenderTask     = **iter;
229   const Camera&                                 defaultCamera         = defaultRenderTask.GetCamera();
230   auto                                          defaultRootNode       = defaultRenderTask.GetSourceNode();
231   Vector3                                       defaultCameraPosition = Vector3::ZERO;
232   Vector2                                       sceneSize             = Vector2::ZERO;
233   if(defaultRootNode)
234   {
235     defaultCameraPosition = defaultCamera.GetWorldPosition(updateBufferIndex);
236     sceneSize             = Vector2(defaultRootNode->GetSize(updateBufferIndex) * defaultRootNode->GetWorldScale(updateBufferIndex));
237   }
238
239   for(RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(), endIter = taskContainer.End(); endIter != iter; ++iter)
240   {
241     RenderTask& renderTask = **iter;
242
243     const bool hasFrameBuffer      = nullptr != renderTask.GetFrameBuffer();
244     const bool isDefaultRenderTask = isFirstRenderTask;
245     isFirstRenderTask              = false;
246
247     if((!renderToFboEnabled && ((!processOffscreen && hasFrameBuffer) ||
248                                 (processOffscreen && !hasFrameBuffer))) ||
249        (renderToFboEnabled && ((processOffscreen && !hasFrameBuffer) ||
250                                (isDefaultRenderTask && processOffscreen) ||
251                                (!isDefaultRenderTask && !processOffscreen && hasFrameBuffer))) ||
252        !renderTask.ReadyToRender(updateBufferIndex))
253     {
254       // Skip to next task.
255       continue;
256     }
257
258     Node* sourceNode = renderTask.GetSourceNode();
259     DALI_ASSERT_DEBUG(NULL != sourceNode); // Otherwise Prepare() should return false
260
261     // Check that the source node is not exclusive to another task.
262     if(!CheckExclusivity(*sourceNode, renderTask))
263     {
264       continue;
265     }
266
267     Layer* layer = FindLayer(*sourceNode);
268     if(!layer)
269     {
270       // Skip to next task as no layer.
271       continue;
272     }
273
274     renderTask.UpdateViewport(updateBufferIndex, sceneSize, defaultCameraPosition);
275
276     const uint32_t currentNumberOfInstructions = instructions.Count(updateBufferIndex);
277
278     if(renderTask.IsRenderRequired())
279     {
280       for(auto&& sortedLayer : sortedLayers)
281       {
282         sortedLayer->ClearRenderables();
283       }
284
285       keepRendering |= AddRenderablesForTask(updateBufferIndex,
286                                              *sourceNode,
287                                              *layer,
288                                              renderTask,
289                                              sourceNode->GetDrawMode(),
290                                              clippingId,
291                                              0u,
292                                              0u,
293                                              hasClippingNodes);
294
295       renderInstructionProcessor.Prepare(updateBufferIndex,
296                                          sortedLayers,
297                                          renderTask,
298                                          renderTask.GetCullMode(),
299                                          hasClippingNodes,
300                                          instructions);
301     }
302
303     if(!processOffscreen && isDefaultRenderTask && renderToFboEnabled && !isRenderingToFbo && hasFrameBuffer)
304     {
305       // Traverse the instructions of the default render task and mark them to be rendered into the frame buffer.
306       const uint32_t count = instructions.Count(updateBufferIndex);
307       for(uint32_t index = currentNumberOfInstructions; index < count; ++index)
308       {
309         RenderInstruction& instruction = instructions.At(updateBufferIndex, index);
310         instruction.mIgnoreRenderToFbo = true;
311       }
312     }
313   }
314
315   return keepRendering;
316 }
317
318 } // Anonymous namespace.
319
320 RenderTaskProcessor::RenderTaskProcessor() = default;
321
322 RenderTaskProcessor::~RenderTaskProcessor() = default;
323
324 bool RenderTaskProcessor::Process(BufferIndex                 updateBufferIndex,
325                                   RenderTaskList&             renderTasks,
326                                   Layer&                      rootNode,
327                                   SortedLayerPointers&        sortedLayers,
328                                   RenderInstructionContainer& instructions,
329                                   bool                        renderToFboEnabled,
330                                   bool                        isRenderingToFbo)
331 {
332   RenderTaskList::RenderTaskContainer& taskContainer = renderTasks.GetTasks();
333   bool                                 keepRendering = false;
334
335   if(taskContainer.IsEmpty())
336   {
337     // Early-exit if there are no tasks to process
338     return keepRendering;
339   }
340
341   // For each render-task:
342   //   1) Prepare the render-task
343   //   2) Clear the layer-stored lists of renderers (TODO check if the layer is not changed and don't clear in this case)
344   //   3) Traverse the scene-graph, filling the lists for the current render-task
345   //   4) Prepare render-instructions
346
347   DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Offscreens first\n");
348
349   // First process off screen render tasks - we may need the results of these for the on screen renders
350
351   keepRendering = ProcessTasks(updateBufferIndex,
352                                taskContainer,
353                                rootNode,
354                                sortedLayers,
355                                instructions,
356                                mRenderInstructionProcessor,
357                                renderToFboEnabled,
358                                isRenderingToFbo,
359                                true);
360
361   DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Onscreen\n");
362
363   // Now that the off screen renders are done we can process on screen render tasks.
364   // Reset the clipping Id for the OnScreen render tasks.
365
366   keepRendering |= ProcessTasks(updateBufferIndex,
367                                 taskContainer,
368                                 rootNode,
369                                 sortedLayers,
370                                 instructions,
371                                 mRenderInstructionProcessor,
372                                 renderToFboEnabled,
373                                 isRenderingToFbo,
374                                 false);
375
376   return keepRendering;
377 }
378
379 } // namespace SceneGraph
380
381 } // namespace Internal
382
383 } // namespace Dali