[3.0] Clipping API feature in Actor
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / render-task-processor.cpp
  */
 
 // CLASS HEADER
-#include <dali/internal/update/manager/process-render-tasks.h>
+#include <dali/internal/update/manager/render-task-processor.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/update/manager/prepare-render-instructions.h>
 #include <dali/internal/update/manager/sorted-layers.h>
 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
@@ -48,22 +47,13 @@ namespace SceneGraph
 namespace //Unnamed namespace
 {
 
-// Return false if the node or it's parents are exclusive to another render-task
+// Return false if the node or it's parents are exclusive to another render-task.
 bool CheckExclusivity( const Node& node, const RenderTask& task )
 {
   const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
-  if ( exclusiveTo )
+  if( exclusiveTo )
   {
-    if ( exclusiveTo == &task )
-    {
-      // Exclusive to the same render-task
-      return true;
-    }
-    else
-    {
-      // Exclusive to another render-task
-      return false;
-    }
+    return ( exclusiveTo == &task );
   }
 
   const Node* parent = node.GetParent();
@@ -72,17 +62,17 @@ bool CheckExclusivity( const Node& node, const RenderTask& task )
     return CheckExclusivity( *parent, task );
   }
 
-  // No exclusive flags set
+  // No exclusive flags set.
   return true;
 }
 
 Layer* FindLayer( Node& node )
 {
   Node* currentNode( &node );
-  Layer* layer(NULL);
+  Layer* layer( NULL );
   while( currentNode )
   {
-    if( (layer = currentNode->GetLayer()) != NULL )
+    if( ( layer = currentNode->GetLayer() ) != NULL )
     {
       return layer;
     }
@@ -94,45 +84,66 @@ Layer* FindLayer( Node& node )
 }
 
 /**
- * Rebuild the Layer::colorRenderables, stencilRenderables and overlayRenderables members,
+ * Rebuild the Layer::colorRenderables and overlayRenderables members,
  * including only renderers which are included in the current render-task.
  * Returns true if all renderers have finished acquiring resources.
+ *
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] node The current node of the scene-graph.
+ * @param[in] currentLayer The current layer containing lists of opaque/transparent renderables.
+ * @param[in] renderTask The current render-task.
+ * @param[in] inheritedDrawMode The draw mode of the parent
+ * @param[in] currentClippingId The current Clipping Id
+ *              Note: ClippingId is passed by reference, so it is permanently modified when traversing back up the tree for uniqueness.
+ * @param[in] clippingDepth The current clipping depth
  */
 bool AddRenderablesForTask( BufferIndex updateBufferIndex,
                             Node& node,
                             Layer& currentLayer,
                             RenderTask& renderTask,
-                            int inheritedDrawMode )
+                            int inheritedDrawMode,
+                            uint32_t& currentClippingId,
+                            uint32_t clippingDepth )
 {
   bool resourcesFinished = true;
 
   // Short-circuit for invisible nodes
-  if ( !node.IsVisible( updateBufferIndex ) )
+  if( !node.IsVisible( updateBufferIndex ) )
   {
     return resourcesFinished;
   }
 
   // Check whether node is exclusive to a different render-task
   const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
-  if ( exclusiveTo &&
-      exclusiveTo != &renderTask )
+  if( exclusiveTo && ( exclusiveTo != &renderTask ) )
   {
     return resourcesFinished;
   }
 
-  Layer* layer = &currentLayer;
-  Layer* nodeIsLayer( node.GetLayer() );
-  if ( nodeIsLayer )
+  // Assume all children go to this layer (if this node is a layer).
+  Layer* layer = node.GetLayer();
+  if( layer )
   {
-    // All children go to this layer
-    layer = nodeIsLayer;
-
     // Layers do not inherit the DrawMode from their parents
-    inheritedDrawMode = DrawMode::NORMAL;
+    inheritedDrawMode = node.GetDrawMode();
   }
+  else
+  {
+    // This node is not a layer.
+    layer = &currentLayer;
+    inheritedDrawMode |= node.GetDrawMode();
+  }
+
   DALI_ASSERT_DEBUG( NULL != layer );
 
-  inheritedDrawMode |= node.GetDrawMode();
+  // Update the clipping Id and depth for this node (if clipping is enabled).
+  if( DALI_UNLIKELY( node.GetClippingMode() != ClippingMode::DISABLED ) )
+  {
+    ++currentClippingId; // This modifies the reference passed in as well as the local value, causing the value to be global to the recursion.
+    ++clippingDepth;     // This only modifies the local value (which is passed in when the method recurses).
+  }
+  // Set the information in the node.
+  node.SetClippingInformation( currentClippingId, clippingDepth );
 
   const unsigned int count = node.GetRendererCount();
   for( unsigned int i = 0; i < count; ++i )
@@ -142,53 +153,57 @@ bool AddRenderablesForTask( BufferIndex updateBufferIndex,
     bool complete = false;
     renderer->GetReadyAndComplete( ready, complete );
 
-    DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Testing renderable:%p ready:%s complete:%s\n", renderer, ready?"T":"F", complete?"T":"F");
+    DALI_LOG_INFO( gRenderTaskLogFilter, Debug::General, "Testing renderable:%p ready:%s complete:%s\n", renderer, ready ? "T" : "F", complete ? "T" : "F" );
 
     resourcesFinished &= complete;
 
-    if( ready ) // i.e. should be rendered (all resources are available)
+    if( ready ) // IE. should be rendered (all resources are available)
     {
-      if( DrawMode::STENCIL == inheritedDrawMode )
+      // Normal is the more-likely draw mode to occur.
+      if( DALI_LIKELY( inheritedDrawMode == DrawMode::NORMAL ) )
       {
-        layer->stencilRenderables.PushBack( Renderable(&node, renderer ) );
-      }
-      else if( DrawMode::OVERLAY_2D == inheritedDrawMode )
-      {
-        layer->overlayRenderables.PushBack( Renderable(&node, renderer ) );
+        layer->colorRenderables.PushBack( Renderable( &node, renderer ) );
       }
       else
       {
-        layer->colorRenderables.PushBack( Renderable(&node, renderer ) );
+        layer->overlayRenderables.PushBack( Renderable( &node, renderer ) );
       }
     }
   }
 
-
-
-  // Recurse children
+  // Recurse children.
   NodeContainer& children = node.GetChildren();
   const NodeIter endIter = children.End();
-  for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
+  for( NodeIter iter = children.Begin(); iter != endIter; ++iter )
   {
     Node& child = **iter;
-    bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode );
+    bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth );
     resourcesFinished &= childResourcesComplete;
   }
 
   return resourcesFinished;
 }
