Apply RenderUntil() on sorted RenderList 66/311366/14
authorjmm <j0064423.lee@samsung.com>
Fri, 19 Apr 2024 11:55:52 +0000 (20:55 +0900)
committerjmm <j0064423.lee@samsung.com>
Tue, 28 May 2024 10:51:27 +0000 (19:51 +0900)
Change-Id: I64a3b567984494d1f284095d68e44b7e318a04d5

automated-tests/src/dali/utc-Dali-RenderTask.cpp
dali/internal/event/render-tasks/render-task-impl.cpp
dali/internal/event/render-tasks/render-task-impl.h
dali/internal/render/common/render-list.h
dali/internal/update/manager/render-instruction-processor.cpp
dali/internal/update/manager/render-task-processor.cpp
dali/internal/update/render-tasks/scene-graph-render-task.cpp
dali/internal/update/render-tasks/scene-graph-render-task.h
dali/public-api/render-tasks/render-task.cpp
dali/public-api/render-tasks/render-task.h

index a2d870ea4c503303e3eba79fa2e3c5f81f92651e..c0b2003bc74381b5f4bc50626ef47f1b692ac802 100644 (file)
@@ -25,6 +25,7 @@
 #include <test-native-image.h>
 
 #include <iostream>
+#include "test-application.h"
 
 #define BOOLSTR(x) ((x) ? "T" : "F")
 
@@ -730,12 +731,12 @@ int UtcDaliRenderTaskGetStopperActorN(void)
   END_TEST;
 }
 
-int UtcDaliRenderTaskRenderUntil(void)
+int UtcDaliRenderTaskRenderUntil01(void)
 {
   TestApplication application;
-  tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the actor.");
+  tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the renderable actor.");
 
-  // Make a new render task and compose a tree.
+  // Get default rendertask
   RenderTaskList taskList = application.GetScene().GetRenderTaskList();
   RenderTask     task     = taskList.GetTask(0u);
 
@@ -775,6 +776,116 @@ int UtcDaliRenderTaskRenderUntil(void)
   END_TEST;
 }
 
+int UtcDaliRenderTaskRenderUntil02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the empty actor.");
+
+  // Get default rendertask
+  RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+  RenderTask     task     = taskList.GetTask(0u);
+
+  Integration::Scene stage = application.GetScene();
+
+  Actor secondChild;
+  for(int i = 0; i < 5; i++)
+  {
+    Actor parent = CreateRenderableActor();
+    parent.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+    parent.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    Actor  child = Actor::New(); // Has no renderer
+    child.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+    stage.Add(parent);
+    parent.Add(child);
+
+    if (i == 1)
+    {
+      secondChild = child;
+    }
+  }
+  task.RenderUntil(secondChild);
+
+  // Update & Render with the actor on-stage
+  TestGlAbstraction& gl        = application.GetGlAbstraction();
+  TraceCallStack&    drawTrace = gl.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut.
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskRenderUntil03(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::RenderUntil(actor) Check that other preceding layers are rendered.");
+
+  // Get default rendertask
+  RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+  RenderTask     task     = taskList.GetTask(0u);
+
+  Integration::Scene stage = application.GetScene();
+
+  // Compose a tree
+  Actor a0 = CreateRenderableActor();
+  a0.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+  a0.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  Layer l0 = Layer::New();
+  l0.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  l0.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  l0.LowerToBottom(); // drawn later
+
+  Actor a1 = CreateRenderableActor();
+  a1.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+  Actor target = CreateRenderableActor();
+  target.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+  Layer l2 = Layer::New(); // same depth index to root, added(drawn) later
+  l2.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  l2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  Actor a2 = CreateRenderableActor();
+  a2.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+  stage.Add(a0);
+  a0.Add(l0);
+  l0.Add(CreateRenderableActor());
+
+  stage.Add(a1);
+  a1.Add(target);
+
+  stage.Add(a2);
+  a2.Add(l2);
+  l2.Add(CreateRenderableActor());
+
+  // draw only a0 and a1 (2 items)
+  // l0 and children is cut(low depth index)
+  // a2 and children are cut(added after target)
+  task.RenderUntil(target);
+
+  // Update & Render with the actor on-stage
+  TestGlAbstraction& gl        = application.GetGlAbstraction();
+  TraceCallStack&    drawTrace = gl.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliRenderTaskSetExclusive(void)
 {
   TestApplication application;
index 9b2de3490d3e17581eae00379c405fb41c7f4621..1df8c118a78f58c89e57e66ef706e23d8cba82fa 100644 (file)
@@ -655,15 +655,15 @@ uint32_t RenderTask::GetRenderTaskId() const
   return mRenderTaskId;
 }
 
-void RenderTask::RenderUntil(Actor* actor)
+void RenderTask::RenderUntil(Actor* stopperActor)
 {
   Actor* target = mSourceActor.GetActor();
-  DALI_ASSERT_ALWAYS((target && actor)
+  DALI_ASSERT_ALWAYS((target && stopperActor)
       && "RenderTask::RenderUntil() has empty actors.");
-  DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < actor->GetHierarchyDepth())
+  DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < stopperActor->GetHierarchyDepth())
       && "RenderTask::RenderUntil() has reversed hierarchy.");
 
