Geometry Batching
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / prepare-render-instructions.cpp
index dde9c68..350d66e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 // INTERNAL INCLUDES
 #include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/public-api/actors/layer.h>
 #include <dali/integration-api/debug.h>
 #include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
-#include <dali/internal/update/effects/scene-graph-material.h>
-#include <dali/internal/update/geometry/scene-graph-geometry.h>
-#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
-#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
 #include <dali/internal/update/manager/sorted-layers.h>
 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
-#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
-#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/update/rendering/scene-graph-texture-set.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
 #include <dali/internal/render/common/render-item.h>
 #include <dali/internal/render/common/render-tracker.h>
 #include <dali/internal/render/common/render-instruction.h>
 #include <dali/internal/render/common/render-instruction-container.h>
 #include <dali/internal/render/shaders/scene-graph-shader.h>
-#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+#include <dali/internal/render/renderers/render-property-buffer.h>
+#include <dali/internal/update/manager/geometry-batcher.h>
 
 namespace
 {
@@ -54,189 +54,103 @@ namespace SceneGraph
 {
 
 /**
- * Set flags for opaque renderlist
- * @param renderList to set the flags to
- * @param transparentRenderersExist is true if there is transparent renderers in this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param depthTestDisabled whether depth test is disabled.
- */
-inline void SetOpaqueRenderFlags( RenderList& renderList, bool transparentRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
-{
-  //@todo MESH_REWORK Move RequiresDepthTest from render thread object to update thread object
-
-  renderList.SetInterleave(transparentRenderersExist);
-
-  // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
-  // and this renderer does not need depth test against itself (e.g. mesh)
-  // and if this layer has got exactly one opaque renderer
-  // and this renderer is not interested in depth testing
-  // (i.e. is an image and not a mesh)
-  if ( (  renderList.Count() == 1 ) &&
-       (  !transparentRenderersExist ) &&
-       (  !renderList.GetRenderer( 0 )->RequiresDepthTest() ) )
-  {
-    // no need to enable depth test or clear depth buffer
-    // if there's something transparent already rendered by previous layers,
-    // this opaque renderer will correctly draw on top of them since no depth test
-    renderList.ClearFlags();
-    renderList.SetInterleave(false);
-  }
-  else if( depthTestDisabled )
-  {
-    renderList.ClearFlags();
-  }
-  else
-  {
-    // Prepare for rendering multiple opaque objects
-    unsigned int flags = RenderList::DEPTH_BUFFER_ENABLED | RenderList::DEPTH_WRITE | RenderList::DEPTH_CLEAR; // clear depth buffer, draw over the previously rendered layers;
-
-    renderList.ClearFlags();
-    renderList.SetFlags(flags);
-  }
-
-  if( stencilRenderablesExist )
-  {
-    renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
-  }
-}
-
-/**
- * Set the transparent flags on the renderlist
- * @param renderList to set the flags on
- * @param opaqueRenderersExist is true if there are opaque renderers on this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param depthTestDisabled whether depth test is disabled.
- */
-inline void SetTransparentRenderFlags( RenderList& renderList, bool opaqueRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
-{
-  renderList.ClearFlags();
-  // We don't need to write to the depth buffer, as transparent objects
-  // don't obscure each other.
-
-  renderList.SetInterleave(opaqueRenderersExist);
-  if ( opaqueRenderersExist && !depthTestDisabled )
-  {
-    // If there are a mix of opaque and transparent objects, the transparent
-    // objects should be rendered with depth test on to avoid background objects
-    // appearing in front of opaque foreground objects.
-    renderList.SetFlags( RenderList::DEPTH_BUFFER_ENABLED );
-  }
-
-  if( stencilRenderablesExist )
-  {
-    renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
-  }
-}
-
-
-/**
- * Set flags for overlay renderlist
- * @param renderList to set the flags for
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- */
-inline void SetOverlayRenderFlags( RenderList& renderList, bool stencilRenderablesExist )
-{
-  if(stencilRenderablesExist)
-  {
-    renderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
-  }
-}
-
-/**
- * Set flags for stencil renderlist
- * @param renderList to set the flags for
- */
-inline void SetStencilRenderFlags( RenderList& renderList )
-{
-  renderList.ClearFlags();
-  renderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
-}
-
-/**
  * Add a renderer to the list
  * @param updateBufferIndex to read the model matrix from
  * @param renderList to add the item to
- * @param renderable attachment
+ * @param renderable Node-Renderer pair
  * @param viewMatrix used to calculate modelview matrix for the item
+ * @param camera The camera used to render
+ * @param geometryBatcher The instance of the geometry batcher
+ * @param isLayer3d Whether we are processing a 3D layer or not
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
                                      RenderList& renderList,
-                                     RenderableAttachment& renderable,
+                                     Renderable& renderable,
                                      const Matrix& viewMatrix,
-                                     SceneGraph::CameraAttachment& cameraAttachment )
+                                     SceneGraph::Camera& camera,
+                                     GeometryBatcher& geometryBatcher,
+                                     bool isLayer3d,
+                                     bool cull )
 {
-  // Check for cull against view frustum
-  Matrix mvm;
-  bool inside = true;
+  // discard renderable early if it belongs to the batch which has been consumed in during frame
+  Node* renderableNode = renderable.mNode;
+  const bool batchingValid( renderable.mRenderer->IsBatchingEnabled() && renderableNode->mBatchIndex != BATCH_NULL_HANDLE );
+  if( batchingValid && geometryBatcher.HasRendered( renderableNode->mBatchIndex ) )
+  {
+    return;
+  }
 
-  const Node& parentNode = renderable.GetParent();
-  const Matrix& worldMatrix = parentNode.GetWorldMatrix( updateBufferIndex );
-  Matrix::Multiply( mvm, worldMatrix, viewMatrix );
+  bool inside( true );
+  const Node* batchParentNode = renderable.mNode->GetBatchParent();
+  const Node* node = ( renderable.mRenderer->IsBatchingEnabled() && batchParentNode ) ?
+        batchParentNode : renderableNode;
 
-  if ( RendererAttachment* rendererAttachment = dynamic_cast< RendererAttachment* >( &renderable ) )
+  if ( cull && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) )
   {
-    if ( rendererAttachment->GetMaterial().GetShader()->GeometryHintEnabled( Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) )
+    const Vector4& boundingSphere = node->GetBoundingSphere();
+    inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
+             (camera.CheckSphereInFrustum( updateBufferIndex, Vector3(boundingSphere), boundingSphere.w ) );
+  }
+
+  if( inside )
+  {
+    if( batchingValid )
+    {
+      geometryBatcher.SetRendered( renderableNode->mBatchIndex );
+    }
+
+    Renderer::Opacity opacity = renderable.mRenderer->GetOpacity( updateBufferIndex, *renderable.mNode );
+    if( opacity != Renderer::TRANSPARENT )
     {
-      // Get the geometry extents for frustum checking
-      const Vector3& position = worldMatrix.GetTranslation3();
-      const Geometry& geometry = rendererAttachment->GetGeometry();
-      const Vector3& localCenter = geometry.mCenter[ updateBufferIndex ];
-      const Vector3& size = parentNode.GetSize( updateBufferIndex );
-      Vector3 center = position + ( localCenter * size );
-
-      // If the size components are all the same, then we can do a quick bounding sphere check
-      if ( fabsf( size.x - size.y ) <= Math::MACHINE_EPSILON_1 * size.x )
+      // Get the next free RenderItem
+      RenderItem& item = renderList.GetNextFreeItem();
+      item.mRenderer = &renderable.mRenderer->GetRenderer();
+      item.mNode = renderable.mNode;
+      item.mIsOpaque = (opacity == Renderer::OPAQUE);
+
+      if( isLayer3d )
       {
-        inside = cameraAttachment.CheckSphereInFrustum( updateBufferIndex, center, geometry.mRadius[ updateBufferIndex ] * size.x );
+        item.mDepthIndex = renderable.mRenderer->GetDepthIndex();
       }
-
-      if ( inside )
+      else
       {
-        // Check against AABB of model
-        inside = cameraAttachment.CheckAABBInFrustum( updateBufferIndex, center, geometry.mHalfExtents[ updateBufferIndex ] * size );
+        item.mDepthIndex = renderable.mRenderer->GetDepthIndex() + static_cast<int>( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER;
       }
+      // save MV matrix onto the item
+      node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
+      Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
     }
   }
-
-  if ( inside )
-  {
-    // Get the next free RenderItem
-    RenderItem& item = renderList.GetNextFreeItem();
-    const Renderer& renderer = renderable.GetRenderer();
-    item.SetRenderer( const_cast< Renderer* >( &renderer ) );
-    item.SetDepthIndex( renderable.GetDepthIndex(updateBufferIndex) );
-
-    // save MV matrix onto the item
-    Matrix& modelViewMatrix = item.GetModelViewMatrix();
-    modelViewMatrix = mvm;
-  }
 }
 
 /**
  * Add all renderers to the list
  * @param updateBufferIndex to read the model matrix from
  * @param renderList to add the items to
- * @param renderable attachments
+ * @param renderers to render
+ * NodeRendererContainer Node-Renderer pairs
  * @param viewMatrix used to calculate modelview matrix for the items
+ * @param camera The camera used to render
+ * @param geometryBatcher The instance of the geometry batcher
+ * @param isLayer3d Whether we are processing a 3D layer or not
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
                                       RenderList& renderList,
-                                      RenderableAttachmentContainer& attachments,
+                                      RenderableContainer& renderers,
                                       const Matrix& viewMatrix,
-                                      SceneGraph::CameraAttachment& cameraAttachment )
+                                      SceneGraph::Camera& camera,
+                                      GeometryBatcher* geometryBatcher,
+                                      bool isLayer3d,
+                                      bool cull)
 {
   DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
 
-  // Add renderer for each attachment
-  int index=0;
-  const RenderableAttachmentIter endIter = attachments.end();
-  for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
+  unsigned int rendererCount( renderers.Size() );
+  for( unsigned int i(0); i<rendererCount; ++i )
   {
-    RenderableAttachment& attachment = **iter;
-    AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix, cameraAttachment );
-
-    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  List[%d].renderer = %p\n", index, &(attachment.GetRenderer()));
-    index++;
+    AddRendererToRenderList( updateBufferIndex, renderList, renderers[i], viewMatrix, camera, *geometryBatcher, isLayer3d, cull );
   }
 }
 
@@ -246,29 +160,28 @@ inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
  * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
  * @param layer that is being processed
  * @param renderList that is cached from frame N-1
- * @param attachmentList that is being used
+ * @param renderables list of renderables
  */
 inline bool TryReuseCachedRenderers( Layer& layer,
                                      RenderList& renderList,
-                                     RenderableAttachmentContainer& attachmentList )
+                                     RenderableContainer& renderables )
 {
   bool retValue = false;
-  size_t renderableCount = attachmentList.size();
+  size_t renderableCount = renderables.Size();
   // check that the cached list originates from this layer and that the counts match
   if( ( renderList.GetSourceLayer() == &layer )&&
       ( renderList.GetCachedItemCount() == renderableCount ) )
   {
-    // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
-    // Attachments are not sorted, but render list is so at this stage renderers may be in different order
+    // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong things
+    // Render list is sorted so at this stage renderers may be in different order
     // therefore we check a combined sum of all renderer addresses
     size_t checkSumNew = 0;
     size_t checkSumOld = 0;
     for( size_t index = 0; index < renderableCount; ++index )
     {
-      RenderableAttachment* attachment = attachmentList[ index ];
-      const Renderer& renderer = attachment->GetRenderer();
+      const Render::Renderer& renderer = renderables[index].mRenderer->GetRenderer();
       checkSumNew += size_t( &renderer );
-      checkSumOld += size_t( renderList.GetRenderer( index ) );
+      checkSumOld += size_t( &renderList.GetRenderer( index ) );
     }
     if( checkSumNew == checkSumOld )
     {
@@ -280,168 +193,88 @@ inline bool TryReuseCachedRenderers( Layer& layer,
   return retValue;
 }
 
-
 /**
  * Function which sorts render items by depth index then by instance
- * ptrs of shader/geometry/material.
+ * ptrs of shader/texture/geometry.
  * @param lhs item
  * @param rhs item
  * @return true if left item is greater than right
  */
 bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
 {
-  // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
-  // encapsulates the same data (e.g. the middle-order bits of the ptrs)
-  if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
+  if( lhs.renderItem->mDepthIndex == rhs.renderItem->mDepthIndex )
   {
     if( lhs.shader == rhs.shader )
     {
-      if( lhs.material == rhs.material )
+      if( lhs.textureResourceId == rhs.textureResourceId )
       {
-        return lhs.geometry < lhs.geometry;
+        return lhs.geometry < rhs.geometry;
       }
-      return lhs.material < rhs.material;
+      return lhs.textureResourceId < rhs.textureResourceId;
     }
-    return lhs.shader < rhs.shader;;
+    return lhs.shader < rhs.shader;
   }
-  return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
+  return lhs.renderItem->mDepthIndex < rhs.renderItem->mDepthIndex;
 }
 /**
- * Function which sorts the render items by depth index then by Z function,
- * then by instance ptrs of shader/geometry/material.
+ * Function which sorts the render items by Z function, then
+ * by instance ptrs of shader/texture/geometry.
  * @param lhs item
  * @param rhs item
  * @return true if left item is greater than right
  */
-bool CompareItemsWithZValue( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
+bool CompareItems3D( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
 {
-  // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
-  // encapsulates the same data (e.g. the middle-order bits of the ptrs)
-
-  if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
+  bool lhsIsOpaque = lhs.renderItem->mIsOpaque;
+  if( lhsIsOpaque ==  rhs.renderItem->mIsOpaque )
   {
-    if( Equals(lhs.zValue, rhs.zValue) )
+    if( lhsIsOpaque )
     {
+      //If both RenderItems are opaque, sort using shader, then texture then geometry
       if( lhs.shader == rhs.shader )
       {
-        if( lhs.material == rhs.material )
+        if( lhs.textureResourceId == rhs.textureResourceId )
         {
-          return lhs.geometry < lhs.geometry;
+          return lhs.geometry < rhs.geometry;
         }
-        return lhs.material < rhs.material;
+        return lhs.textureResourceId < rhs.textureResourceId;
       }
-      return lhs.shader < rhs.shader;;
+      return lhs.shader < rhs.shader;
     }
-    return lhs.zValue > rhs.zValue;
-  }
-  return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
-}
-
-inline void SortOpaqueRenderItems(
-  BufferIndex bufferIndex,
-  RenderList& opaqueRenderList,
-  Layer& layer,
-  RenderItemSortingHelper& sortingHelper )
-{
-  const size_t renderableCount = opaqueRenderList.Count();
-  // reserve space if needed
-  const unsigned int oldcapacity = sortingHelper.size();
-  if( oldcapacity < renderableCount )
-  {
-    sortingHelper.reserve( renderableCount );
-    // add real objects (reserve does not construct objects)
-    sortingHelper.insert( sortingHelper.begin() + oldcapacity,
-                          (renderableCount - oldcapacity),
-                          RendererWithSortAttributes() );
-  }
-  else
-  {
-    // clear extra elements from helper, does not decrease capability
-    sortingHelper.resize( renderableCount );
-  }
-
-  for( size_t index = 0; index < renderableCount; ++index )
-  {
-    RenderItem& item = opaqueRenderList.GetItem( index );
-
-    //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
-    layer.opaqueRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
-
-    sortingHelper[ index ].zValue = 0;
-    sortingHelper[ index ].renderItem = &item;
-  }
-
-  // Sort the renderers by depth index, then by instance
-  std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
-
-  DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Opaque List:\n");
-
-  // Repopulate the render items in the render list based on the sorting helper
-  RenderItemContainer::Iterator renderListIter = opaqueRenderList.GetContainer().Begin();
-  for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
-  {
-    *renderListIter = sortingHelper[ index ].renderItem;
-    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", sortingHelper[ index ].renderItem->GetRenderer() );
-  }
-}
-
-/**
- * Add opaque renderers from the layer onto the next free render list
- * @param updateBufferIndex to use
- * @param layer to get the renderers from
- * @param viewmatrix for the camera from rendertask
- * @param cameraAttachment to use the view frustum
- * @param transparentRenderersExist is true if there is transparent renderers in this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param instruction to fill in
- * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
- */
-inline void AddOpaqueRenderers( BufferIndex updateBufferIndex,
-                                Layer& layer,
-                                const Matrix& viewMatrix,
-                                SceneGraph::CameraAttachment& cameraAttachment,
-                                bool transparentRenderablesExist,
-                                bool stencilRenderablesExist,
-                                RenderInstruction& instruction,
-                                RendererSortingHelper& sortingHelper,
-                                bool tryReuseRenderList )
-{
-  const size_t renderableCount = layer.opaqueRenderables.size();
-  RenderList& opaqueRenderList = instruction.GetNextFreeRenderList( layer.opaqueRenderables.size() );
-  opaqueRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-
-  // try to reuse cached renderitems from last time around
-  if( tryReuseRenderList )
-  {
-    if( TryReuseCachedRenderers( layer, opaqueRenderList, layer.opaqueRenderables ) )
+    else
     {
-      // reset the flags as other layers might have changed
-      // opaque flags can only be set after renderers are added
-      SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
-      return;
+      //If both RenderItems are transparent, sort using z,then shader, then texture, then geometry
+      if( Equals(lhs.zValue, rhs.zValue) )
+      {
+        if( lhs.shader == rhs.shader )
+        {
+          if( lhs.textureResourceId == rhs.textureResourceId )
+          {
+            return lhs.geometry < rhs.geometry;
+          }
+          return lhs.textureResourceId < rhs.textureResourceId;
+        }
+        return lhs.shader < rhs.shader;
+      }
+      return lhs.zValue > rhs.zValue;
     }
   }
-  AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix, cameraAttachment );
-
-  // opaque flags can only be set after renderers are added
-  SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
-
-  // sorting is only needed if more than 1 item
-  if( renderableCount > 1 )
+  else
   {
-    SortOpaqueRenderItems( updateBufferIndex, opaqueRenderList, layer, sortingHelper.opaque );
+    return lhsIsOpaque;
   }
 }
 
 /**
- * Sort transparent render items
- * @param transparentRenderList to sort
+ * Sort render items
+ * @param bufferIndex The buffer to read from
+ * @param renderList to sort
  * @param layer where the renderers are from
  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
  */
-inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& transparentRenderList, Layer& layer, RenderItemSortingHelper& sortingHelper )
+inline void SortRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, RendererSortingHelper& sortingHelper )
 {
-  const size_t renderableCount = transparentRenderList.Count();
+  const size_t renderableCount = renderList.Count();
   // reserve space if needed
   const unsigned int oldcapacity = sortingHelper.size();
   if( oldcapacity < renderableCount )
@@ -464,13 +297,12 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra
   {
     for( size_t index = 0; index < renderableCount; ++index )
     {
-      RenderItem& item = transparentRenderList.GetItem( index );
+      RenderItem& item = renderList.GetItem( index );
 
-      //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
-      layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+      item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
 
       // the default sorting function should get inlined here
-      sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() );
+      sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex;
 
       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
       sortingHelper[ index ].renderItem = &item;
@@ -481,73 +313,84 @@ inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& tra
     const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
     for( size_t index = 0; index < renderableCount; ++index )
     {
-      RenderItem& item = transparentRenderList.GetItem( index );
+      RenderItem& item = renderList.GetItem( index );
 
-      layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
-      sortingHelper[ index ].zValue = (*sortFunction)( item.GetModelViewMatrix().GetTranslation3() );
+      item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+      sortingHelper[ index ].zValue = (*sortFunction)( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex;
 
       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
       sortingHelper[ index ].renderItem = &item;
     }
   }
 
-  // sort the renderers back to front, Z Axis point from near plane to far plane
-  std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItemsWithZValue );
+  if( layer.GetBehavior() ==  Dali::Layer::LAYER_3D)
+  {
+    // sort the renderers back to front, Z Axis point from near plane to far plane
+    std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems3D );
+  }
+  else
+  {
+    // sort the renderers based on DepthIndex
+    std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
+  }
 
   // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
   DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n");
-  RenderItemContainer::Iterator renderListIter = transparentRenderList.GetContainer().Begin();
+  RenderItemContainer::Iterator renderListIter = renderList.GetContainer().Begin();
   for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
   {
     *renderListIter = sortingHelper[ index ].renderItem;
-    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->GetRenderer() );
+    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->mRenderer);
   }
 }
 
 /**
- * Add transparent renderers from the layer onto the next free render list
+ * Add color renderers from the layer onto the next free render list
  * @param updateBufferIndex to use
  * @param layer to get the renderers from
  * @param viewmatrix for the camera from rendertask
- * @param opaqueRenderablesExist is true if there are opaque renderers on this layer
+ * @param camera to use the view frustum
  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
  * @param instruction to fill in
  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
+ * @param geometryBatcher the instance of the geometry batcher
  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
  */
-inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
-                                     Layer& layer,
-                                     const Matrix& viewMatrix,
-                                     SceneGraph::CameraAttachment& cameraAttachment,
-                                     bool opaqueRenderablesExist,
-                                     bool stencilRenderablesExist,
-                                     RenderInstruction& instruction,
-                                     RendererSortingHelper& sortingHelper,
-                                     bool tryReuseRenderList )
+inline void AddColorRenderers( BufferIndex updateBufferIndex,
+                               Layer& layer,
+                               const Matrix& viewMatrix,
+                               SceneGraph::Camera& camera,
+                               bool stencilRenderablesExist,
+                               RenderInstruction& instruction,
+                               RendererSortingHelper& sortingHelper,
+                               GeometryBatcher& geometryBatcher,
+                               bool tryReuseRenderList,
+                               bool cull)
 {
-  const size_t renderableCount = layer.transparentRenderables.size();
-  RenderList& transparentRenderList = instruction.GetNextFreeRenderList( renderableCount );
-  transparentRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-
-  // transparent flags are independent of the amount of transparent renderers
-  SetTransparentRenderFlags( transparentRenderList, opaqueRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
+  RenderList& renderList = instruction.GetNextFreeRenderList( layer.colorRenderables.Size() );
+  renderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
+  renderList.SetSourceLayer( &layer );
+  renderList.SetHasColorRenderItems( true );
 
   // try to reuse cached renderitems from last time around
   if( tryReuseRenderList )
   {
-    if( TryReuseCachedRenderers( layer, transparentRenderList, layer.transparentRenderables ) )
+    if( TryReuseCachedRenderers( layer, renderList, layer.colorRenderables ) )
     {
       return;
     }
   }
-  transparentRenderList.SetSourceLayer( &layer );
 
-  AddRenderersToRenderList( updateBufferIndex, transparentRenderList, layer.transparentRenderables, viewMatrix, cameraAttachment );
+  AddRenderersToRenderList( updateBufferIndex, renderList, layer.colorRenderables, viewMatrix, camera, &geometryBatcher, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
+  SortRenderItems( updateBufferIndex, renderList, layer, sortingHelper );
 
-  // sorting is only needed if more than 1 item
-  if( renderableCount > 1 )
+  // Setup the render flags for stencil.
+  renderList.ClearFlags();
+  if( stencilRenderablesExist )
   {
-    SortTransparentRenderItems( updateBufferIndex, transparentRenderList, layer, sortingHelper.transparent );
+    // Note: SetFlags does not overwrite, it ORs, so ClearFlags() is also required.
+    renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
   }
 }
 
@@ -556,21 +399,33 @@ inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
  * @param updateBufferIndex to use
  * @param layer to get the renderers from
  * @param viewmatrix for the camera from rendertask
+ * @param camera to use
  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
  * @param instruction to fill in
  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
                                  Layer& layer,
                                  const Matrix& viewMatrix,
-                                 SceneGraph::CameraAttachment& cameraAttachment,
+                                 SceneGraph::Camera& camera,
                                  bool stencilRenderablesExist,
                                  RenderInstruction& instruction,
-                                 bool tryReuseRenderList )
+                                 RendererSortingHelper& sortingHelper,
+                                 bool tryReuseRenderList,
+                                 bool cull )
 {
-  RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
+  RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.Size() );
   overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-  SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist );
