Fix partial update issues 61/284761/7
authorHeeyong Song <heeyong.song@samsung.com>
Fri, 25 Nov 2022 06:36:00 +0000 (15:36 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Thu, 8 Dec 2022 08:43:23 +0000 (17:43 +0900)
Try to reuse RenderItems of the default root layer

Handle below cases for partial update
- One actor has multiple renderers
- One renderer is used by multiple actors
- Update uniform hash every frame

Change-Id: Iac12c5e00f9eb3fc507bbd4d15560f39f13b3061

24 files changed:
automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-DecoratedVisualRenderer.cpp
automated-tests/src/dali/utc-Dali-Renderer.cpp
automated-tests/src/dali/utc-Dali-Texture.cpp
automated-tests/src/dali/utc-Dali-VisualRenderer.cpp
dali/internal/common/core-impl.cpp
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-manager.cpp
dali/internal/render/data-providers/render-data-provider.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/render/renderers/render-texture.cpp
dali/internal/render/renderers/render-texture.h
dali/internal/update/common/node-resetter.h
dali/internal/update/manager/render-instruction-processor.cpp
dali/internal/update/manager/update-algorithms.cpp
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/nodes/partial-rendering-data.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h
dali/internal/update/rendering/scene-graph-texture-set.cpp

index 09ec1a6..a4264a4 100644 (file)
@@ -8790,9 +8790,11 @@ int utcDaliActorPartialUpdateSetColor(void)
 
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   // 2. Set new color
   actor.SetProperty(Actor::Property::COLOR, Vector3(1.0f, 0.0f, 0.0f));
@@ -9000,7 +9002,7 @@ int utcDaliActorPartialUpdateTwoActors(void)
   END_TEST;
 }
 
-int utcDaliActorPartialUpdateActorsWithSizeHint(void)
+int utcDaliActorPartialUpdateActorsWithSizeHint01(void)
 {
   TestApplication application(
     TestApplication::DEFAULT_SURFACE_WIDTH,
@@ -9053,10 +9055,6 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
-
   // Ensure the damaged rect is empty
   DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
@@ -9095,6 +9093,67 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Chnage UPDATE_AREA_HINT
+  actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(-32.0f, -16.0f, 64.0f, 64.0f));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  clippingRect = Rect<int>(0, 720, 80, 80);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliActorPartialUpdateActorsWithSizeHint02(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with partial update and actor size hint");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  Actor actor = CreateRenderableActor();
+  actor.SetProperty(Actor::Property::POSITION, Vector3(64.0f, 64.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(32.0f, 32.0f, 0.0f));
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  std::vector<Rect<int>> damagedRects;
+  application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  Rect<int> clippingRect = Rect<int>(48, 720, 48, 48);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
@@ -9103,7 +9162,32 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
   DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
   // Chnage UPDATE_AREA_HINT
-  actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(-32.0f, -16.0f, 64.0f, 64.0f));
+  actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(0.0f, 0.0f, 64.0f, 64.0f));
+
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  clippingRect = Rect<int>(32, 704, 80, 80);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Chnage UPDATE_AREA_HINT
+  actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(16.0f, 16.0f, 64.0f, 64.0f));
   application.GetScene().Add(actor);
 
   application.SendNotification();
@@ -9111,7 +9195,7 @@ int utcDaliActorPartialUpdateActorsWithSizeHint(void)
 
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
 
-  clippingRect = Rect<int>(0, 720, 80, 80);
+  clippingRect = Rect<int>(32, 688, 96, 96);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
 
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
@@ -9168,11 +9252,6 @@ int utcDaliActorPartialUpdateAnimation(void)
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  damagedRects.clear();
-  clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
-
   // Make an animation
   Animation animation = Animation::New(1.0f);
   animation.AnimateTo(Property(actor2, Actor::Property::POSITION_X), 160.0f, TimePeriod(0.5f, 0.5f));
@@ -9235,8 +9314,7 @@ int utcDaliActorPartialUpdateAnimation(void)
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(500, nullptr, damagedRects);
 
-  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
-  DALI_TEST_EQUALS<Rect<int>>(expectedRect2, damagedRects[0], TEST_LOCATION);
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
@@ -9672,7 +9750,7 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
 
   // Aligned by 16
-  Rect<int> clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates, includes 3 last frames updates
+  Rect<int> clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
 
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
@@ -9685,9 +9763,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
   // Make the actor transparent by changing opacity of the Renderer
   // It changes a uniform value
@@ -9699,9 +9776,9 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   // The damaged rect should be same
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
-  DALI_TEST_CHECK(damagedRects.size() > 0);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
@@ -9718,12 +9795,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   // The damaged rect should not be empty
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
-
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   damagedRects.clear();
@@ -9741,12 +9814,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   // The damaged rect should not be empty
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
-
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   damagedRects.clear();
@@ -9764,12 +9833,8 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   // The damaged rect should not be empty
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
-
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   damagedRects.clear();
@@ -9787,9 +9852,9 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   // The damaged rect should be same
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_CHECK(damagedRects.size() > 0);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
@@ -9806,9 +9871,9 @@ int utcDaliActorPartialUpdateChangeTransparency(void)
   // The damaged rect should not be empty
   damagedRects.clear();
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
   END_TEST;
 }
@@ -10116,6 +10181,192 @@ int utcDaliActorPartialUpdate3DTransform(void)
   END_TEST;
 }
 