-  Actor* parent = actor;
+  Actor* parent = stopperActor;
   while(parent != target && !(parent->IsLayer()))
   {
     parent = parent->GetParent();
@@ -671,8 +671,8 @@ void RenderTask::RenderUntil(Actor* actor)
 
   if(parent == target && GetRenderTaskSceneObject())
   {
-    mStopperActor.SetActor(actor);
-    SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &actor->GetNode());
+    mStopperActor.SetActor(stopperActor);
+    SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &stopperActor->GetNode());
   }
 }
 
index 84be7da6ad6cc95e9855765498dc9a7f9c71fb0d..efed82f3937407bcb8aa7d604e9fe9699cafa095 100644 (file)
@@ -71,6 +71,9 @@ public:
    */
   Actor* GetSourceActor() const;
 
+  /**
+   * @copydoc Dali::RenderTask::GetStopperActor()
+   */
   Actor* GetStopperActor() const;
 
   /**
@@ -286,7 +289,10 @@ public:
    */
   uint32_t GetRenderTaskId() const;
 
-  void RenderUntil(Actor* actor);
+  /**
+   * @copydoc Dali::RenderTask::RenderUntil
+   */
+  void RenderUntil(Actor* stopperActor);
 
 public: // Used by RenderTaskList, which owns the SceneGraph::RenderTasks
   /**
index 29fd0b3fd260e8af74547fd67538a165caea007d..05d7dc99513773c2b12f61aac8405c3d16c40bbe 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <cstdint>
+#include <dali/internal/update/nodes/node.h>
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/common/owner-container.h>
@@ -236,6 +237,27 @@ public:
     }
   }
 
+  /**
+   * Trim the list by stopperNode
+   * @param stopperNode The node to stop rendering. Rendering will not include the node.
+   * @return Whether trimming actually occured.
+   */
+  bool RenderUntil(Node* stopperNode)
+  {
+    RenderItemContainer::Iterator iter = mItems.Begin();
+    for(uint32_t index = 0u; iter != mItems.End(); ++iter, ++index)
+    {
+      RenderItem* item = iter->Get();
+      if(item->mNode == stopperNode)
+      {
+        mNextFree = index;
+        ReleaseUnusedItems();
+        return true;
+      }
+    }
+    return false;
+  }
+
   /**
    * @return the source layer these renderitems originate from
    */
