Use Vector4 for the update area 61/287661/2
authorHeeyong Song <heeyong.song@samsung.com>
Thu, 2 Feb 2023 04:41:10 +0000 (13:41 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Mon, 6 Feb 2023 09:42:56 +0000 (18:42 +0900)
Change AnimatableProperty to Vector4 for Node::mUpdateAreaHint
because it is not an animatable property
And merge the rect if the previous area is not used yet

Change-Id: I40ebe9c87201e58cd09a15b3ad8202b865575324

automated-tests/src/dali/utc-Dali-Actor.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/update/common/node-resetter.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h

index 69e13e8..92a7a0a 100644 (file)
@@ -9086,7 +9086,7 @@ int utcDaliActorPartialUpdateActorsWithSizeHint01(void)
     true,
     true);
 
-  tet_infoline("Check the damaged rect with partial update and actor size hint");
+  tet_infoline("Check the damaged rect with partial update and update area hint");
 
   const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
 
@@ -9202,7 +9202,7 @@ int utcDaliActorPartialUpdateActorsWithSizeHint02(void)
     true,
     true);
 
-  tet_infoline("Check the damaged rect with partial update and actor size hint");
+  tet_infoline("Check the damaged rect with partial update and update area hint");
 
   const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
 
@@ -9235,7 +9235,7 @@ int utcDaliActorPartialUpdateActorsWithSizeHint02(void)
   // Ensure the damaged rect is empty
   DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
 
-  // Chnage UPDATE_AREA_HINT
+  // Change UPDATE_AREA_HINT
   actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(0.0f, 0.0f, 64.0f, 64.0f));
 
   application.SendNotification();
@@ -9282,6 +9282,75 @@ int utcDaliActorPartialUpdateActorsWithSizeHint02(void)
   END_TEST;
 }
 
+int utcDaliActorPartialUpdateActorsWithSizeHint03(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 update area 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.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(0.0f, 0.0f, 64.0f, 64.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>(32, 704, 80, 80);
+  DirtyRectChecker(damagedRects, {clippingRect}, true, 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 UPDATE_AREA_HINT twice before rendering
+  actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(0.0f, 0.0f, 32.0f, 32.0f));
+  application.SendNotification();
+
+  actor.SetProperty(Actor::Property::UPDATE_AREA_HINT, Vector4(32.0f, -32.0f, 32.0f, 32.0f));
+  application.SendNotification();
+
+  damagedRects.clear();
+  application.PreRenderWithPartialUpdate(TestApplication::DEFAULT_RENDER_INTERVAL, nullptr, damagedRects);
+
+  DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+  clippingRect = Rect<int>(32, 704, 96, 96);
+  DirtyRectChecker(damagedRects, {clippingRect}, true, 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 utcDaliActorPartialUpdateAnimation(void)
 {
   TestApplication application(
index ab20929..4893f2f 100644 (file)
@@ -1728,7 +1728,7 @@ void Actor::SetInheritLayoutDirection(bool inherit)
 void Actor::SetUpdateAreaHint(const Vector4& updateAreaHint)
 {
   // node is being used in a separate thread; queue a message to set the value & base value
-  SceneGraph::NodePropertyMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateAreaHint, &AnimatableProperty<Vector4>::Bake, updateAreaHint);
+  SetUpdateAreaHintMessage(GetEventThreadServices(), GetNode(), updateAreaHint);
 }
 
 } // namespace Internal
index 7f27624..f3a4142 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENEGRAPH_NODE_RESETTER_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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,7 +84,6 @@ public:
 
       mNode->mVisible.ResetToBaseValue(updateBufferIndex);
       mNode->mColor.ResetToBaseValue(updateBufferIndex);
-      mNode->mUpdateAreaHint.ResetToBaseValue(updateBufferIndex);
     }
   };
 
@@ -103,7 +102,6 @@ public:
 
     mNode->mVisible.MarkAsDirty();
     mNode->mColor.MarkAsDirty();
-    mNode->mUpdateAreaHint.MarkAsDirty();
   }
 
   /**
@@ -159,7 +157,6 @@ protected:
   {
     mNode->mVisible.MarkAsDirty();
     mNode->mColor.MarkAsDirty();
-    mNode->mUpdateAreaHint.MarkAsDirty();
   }
 
   Node*  mNode;         ///< The node that owns the properties
index e428837..f43da4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -102,7 +102,8 @@ Node::Node()
   mIsLayer(false),
   mIsCamera(false),
   mPositionUsesAnchorPoint(true),
-  mTransparent(false)
+  mTransparent(false),
+  mUpdateAreaChanged(false)
 {
 #ifdef DEBUG_ENABLED
   gNodeCount++;
@@ -256,12 +257,6 @@ NodePropertyFlags Node::GetDirtyFlags() const
     flags |= NodePropertyFlags::COLOR;
   }
 
-  // Check whether the update area property has changed
-  if(!mUpdateAreaHint.IsClean())
-  {
-    flags |= NodePropertyFlags::TRANSFORM;
-  }
-
   return flags;
 }
 
@@ -278,6 +273,8 @@ NodePropertyFlags Node::GetInheritedDirtyFlags(NodePropertyFlags parentFlags) co
 void Node::ResetDirtyFlags(BufferIndex updateBufferIndex)
 {
   mDirtyFlags = NodePropertyFlags::NOTHING;
+
+  mUpdateAreaChanged = false;
 }
 
 void Node::UpdateUniformHash(BufferIndex bufferIndex)
index ca9d5a8..7611531 100644 (file)
@@ -665,17 +665,35 @@ public:
   }
 
   /**
-   * Retrieve the update area hint of the node.
-   * @return The update area hint.
+   * Set the update area hint of the node.
+   * @param[in] updateAreaHint The update area hint.
    */