+int utcDaliActorPartialUpdateOneActorMultipleRenderers(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with one actor which has multiple renderers");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  Actor actor = CreateRenderableActor();
+
+  // Create another renderer
+  Geometry geometry  = CreateQuadGeometry();
+  Shader   shader    = CreateShader();
+  Renderer renderer2 = Renderer::New(geometry, shader);
+  actor.AddRenderer(renderer2);
+
+  actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  actor[Actor::Property::POSITION]     = Vector3(16.0f, 16.0f, 0.0f);
+  actor[Actor::Property::SIZE]         = Vector3(16.0f, 16.0f, 0.0f);
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 2u, TEST_LOCATION);
+
+  std::vector<Rect<int>> damagedRects;
+
+  // Actor added, damaged rect is added size of actor
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION);
+
+  // Aligned by 16
+  Rect<int> clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[1], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Make renderer2 dirty
+  renderer2[DevelRenderer::Property::OPACITY] = 0.5f;
+
+  application.SendNotification();
+
+  // The damaged rect should be the actor area
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Make renderer2 dirty
+  renderer2[Renderer::Property::FACE_CULLING_MODE] = FaceCullingMode::BACK;
+
+  application.SendNotification();
+
+  // The damaged rect should be the actor area
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliActorPartialUpdateMultipleActorsOneRenderer(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with multiple actors which share a same renderer");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  Actor actor                          = CreateRenderableActor();
+  actor[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  actor[Actor::Property::POSITION]     = Vector3(16.0f, 16.0f, 0.0f);
+  actor[Actor::Property::SIZE]         = Vector3(16.0f, 16.0f, 0.0f);
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  application.GetScene().Add(actor);
+
+  // Create another actor which has the same renderer with actor1
+  Actor    actor2   = Actor::New();
+  Renderer renderer = actor.GetRendererAt(0);
+  actor2.AddRenderer(renderer);
+  actor2[Actor::Property::ANCHOR_POINT] = AnchorPoint::TOP_LEFT;
+  actor2[Actor::Property::POSITION]     = Vector3(16.0f, 16.0f, 0.0f);
+  actor2[Actor::Property::SIZE]         = Vector3(16.0f, 16.0f, 0.0f);
+  actor2.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  application.GetScene().Add(actor2);
+
+  application.SendNotification();
+
+  std::vector<Rect<int>> damagedRects;
+
+  // Actor added, damaged rect is added size of actor
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION);
+
+  // Aligned by 16
+  Rect<int> clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[1], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Make renderer dirty
+  renderer[DevelRenderer::Property::OPACITY] = 0.5f;
+
+  application.SendNotification();
+
+  // The damaged rect should be the actor area
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS(damagedRects.size(), 2, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[1], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliActorCaptureAllTouchAfterStartPropertyP(void)
 {
   TestApplication application;
index ab8eb18..e0f8c28 100644 (file)
@@ -848,9 +848,8 @@ int UtcDaliDecoratedVisualRendererPartialUpdate(void)
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
   // Set clippingRect as full surface now. TODO : Set valid rect if we can.
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
@@ -1027,4 +1026,4 @@ int UtcDaliDecoratedVisualRendererPartialUpdate(void)
   DALI_TEST_EQUALS(renderer.GetProperty<float>(index), -1.0f, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
index 0ae0595..3fd820b 100644 (file)
@@ -3980,3 +3980,221 @@ int UtcDaliRendererUniformArrayOfStruct(void)
 
   END_TEST;
 }
+
+int utcDaliRendererPartialUpdateChangeUniform(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with changing uniform");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  std::vector<Rect<int>> damagedRects;
+  Rect<int>              clippingRect;
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  // First render pass, nothing to render, adaptor would just do swap buffer.
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  Shader   shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  Property::Index colorIndex = renderer.RegisterProperty("uFadeColor", Color::WHITE);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+
+  // 1. Actor added, damaged rect is added size of actor
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // 2. Change the uniform value
+  renderer.SetProperty(colorIndex, Color::RED);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 3. Change the uniform value and another property together
+  actor.SetProperty(Actor::Property::COLOR, Color::YELLOW);
+  renderer.SetProperty(colorIndex, Color::BLUE);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 4. Change the uniform value only
+  renderer.SetProperty(colorIndex, Color::RED); // Set the previous value (#2)
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliRendererPartialUpdateAddRemoveRenderer(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with adding / removing renderer");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  Shader   shader   = Shader::New("VertexSource", "FragmentSource");
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+
+  std::vector<Rect<int>> damagedRects;
+  Rect<int>              clippingRect;
+
+  // 1. Actor added, damaged rect is added size of actor
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  // 2. Remove renderer
+  actor.RemoveRenderer(renderer);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 3. Change a property value of the Renderer
+  renderer.SetProperty(DevelRenderer::Property::OPACITY, 0.5f);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 4. Add renderer again
+  actor.AddRenderer(renderer);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // 5. Remove renderer agin
+  actor.RemoveRenderer(renderer);
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  END_TEST;
+}
index b16d10b..36ae1d3 100644 (file)
@@ -1319,3 +1319,175 @@ int UtcDaliTextureGetPixelFormat(void)
 
   END_TEST;
 }
+
+int utcDaliTexturePartialUpdate01(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with partial update and texture change");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  std::vector<Rect<int32_t>> damagedRects;
+  Rect<int32_t>              clippingRect;
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader   shader   = Shader::New("vertexSrc", "fragmentSrc");
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  uint32_t   width(4);
+  uint32_t   height(4);
+  Texture    texture    = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+  TextureSet textureSet = TextureSet::New();
+  textureSet.SetTexture(0u, texture);
+  renderer.SetTextures(textureSet);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  application.GetScene().Add(actor);
+
+  damagedRects.clear();
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int32_t>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int32_t>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Upload texture
+  uint32_t  bufferSize(width * height * 4);
+  uint8_t*  buffer    = reinterpret_cast<unsigned char*>(malloc(bufferSize));
+  PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+  texture.Upload(pixelData);
+
+  damagedRects.clear();
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int32_t>(16, 768, 32, 32); // in screen coordinates
+  DALI_TEST_EQUALS<Rect<int32_t>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliTexturePartialUpdate02(void)
+{
+  TestApplication application(
+    TestApplication::DEFAULT_SURFACE_WIDTH,
+    TestApplication::DEFAULT_SURFACE_HEIGHT,
+    TestApplication::DEFAULT_HORIZONTAL_DPI,
+    TestApplication::DEFAULT_VERTICAL_DPI,
+    true,
+    true);
+
+  tet_infoline("Check the damaged rect with partial update and texture change");
+
+  const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+  std::vector<Rect<int32_t>> damagedRects;
+  Rect<int32_t>              clippingRect;
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader   shader   = Shader::New("vertexSrc", "fragmentSrc");
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  uint32_t   width(4);
+  uint32_t   height(4);
+  Texture    texture1   = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+  Texture    texture2   = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+  TextureSet textureSet = TextureSet::New();
+  textureSet.SetTexture(0u, texture1);
+  renderer.SetTextures(textureSet);
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+  actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+  application.GetScene().Add(actor);
+
+  damagedRects.clear();
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int32_t>(16, 768, 32, 32); // in screen coordinates, includes 3 last frames updates
+  DALI_TEST_EQUALS<Rect<int32_t>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  // Set another texture
+  textureSet.SetTexture(0u, texture2);
+
+  damagedRects.clear();
+  application.SendNotification();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  // Aligned by 16
+  clippingRect = Rect<int32_t>(16, 768, 32, 32); // in screen coordinates, includes 3 last frames updates
+  DALI_TEST_EQUALS<Rect<int32_t>>(clippingRect, damagedRects[0], TEST_LOCATION);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+  DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+
+  END_TEST;
+}
index b274772..d5b2f70 100644 (file)
@@ -723,7 +723,7 @@ int UtcDaliVisualRendererPartialUpdate(void)
   DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
 
   // Aligned by 16
-  Rect<int> clippingRect = Rect<int>(64, 672, 80, 80); // in screen coordinates, includes 3 last frames updates
+  Rect<int> clippingRect = Rect<int>(64, 672, 80, 80); // in screen coordinates
   DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
 
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
@@ -736,9 +736,8 @@ int UtcDaliVisualRendererPartialUpdate(void)
   application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  damagedRects.clear();
-  application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
-  application.RenderWithPartialUpdate(damagedRects, clippingRect);
+  // Ensure the damaged rect is empty
+  DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
   // Set clippingRect as full surface now. TODO : Set valid rect if we can.
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
@@ -914,4 +913,4 @@ int UtcDaliVisualRendererPartialUpdate(void)
   DALI_TEST_EQUALS(renderer.GetProperty<Vector2>(index), Vector2(0.5f, 2.0f), TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
index 919d6f5..9a5c89e 100644 (file)
@@ -234,6 +234,7 @@ void Core::RenderScene(RenderStatus& status, Integration::Scene& scene, bool ren
 
 void Core::PostRender()
 {
+  mUpdateManager->PostRender();
   mRenderManager->PostRender();
 }
 
index 0a301cb..fac9fbe 100644 (file)
@@ -651,7 +651,8 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
     bool skip = true;
     if(!rootClippingRect.IsEmpty())
     {
-      auto rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(item.mUpdateArea.x, item.mUpdateArea.y, 0.0f), Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f), mViewportRectangle.width, mViewportRectangle.height);
+      Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(bufferIndex, item.mUpdateArea) : item.mUpdateArea;
+      auto    rect       = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(updateArea.x, updateArea.y, 0.0f), Vector3(updateArea.z, updateArea.w, 0.0f), mViewportRectangle.width, mViewportRectangle.height);
 
       if(rect.Intersect(rootClippingRect))
       {
index 6c1b4de..c7b88c1 100644 (file)
@@ -630,11 +630,13 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>&
               // If the item refers to updated node or renderer.
               if(item.mIsUpdated ||
                  (item.mNode &&
-                  (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex, item.mNode)))))
+                  (item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated(mImpl->renderBufferIndex)))))
               {
                 item.mIsUpdated = false;
 
-                rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(item.mUpdateArea.x, item.mUpdateArea.y, 0.0f), Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f), viewportRect.width, viewportRect.height);
+                Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(mImpl->renderBufferIndex, item.mUpdateArea) : item.mUpdateArea;
+
+                rect = RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(updateArea.x, updateArea.y, 0.0f), Vector3(updateArea.z, updateArea.w, 0.0f), viewportRect.width, viewportRect.height);
                 if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
                 {
                   const int left   = rect.x;
@@ -713,13 +715,6 @@ void RenderManager::PreRender(Integration::Scene& scene, std::vector<Rect<int>>&
   {
     damagedRectCleaner.SetCleanOnReturn(false);
   }
-
-  // Reset updated flag from the root
-  Layer* root = sceneObject->GetRoot();
-  if(root)
-  {
-    root->SetUpdatedTree(false);
-  }
 }
 
 void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo)