-} //Unnamed namespace
-
-void ProcessRenderTasks( BufferIndex updateBufferIndex,
-                         RenderTaskList& renderTasks,
-                         Layer& rootNode,
-                         SortedLayerPointers& sortedLayers,
-                         RendererSortingHelper& sortingHelper,
-                         RenderInstructionContainer& instructions )
+
+} // Anonymous namespace.
+
+
+RenderTaskProcessor::RenderTaskProcessor()
+{
+}
+
+RenderTaskProcessor::~RenderTaskProcessor()
+{
+}
+
+void RenderTaskProcessor::Process( BufferIndex updateBufferIndex,
+                                   RenderTaskList& renderTasks,
+                                   Layer& rootNode,
+                                   SortedLayerPointers& sortedLayers,
+                                   RenderInstructionContainer& instructions )
 {
   RenderTaskList::RenderTaskContainer& taskContainer = renderTasks.GetTasks();
 
-  if ( taskContainer.IsEmpty() )
+  if( taskContainer.IsEmpty() )
   {
     // Early-exit if there are no tasks to process
     return;
@@ -200,32 +215,30 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
   //   3) Traverse the scene-graph, filling the lists for the current render-task
   //   4) Prepare render-instructions
 
-  DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Offscreens first\n");
+  DALI_LOG_INFO( gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Offscreens first\n" );
 
   // First process off screen render tasks - we may need the results of these for the on screen renders
+  uint32_t clippingId = 0u;
+  bool hasClippingNodes = false;
+
   RenderTaskList::RenderTaskContainer::ConstIterator endIter = taskContainer.End();
-  for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
+  for( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
   {
     RenderTask& renderTask = **iter;
 
-    // off screen only
-    if(0 == renderTask.GetFrameBufferId() && renderTask.GetFrameBuffer() == 0 )
-    {
-      // Skip to next task
-      continue;
-    }
-
-    if ( !renderTask.ReadyToRender( updateBufferIndex ) )
+    // Off screen only.
+    if( ( ( 0 == renderTask.GetFrameBufferId() ) && ( renderTask.GetFrameBuffer() == 0 ) ) ||
+        ( !renderTask.ReadyToRender( updateBufferIndex ) ) )
     {
-      // Skip to next task
+      // Skip to next task.
       continue;
     }
 
     Node* sourceNode = renderTask.GetSourceNode();
-    DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
+    DALI_ASSERT_DEBUG( NULL != sourceNode ); // Otherwise Prepare() should return false
 
-    // Check that the source node is not exclusive to another task
-    if ( ! CheckExclusivity( *sourceNode, renderTask ) )
+    // Check that the source node is not exclusive to another task.
+    if( ! CheckExclusivity( *sourceNode, renderTask ) )
     {
       continue;
     }
@@ -233,7 +246,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
     Layer* layer = FindLayer( *sourceNode );
     if( !layer )
     {
-      // Skip to next task as no layer
+      // Skip to next task as no layer.
       continue;
     }
 
@@ -250,15 +263,21 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
                                                  *sourceNode,
                                                  *layer,
                                                  renderTask,
-                                                 sourceNode->GetDrawMode() );
+                                                 sourceNode->GetDrawMode(),
+                                                 clippingId,
+                                                 0u );
 
       renderTask.SetResourcesFinished( resourcesFinished );
-      PrepareRenderInstruction( updateBufferIndex,
-                                sortedLayers,
-                                renderTask,
-                                sortingHelper,
-                                renderTask.GetCullMode(),
-                                instructions );
+
+      // If the clipping Id is still 0 after adding all Renderables, there is no clipping required for this RenderTaskList.
+      hasClippingNodes = clippingId != 0u;
+
+      mRenderInstructionProcessor.Prepare( updateBufferIndex,
+                                  sortedLayers,
+                                  renderTask,
+                                  renderTask.GetCullMode(),
+                                  hasClippingNodes,
+                                  instructions );
     }
     else
     {
@@ -266,30 +285,29 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
     }
   }
 
-  DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Onscreen\n");
+  DALI_LOG_INFO( gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Onscreen\n" );
 
-  // Now that the off screen renders are done we can process on screen render tasks
+  // Now that the off screen renders are done we can process on screen render tasks.
+  // Reset the clipping Id for the OnScreen render tasks.
+  clippingId = 0u;
   for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
   {
     RenderTask& renderTask = **iter;
 
-    // on screen only
-    if(0 != renderTask.GetFrameBufferId() || renderTask.GetFrameBuffer() != 0 )
+    // On screen only.
+    if( ( 0 != renderTask.GetFrameBufferId() ) ||
+        ( renderTask.GetFrameBuffer() != 0 )   ||
+        ( !renderTask.ReadyToRender( updateBufferIndex ) ) )
     {
-      // Skip to next task
-      continue;
-    }
-    if ( !renderTask.ReadyToRender( updateBufferIndex ) )
-    {
-      // Skip to next task
+      // Skip to next task.
       continue;
     }
 
     Node* sourceNode = renderTask.GetSourceNode();
-    DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
+    DALI_ASSERT_DEBUG( NULL != sourceNode ); // Otherwise Prepare() should return false.
 
-    // Check that the source node is not exclusive to another task
-    if ( ! CheckExclusivity( *sourceNode, renderTask ) )
+    // Check that the source node is not exclusive to another task.
+    if( ! CheckExclusivity( *sourceNode, renderTask ) )
     {
       continue;
     }
@@ -297,7 +315,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
     Layer* layer = FindLayer( *sourceNode );
     if( !layer )
     {
-      // Skip to next task as no layer
+      // Skip to next task as no layer.
       continue;
     }
 
@@ -305,7 +323,7 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
     if( renderTask.IsRenderRequired() )
     {
       size_t layerCount( sortedLayers.size() );
-      for( size_t i(0); i<layerCount; ++i )
+      for( size_t i(0); i < layerCount; ++i )
       {
         sortedLayers[i]->ClearRenderables();
       }
@@ -314,14 +332,19 @@ void ProcessRenderTasks( BufferIndex updateBufferIndex,
                                                  *sourceNode,
                                                  *layer,
                                                  renderTask,
-                                                 sourceNode->GetDrawMode() );
-
-      PrepareRenderInstruction( updateBufferIndex,
-                                sortedLayers,
-                                renderTask,
-                                sortingHelper,
-                                renderTask.GetCullMode(),
-                                instructions );
+                                                 sourceNode->GetDrawMode(),
+                                                 clippingId,
+                                                 0u );
+
+      // If the clipping Id is still 0 after adding all Renderables, there is no clipping required for this RenderTaskList.
+      hasClippingNodes = clippingId != 0;
+
+      mRenderInstructionProcessor.Prepare( updateBufferIndex,
+                                  sortedLayers,
+                                  renderTask,
+                                  renderTask.GetCullMode(),
+                                  hasClippingNodes,
+                                  instructions );
     }
 
     renderTask.SetResourcesFinished( resourcesFinished );