Fix RenderUntil not working well if stopper node is under layer + RenderUntil more... 74/316474/4
authorEunki, Hong <eunkiki.hong@samsung.com>
Thu, 22 Aug 2024 03:51:28 +0000 (12:51 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 22 Aug 2024 10:44:58 +0000 (19:44 +0900)
For now, RenderUntil consider the layer order at
render-instruction-processor side.

But RenderUntil API only consider root layer cases.

To fix this issue, let we don't check the stopper actor's parenet
is layer or not.

+

Let we make RenderUntil API more stable.

Currently, we only allow given stopper actor is under source actor.
But actually, we don't trace that stopper actor unparent or destroyed
after we call RenderUntil.

Trace that life control is quite heavy. Instead, let we make RenderUntil input
actor added freely, and instead, make the task result will render full scene
if stopper node is not under source node.

Change-Id: I9550c4c77e550d9daa61fe545dc005417a4a3f2a
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-RenderTask.cpp
dali/internal/event/render-tasks/render-task-impl.cpp
dali/internal/update/manager/render-instruction-processor.cpp
dali/public-api/render-tasks/render-task.cpp
dali/public-api/render-tasks/render-task.h

index a88f253..dce5075 100644 (file)
@@ -708,6 +708,11 @@ int UtcDaliRenderTaskGetStopperActorP(void)
 
   DALI_TEST_EQUALS(actor, task.GetStopperActor(), TEST_LOCATION);
 
+  // Cancel render until, by set empty handle
+  task.RenderUntil(Dali::Actor());
+
+  DALI_TEST_EQUALS(Dali::Actor(), task.GetStopperActor(), TEST_LOCATION);
+
   END_TEST;
 }
 
@@ -833,43 +838,378 @@ int UtcDaliRenderTaskRenderUntil03(void)
 
   Integration::Scene stage = application.GetScene();
 
+  auto CreateRenderableActorWithName = [](const char* name) -> Actor {
+    Actor actor = CreateRenderableActor();
+    actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    actor.SetProperty(Actor::Property::NAME, name);
+
+    return actor;
+  };
+
   // Compose a tree
-  Actor a0 = CreateRenderableActor();
-  a0.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
-  a0.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  //
+  // stage (depth = 0)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 1)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- target (stopper node)
+  // |- a2 (renderable)
+  //     |- l2  (depth = 2)
+  //         |- (renderable)
+  //         |- (renderable)
+  //         |- (renderable)
+  Actor a0 = CreateRenderableActorWithName("a0");
 
   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 a1 = CreateRenderableActorWithName("a1");
 
-  Actor target = CreateRenderableActor();
-  target.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+  Actor target = CreateRenderableActorWithName("target");
 
-  Layer l2 = Layer::New(); // same depth index to root, added(drawn) later
+  Layer l2 = Layer::New();
   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));
+  Actor a2 = CreateRenderableActorWithName("a2");
 
   stage.Add(a0);
   a0.Add(l0);
-  l0.Add(CreateRenderableActor());
+  l0.Add(CreateRenderableActorWithName("l0-c0"));
+  l0.Add(CreateRenderableActorWithName("l0-c1"));
 
   stage.Add(a1);
   a1.Add(target);
 
   stage.Add(a2);
   a2.Add(l2);
-  l2.Add(CreateRenderableActor());
+  l2.Add(CreateRenderableActorWithName("l2-c0"));
+  l2.Add(CreateRenderableActorWithName("l2-c1"));
+  l2.Add(CreateRenderableActorWithName("l2-c2"));
 
   // draw only a0 and a1 (2 items)
