[3.0] Combine StencilMode and WriteToColorBuffer to RenderMode
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / process-render-tasks.cpp
1 /*
2  * Copyright (c) 2016 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/process-render-tasks.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/update/manager/prepare-render-instructions.h>
23 #include <dali/internal/update/manager/sorted-layers.h>
24 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
25 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
26 #include <dali/internal/update/nodes/scene-graph-layer.h>
27 #include <dali/internal/render/common/render-item.h>
28 #include <dali/internal/render/common/render-tracker.h>
29 #include <dali/internal/render/common/render-instruction.h>
30 #include <dali/internal/render/common/render-instruction-container.h>
31 #include <dali/internal/render/renderers/render-renderer.h>
32 #include <dali/integration-api/debug.h>
33
34 #if defined(DEBUG_ENABLED)
35 extern Debug::Filter* gRenderTaskLogFilter;
36 #endif
37
38 namespace Dali
39 {
40
41 namespace Internal
42 {
43
44
45 namespace SceneGraph
46 {
47
48 namespace //Unnamed namespace
49 {
50
51 // Return false if the node or it's parents are exclusive to another render-task
52 bool CheckExclusivity( const Node& node, const RenderTask& task )
53 {
54   const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
55   if ( exclusiveTo )
56   {
57     if ( exclusiveTo == &task )
58     {
59       // Exclusive to the same render-task
60       return true;
61     }
62     else
63     {
64       // Exclusive to another render-task
65       return false;
66     }
67   }
68
69   const Node* parent = node.GetParent();
70   if ( parent )
71   {
72     return CheckExclusivity( *parent, task );
73   }
74
75   // No exclusive flags set
76   return true;
77 }
78
79 Layer* FindLayer( Node& node )
80 {
81   Node* currentNode( &node );
82   Layer* layer(NULL);
83   while( currentNode )
84   {
85     if( (layer = currentNode->GetLayer()) != NULL )
86     {
87       return layer;
88     }
89
90     currentNode = currentNode->GetParent();
91   }
92
93   return NULL;
94 }
95
96 /**
97  * Rebuild the Layer::colorRenderables, stencilRenderables and overlayRenderables members,
98  * including only renderers which are included in the current render-task.
99  * Returns true if all renderers have finished acquiring resources.
100  */
101 bool AddRenderablesForTask( BufferIndex updateBufferIndex,
102                             Node& node,
103                             Layer& currentLayer,
104                             RenderTask& renderTask,
105                             int inheritedDrawMode )
106 {
107   bool resourcesFinished = true;
108
109   // Short-circuit for invisible nodes
110   if ( !node.IsVisible( updateBufferIndex ) )
111   {
112     return resourcesFinished;
113   }
114
115   // Check whether node is exclusive to a different render-task
116   const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
117   if ( exclusiveTo &&
118       exclusiveTo != &renderTask )
119   {
120     return resourcesFinished;
121   }
122
123   Layer* layer = &currentLayer;
124   Layer* nodeIsLayer( node.GetLayer() );
125   if ( nodeIsLayer )
126   {
127     // All children go to this layer
128     layer = nodeIsLayer;
129
130     // Layers do not inherit the DrawMode from their parents
131     inheritedDrawMode = DrawMode::NORMAL;
132   }
133   DALI_ASSERT_DEBUG( NULL != layer );
134
135   inheritedDrawMode |= node.GetDrawMode();
136
137   const unsigned int count = node.GetRendererCount();
138   for( unsigned int i = 0; i < count; ++i )
139   {
140     SceneGraph::Renderer* renderer = node.GetRendererAt( i );
141     bool ready = false;
142     bool complete = false;
143     renderer->GetReadyAndComplete( ready, complete );
144
145     DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Testing renderable:%p ready:%s complete:%s\n", renderer, ready?"T":"F", complete?"T":"F");
146
147     resourcesFinished &= complete;
148
149     if( ready ) // i.e. should be rendered (all resources are available)
150     {
151       if( DrawMode::STENCIL == inheritedDrawMode )
152       {
153         layer->stencilRenderables.PushBack( Renderable(&node, renderer ) );
154       }
155       else if( DrawMode::OVERLAY_2D == inheritedDrawMode )
156       {
157         layer->overlayRenderables.PushBack( Renderable(&node, renderer ) );
158       }
159       else
160       {
161         layer->colorRenderables.PushBack( Renderable(&node, renderer ) );
162       }
163     }
164   }
165
166
167
168   // Recurse children
169   NodeContainer& children = node.GetChildren();
170   const NodeIter endIter = children.End();
171   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
172   {
173     Node& child = **iter;
174     bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode );
175     resourcesFinished &= childResourcesComplete;
176   }
177
178   return resourcesFinished;
179 }
180 } //Unnamed namespace
181
182 void ProcessRenderTasks( BufferIndex updateBufferIndex,
183                          RenderTaskList& renderTasks,
184                          Layer& rootNode,
185                          SortedLayerPointers& sortedLayers,
186                          RendererSortingHelper& sortingHelper,
187                          RenderInstructionContainer& instructions )
188 {
189   RenderTaskList::RenderTaskContainer& taskContainer = renderTasks.GetTasks();
190
191   if ( taskContainer.IsEmpty() )
192   {
193     // Early-exit if there are no tasks to process
194     return;
195   }
196
197   // For each render-task:
198   //   1) Prepare the render-task
199   //   2) Clear the layer-stored lists of renderers (TODO check if the layer is not changed and don't clear in this case)
200   //   3) Traverse the scene-graph, filling the lists for the current render-task
201   //   4) Prepare render-instructions
202
203   DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Offscreens first\n");
204
205   // First process off screen render tasks - we may need the results of these for the on screen renders
206   RenderTaskList::RenderTaskContainer::ConstIterator endIter = taskContainer.End();
207   for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
208   {
209     RenderTask& renderTask = **iter;
210
211     // off screen only
212     if(0 == renderTask.GetFrameBufferId() && renderTask.GetFrameBuffer() == 0 )
213     {
214       // Skip to next task
215       continue;
216     }
217
218     if ( !renderTask.ReadyToRender( updateBufferIndex ) )
219     {
220       // Skip to next task
221       continue;
222     }
223
224     Node* sourceNode = renderTask.GetSourceNode();
225     DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
226
227     // Check that the source node is not exclusive to another task
228     if ( ! CheckExclusivity( *sourceNode, renderTask ) )
229     {
230       continue;
231     }
232
233     Layer* layer = FindLayer( *sourceNode );
234     if( !layer )
235     {
236       // Skip to next task as no layer
237       continue;
238     }
239
240     bool resourcesFinished = false;
241     if( renderTask.IsRenderRequired() )
242     {
243       size_t layerCount( sortedLayers.size() );
244       for( size_t i(0); i<layerCount; ++i )
245       {
246         sortedLayers[i]->ClearRenderables();
247       }
248
249       resourcesFinished = AddRenderablesForTask( updateBufferIndex,
250                                                  *sourceNode,
251                                                  *layer,
252                                                  renderTask,
253                                                  sourceNode->GetDrawMode() );
254
255       renderTask.SetResourcesFinished( resourcesFinished );
256       PrepareRenderInstruction( updateBufferIndex,
257                                 sortedLayers,
258                                 renderTask,
259                                 sortingHelper,
260                                 renderTask.GetCullMode(),
261                                 instructions );
262     }
263     else
264     {
265       renderTask.SetResourcesFinished( resourcesFinished );
266     }
267   }
268
269   DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Onscreen\n");
270
271   // Now that the off screen renders are done we can process on screen render tasks
272   for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
273   {
274     RenderTask& renderTask = **iter;
275
276     // on screen only
277     if(0 != renderTask.GetFrameBufferId() || renderTask.GetFrameBuffer() != 0 )
278     {
279       // Skip to next task
280       continue;
281     }
282     if ( !renderTask.ReadyToRender( updateBufferIndex ) )
283     {
284       // Skip to next task
285       continue;
286     }
287
288     Node* sourceNode = renderTask.GetSourceNode();
289     DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
290
291     // Check that the source node is not exclusive to another task
292     if ( ! CheckExclusivity( *sourceNode, renderTask ) )
293     {
294       continue;
295     }
296
297     Layer* layer = FindLayer( *sourceNode );
298     if( !layer )
299     {
300       // Skip to next task as no layer
301       continue;
302     }
303
304     bool resourcesFinished = false;
305     if( renderTask.IsRenderRequired() )
306     {
307       size_t layerCount( sortedLayers.size() );
308       for( size_t i(0); i<layerCount; ++i )
309       {
310         sortedLayers[i]->ClearRenderables();
311       }
312
313       resourcesFinished = AddRenderablesForTask( updateBufferIndex,
314                                                  *sourceNode,
315                                                  *layer,
316                                                  renderTask,
317                                                  sourceNode->GetDrawMode() );
318
319       PrepareRenderInstruction( updateBufferIndex,
320                                 sortedLayers,
321                                 renderTask,
322                                 sortingHelper,
323                                 renderTask.GetCullMode(),
324                                 instructions );
325     }
326
327     renderTask.SetResourcesFinished( resourcesFinished );
328   }
329 }
330
331
332 } // SceneGraph
333
334 } // Internal
335
336 } // Dali