@@ -1013,6 +1008,12 @@ void RenderManager::PostRender()
     iter->OnRenderFinished();
   }
 
+  // Notify RenderTexture that rendering has finished
+  for(auto&& iter : mImpl->textureContainer)
+  {
+    iter->OnRenderFinished();
+  }
+
   mImpl->UpdateTrackers();
 
   uint32_t count = 0u;
index f33822d..d8a3a0b 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDER_DATA_PROVIDER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -82,9 +82,24 @@ public:
 
   /**
    * Get the opacity
+   * @param[in] bufferIndex The current buffer index.
    * @return The opacity
    */
   virtual float GetOpacity(BufferIndex bufferIndex) const = 0;
+
+  /**
+   * @brief Retrieve if the render data is updated
+   * @return An updated flag
+   */
+  virtual bool IsUpdated() const = 0;
+
+  /**
+   * @brief Get the update area after visual properties applied.
+   * @param[in] bufferIndex The current buffer index.
+   * @param[in] originalUpdateArea The original update area before apply the visual properties.
+   * @return The recalculated size after visual properties applied.
+   */
+  virtual Vector4 GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) noexcept = 0;
 };
 
 } // namespace SceneGraph
index 4731747..b70408b 100644 (file)
@@ -186,8 +186,7 @@ Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
   mDepthWriteMode(depthWriteMode),
   mDepthTestMode(depthTestMode),
   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
-  mShaderChanged(false),
-  mUpdated(true)
+  mShaderChanged(false)
 {
   if(blendingBitmask != 0u)
   {
@@ -211,7 +210,6 @@ Renderer::~Renderer() = default;
 void Renderer::SetGeometry(Render::Geometry* geometry)
 {
   mGeometry = geometry;
-  mUpdated  = true;
 }
 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
 {
@@ -264,49 +262,41 @@ void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector<Graph
 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
 {
   mFaceCullingMode = mode;
-  mUpdated         = true;
 }
 
 void Renderer::SetBlendingBitMask(uint32_t bitmask)
 {
   mBlendingOptions.SetBitmask(bitmask);
-  mUpdated = true;
 }
 
 void Renderer::SetBlendColor(const Vector4& color)
 {
   mBlendingOptions.SetBlendColor(color);
-  mUpdated = true;
 }
 
 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
 {
   mIndexedDrawFirstElement = firstElement;
-  mUpdated                 = true;
 }
 
 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
 {
   mIndexedDrawElementsCount = elementsCount;
-  mUpdated                  = true;
 }
 
 void Renderer::EnablePreMultipliedAlpha(bool enable)
 {
   mPremultipliedAlphaEnabled = enable;
-  mUpdated                   = true;
 }
 
 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
 {
   mDepthWriteMode = depthWriteMode;
-  mUpdated        = true;
 }
 
 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
 {
   mDepthTestMode = depthTestMode;
-  mUpdated       = true;
 }
 
 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
@@ -322,7 +312,6 @@ DepthTestMode::Type Renderer::GetDepthTestMode() const
 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
 {
   mDepthFunction = depthFunction;
-  mUpdated       = true;
 }
 
 DepthFunction::Type Renderer::GetDepthFunction() const
@@ -333,7 +322,6 @@ DepthFunction::Type Renderer::GetDepthFunction() const
 void Renderer::SetRenderMode(RenderMode::Type renderMode)
 {
   mStencilParameters.renderMode = renderMode;
-  mUpdated                      = true;
 }
 
 RenderMode::Type Renderer::GetRenderMode() const
@@ -344,7 +332,6 @@ RenderMode::Type Renderer::GetRenderMode() const
 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
 {
   mStencilParameters.stencilFunction = stencilFunction;
-  mUpdated                           = true;
 }
 
 StencilFunction::Type Renderer::GetStencilFunction() const
@@ -355,7 +342,6 @@ StencilFunction::Type Renderer::GetStencilFunction() const
 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
 {
   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
-  mUpdated                               = true;
 }
 
 int Renderer::GetStencilFunctionMask() const
@@ -366,7 +352,6 @@ int Renderer::GetStencilFunctionMask() const
 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
 {
   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
-  mUpdated                                    = true;
 }
 
 int Renderer::GetStencilFunctionReference() const
@@ -377,7 +362,6 @@ int Renderer::GetStencilFunctionReference() const
 void Renderer::SetStencilMask(int stencilMask)
 {
   mStencilParameters.stencilMask = stencilMask;
-  mUpdated                       = true;
 }
 
 int Renderer::GetStencilMask() const
@@ -388,7 +372,6 @@ int Renderer::GetStencilMask() const
 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
 {
   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
-  mUpdated                                  = true;
 }
 
 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
@@ -399,7 +382,6 @@ StencilOperation::Type Renderer::GetStencilOperationOnFail() const
 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
 {
   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
-  mUpdated                                   = true;
 }
 
 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
@@ -410,7 +392,6 @@ StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
 {
   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
-  mUpdated                                   = true;
 }
 
 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
@@ -575,7 +556,6 @@ bool Renderer::Render(Graphics::CommandBuffer&                             comma
     }
   }
 
-  mUpdated = false;
   return drawn;
 }
 
@@ -877,15 +857,9 @@ void Renderer::SetShaderChanged(bool value)
   mShaderChanged = value;
 }
 
-bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
+bool Renderer::Updated(BufferIndex bufferIndex)
 {
-  if(mUpdated)
-  {
-    mUpdated = false;
-    return true;
-  }
-
-  if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged())
+  if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged() || mRenderDataProvider->IsUpdated())
   {
     return true;
   }
@@ -896,48 +870,26 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid
     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
     {
       auto texture = *iter;
-      if(texture && texture->IsNativeImage())
+      if(texture && texture->Updated())
       {
         return true;
       }
     }
   }
-
-  // Hash the property values. If the values are different, then rendering is required.
-  uint64_t                      hash           = 0xc70f6907UL;
-  const SceneGraph::UniformMap& uniformMapNode = node->GetNodeUniformMap();
-  for(uint32_t i = 0u, count = uniformMapNode.Count(); i < count; ++i)
-  {
-    hash = uniformMapNode[i].propertyPtr->Hash(bufferIndex, hash);
-  }
-
-  const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
-  const SceneGraph::CollectedUniformMap&    collectedUniformMap    = uniformMapDataProvider.GetCollectedUniformMap();
-  for(uint32_t i = 0u, count = collectedUniformMap.Count(); i < count; ++i)
-  {
-    hash = collectedUniformMap.mUniformMap[i].propertyPtr->Hash(bufferIndex, hash);
-  }
-
-  if(mUniformsHash != hash)
-  {
-    mUniformsHash = hash;
-    return true;
-  }
-
   return false;
 }
 
+Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept
+{
+  return mRenderDataProvider->GetVisualTransformedUpdateArea(bufferIndex, originalUpdateArea);
+}
+
 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
   Program&                                             program,
   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
   const SceneGraph::NodeDataProvider&                  node,
   bool                                                 blend)
 {
-  if(mGeometry->AttributesChanged())
-  {
-    mUpdated = true;
-  }
-
   // Prepare query info
   PipelineCacheQueryInfo queryInfo{};
   queryInfo.program               = &program;
index d548efc..51f661e 100644 (file)
@@ -426,9 +426,8 @@ public:
    * Check if the renderer attributes/uniforms are updated and returns the flag
    *
    * @param[in] bufferIndex The current update buffer index.
-   * @param[in] node The node using this renderer
    */
-  bool Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node);
+  bool Updated(BufferIndex bufferIndex);
 
   template<class T>
   bool WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo,
@@ -450,6 +449,16 @@ public:
     return mFaceCullingMode;
   }
 
+  /**
+   * @brief Gets update area after visual properties applied.
+   *
+   * @param[in] bufferIndex The index of the previous update buffer.
+   * @param[in] originalUpdateArea The original update area before apply the visual properties.
+   *
+   * @return The recalculated update area after visual properties applied.
+   */
+  Vector4 GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept;
+
 private:
   struct UniformIndexMap;
 
@@ -585,15 +594,12 @@ private:
   using UniformIndexMappings = std::vector<UniformIndexMap>;
   std::vector<UniformIndexMappings> mUniformIndexMaps; ///< Cached map per node/renderer/shader.
 
-  uint64_t mUniformsHash{0}; ///< Hash of uniform map property values
-
   DepthFunction::Type   mDepthFunction : 4;             ///< The depth function
   FaceCullingMode::Type mFaceCullingMode : 3;           ///< The mode of face culling
   DepthWriteMode::Type  mDepthWriteMode : 3;            ///< The depth write mode
   DepthTestMode::Type   mDepthTestMode : 3;             ///< The depth test mode
   bool                  mPremultipliedAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
   bool                  mShaderChanged : 1;             ///< Flag indicating the shader changed and uniform maps have to be updated
-  bool                  mUpdated : 1;
 
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands; // Devel stuff
   RenderCallback*                               mRenderCallback{nullptr};
index f2bc5a3..0d97e69 100644 (file)
@@ -214,7 +214,8 @@ Texture::Texture(Type type, Pixel::Format format, ImageDimensions size)
   mWidth(size.GetWidth()),
   mHeight(size.GetHeight()),
   mType(type),
-  mHasAlpha(HasAlpha(format))
+  mHasAlpha(HasAlpha(format)),
+  mUpdated(true)
 {
 }
 
@@ -227,7 +228,8 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
   mWidth(static_cast<uint16_t>(nativeImageInterface->GetWidth())),   // ignoring overflow, not happening in practice
   mHeight(static_cast<uint16_t>(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice
   mType(TextureType::TEXTURE_2D),
-  mHasAlpha(nativeImageInterface->RequiresBlending())
+  mHasAlpha(nativeImageInterface->RequiresBlending()),
+  mUpdated(true)
 {
 }
 
@@ -345,6 +347,8 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara
   updateSourceInfo.memorySource.memory = pixelData->GetBuffer();
 
   mGraphicsController->UpdateTextures({info}, {updateSourceInfo});
+
+  SetUpdated(true);
 }
 
 bool Texture::HasAlphaChannel() const
@@ -367,6 +371,11 @@ void Texture::GenerateMipmaps()
   mGraphicsController->GenerateTextureMipmaps(*mGraphicsTexture.get());
 }
 
+void Texture::OnRenderFinished()
+{
+  SetUpdated(false);
+}
+
 } // namespace Render
 
 } // namespace Internal
index a3945d8..dffbff9 100644 (file)
@@ -131,6 +131,33 @@ public:
     return static_cast<bool>(mNativeImage);
   }
 