-  // l0 and children is cut(low depth index)
+  // l0, l2 and children is cut(high depth index than stage)
+  // 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);
+
+  drawTrace.Reset();
+
+  // Move l2 lower than stage.
+  //
+  // stage (depth = 1)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 2)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- target (stopper node)
+  // |- a2 (renderable)
+  //     |- l2  (depth = 0)
+  //         |- (renderable)
+  //         |- (renderable)
+  //         |- (renderable)
+  l2.LowerToBottom();
+
+  // After now, draw a0, a1, and child of l2 (2 + 3 items)
+  // l0 and children is cut(high depth index than stage)
   // a2 and children are cut(added after target)
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 5, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskRenderUntil04(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::RenderUntil(actor) Check that other preceding layers are rendered, for more complex cases");
+
+  // Get default rendertask
+  RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+  RenderTask     task     = taskList.GetTask(0u);
+
+  Integration::Scene stage = application.GetScene();
+
+  auto CreateRenderableActorWithName = [](const char* name) -> Actor {
+    Actor actor = CreateRenderableActor();
+    actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    actor.SetProperty(Actor::Property::NAME, name);
+
+    return actor;
+  };
+
+  // Compose a tree
+  //
+  // stage (depth = 0)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 1)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- l1 (depth = 2)
+  //         |- b0 (renderable)
+  //         |- target (stopper node)
+  //         |- b1 (renderable)
+  // |- a2 (renderable)
+  //     |- l2  (depth = 3)
+  //         |- (renderable)
+  //         |- (renderable)
+  //         |- (renderable)
+  Actor a0 = CreateRenderableActorWithName("a0");
+
+  Layer l0 = Layer::New();
+  l0.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  l0.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  Actor a1 = CreateRenderableActorWithName("a1");
+
+  Layer l1 = Layer::New();
+  l1.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  l1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  Actor b0 = CreateRenderableActorWithName("b0");
+
+  Actor target = CreateRenderableActorWithName("target");
+
+  Actor b1 = CreateRenderableActorWithName("b1");
+
+  Layer l2 = Layer::New();
+  l2.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  l2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+  Actor a2 = CreateRenderableActorWithName("a2");
+
+  stage.Add(a0);
+  a0.Add(l0);
+  l0.Add(CreateRenderableActorWithName("l0-c0"));
+  l0.Add(CreateRenderableActorWithName("l0-c1"));
+
+  stage.Add(a1);
+  a1.Add(l1);
+  l1.Add(b0);
+  l1.Add(target);
+  l1.Add(b1);
+
+  stage.Add(a2);
+  a2.Add(l2);
+  l2.Add(CreateRenderableActorWithName("l2-c0"));
+  l2.Add(CreateRenderableActorWithName("l2-c1"));
+  l2.Add(CreateRenderableActorWithName("l2-c2"));
+
+  // draw a0, a1, a2, and l0, and b0 (3 + 2 + 1 items)
+  // l2 and children is cut(high depth index than l1)
+  // b1 is cut out (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"), 6, TEST_LOCATION);
+
+  drawTrace.Reset();
+
+  // Move l1 lower than stage.
+  //
+  // stage (depth = 1)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 2)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- l1 (depth = 0)
+  //         |- b0 (renderable)
+  //         |- target (stopper node)
+  //         |- b1 (renderable)
+  // |- a2 (renderable)
+  //     |- l2  (depth = 3)
+  //         |- (renderable)
+  //         |- (renderable)
+  //         |- (renderable)
+  l1.LowerToBottom();
+
+  // After now, draw b0 only.
+  // root layer, l1, l2 and children is cut(high depth index than l1, what target hold)
+  // b1 is cut out (added after target)
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION);
+
+  drawTrace.Reset();
+
+  // Move l2 lower than stage.
+  //
+  // stage (depth = 2)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 3)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- l1 (depth = 1)
+  //         |- b0 (renderable)
+  //         |- target (stopper node)
+  //         |- b1 (renderable)
+  // |- a2 (renderable)
+  //     |- l2  (depth = 0)
+  //         |- (renderable)
+  //         |- (renderable)
+  //         |- (renderable)
+  l2.LowerToBottom();
+
+  // After now, draw b0 and l2 (1 + 3 items).
+  // root layer, l1 and children is cut(high depth index than l1, what target hold)
+  // b1 is cut out (added after target)
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 4, TEST_LOCATION);
+
+  drawTrace.Reset();
+
+  // Make b0 and a2 draw mode as overlay
+  //
+  // stage (depth = 2)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 3)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- l1 (depth = 1)
+  //         |- b0 (renderable) (overlay)
+  //         |- target (stopper node)
+  //         |- b1 (renderable)
+  // |- a2 (renderable) (overlay)
+  //     |- l2  (depth = 0)
+  //         |- (renderable) (overlay)
+  //         |- (renderable)
+  //         |- (renderable)
+  b0.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+  a2.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+  l2.GetChildAt(0).SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+
+  // After now, draw l2 (3 items).
+  // root layer, l1 and children is cut(high depth index than l1, what target hold)
+  // b1 is cut out (added after target)
+  // b0 is cut out (overlay mode)
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 3, TEST_LOCATION);
+
+  drawTrace.Reset();
+
+  // Make target draw mode as overlay
+  //
+  // stage (depth = 2)
+  // |- a0 (renderable)
+  //     |- l0 (depth = 3)
+  //         |- (renderable)
+  //         |- (renderable)
+  // |- a1 (renderable)
+  //     |- l1 (depth = 1)
+  //         |- b0 (renderable) (overlay)
+  //         |- target (stopper node) (overlay)
+  //         |- b1 (renderable)
+  // |- a2 (renderable) (overlay)
+  //     |- l2  (depth = 0)
+  //         |- (renderable) (overlay)
+  //         |- (renderable)
+  //         |- (renderable)
+  target.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+
+  // After now, draw b0, b1, and l2 (2 + 3 items).
+  // root layer, l1 and children is cut(high depth index than l1, what target hold)
+  // b1 is not be cut out due to target is overlay mode
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 5, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskRenderUntil05(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::RenderUntil(actor) Check that stopper actor scene off and scene on again");
+
+  // Get default rendertask
+  RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+  RenderTask     task     = taskList.GetTask(0u);
+
+  Integration::Scene stage = application.GetScene();
+
+  auto CreateRenderableActorWithName = [](const char* name) -> Actor {
+    Actor actor = CreateRenderableActor();
+    actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    actor.SetProperty(Actor::Property::NAME, name);
+
+    return actor;
+  };
+
+  // Compose a tree
+  //
+  // stage (depth = 0)
+  // |- a0 (renderable)
+  // |- a1 (renderable)
+  //     |- target (stopper node)
+  // |- a2 (renderable)
+  Actor a0     = CreateRenderableActorWithName("a0");
+  Actor a1     = CreateRenderableActorWithName("a1");
+  Actor a2     = CreateRenderableActorWithName("a2");
+  Actor target = CreateRenderableActorWithName("target");
+
+  stage.Add(a0);
+  stage.Add(a1);
+  stage.Add(a2);
+  a1.Add(target);
+
+  // draw a0, a1 (2 items)
   task.RenderUntil(target);
 
   // Update & Render with the actor on-stage
@@ -884,6 +1224,65 @@ int UtcDaliRenderTaskRenderUntil03(void)
   // Check that rendering was cut
   DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION);
 
