b04a108362d54d9fcfc6599c6ac713f24a43e079
[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   // Recurse children
167   NodeContainer& children = node.GetChildren();
168   const NodeIter endIter = children.End();
169   for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
170   {
171     Node& child = **iter;
172     bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode );
173     resourcesFinished &= childResourcesComplete;
174   }
175
176   return resourcesFinished;
177 }
178 } //Unnamed namespace
179
180 void ProcessRenderTasks( BufferIndex updateBufferIndex,
181                          RenderTaskList& renderTasks,
182                          Layer& rootNode,
183                          SortedLayerPointers& sortedLayers,
184                          RendererSortingHelper& sortingHelper,
185                          GeometryBatcher& geometryBatcher,
186                          RenderInstructionContainer& instructions )
187 {
188   RenderTaskList::RenderTaskContainer& taskContainer = renderTasks.GetTasks();
189
190   if ( taskContainer.IsEmpty() )
191   {
192     // Early-exit if there are no tasks to process
193     return;
194   }
195
196   // For each render-task:
197   //   1) Prepare the render-task
198   //   2) Clear the layer-stored lists of renderers (TODO check if the layer is not changed and don't clear in this case)
199   //   3) Traverse the scene-graph, filling the lists for the current render-task
200   //   4) Prepare render-instructions
201
202   DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Offscreens first\n");
203
204   // First process off screen render tasks - we may need the results of these for the on screen renders
205   RenderTaskList::RenderTaskContainer::ConstIterator endIter = taskContainer.End();
206   for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
207   {
208     RenderTask& renderTask = **iter;
209
210     // off screen only
211     if(0 == renderTask.GetFrameBufferId() && renderTask.GetFrameBuffer() == 0 )
212     {
213       // Skip to next task
214       continue;
215     }
216
217     if ( !renderTask.ReadyToRender( updateBufferIndex ) )
218     {
219       // Skip to next task
220       continue;
221     }
222
223     Node* sourceNode = renderTask.GetSourceNode();
224     DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
225
226     // Check that the source node is not exclusive to another task
227     if ( ! CheckExclusivity( *sourceNode, renderTask ) )
228     {
229       continue;
230     }
231
232     Layer* layer = FindLayer( *sourceNode );
233     if( !layer )
234     {
235       // Skip to next task as no layer
236       continue;
237     }
238
239     bool resourcesFinished = false;
240     if( renderTask.IsRenderRequired() )
241     {
242       size_t layerCount( sortedLayers.size() );
243       for( size_t i(0); i<layerCount; ++i )
244       {
245         sortedLayers[i]->ClearRenderables();
246       }
247
248       resourcesFinished = AddRenderablesForTask( updateBufferIndex,
249                                                  *sourceNode,
250                                                  *layer,
251                                                  renderTask,
252                                                  sourceNode->GetDrawMode() );
253
254       renderTask.SetResourcesFinished( resourcesFinished );
255       PrepareRenderInstruction( updateBufferIndex,
256                                 sortedLayers,
257                                 renderTask,
258                                 sortingHelper,
259                                 renderTask.GetCullMode(),
260                                 instructions,
261                                 geometryBatcher );
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                                 geometryBatcher );
326     }
327
328     renderTask.SetResourcesFinished( resourcesFinished );
329   }
330 }
331
332
333 } // SceneGraph
334
335 } // Internal
336
337 } // Dali