index acee7f3639564c55ed68e64c2f7262dfb1dc1d52..5b86a324060e8983230c97e43f8c295dd74461cf 100644 (file)
@@ -194,6 +194,7 @@ inline bool SetNodeUpdateArea(Node* node, bool isLayer3d, Matrix& nodeWorldMatri
  * @param viewportSet Whether the viewport is set or not
  * @param viewport The viewport
  * @param cullingEnabled Whether frustum culling is enabled or not
+ * @param stopperNode Marker node that stops rendering(must be rendered)
  */
 inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
                                     uint32_t                  renderPass,
@@ -205,7 +206,8 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
                                     bool                      isLayer3d,
                                     bool                      viewportSet,
                                     const Viewport&           viewport,
-                                    bool                      cullingEnabled)
+                                    bool                      cullingEnabled,
+                                    Node*                     stopperNode)
 {
   bool    inside(true);
   Node*   node = renderable.mNode;
@@ -223,7 +225,8 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
   bool hasRenderCallback = (rendererExist && renderable.mRenderer->GetRenderCallback());
 
   auto requiredInsideCheck = [&]() {
-    if(cullingEnabled &&
+    if(node != stopperNode &&
+       cullingEnabled &&
        !hasRenderCallback &&
        node->GetClippingMode() == ClippingMode::DISABLED &&
        rendererExist)
@@ -283,7 +286,10 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
       const Renderer::OpacityType opacityType = rendererExist ? (isVisualRendererUnder3D ? Renderer::TRANSLUCENT : renderable.mRenderer->GetOpacityType(updateBufferIndex, renderPass, *node)) : Renderer::OPAQUE;
 
       // We can skip render when node is not clipping and transparent
-      skipRender = (opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED);
+      // We must not skip when node is a stopper
+      skipRender = (opacityType == Renderer::TRANSPARENT &&
+          node->GetClippingMode() == ClippingMode::DISABLED &&
+          node != stopperNode);
 
       isOpaque = (opacityType == Renderer::OPAQUE);
     }
@@ -371,6 +377,7 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
  * @param viewportSet Whether the viewport is set or not
  * @param viewport The viewport
  * @param cullingEnabled Whether frustum culling is enabled or not
+ * @param stopperNode Marker node that stops rendering(must be rendered)
  */
 inline void AddRenderersToRenderList(BufferIndex               updateBufferIndex,
                                      uint32_t                  renderPass,
@@ -382,7 +389,8 @@ inline void AddRenderersToRenderList(BufferIndex               updateBufferIndex
                                      bool                      isLayer3d,
                                      bool                      viewportSet,
                                      const Viewport&           viewport,
-                                     bool                      cullingEnabled)
+                                     bool                      cullingEnabled,
+                                     Node*                     stopperNode)
 {
   DALI_LOG_INFO(gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
 
@@ -398,7 +406,8 @@ inline void AddRenderersToRenderList(BufferIndex               updateBufferIndex
                             isLayer3d,
                             viewportSet,
                             viewport,
-                            cullingEnabled);
+                            cullingEnabled,
+                            stopperNode);
   }
 }
 
@@ -574,6 +583,8 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
   Viewport viewport;
   bool     viewportSet = renderTask.QueryViewport(updateBufferIndex, viewport);
 
+  Node* stopperNode = renderTask.GetStopperNode();
+
   const SortedLayersIter endIter = sortedLayers.end();
   for(SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter)
   {
@@ -605,7 +616,8 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
                                  isLayer3D,
                                  viewportSet,
                                  viewport,
-                                 cull);
+                                 cull,
+                                 stopperNode);
 
         // We only use the clipping version of the sort comparitor if any clipping nodes exist within the RenderList.
         SortRenderItems(updateBufferIndex, *renderList, layer, hasClippingNodes, isOrthographicCamera);
@@ -616,6 +628,11 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
       }
 
       isRenderListAdded = true;
+
+      if(stopperNode && renderList->RenderUntil(stopperNode))
+      {
+        break;
+      }
     }
 
     if(!layer.overlayRenderables.Empty())
@@ -635,7 +652,8 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
                                  isLayer3D,
                                  viewportSet,
                                  viewport,
-                                 cull);
+                                 cull,
+                                 stopperNode);
 
         // Clipping hierarchy is irrelevant when sorting overlay items, so we specify using the non-clipping version of the sort comparitor.
         SortRenderItems(updateBufferIndex, *renderList, layer, false, isOrthographicCamera);
@@ -646,6 +664,11 @@ void RenderInstructionProcessor::Prepare(BufferIndex                 updateBuffe
       }
 
       isRenderListAdded = true;
+
+      if(stopperNode && renderList->RenderUntil(stopperNode))
+      {
+        break;
+      }
     }
   }
 
index 2f87cf28aa6eb7986699b5e359dbaee8ef7d4e35..517868b87eb548c5381ef6004ba9a9f958731240 100644 (file)
@@ -94,7 +94,6 @@ Layer* FindLayer(Node& node)
  * @param[in]  clippingDepth The current scissor clipping depth
  * @param[out] clippingUsed  Gets set to true if any clipping nodes have been found
  * @param[out] keepRendering Gets set to true if rendering should be kept.