+  /**
+   * Called from RenderManager to notify the texture that current rendering pass has finished.
+   */
+  void OnRenderFinished();
+
+  /**
+   * Set the updated flag.
+   * @param[in] updated The updated flag
+   */
+  void SetUpdated(bool updated)
+  {
+    mUpdated = updated;
+  }
+
+  /**
+   * Check if the texture is updated
+   * @return True if the texture is updated
+   */
+  [[nodiscard]] bool Updated()
+  {
+    if(mUpdated || IsNativeImage())
+    {
+      return true;
+    }
+    return false;
+  }
+
 private:
   /**
    * Helper method to apply a sampler to the texture
@@ -150,6 +177,7 @@ private:
   uint16_t      mHeight;       ///< Height of the texture
   Type          mType : 3;     ///< Type of the texture
   bool          mHasAlpha : 1; ///< Whether the format has an alpha channel
+  bool          mUpdated : 1;  ///< Whether the texture is updated
 };
 
 } // namespace Render
index 6d31da5..7f27624 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -84,6 +84,7 @@ public:
 
       mNode->mVisible.ResetToBaseValue(updateBufferIndex);
       mNode->mColor.ResetToBaseValue(updateBufferIndex);
+      mNode->mUpdateAreaHint.ResetToBaseValue(updateBufferIndex);
     }
   };
 
@@ -102,6 +103,7 @@ public:
 
     mNode->mVisible.MarkAsDirty();
     mNode->mColor.MarkAsDirty();
+    mNode->mUpdateAreaHint.MarkAsDirty();
   }
 
   /**
@@ -157,6 +159,7 @@ protected:
   {
     mNode->mVisible.MarkAsDirty();
     mNode->mColor.MarkAsDirty();
+    mNode->mUpdateAreaHint.MarkAsDirty();
   }
 
   Node*  mNode;         ///< The node that owns the properties
index 3bc7f79..50bdc0e 100644 (file)
@@ -199,14 +199,13 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
   Vector3 nodeSize;
   Vector4 nodeUpdateArea;
   bool    nodeUpdateAreaSet(false);
-  bool    nodeUpdateAreaUseHint(false);
   Matrix  nodeModelViewMatrix(false);
   bool    nodeModelViewMatrixSet(false);
 
   // Don't cull items which have render callback
   bool hasRenderCallback = (renderable.mRenderer && renderable.mRenderer->GetRenderCallback());
 
-  if(cull && renderable.mRenderer && (hasRenderCallback || (!renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED)))
+  if(cull && renderable.mRenderer && !hasRenderCallback && !renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED)
   {
     const Vector4& boundingSphere = node->GetBoundingSphere();
     inside                        = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
@@ -214,8 +213,8 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
 
     if(inside && !isLayer3d && viewportSet)
     {
-      nodeUpdateAreaUseHint = SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
-      nodeUpdateAreaSet     = true;
+      SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
+      nodeUpdateAreaSet = true;
 
       const Vector3& scale = node->GetWorldScale(updateBufferIndex);
       const Vector3& size  = Vector3(nodeUpdateArea.z, nodeUpdateArea.w, 1.0f) * scale;
@@ -261,21 +260,6 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
       // Get the next free RenderItem.
       RenderItem& item = renderList.GetNextFreeItem();
 
-      PartialRenderingData partialRenderingData;
-
-      partialRenderingData.node       = node;
-      partialRenderingData.renderer   = renderable.mRenderer;
-      partialRenderingData.color      = node->GetWorldColor(updateBufferIndex);
-      partialRenderingData.depthIndex = node->GetDepthIndex();
-      partialRenderingData.isOpaque   = isOpaque;
-
-      partialRenderingData.textureSet = nullptr;
-      if(DALI_LIKELY(renderable.mRenderer))
-      {
-        partialRenderingData.color.a *= renderable.mRenderer->GetOpacity(updateBufferIndex);
-        partialRenderingData.textureSet = renderable.mRenderer->GetTextureSet();
-      }
-
       item.mNode     = node;
       item.mIsOpaque = isOpaque;
       item.mColor    = node->GetColor(updateBufferIndex);
@@ -291,9 +275,6 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
         item.mRenderer   = &renderable.mRenderer->GetRenderer();
         item.mTextureSet = renderable.mRenderer->GetTextureSet();
         item.mDepthIndex += renderable.mRenderer->GetDepthIndex();
-
-        // Get whether collected map is up to date
-        item.mIsUpdated |= renderable.mRenderer->UniformMapUpdated();
       }
       else
       {
@@ -304,27 +285,22 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
 
       if(!nodeUpdateAreaSet)
       {
-        nodeUpdateAreaUseHint = SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
+        SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
       }
 
       item.mSize        = nodeSize;
       item.mUpdateArea  = nodeUpdateArea;
       item.mModelMatrix = nodeWorldMatrix;
 
-      // Apply transform informations if node doesn't have update size hint and use VisualRenderer.
-      if(!nodeUpdateAreaUseHint && renderable.mRenderer && renderable.mRenderer->GetVisualProperties())
-      {
-        Vector3 updateSize = renderable.mRenderer->CalculateVisualTransformedUpdateSize(updateBufferIndex, Vector3(item.mUpdateArea.z, item.mUpdateArea.w, 0.0f));
-        item.mUpdateArea.z = updateSize.x;
-        item.mUpdateArea.w = updateSize.y;
-      }
-
       if(!nodeModelViewMatrixSet)
       {
         MatrixUtils::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
       }
       item.mModelViewMatrix = nodeModelViewMatrix;
 
+      PartialRenderingData partialRenderingData;
+      partialRenderingData.color               = node->GetWorldColor(updateBufferIndex);
+      partialRenderingData.depthIndex          = node->GetDepthIndex();
       partialRenderingData.matrix              = item.mModelViewMatrix;
       partialRenderingData.updatedPositionSize = item.mUpdateArea;
       partialRenderingData.size                = item.mSize;
@@ -489,10 +465,8 @@ inline void RenderInstructionProcessor::SortRenderItems(BufferIndex bufferIndex,
 
   // List of zValue calculating functions.
   const Dali::Layer::SortFunctionType zValueFunctionFromVector3[] = {
-    [](const Vector3& position)
-    { return position.z; },
-    [](const Vector3& position)
-    { return position.LengthSquared(); },
+    [](const Vector3& position) { return position.z; },
+    [](const Vector3& position) { return position.LengthSquared(); },
     layer.GetSortFunction(),
   };
 
index 98e5a93..7cd6ac6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -113,7 +113,7 @@ inline NodePropertyFlags UpdateNodes(Node&             node,
 
   UpdateNodeOpacity(node, nodeDirtyFlags, updateBufferIndex);
 
-
+  node.UpdateUniformHash(updateBufferIndex);
 
   // For partial update, mark all children of an animating node as updated.
   if(updated) // Only set to updated if parent was updated.
@@ -211,6 +211,20 @@ inline void UpdateLayers(Node&             node,
   {
     layer->SetReuseRenderers(updateBufferIndex, false);
   }
+  else
+  {
+    // If the node is not dirty, then check renderers
+    const uint32_t count = node.GetRendererCount();
+    for(uint32_t i = 0; i < count; ++i)
+    {
+      SceneGraph::Renderer* renderer = node.GetRendererAt(i);
+      if(renderer->IsDirty())
+      {
+        layer->SetReuseRenderers(updateBufferIndex, false);
+        break;
+      }
+    }
+  }
 
   // recurse children
   NodeContainer& children = node.GetChildren();
@@ -228,6 +242,8 @@ void UpdateLayerTree(Layer&      layer,
   NodePropertyFlags nodeDirtyFlags = layer.GetDirtyFlags();
   nodeDirtyFlags |= (layer.IsLocalMatrixDirty() ? NodePropertyFlags::TRANSFORM : NodePropertyFlags::NOTHING);
 
+  layer.SetReuseRenderers(updateBufferIndex, nodeDirtyFlags == NodePropertyFlags::NOTHING);
+
   // recurse children
   NodeContainer& children = layer.GetChildren();
   const NodeIter endIter  = children.End();
index 1574b5d..1b5c1a3 100644 (file)
@@ -1140,6 +1140,20 @@ uint32_t UpdateManager::Update(float    elapsedSeconds,
   return keepUpdating;
 }
 
+void UpdateManager::PostRender()
+{
+  // Reset dirty flag
+  for(auto&& renderer : mImpl->renderers)
+  {
+    renderer->ResetDirtyFlag();
+  }
+
+  for(auto&& scene : mImpl->scenes)
+  {
+    scene->root->SetUpdatedTree(false);
+  }
+}
+
 uint32_t UpdateManager::KeepUpdatingCheck(float elapsedSeconds) const
 {
   // Update the duration set via Stage::KeepRendering()
index d1f82be..3065d34 100644 (file)
@@ -612,6 +612,11 @@ public:
                   bool     uploadOnly);
 
   /**
+   * This is called after rendering all the scenes in the next frame.
+   */
+  void PostRender();
+
+  /**
    * @copydoc Dali::Stage::KeepRendering()
    */
   void KeepRendering(float durationSeconds);