-  const Vector4& GetUpdateAreaHint() const
+  void SetUpdateAreaHint(const Vector4& updateAreaHint)
   {
-    if(mTransformManagerData.Id() != INVALID_TRANSFORM_ID)
+    if(mUpdateAreaChanged)
+    {
+      // Merge area if the update area is dirty
+      float x         = std::min(updateAreaHint.x - updateAreaHint.z / 2.0f, mUpdateAreaHint.x - mUpdateAreaHint.z / 2.0f);
+      float y         = std::min(updateAreaHint.y - updateAreaHint.w / 2.0f, mUpdateAreaHint.y - mUpdateAreaHint.w / 2.0f);
+      float width     = std::max(updateAreaHint.x + updateAreaHint.z / 2.0f, mUpdateAreaHint.x + mUpdateAreaHint.z / 2.0f) - x;
+      float height    = std::max(updateAreaHint.y + updateAreaHint.w / 2.0f, mUpdateAreaHint.y + mUpdateAreaHint.w / 2.0f) - y;
+      mUpdateAreaHint = Vector4(x + width / 2, y + height / 2, width, height);
+    }
+    else
     {
-      return mUpdateAreaHint.Get(0);
+      mUpdateAreaHint    = updateAreaHint;
+      mUpdateAreaChanged = true;
     }
+    mDirtyFlags |= NodePropertyFlags::TRANSFORM;
+  }
 
-    return Vector4::ZERO;
+  /**
+   * Retrieve the update area hint of the node.
+   * @return The update area hint.
+   */
+  const Vector4& GetUpdateAreaHint() const
+  {
+    return mUpdateAreaHint;
   }
 
   /**
@@ -987,8 +1005,7 @@ public: // Default properties
   AnimatableProperty<bool>    mCulled;         ///< True if the node is culled. This is not animatable. It is just double-buffered.
   AnimatableProperty<Vector4> mColor;          ///< Color can be inherited from the Node hierarchy
   InheritedColor              mWorldColor;     ///< Full inherited color
-  AnimatableProperty<Vector4> mUpdateAreaHint; ///< Update area hint is provided for damaged area calculation. (x, y, width, height)
-                                               ///< This is not animatable. It is just double-buffered. (Because all these bloody properties are).
+  Vector4                     mUpdateAreaHint; ///< Update area hint is provided for damaged area calculation. (x, y, width, height)
 
   uint64_t       mUniformsHash{0u};     ///< Hash of uniform map property values
   uint32_t       mClippingSortModifier; ///< Contains bit-packed clipping information for quick access when sorting
@@ -1020,6 +1037,7 @@ protected:
   bool               mIsCamera : 1;                ///< True if the node is a camera
   bool               mPositionUsesAnchorPoint : 1; ///< True if the node should use the anchor-point when calculating the position
   bool               mTransparent : 1;             ///< True if this node is transparent. This value do not affect children.
+  bool               mUpdateAreaChanged : 1;       ///< True if the update area of the node is changed.
 
   // Changes scope, should be at end of class
   DALI_LOG_OBJECT_STRING_DECLARATION;
@@ -1159,6 +1177,17 @@ inline void SetPositionUsesAnchorPointMessage(EventThreadServices& eventThreadSe
   new(slot) LocalType(&node, &Node::SetPositionUsesAnchorPoint, positionUsesAnchorPoint);
 }
 
+inline void SetUpdateAreaHintMessage(EventThreadServices& eventThreadServices, const Node& node, const Vector4& updateAreaHint)
+{
+  using LocalType = MessageValue1<Node, Vector4>;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new(slot) LocalType(&node, &Node::SetUpdateAreaHint, updateAreaHint);
+}
+
 } // namespace SceneGraph
 
 // Template specialisation for OwnerPointer<Node>, because delete is protected