- * @param[out] renderStopped Gets set to true if rendering should be stopped.
  */
 void AddRenderablesForTask(BufferIndex updateBufferIndex,
                            Node&       node,
@@ -106,14 +105,8 @@ void AddRenderablesForTask(BufferIndex updateBufferIndex,
                            uint32_t    clippingDepth,
                            uint32_t    scissorDepth,
                            bool&       clippingUsed,
-                           bool&       keepRendering,
-                           bool&       renderStopped)
+                           bool&       keepRendering)
 {
-  if(renderStopped)
-  {
-    return;
-  }
-
   // Short-circuit for invisible nodes
   if(!node.IsVisible(updateBufferIndex))
   {
@@ -192,18 +185,19 @@ void AddRenderablesForTask(BufferIndex updateBufferIndex,
     keepRendering = keepRendering || (rendererKey->GetRenderingBehavior() == DevelRenderer::Rendering::CONTINUOUSLY);
   }
 
+  if(DALI_UNLIKELY(node == renderTask.GetStopperNode() && count == 0u))
+  {
+    // Forcibly add renderables if stopper node don't have renderer.
+    target.PushBack(Renderable(&node, RendererKey{}));
+  }
+
   // Recurse children.
   NodeContainer& children = node.GetChildren();
   const NodeIter endIter  = children.End();
-  for(NodeIter iter = children.Begin(); !renderStopped && iter != endIter; ++iter)
+  for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
   {
     Node& child = **iter;
-    if(child == renderTask.GetStopperNode())
-    {
-      renderStopped = true;
-      break;
-    }
-    AddRenderablesForTask(updateBufferIndex, child, parentVisibilityChanged, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering, renderStopped);
+    AddRenderablesForTask(updateBufferIndex, child, parentVisibilityChanged, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering);
   }
 }
 
@@ -295,8 +289,6 @@ void ProcessTasks(BufferIndex                          updateBufferIndex,
         sortedLayer->ClearRenderables();
       }
 
-      bool stopRendering = false;
-
       AddRenderablesForTask(updateBufferIndex,
                             *sourceNode,
                             false,
@@ -307,8 +299,7 @@ void ProcessTasks(BufferIndex                          updateBufferIndex,
                             0u,
                             0u,
                             hasClippingNodes,
-                            keepRendering,
-                            stopRendering);
+                            keepRendering);
 
       renderInstructionProcessor.Prepare(updateBufferIndex,
                                          sortedLayers,
index 67d0167ced635492e8a813e62615f09a285f76f1..7fbba3d7412402b4034f5e84bbb5e2f04448369a 100644 (file)
@@ -512,6 +512,7 @@ RenderTask::RenderTask()
   mRenderMessageDispatcher(nullptr),
   mRenderSyncTracker(nullptr),
   mSourceNode(nullptr),
+  mStopperNode(nullptr),
   mCameraNode(nullptr),
   mViewportGuideNode(nullptr),
   mFrameBuffer(nullptr),
index 6b866a834e5850d178df1fa68f9e859bc5be7229..6099aeaab27645cc8c4fcfe308d619ec6b5e6f56 100644 (file)
@@ -87,7 +87,16 @@ public:
    */
   Node* GetSourceNode() const;
 
+  /**
+   * Set the node to stop rendering.
+   * @param[in] node This node will mark where to stop rendering.
+   */
   void SetStopperNode(Node* node);
+
+  /**
+   * Retrieve the stopper node.
+   * @return A marker node to stop rendering.
+   */
   Node* GetStopperNode() const;
 
   /**
index 7b26b567b4a17d6625014abd58158c68ce1eb025..e249d4771a2f314e245e8cbd2596613291a5bf19 100644 (file)
@@ -312,10 +312,10 @@ uint32_t RenderTask::GetRenderTaskId() const
   return GetImplementation(*this).GetRenderTaskId();
 }
 
-void RenderTask::RenderUntil(Actor actor)
+void RenderTask::RenderUntil(Actor stopperActor)
 {
-  DALI_ASSERT_ALWAYS(actor && "RenderUntil() actor does not exist.");
-  Internal::Actor* actorImpl(&GetImplementation(actor));
+  DALI_ASSERT_ALWAYS(stopperActor && "RenderUntil() stopperActor does not exist.");
+  Internal::Actor* actorImpl(&GetImplementation(stopperActor));
   return GetImplementation(*this).RenderUntil(actorImpl);
 }
 
index 5d6be1ae82a5847ce5e42846e70a69a825f055b4..e00eea8eeec5b2c97bb4e19d7ae7864a50472cd2 100644 (file)
@@ -256,6 +256,11 @@ public:
    */
   Actor GetSourceActor() const;
 
+  /**
+   * @brief Retrives stopper actor.
+   * @SINCE_2_3.23
+   * @return The actor that marks where to stop rendering.
+   */
   Actor GetStopperActor() const;
 
   /**
@@ -581,7 +586,12 @@ public:
    */
   uint32_t GetRenderTaskId() const;
 
-  void RenderUntil(Actor actor);
+  /**
+   * @brief Stop rendering from given actor. The actor is not included.
+   * @SINCE_2_3.23
+   * @param[in] stopperActor A marker to stop rendering.
+   */
+  void RenderUntil(Actor stopperActor);
 
 public: // Signals
   /**