+  drawTrace.Reset();
+
+  // Unparent target
+  //
+  // stage (depth = 0)
+  // |- a0 (renderable)
+  // |- a1 (renderable)
+  // |- a2 (renderable)
+  target.Unparent();
+
+  // After now, draw all actors, a0, a1, and a2.
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 3, TEST_LOCATION);
+
+  drawTrace.Reset();
+
+  // Add target under a0.
+  //
+  // stage (depth = 0)
+  // |- a0 (renderable)
+  //     |- target (stopper node)
+  // |- a1 (renderable)
+  // |- a2 (renderable)
+  a0.Add(target);
+
+  // After now, draw a0 only.
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 1, TEST_LOCATION);
+
+  drawTrace.Reset();
+
+  // Cancel RenderUntil.
+  //
+  // stage (depth = 0)
+  // |- a0 (renderable)
+  //     |- target (renderable)
+  // |- a1 (renderable)
+  // |- a2 (renderable)
+  task.RenderUntil(Dali::Actor());
+
+  // After now, draw all actors (4 items).
+
+  // Update & Render
+  application.SendNotification();
+  application.Render();
+
+  // Check that rendering was cut
+  DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 4, TEST_LOCATION);
+
   END_TEST;
 }
 
index c9bce25..f1a2f9e 100644 (file)
@@ -657,20 +657,18 @@ uint32_t RenderTask::GetRenderTaskId() const
 
 void RenderTask::RenderUntil(Actor* stopperActor)
 {
-  Actor* target = mSourceActor.GetActor();
-  DALI_ASSERT_ALWAYS((target && stopperActor) && "RenderTask::RenderUntil() has empty actors.");
-  DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < stopperActor->GetHierarchyDepth()) && "RenderTask::RenderUntil() has reversed hierarchy.");
+  mStopperActor.SetActor(stopperActor);
 
-  Actor* parent = stopperActor;
-  while(parent != target && !(parent->IsLayer()))
-  {
-    parent = parent->GetParent();
-  }
-
-  if(parent == target && GetRenderTaskSceneObject())
+  if(GetRenderTaskSceneObject())
   {
-    mStopperActor.SetActor(stopperActor);
-    SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &stopperActor->GetNode());
+    if(stopperActor)
+    {
+      SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &stopperActor->GetNode());
+    }
+    else
+    {
+      SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), nullptr);
+    }
   }
 }
 
index 5b86a32..a3fff00 100644 (file)
@@ -288,8 +288,8 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
       // We can skip render when node is not clipping and transparent
       // We must not skip when node is a stopper
       skipRender = (opacityType == Renderer::TRANSPARENT &&
-          node->GetClippingMode() == ClippingMode::DISABLED &&
-          node != stopperNode);
+                    node->GetClippingMode() == ClippingMode::DISABLED &&
+                    node != stopperNode);
 
       isOpaque = (opacityType == Renderer::OPAQUE);
     }
index e249d47..a30f971 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -314,8 +314,12 @@ uint32_t RenderTask::GetRenderTaskId() const
 
 void RenderTask::RenderUntil(Actor stopperActor)
 {
-  DALI_ASSERT_ALWAYS(stopperActor && "RenderUntil() stopperActor does not exist.");
-  Internal::Actor* actorImpl(&GetImplementation(stopperActor));
+  // NULL handle is allowed
+  Internal::Actor* actorImpl(nullptr);
+  if(stopperActor)
+  {
+    actorImpl = &GetImplementation(stopperActor);
+  }
   return GetImplementation(*this).RenderUntil(actorImpl);
 }
 
index e00eea8..1835d06 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_RENDER_TASK_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -590,6 +590,7 @@ public:
    * @brief Stop rendering from given actor. The actor is not included.
    * @SINCE_2_3.23
    * @param[in] stopperActor A marker to stop rendering.
+   * If actor is an empty handle, or stopperActor is not a child of sourceActor, then full scene will be rendered
    */
   void RenderUntil(Actor stopperActor);