+  overlayRenderList.SetSourceLayer( &layer );
+  overlayRenderList.SetHasColorRenderItems( false );
+
+  //Set render flags
+  overlayRenderList.ClearFlags();
+  if(stencilRenderablesExist)
+  {
+    overlayRenderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
+  }
 
   // try to reuse cached renderitems from last time around
   if( tryReuseRenderList )
@@ -580,7 +435,8 @@ inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
       return;
     }
   }
-  AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, cameraAttachment );
+  AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, camera, NULL, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
+  SortRenderItems( updateBufferIndex, overlayRenderList, layer, sortingHelper );
 }
 
 /**
@@ -588,19 +444,27 @@ inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
  * @param updateBufferIndex to use
  * @param layer to get the renderers from
  * @param viewmatrix for the camera from rendertask
+ * @param camera to use
  * @param instruction to fill in
  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddStencilRenderers( BufferIndex updateBufferIndex,
                                  Layer& layer,
                                  const Matrix& viewMatrix,
-                                 SceneGraph::CameraAttachment& cameraAttachment,
+                                 SceneGraph::Camera& camera,
                                  RenderInstruction& instruction,
-                                 bool tryReuseRenderList )
+                                 bool tryReuseRenderList,
+                                 bool cull )
 {
-  RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
+  RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.Size() );
   stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-  SetStencilRenderFlags( stencilRenderList );
+  stencilRenderList.SetSourceLayer( &layer );
+  stencilRenderList.SetHasColorRenderItems( false );
+
+  //Set render flags
+  stencilRenderList.ClearFlags();
+  stencilRenderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
 
   // try to reuse cached renderitems from last time around
   if( tryReuseRenderList )
@@ -610,24 +474,16 @@ inline void AddStencilRenderers( BufferIndex updateBufferIndex,
       return;
     }
   }
-  AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, cameraAttachment );
+  AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, camera, NULL, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
 }
 
-/**
- * Prepare a single render instruction
- * @param updateBufferIndex to use
- * @param sortedLayers to prepare the instruction from
- * @param renderTask to get the view matrix
- * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
- * @param renderTracker An optional render tracker object
- * @param instructions container
- */
 void PrepareRenderInstruction( BufferIndex updateBufferIndex,
                                SortedLayerPointers& sortedLayers,
                                RenderTask& renderTask,
                                RendererSortingHelper& sortingHelper,
-                               RenderTracker* renderTracker,
-                               RenderInstructionContainer& instructions )
+                               bool cull,
+                               RenderInstructionContainer& instructions,
+                               GeometryBatcher& geometryBatcher )
 {
   // Retrieve the RenderInstruction buffer from the RenderInstructionContainer
   // then populate with instructions.
@@ -636,65 +492,46 @@ void PrepareRenderInstruction( BufferIndex updateBufferIndex,
   bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
 
   const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
-  SceneGraph::CameraAttachment& cameraAttachment = renderTask.GetCameraAttachment();
+  SceneGraph::Camera& camera = renderTask.GetCamera();
 
   const SortedLayersIter endIter = sortedLayers.end();
   for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
   {
     Layer& layer = **iter;
 
-    const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
-    const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() );
-    const bool transparentRenderablesExist( !layer.transparentRenderables.empty() );
-    const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
-    const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers(renderTask.GetCamera()) );
+    const bool stencilRenderablesExist( !layer.stencilRenderables.Empty() );
+    const bool colorRenderablesExist( !layer.colorRenderables.Empty() );
+    const bool overlayRenderablesExist( !layer.overlayRenderables.Empty() );
+    const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers( &renderTask.GetCamera() ) );
 
     // Ignore stencils if there's nothing to test
     if( stencilRenderablesExist &&
-        ( opaqueRenderablesExist || transparentRenderablesExist || overlayRenderablesExist ) )
+        ( colorRenderablesExist || overlayRenderablesExist ) )
     {
-      AddStencilRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, instruction, tryReuseRenderList );
+      AddStencilRenderers( updateBufferIndex, layer, viewMatrix, camera, instruction, tryReuseRenderList, cull );
     }
 
