Make an Actor be exclusive source actor for multiple RenderTask 87/297787/2
authorseungho baek <sbsh.baek@samsung.com>
Thu, 24 Aug 2023 08:12:14 +0000 (17:12 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Thu, 24 Aug 2023 08:36:34 +0000 (17:36 +0900)
Change-Id: Id0e6db5a514c3fc2d4c53bb3e5da83ea9f27f0c4
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
automated-tests/src/dali/utc-Dali-RenderTask.cpp
dali/internal/update/manager/render-task-processor.cpp
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/render-tasks/scene-graph-render-task.cpp

index a74afa9..b92b19c 100644 (file)
@@ -894,6 +894,68 @@ int UtcDaliRenderTaskSetExclusive02(void)
   END_TEST;
 }
 
+int UtcDaliRenderTaskSetExclusive03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetExclusive() Check that changing from exclusive to not-exclusive works");
+
+  std::vector<GLuint> ids;
+  ids.push_back(8); // 8 = actor1
+  application.GetGlAbstraction().SetNextTextureIds(ids);
+
+  Texture img1   = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 1, 1);
+  Actor   actor1 = CreateRenderableActor(img1);
+  actor1.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+  application.GetScene().Add(actor1);
+
+  RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+  RenderTask     task     = taskList.CreateTask();
+
+  task.SetSourceActor(actor1);
+  task.SetExclusive(true); // Actor should only render once
+
+  TestGlAbstraction& gl        = application.GetGlAbstraction();
+  TraceCallStack&    drawTrace = gl.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  // Update & Render actor1
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION);
+
+  // Set task to non-exclusive - actor1 should render twice:
+  drawTrace.Reset();
+
+  RenderTask task2 = taskList.CreateTask();
+  task2.SetSourceActor(actor1);
+  task2.SetExclusive(true); // Actor should only render once
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION);
+
+  // Set task to non-exclusive - actor1 should render twice:
+  drawTrace.Reset();
+  task.SetExclusive(false);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION);
+
+  // Set task to non-exclusive - actor1 should render twice:
+  drawTrace.Reset();
+  task2.SetExclusive(false);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 3, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliRenderTaskSetExclusiveN(void)
 {
   TestApplication application;
index e3d937c..865e910 100644 (file)
@@ -45,10 +45,9 @@ namespace // Unnamed namespace
 // 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(node.IsExclusiveRenderTask(&task))
   {
-    return (exclusiveTo == &task);
+    return true;
   }
 
   const Node* parent = node.GetParent();
@@ -122,8 +121,7 @@ bool AddRenderablesForTask(BufferIndex updateBufferIndex,
   }
 
   // Check whether node is exclusive to a different render-task
-  const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
-  if(exclusiveTo && (exclusiveTo != &renderTask))
+  if(node.GetExclusiveRenderTaskCount() && !node.IsExclusiveRenderTask(&renderTask))
   {
     return keepRendering;
   }
index 55447df..d55095b 100644 (file)
@@ -96,7 +96,6 @@ Node::Node()
   mClippingSortModifier(0u),
   mId(++mNodeCounter),
   mParent(nullptr),
-  mExclusiveRenderTask(nullptr),
   mChildren(),
   mClippingDepth(0u),
   mScissorDepth(0u),
index 34440f2..2af3568 100644 (file)
@@ -75,6 +75,8 @@ static NodePropertyFlags RenderableUpdateFlags = NodePropertyFlags::TRANSFORM |
 class Node : public PropertyOwner, public NodeDataProvider
 {
 public:
+  using RenderTaskContainer = std::vector<RenderTask*>;
+
   // Defaults
   static const ColorMode DEFAULT_COLOR_MODE;
 
@@ -760,21 +762,53 @@ public:
   }
 
   /**
-   * Mark the node as exclusive to a single RenderTask.
-   * @param[in] renderTask The render-task, or NULL if the Node is not exclusive to a single RenderTask.
+   * Add RenderTask that will exclusively render this node.
+   * @param[in] renderTask The render-task to render this node exclusively.
    */
-  void SetExclusiveRenderTask(RenderTask* renderTask)
+  void AddExclusiveRenderTask(RenderTask* renderTask)
   {
-    mExclusiveRenderTask = renderTask;
+    auto found = std::find(mExclusiveRenderTasks.begin(), mExclusiveRenderTasks.end(), renderTask);
+    if(found == mExclusiveRenderTasks.end())
+    {
+      mExclusiveRenderTasks.push_back(renderTask);
+    }
   }
 
   /**
-   * Query whether the node is exclusive to a single RenderTask.
-   * @return The render-task, or NULL if the Node is not exclusive to a single RenderTask.
+   * Remove a RenderTask from exclusive render task queue.
+   * The RenderTask cannot render this node if this node is exclusive to other RenderTasks.
+   * @param[in] renderTask The render-task to be removed from exclusive render task queue.
    */
-  RenderTask* GetExclusiveRenderTask() const
+  void RemoveExclusiveRenderTask(RenderTask* renderTask)
   {
-    return mExclusiveRenderTask;
+    auto found = std::find(mExclusiveRenderTasks.begin(), mExclusiveRenderTasks.end(), renderTask);
+    if(found != mExclusiveRenderTasks.end())
+    {
+      mExclusiveRenderTasks.erase(found);
+    }
+  }
+
+  /**
+   * Retrieves the number of exclusive RenderTask for this node.
+   * @return The number of exclusive RenderTask.
+   */
+  uint32_t GetExclusiveRenderTaskCount()
+  {
+    return mExclusiveRenderTasks.size();
+  }
+
+  /**
+   * Query whether the node is exclusive to the renderTask.
+   * @return true if this node is exclusive to the renderTask.
+   */
+  bool IsExclusiveRenderTask(const RenderTask* renderTask) const
+  {
+    auto found = std::find(mExclusiveRenderTasks.begin(), mExclusiveRenderTasks.end(), renderTask);
+    if(found != mExclusiveRenderTasks.end())
+    {
+      return true;
+    }
+    return false;
   }
 
   /**
@@ -1025,8 +1059,8 @@ protected:
 
   PartialRenderingData mPartialRenderingData; ///< Cache to determine if this should be rendered again
 
-  Node*       mParent;              ///< Pointer to parent node (a child is owned by its parent)
-  RenderTask* mExclusiveRenderTask; ///< Nodes can be marked as exclusive to a single RenderTask
+  Node*               mParent;               ///< Pointer to parent node (a child is owned by its parent)
+  RenderTaskContainer mExclusiveRenderTasks; ///< Nodes can be marked as exclusive to multiple RenderTasks
 
   RendererContainer mRenderers; ///< Container of renderers; not owned
 
index 352d2a3..bfe2f5e 100644 (file)
@@ -48,7 +48,7 @@ RenderTask::~RenderTask()
     mSourceNode->RemoveObserver(*this);
     if(mExclusive)
     {
-      mSourceNode->SetExclusiveRenderTask(nullptr);
+      mSourceNode->RemoveExclusiveRenderTask(this);
     }
   }
   if(mCameraNode)
@@ -73,10 +73,7 @@ void RenderTask::SetSourceNode(Node* node)
   if(mSourceNode)
   {
     mSourceNode->RemoveObserver(*this);
-    if(this == mSourceNode->GetExclusiveRenderTask())
-    {
-      mSourceNode->SetExclusiveRenderTask(nullptr);
-    }
+    mSourceNode->RemoveExclusiveRenderTask(this);
   }
 
   mSourceNode = node;
@@ -86,7 +83,7 @@ void RenderTask::SetSourceNode(Node* node)
     mSourceNode->AddObserver(*this);
     if(mExclusive)
     {
-      mSourceNode->SetExclusiveRenderTask(this);
+      mSourceNode->AddExclusiveRenderTask(this);
     }
   }
   SetActiveStatus();
@@ -115,11 +112,11 @@ void RenderTask::SetExclusive(bool exclusive)
   {
     if(mExclusive)
     {
-      mSourceNode->SetExclusiveRenderTask(this);
+      mSourceNode->AddExclusiveRenderTask(this);
     }
-    else if(this == mSourceNode->GetExclusiveRenderTask())
+    else
     {
-      mSourceNode->SetExclusiveRenderTask(nullptr);
+      mSourceNode->RemoveExclusiveRenderTask(this);
     }
   }
 }