index af5962d..f0f4943 100644 (file)
@@ -270,6 +270,12 @@ NodePropertyFlags Node::GetDirtyFlags() const
     flags |= NodePropertyFlags::COLOR;
   }
 
+  // Check whether the update area property has changed
+  if(!mUpdateAreaHint.IsClean())
+  {
+    flags |= NodePropertyFlags::TRANSFORM;
+  }
+
   return flags;
 }
 
@@ -288,6 +294,20 @@ void Node::ResetDirtyFlags(BufferIndex updateBufferIndex)
   mDirtyFlags = NodePropertyFlags::NOTHING;
 }
 
+void Node::UpdateUniformHash(BufferIndex bufferIndex)
+{
+  uint64_t hash = 0xc70f6907UL;
+  for(uint32_t i = 0u, count = mUniformMaps.Count(); i < count; ++i)
+  {
+    hash = mUniformMaps[i].propertyPtr->Hash(bufferIndex, hash);
+  }
+  if(mUniformsHash != hash)
+  {
+    mUniformsHash = hash;
+    SetUpdated(true);
+  }
+}
+
 void Node::SetParent(Node& parentNode)
 {
   DALI_ASSERT_ALWAYS(this != &parentNode);
index d9acd62..3e28d7b 100644 (file)
@@ -212,6 +212,7 @@ public:
   void SetClippingMode(const ClippingMode::Type clippingMode)
   {
     mClippingMode = clippingMode;
+    SetDirtyFlag(NodePropertyFlags::TRANSFORM);
   }
 
   /**
@@ -876,6 +877,12 @@ public:
    */
   void ResetDirtyFlags(BufferIndex updateBufferIndex);
 
+  /**
+   * Update uniform hash
+   * @param[in] bufferIndex The buffer to read from.
+   */
+  void UpdateUniformHash(BufferIndex bufferIndex);
+
 protected:
   /**
    * Set the parent of a Node.
@@ -914,10 +921,10 @@ private: // from NodeDataProvider
 
 private:
   // Delete copy and move
-  Node(const Node&)                = delete;
-  Node(Node&&)                     = delete;
+  Node(const Node&) = delete;
+  Node(Node&&)      = delete;
   Node& operator=(const Node& rhs) = delete;
-  Node& operator=(Node&& rhs)      = delete;
+  Node& operator=(Node&& rhs) = delete;
 
   /**
    * Recursive helper to disconnect a Node and its children.
@@ -955,6 +962,7 @@ public: // Default properties
   TransformManagerMatrixInput     mWorldMatrix;      ///< Full inherited world matrix
   InheritedColor                  mWorldColor;       ///< Full inherited color
 
+  uint64_t       mUniformsHash{0u};     ///< Hash of uniform map property values
   uint32_t       mClippingSortModifier; ///< Contains bit-packed clipping information for quick access when sorting
   const uint32_t mId;                   ///< The Unique ID of the node.
 
index d487908..cd52c50 100644 (file)
@@ -33,16 +33,12 @@ class TextureSet;
  */
 struct PartialRenderingData
 {
-  Node*             node{nullptr};                  /// Node associated with the entry
-  Renderer*         renderer{nullptr};              /// Renderer object
-  const TextureSet* textureSet{nullptr};            /// TextureSet object
-  Matrix            matrix{};                       /// Model-view matrix
-  Vector4           color{};                        /// Color
-  Vector4           updatedPositionSize{};          /// Updated position/size (x, y, width, height)
-  Vector3           size{};                         /// Size
-  uint32_t          depthIndex{0u};                 /// Depth index
-  uint32_t          hash;                           /// Last frame's hash
-  bool              isOpaque{};                     /// Opacity state
+  Matrix   matrix{};              /// Model-view matrix
+  Vector4  color{};               /// Color
+  Vector4  updatedPositionSize{}; /// Updated position/size (x, y, width, height)
+  Vector3  size{};                /// Size
+  uint32_t depthIndex{0u};        /// Depth index
+  uint32_t hash;                  /// Last frame's hash
 
   bool mVisible{true};   /// Visible state (Not hashed)
   bool mRendered{false}; /// Rendering state (Not hashed)
@@ -53,15 +49,11 @@ struct PartialRenderingData
   void CalculateHash()
   {
     hash = Dali::INITIAL_HASH_VALUE;
-    AddToHash(hash, &node, sizeof(decltype(node)));
-    AddToHash(hash, &renderer, sizeof(decltype(renderer)));
-    AddToHash(hash, &textureSet, sizeof(decltype(textureSet)));
     AddToHash(hash, &matrix, sizeof(decltype(matrix)));
     AddToHash(hash, &color, sizeof(decltype(color)));
     AddToHash(hash, &updatedPositionSize, sizeof(decltype(updatedPositionSize)));
     AddToHash(hash, &size, sizeof(decltype(size)));
     AddToHash(hash, &depthIndex, sizeof(decltype(depthIndex)));
-    AddToHash(hash, &isOpaque, sizeof(decltype(isOpaque)));
   }
 
   /**
@@ -73,30 +65,21 @@ struct PartialRenderingData
     frameCache.CalculateHash();
 
     return hash != frameCache.hash ||
-           node != frameCache.node ||
-           renderer != frameCache.renderer ||
-           textureSet != frameCache.textureSet ||
            matrix != frameCache.matrix ||
            color != frameCache.color ||
            updatedPositionSize != frameCache.updatedPositionSize ||
            size != frameCache.size ||
            depthIndex != frameCache.depthIndex ||
-           isOpaque != frameCache.isOpaque ||
-
            !mRendered; // If everything is the same, check if we didn't render last frame.
   }
 
   void Update(const PartialRenderingData& frameCache)
   {
-    node                = frameCache.node;
-    renderer            = frameCache.renderer;
-    textureSet          = frameCache.textureSet;
     matrix              = frameCache.matrix;
     color               = frameCache.color;
     updatedPositionSize = frameCache.updatedPositionSize;
     size                = frameCache.size;
     depthIndex          = frameCache.depthIndex;
-    isOpaque            = frameCache.isOpaque;
     hash                = frameCache.hash;
 
     mRendered = true;
index 0036c92..6f4b485 100644 (file)
@@ -104,8 +104,8 @@ Renderer::Renderer()
   mRenderingBehavior(DevelRenderer::Rendering::IF_REQUIRED),
   mUpdateDecay(Renderer::Decay::INITIAL),
   mRegenerateUniformMap(false),
-  mUniformMapUpdated(false),
   mPremultipledAlphaEnabled(false),
+  mDirtyFlag(true),
   mOpacity(1.0f),
   mDepthIndex(0)
 {
@@ -293,11 +293,13 @@ bool Renderer::PrepareRender(BufferIndex updateBufferIndex)
       new(slot) DerivedType(mRenderer, &Render::Renderer::SetRenderCallback, mRenderCallback);
     }
 
+    SetUpdated(true);
+
     mResendFlag = 0;
   }
 
   // Ensure collected map is up to date
-  UpdateUniformMap();
+  UpdateUniformMap(updateBufferIndex);
 
   return rendererUpdated;
 }
@@ -307,6 +309,9 @@ void Renderer::SetTextures(TextureSet* textureSet)
   DALI_ASSERT_DEBUG(textureSet != NULL && "Texture set pointer is NULL");
 
   mTextureSet = textureSet;
+
+  mDirtyFlag = true;
+  SetUpdated(true);
 }
 
 const Vector<Render::Texture*>* Renderer::GetTextures() const
@@ -332,6 +337,7 @@ void Renderer::SetShader(Shader* shader)
   mShader->AddUniformMapObserver(*this);
   mRegenerateUniformMap = true;
   mResendFlag |= RESEND_GEOMETRY | RESEND_SHADER;
+  mDirtyFlag = true;
 }
 
 void Renderer::SetGeometry(Render::Geometry* geometry)
@@ -348,6 +354,9 @@ void Renderer::SetGeometry(Render::Geometry* geometry)
 void Renderer::SetDepthIndex(int depthIndex)
 {
   mDepthIndex = depthIndex;
+
+  mDirtyFlag = true;
+  SetUpdated(true);
 }
 
 void Renderer::SetFaceCullingMode(FaceCullingMode::Type faceCullingMode)
@@ -364,6 +373,9 @@ FaceCullingMode::Type Renderer::GetFaceCullingMode() const
 void Renderer::SetBlendMode(BlendMode::Type blendingMode)
 {
   mBlendMode = blendingMode;
+
+  mDirtyFlag = true;
+  SetUpdated(true);
 }
 
 BlendMode::Type Renderer::GetBlendMode() const
@@ -377,6 +389,7 @@ void Renderer::SetBlendingOptions(uint32_t options)
   {
     mBlendBitmask = options;
     mResendFlag |= RESEND_BLEND_BIT_MASK;
+    mDirtyFlag = true;
   }
 }
 
@@ -533,6 +546,7 @@ void Renderer::SetRenderCallback(RenderCallback* callback)
 {
   mRenderCallback = callback;
   mResendFlag |= RESEND_SET_RENDER_CALLBACK;
+  mDirtyFlag = true;
 }
 
 const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() const
@@ -543,6 +557,9 @@ const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() cons
 void Renderer::BakeOpacity(BufferIndex updateBufferIndex, float opacity)
 {
   mOpacity.Bake(updateBufferIndex, opacity);
+
+  mDirtyFlag = true;
+  SetUpdated(true);
 }
 
 float Renderer::GetOpacity(BufferIndex updateBufferIndex) const
@@ -553,6 +570,7 @@ float Renderer::GetOpacity(BufferIndex updateBufferIndex) const
 void Renderer::SetRenderingBehavior(DevelRenderer::Rendering::Type renderingBehavior)
 {
   mRenderingBehavior = renderingBehavior;
+  SetUpdated(true);
 }
 
 DevelRenderer::Rendering::Type Renderer::GetRenderingBehavior() const
@@ -656,7 +674,7 @@ Renderer::OpacityType Renderer::GetOpacityType(BufferIndex updateBufferIndex, co
   return opacityType;
 }
 
-void Renderer::UpdateUniformMap()
+void Renderer::UpdateUniformMap(BufferIndex updateBufferIndex)
 {
   if(mRegenerateUniformMap)
   {
@@ -679,7 +697,20 @@ void Renderer::UpdateUniformMap()
     }
     localMap.UpdateChangeCounter();
     mRegenerateUniformMap = false;
-    mUniformMapUpdated    = true;
+    SetUpdated(true);
+  }
+
+  uint64_t                                  hash                   = 0xc70f6907UL;
+  const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = GetUniformMapDataProvider();
+  const SceneGraph::CollectedUniformMap&    collectedUniformMap    = uniformMapDataProvider.GetCollectedUniformMap();
+  for(uint32_t i = 0u, count = collectedUniformMap.Count(); i < count; ++i)
+  {
+    hash = collectedUniformMap.mUniformMap[i].propertyPtr->Hash(updateBufferIndex, hash);
+  }
+  if(mUniformsHash != hash)
+  {
+    mUniformsHash = hash;
+    SetUpdated(true);
   }
 }
 
@@ -690,6 +721,19 @@ void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands,
   mResendFlag |= RESEND_DRAW_COMMANDS;
 }
 
+bool Renderer::IsDirty() const
+{
+  // Check whether the opacity property has changed
+  return (mDirtyFlag || !mOpacity.IsClean());
+}
+
+void Renderer::ResetDirtyFlag()
+{
+  mDirtyFlag = false;
+
+  SetUpdated(false);
+}
+
 void Renderer::UniformMappingsChanged(const UniformMap& mappings)
 {
   // The mappings are either from PropertyOwner base class, or the Shader
@@ -701,7 +745,7 @@ const CollectedUniformMap& Renderer::GetCollectedUniformMap() const
   return mCollectedUniformMap;
 }
 
-Vector3 Renderer::CalculateVisualTransformedUpdateSize(BufferIndex updateBufferIndex, const Vector3& originalSize)
+Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex updateBufferIndex, const Vector4& originalUpdateArea) noexcept
 {
   if(mVisualProperties)
   {
@@ -819,19 +863,23 @@ Vector3 Renderer::CalculateVisualTransformedUpdateSize(BufferIndex updateBufferI
     //                  = scaleVertexPosition + 2.0f * abs(basicVertexPosition)
     // Cause transform matrix will think center of vertex is (0, 0)
 
-    const Vector2 basicVertexPosition = mVisualPropertiesCoefficient.coefXB * originalSize.GetVectorXY() + mVisualPropertiesCoefficient.coefCB;
-    const Vector2 scaleVertexPosition = mVisualPropertiesCoefficient.coefXA * originalSize.GetVectorXY() + mVisualPropertiesCoefficient.coefCA;
+    const Vector2 originalXY = Vector2(originalUpdateArea.x, originalUpdateArea.y);
+    const Vector2 originalWH = Vector2(originalUpdateArea.z, originalUpdateArea.w);
+
+    const Vector2 basicVertexPosition = mVisualPropertiesCoefficient.coefXB * originalWH + mVisualPropertiesCoefficient.coefCB;
+    const Vector2 scaleVertexPosition = mVisualPropertiesCoefficient.coefXA * originalWH + mVisualPropertiesCoefficient.coefCA;
 
-    // VisualTransform don't set z value. Just copy from original z size
-    const Vector3 resultSize = Vector3(scaleVertexPosition.x + 2.0f * abs(basicVertexPosition.x) + mVisualPropertiesCoefficient.coefD,
-                                       scaleVertexPosition.y + 2.0f * abs(basicVertexPosition.y) + mVisualPropertiesCoefficient.coefD,
-                                       originalSize.z);
+    // TODO : We need to re-generate coefficient to consitder area width/height
+    const Vector4 resultArea = Vector4(originalXY.x,
+                                       originalXY.y,
+                                       scaleVertexPosition.x + 2.0f * abs(basicVertexPosition.x) + mVisualPropertiesCoefficient.coefD,
+                                       scaleVertexPosition.y + 2.0f * abs(basicVertexPosition.y) + mVisualPropertiesCoefficient.coefD);
 
-    DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "%f %f --> %f %f\n", originalSize.x, originalSize.y, resultSize.x, resultSize.y);
+    DALI_LOG_INFO(gSceneGraphRendererLogFilter, Debug::Verbose, "%f %f %f %f--> %f %f %f %f\n", originalUpdateArea.x, originalUpdateArea.y, originalUpdateArea.z, originalUpdateArea.w, resultArea.x, resultArea.y, resultArea.z, resultArea.w);
 
-    return resultSize;
+    return resultArea;
   }
-  return originalSize;
+  return originalUpdateArea;
 }
 
 } // namespace SceneGraph
index 1e672a0..f2a84d6 100644 (file)
@@ -380,6 +380,19 @@ public:
   };
 
   /**
+   * @copydoc RenderDataProvider::IsUpdated()
+   */
+  bool IsUpdated() const override
+  {
+    return Updated();
+  }
+
+  /**
+   * @copydoc RenderDataProvider::GetVisualTransformedUpdateArea()
+   */
+  Vector4 GetVisualTransformedUpdateArea(BufferIndex updateBufferIndex, const Vector4& originalUpdateArea) noexcept override;
+
+  /**
    * Sets RenderCallback object
    *
    * @param[in] callback Valid pointer to RenderCallback object
@@ -400,28 +413,27 @@ public:
    * Merge shader uniform map into renderer uniform map if any of the
    * maps have changed.  Only update uniform map if added to render
    * instructions.
+   * @param[in] updateBufferIndex The current update buffer index.
    */
-  void UpdateUniformMap();
+  void UpdateUniformMap(BufferIndex updateBufferIndex);
 
   /**
-   * @brief CHeck if the uniformMap regenerated
-   * @return True if the uniformMap changed after latest checkup.
-   * @note The uniform map updated flag is reset after calling this.
+   * Set the given external draw commands on this renderer.
    */
-  [[nodiscard]] inline bool UniformMapUpdated() noexcept
-  {
-    if(mUniformMapUpdated)
-    {
-      mUniformMapUpdated = false;
-      return true;
-    }
-    return false;
-  }
+  void SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size);
 
   /**
-   * Set the given external draw commands on this renderer.
+   * Query whether a renderer is dirty.
+   * @return true if the renderer is dirty.
+   * @note It is used to decide whether to reuse the RenderList. We can't reuse the RenderList if this is dirty.
    */
-  void SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size);
+  bool IsDirty() const;
+
+  /**
+   * Reset both dirty flag and updated flag.
+   * @note This is called after rendering has completed.
+   */
+  void ResetDirtyFlag();
 
 public: // UniformMap::Observer
   /**
@@ -458,16 +470,6 @@ public: // For VisualProperties
     return mVisualProperties.Get();
   }
 
-  /**
-   * @brief Recalculate size after visual properties applied.
-   *
-   * @param[in] updateBufferIndex The current update buffer index.
-   * @param[in] originalSize The original size before apply the visual properties.
-   *
-   * @return The recalculated size after visual properties applied.
-   */
-  Vector3 CalculateVisualTransformedUpdateSize(BufferIndex updateBufferIndex, const Vector3& originalSize);
-
 private:
   /**
    * Protected constructor; See also Renderer::New()
@@ -496,6 +498,7 @@ private:
 
   Dali::Internal::Render::Renderer::StencilParameters mStencilParameters; ///< Struct containing all stencil related options
 
+  uint64_t mUniformsHash{0};             ///< Hash of uniform map property values
   uint32_t mIndexedDrawFirstElement;     ///< first element index to be drawn using indexed draw
   uint32_t mIndexedDrawElementsCount;    ///< number of elements to be drawn using indexed draw
   uint32_t mBlendBitmask;                ///< The bitmask of blending options
@@ -510,9 +513,10 @@ private:
   DevelRenderer::Rendering::Type mRenderingBehavior : 2; ///< The rendering behavior
   Decay                          mUpdateDecay : 2;       ///< Update decay (aging)
 
-  bool                                          mRegenerateUniformMap : 1;     ///< true if the map should be regenerated
-  bool                                          mUniformMapUpdated : 1;        ///< true if the map regenerated recently.
-  bool                                          mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
+  bool mRegenerateUniformMap : 1;     ///< true if the map should be regenerated
+  bool mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
+  bool mDirtyFlag : 1;                ///< Flag indicating whether the properties are changed
+
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands;
   Dali::RenderCallback*                         mRenderCallback{nullptr};
 
index 0fa96f0..0269286 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -68,6 +68,11 @@ void TextureSet::SetSampler(uint32_t index, Render::Sampler* sampler)
   }
 
   mSamplers[index] = sampler;
+
+  if(index < static_cast<uint32_t>(mTextures.Size()))
+  {
+    mTextures[index]->SetUpdated(true);
+  }
 }
 
 void TextureSet::SetTexture(uint32_t index, Render::Texture* texture)
@@ -99,6 +104,7 @@ void TextureSet::SetTexture(uint32_t index, Render::Texture* texture)
   if(texture)
   {
     mHasAlpha |= texture->HasAlphaChannel();
+    texture->SetUpdated(true);
   }
 }