-    if ( opaqueRenderablesExist )
+    if ( colorRenderablesExist )
     {
-      AddOpaqueRenderers( updateBufferIndex,
-                          layer,
-                          viewMatrix,
-                          cameraAttachment,
-                          transparentRenderablesExist,
-                          stencilRenderablesExist,
-                          instruction,
-                          sortingHelper,
-                          tryReuseRenderList );
+      AddColorRenderers( updateBufferIndex,
+                         layer,
+                         viewMatrix,
+                         camera,
+                         stencilRenderablesExist,
+                         instruction,
+                         sortingHelper,
+                         geometryBatcher,
+                         tryReuseRenderList,
+                         cull );
     }
 
-    if ( transparentRenderablesExist )
-    {
-      AddTransparentRenderers( updateBufferIndex,
-                               layer,
-                               viewMatrix,
-                               cameraAttachment,
-                               opaqueRenderablesExist,
-                               stencilRenderablesExist,
-                               instruction,
-                               sortingHelper,
-                               tryReuseRenderList );
-    }
-
-    // @todo MESH_REWORK Mark opaque and transparent render lists as interleaveable.
-    // ( Saves having to have a pair of lists for each depth index )
-
     if ( overlayRenderablesExist )
     {
-      AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, stencilRenderablesExist,
-                           instruction, tryReuseRenderList );
+      AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, camera, stencilRenderablesExist,
+                           instruction, sortingHelper, tryReuseRenderList, cull );
     }
   }
 
-  instruction.mRenderTracker = renderTracker;
-  instruction.mCullMode = renderTask.GetCullMode();
-
   // inform the render instruction that all renderers have been added and this frame is complete
   instruction.UpdateCompleted();
 }