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