27c074cacb86b9dce710a76c27a8c95419bed391
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / prepare-render-instructions.cpp
1 /*
2  * Copyright (c) 2015 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/prepare-render-instructions.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
24 #include <dali/internal/update/resources/resource-manager-declarations.h>
25 #include <dali/internal/update/manager/sorted-layers.h>
26 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
27 #include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
28 #include <dali/internal/update/nodes/scene-graph-layer.h>
29 #include <dali/internal/render/common/render-item.h>
30 #include <dali/internal/render/common/render-tracker.h>
31 #include <dali/internal/render/common/render-instruction.h>
32 #include <dali/internal/render/common/render-instruction-container.h>
33 #include <dali/internal/render/renderers/scene-graph-renderer.h>
34
35 namespace
36 {
37 #if defined(DEBUG_ENABLED)
38 Debug::Filter* gRenderListLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_LISTS");
39 #endif
40 }
41
42 namespace Dali
43 {
44
45 namespace Internal
46 {
47
48 namespace SceneGraph
49 {
50
51 /**
52  * Set flags for opaque renderlist
53  * @param renderList to set the flags to
54  * @param transparentRenderersExist is true if there is transparent renderers in this layer
55  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
56  * @param depthTestDisabled whether depth test is disabled.
57  */
58 inline void SetOpaqueRenderFlags( RenderList& renderList, bool transparentRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
59 {
60   //@todo MESH_REWORK Move RequiresDepthTest from render thread object to update thread object
61
62   renderList.SetInterleave(transparentRenderersExist);
63
64   // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
65   // and this renderer does not need depth test against itself (e.g. mesh)
66   // and if this layer has got exactly one opaque renderer
67   // and this renderer is not interested in depth testing
68   // (i.e. is an image and not a mesh)
69   if ( (  renderList.Count() == 1 ) &&
70        (  !transparentRenderersExist ) &&
71        (  !renderList.GetRenderer( 0 )->RequiresDepthTest() ) )
72   {
73     // no need to enable depth test or clear depth buffer
74     // if there's something transparent already rendered by previous layers,
75     // this opaque renderer will correctly draw on top of them since no depth test
76     renderList.ClearFlags();
77     renderList.SetInterleave(false);
78   }
79   else if( depthTestDisabled )
80   {
81     renderList.ClearFlags();
82   }
83   else
84   {
85     // Prepare for rendering multiple opaque objects
86     unsigned int flags = RenderList::DEPTH_BUFFER_ENABLED | RenderList::DEPTH_WRITE | RenderList::DEPTH_CLEAR; // clear depth buffer, draw over the previously rendered layers;
87
88     renderList.ClearFlags();
89     renderList.SetFlags(flags);
90   }
91
92   if( stencilRenderablesExist )
93   {
94     renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
95   }
96 }
97
98 /**
99  * Set the transparent flags on the renderlist
100  * @param renderList to set the flags on
101  * @param opaqueRenderersExist is true if there are opaque renderers on this layer
102  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
103  * @param depthTestDisabled whether depth test is disabled.
104  */
105 inline void SetTransparentRenderFlags( RenderList& renderList, bool opaqueRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
106 {
107   renderList.ClearFlags();
108   // We don't need to write to the depth buffer, as transparent objects
109   // don't obscure each other.
110
111   renderList.SetInterleave(opaqueRenderersExist);
112   if ( opaqueRenderersExist && !depthTestDisabled )
113   {
114     // If there are a mix of opaque and transparent objects, the transparent
115     // objects should be rendered with depth test on to avoid background objects
116     // appearing in front of opaque foreground objects.
117     renderList.SetFlags( RenderList::DEPTH_BUFFER_ENABLED );
118   }
119
120   if( stencilRenderablesExist )
121   {
122     renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
123   }
124 }
125
126
127 /**
128  * Set flags for overlay renderlist
129  * @param renderList to set the flags for
130  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
131  */
132 inline void SetOverlayRenderFlags( RenderList& renderList, bool stencilRenderablesExist )
133 {
134   if(stencilRenderablesExist)
135   {
136     renderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
137   }
138 }
139
140 /**
141  * Set flags for stencil renderlist
142  * @param renderList to set the flags for
143  */
144 inline void SetStencilRenderFlags( RenderList& renderList )
145 {
146   renderList.ClearFlags();
147   renderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
148 }
149
150 /**
151  * Add a renderer to the list
152  * @param updateBufferIndex to read the model matrix from
153  * @param renderList to add the item to
154  * @param renderable attachment
155  * @param viewMatrix used to calculate modelview matrix for the item
156  */
157 inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
158                                      RenderList& renderList,
159                                      RenderableAttachment& renderable,
160                                      const Matrix& viewMatrix )
161 {
162   const Renderer& renderer = renderable.GetRenderer();
163
164   // Get the next free RenderItem
165   RenderItem& item = renderList.GetNextFreeItem();
166   item.SetRenderer( const_cast< Renderer* >( &renderer ) );
167   item.SetDepthIndex( renderable.GetDepthIndex(updateBufferIndex) );
168
169   // calculate MV matrix onto the item
170   Matrix& modelViewMatrix = item.GetModelViewMatrix();
171   const Matrix& worldMatrix = renderable.GetParent().GetWorldMatrix( updateBufferIndex );
172
173   Matrix::Multiply( modelViewMatrix, worldMatrix, viewMatrix );
174 }
175
176 /**
177  * Add all renderers to the list
178  * @param updateBufferIndex to read the model matrix from
179  * @param renderList to add the items to
180  * @param renderable attachments
181  * @param viewMatrix used to calculate modelview matrix for the items
182  */
183 inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
184                                       RenderList& renderList,
185                                       RenderableAttachmentContainer& attachments,
186                                       const Matrix& viewMatrix )
187 {
188   DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
189
190   // Add renderer for each attachment
191   int index=0;
192   const RenderableAttachmentIter endIter = attachments.end();
193   for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
194   {
195     RenderableAttachment& attachment = **iter;
196     AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix );
197
198     DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  List[%d].renderer = %p\n", index, &(attachment.GetRenderer()));
199     index++;
200   }
201 }
202
203 /**
204  * Try to reuse cached renderitems from the renderlist
205  * This avoids recalculating the model view matrices in case this part of the scene was static
206  * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
207  * @param layer that is being processed
208  * @param renderList that is cached from frame N-1
209  * @param attachmentList that is being used
210  */
211 inline bool TryReuseCachedRenderers( Layer& layer,
212                                      RenderList& renderList,
213                                      RenderableAttachmentContainer& attachmentList )
214 {
215   bool retValue = false;
216   size_t renderableCount = attachmentList.size();
217   // check that the cached list originates from this layer and that the counts match
218   if( ( renderList.GetSourceLayer() == &layer )&&
219       ( renderList.GetCachedItemCount() == renderableCount ) )
220   {
221     // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
222     // Attachments are not sorted, but render list is so at this stage renderers may be in different order
223     // therefore we check a combined sum of all renderer addresses
224     size_t checkSumNew = 0;
225     size_t checkSumOld = 0;
226     for( size_t index = 0; index < renderableCount; ++index )
227     {
228       RenderableAttachment* attachment = attachmentList[ index ];
229       const Renderer& renderer = attachment->GetRenderer();
230       checkSumNew += size_t( &renderer );
231       checkSumOld += size_t( renderList.GetRenderer( index ) );
232     }
233     if( checkSumNew == checkSumOld )
234     {
235       // tell list to reuse its existing items
236       renderList.ReuseCachedItems();
237       retValue = true;
238     }
239   }
240   return retValue;
241 }
242
243
244 /**
245  * Function which sorts render items by depth index then by instance
246  * ptrs of shader/geometry/material.
247  * @param lhs item
248  * @param rhs item
249  * @return true if left item is greater than right
250  */
251 bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
252 {
253   // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
254   // encapsulates the same data (e.g. the middle-order bits of the ptrs)
255   if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
256   {
257     if( lhs.shader == rhs.shader )
258     {
259       if( lhs.material == rhs.material )
260       {
261         return lhs.geometry < lhs.geometry;
262       }
263       return lhs.material < rhs.material;
264     }
265     return lhs.shader < rhs.shader;;
266   }
267   return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
268 }
269 /**
270  * Function which sorts the render items by depth index then by Z function,
271  * then by instance ptrs of shader/geometry/material.
272  * @param lhs item
273  * @param rhs item
274  * @return true if left item is greater than right
275  */
276 bool CompareItemsWithZValue( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
277 {
278   // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
279   // encapsulates the same data (e.g. the middle-order bits of the ptrs)
280
281   if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
282   {
283     if( Equals(lhs.zValue, rhs.zValue) )
284     {
285       if( lhs.shader == rhs.shader )
286       {
287         if( lhs.material == rhs.material )
288         {
289           return lhs.geometry < lhs.geometry;
290         }
291         return lhs.material < rhs.material;
292       }
293       return lhs.shader < rhs.shader;;
294     }
295     return lhs.zValue > rhs.zValue;
296   }
297   return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
298 }
299
300 inline void SortOpaqueRenderItems(
301   BufferIndex bufferIndex,
302   RenderList& opaqueRenderList,
303   Layer& layer,
304   RenderItemSortingHelper& sortingHelper )
305 {
306   const size_t renderableCount = opaqueRenderList.Count();
307   // reserve space if needed
308   const unsigned int oldcapacity = sortingHelper.size();
309   if( oldcapacity < renderableCount )
310   {
311     sortingHelper.reserve( renderableCount );
312     // add real objects (reserve does not construct objects)
313     sortingHelper.insert( sortingHelper.begin() + oldcapacity,
314                           (renderableCount - oldcapacity),
315                           RendererWithSortAttributes() );
316   }
317   else
318   {
319     // clear extra elements from helper, does not decrease capability
320     sortingHelper.resize( renderableCount );
321   }
322
323   for( size_t index = 0; index < renderableCount; ++index )
324   {
325     RenderItem& item = opaqueRenderList.GetItem( index );
326
327     //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
328     layer.opaqueRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
329
330     sortingHelper[ index ].zValue = 0;
331     sortingHelper[ index ].renderItem = &item;
332   }
333
334   // Sort the renderers by depth index, then by instance
335   std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
336
337   DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Opaque List:\n");
338
339   // Repopulate the render items in the render list based on the sorting helper
340   RenderItemContainer::Iterator renderListIter = opaqueRenderList.GetContainer().Begin();
341   for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
342   {
343     *renderListIter = sortingHelper[ index ].renderItem;
344     DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", sortingHelper[ index ].renderItem->GetRenderer() );
345   }
346 }
347
348 /**
349  * Add opaque renderers from the layer onto the next free render list
350  * @param updateBufferIndex to use
351  * @param layer to get the renderers from
352  * @param viewmatrix for the camera from rendertask
353  * @param transparentRenderersExist is true if there is transparent renderers in this layer
354  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
355  * @param instruction to fill in
356  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
357  */
358 inline void AddOpaqueRenderers( BufferIndex updateBufferIndex,
359                                 Layer& layer,
360                                 const Matrix& viewMatrix,
361                                 bool transparentRenderablesExist,
362                                 bool stencilRenderablesExist,
363                                 RenderInstruction& instruction,
364                                 RendererSortingHelper& sortingHelper,
365                                 bool tryReuseRenderList )
366 {
367   const size_t renderableCount = layer.opaqueRenderables.size();
368   RenderList& opaqueRenderList = instruction.GetNextFreeRenderList( layer.opaqueRenderables.size() );
369   opaqueRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
370
371   // try to reuse cached renderitems from last time around
372   if( tryReuseRenderList )
373   {
374     if( TryReuseCachedRenderers( layer, opaqueRenderList, layer.opaqueRenderables ) )
375     {
376       // reset the flags as other layers might have changed
377       // opaque flags can only be set after renderers are added
378       SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
379       return;
380     }
381   }
382   AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix );
383
384   // opaque flags can only be set after renderers are added
385   SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
386
387   // sorting is only needed if more than 1 item
388   if( renderableCount > 1 )
389   {
390     SortOpaqueRenderItems( updateBufferIndex, opaqueRenderList, layer, sortingHelper.opaque );
391   }
392 }
393
394
395 /**
396  * Sort transparent render items
397  * @param transparentRenderList to sort
398  * @param layer where the renderers are from
399  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
400  */
401 inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& transparentRenderList, Layer& layer, RenderItemSortingHelper& sortingHelper )
402 {
403   const size_t renderableCount = transparentRenderList.Count();
404   // reserve space if needed
405   const unsigned int oldcapacity = sortingHelper.size();
406   if( oldcapacity < renderableCount )
407   {
408     sortingHelper.reserve( renderableCount );
409     // add real objects (reserve does not construct objects)
410     sortingHelper.insert( sortingHelper.begin() + oldcapacity,
411                           (renderableCount - oldcapacity),
412                           RendererWithSortAttributes() );
413   }
414   else
415   {
416     // clear extra elements from helper, does not decrease capability
417     sortingHelper.resize( renderableCount );
418   }
419
420   // calculate the sorting value, once per item by calling the layers sort function
421   // Using an if and two for-loops rather than if inside for as its better for branch prediction
422   if( layer.UsesDefaultSortFunction() )
423   {
424     for( size_t index = 0; index < renderableCount; ++index )
425     {
426       RenderItem& item = transparentRenderList.GetItem( index );
427
428       //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
429       layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
430
431       // the default sorting function should get inlined here
432       sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() );
433
434       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
435       sortingHelper[ index ].renderItem = &item;
436     }
437   }
438   else
439   {
440     const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
441     for( size_t index = 0; index < renderableCount; ++index )
442     {
443       RenderItem& item = transparentRenderList.GetItem( index );
444
445       layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
446       sortingHelper[ index ].zValue = (*sortFunction)( item.GetModelViewMatrix().GetTranslation3() );
447
448       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
449       sortingHelper[ index ].renderItem = &item;
450     }
451   }
452
453   // sort the renderers back to front, Z Axis point from near plane to far plane
454   std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItemsWithZValue );
455
456   // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
457   DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n");
458   RenderItemContainer::Iterator renderListIter = transparentRenderList.GetContainer().Begin();
459   for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
460   {
461     *renderListIter = sortingHelper[ index ].renderItem;
462     DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->GetRenderer() );
463   }
464 }
465
466 /**
467  * Add transparent renderers from the layer onto the next free render list
468  * @param updateBufferIndex to use
469  * @param layer to get the renderers from
470  * @param viewmatrix for the camera from rendertask
471  * @param opaqueRenderablesExist is true if there are opaque renderers on this layer
472  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
473  * @param instruction to fill in
474  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
475  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
476  */
477 inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
478                                      Layer& layer,
479                                      const Matrix& viewMatrix,
480                                      bool opaqueRenderablesExist,
481                                      bool stencilRenderablesExist,
482                                      RenderInstruction& instruction,
483                                      RendererSortingHelper& sortingHelper,
484                                      bool tryReuseRenderList )
485 {
486   const size_t renderableCount = layer.transparentRenderables.size();
487   RenderList& transparentRenderList = instruction.GetNextFreeRenderList( renderableCount );
488   transparentRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
489
490   // transparent flags are independent of the amount of transparent renderers
491   SetTransparentRenderFlags( transparentRenderList, opaqueRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
492
493   // try to reuse cached renderitems from last time around
494   if( tryReuseRenderList )
495   {
496     if( TryReuseCachedRenderers( layer, transparentRenderList, layer.transparentRenderables ) )
497     {
498       return;
499     }
500   }
501   transparentRenderList.SetSourceLayer( &layer );
502
503   AddRenderersToRenderList( updateBufferIndex, transparentRenderList, layer.transparentRenderables, viewMatrix );
504
505   // sorting is only needed if more than 1 item
506   if( renderableCount > 1 )
507   {
508     SortTransparentRenderItems( updateBufferIndex, transparentRenderList, layer, sortingHelper.transparent );
509   }
510 }
511
512 /**
513  * Add overlay renderers from the layer onto the next free render list
514  * @param updateBufferIndex to use
515  * @param layer to get the renderers from
516  * @param viewmatrix for the camera from rendertask
517  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
518  * @param instruction to fill in
519  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
520  */
521 inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
522                                  Layer& layer,
523                                  const Matrix& viewMatrix,
524                                  bool stencilRenderablesExist,
525                                  RenderInstruction& instruction,
526                                  bool tryReuseRenderList )
527 {
528   RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
529   overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
530   SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist );
531
532   // try to reuse cached renderitems from last time around
533   if( tryReuseRenderList )
534   {
535     if( TryReuseCachedRenderers( layer, overlayRenderList, layer.overlayRenderables ) )
536     {
537       return;
538     }
539   }
540   AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix );
541 }
542
543 /**
544  * Add stencil renderers from the layer onto the next free render list
545  * @param updateBufferIndex to use
546  * @param layer to get the renderers from
547  * @param viewmatrix for the camera from rendertask
548  * @param instruction to fill in
549  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
550  */
551 inline void AddStencilRenderers( BufferIndex updateBufferIndex,
552                                  Layer& layer,
553                                  const Matrix& viewMatrix,
554                                  RenderInstruction& instruction,
555                                  bool tryReuseRenderList )
556 {
557   RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
558   stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
559   SetStencilRenderFlags( stencilRenderList );
560
561   // try to reuse cached renderitems from last time around
562   if( tryReuseRenderList )
563   {
564     if( TryReuseCachedRenderers( layer, stencilRenderList, layer.stencilRenderables ) )
565     {
566       return;
567     }
568   }
569   AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix );
570 }
571
572 /**
573  * Prepare a single render instruction
574  * @param updateBufferIndex to use
575  * @param sortedLayers to prepare the instruction from
576  * @param renderTask to get the view matrix
577  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
578  * @param renderTracker An optional render tracker object
579  * @param instructions container
580  */
581 void PrepareRenderInstruction( BufferIndex updateBufferIndex,
582                                SortedLayerPointers& sortedLayers,
583                                RenderTask& renderTask,
584                                RendererSortingHelper& sortingHelper,
585                                RenderTracker* renderTracker,
586                                RenderInstructionContainer& instructions )
587 {
588   // Retrieve the RenderInstruction buffer from the RenderInstructionContainer
589   // then populate with instructions.
590   RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex );
591   renderTask.PrepareRenderInstruction( instruction, updateBufferIndex );
592   bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
593
594   const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
595
596   const SortedLayersIter endIter = sortedLayers.end();
597   for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
598   {
599     Layer& layer = **iter;
600
601     const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
602     const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() );
603     const bool transparentRenderablesExist( !layer.transparentRenderables.empty() );
604     const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
605     const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers(renderTask.GetCamera()) );
606
607     // Ignore stencils if there's nothing to test
608     if( stencilRenderablesExist &&
609         ( opaqueRenderablesExist || transparentRenderablesExist || overlayRenderablesExist ) )
610     {
611       AddStencilRenderers( updateBufferIndex, layer, viewMatrix, instruction, tryReuseRenderList );
612     }
613
614     if ( opaqueRenderablesExist )
615     {
616       AddOpaqueRenderers( updateBufferIndex,
617                           layer,
618                           viewMatrix,
619                           transparentRenderablesExist,
620                           stencilRenderablesExist,
621                           instruction,
622                           sortingHelper,
623                           tryReuseRenderList );
624     }
625
626     if ( transparentRenderablesExist )
627     {
628       AddTransparentRenderers( updateBufferIndex,
629                                layer,
630                                viewMatrix,
631                                opaqueRenderablesExist,
632                                stencilRenderablesExist,
633                                instruction,
634                                sortingHelper,
635                                tryReuseRenderList );
636     }
637
638     // @todo MESH_REWORK Mark opaque and transparent render lists as interleaveable.
639     // ( Saves having to have a pair of lists for each depth index )
640
641     if ( overlayRenderablesExist )
642     {
643       AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, stencilRenderablesExist,
644                            instruction, tryReuseRenderList );
645     }
646   }
647
648   instruction.mRenderTracker = renderTracker;
649   instruction.mCullMode = renderTask.GetCullMode();
650
651   // inform the render instruction that all renderers have been added and this frame is complete
652   instruction.UpdateCompleted();
653 }
654
655 } // SceneGraph
656
657 } // Internal
658
659 } // Dali