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