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());
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());
// 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();
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(
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
#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.
mNode->mVisible.ResetToBaseValue(updateBufferIndex);
mNode->mColor.ResetToBaseValue(updateBufferIndex);
- mNode->mUpdateAreaHint.ResetToBaseValue(updateBufferIndex);
}
};
mNode->mVisible.MarkAsDirty();
mNode->mColor.MarkAsDirty();
- mNode->mUpdateAreaHint.MarkAsDirty();
}
/**
{
mNode->mVisible.MarkAsDirty();
mNode->mColor.MarkAsDirty();
- mNode->mUpdateAreaHint.MarkAsDirty();
}
Node* mNode; ///< The node that owns the properties
/*
- * 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.
mIsLayer(false),
mIsCamera(false),
mPositionUsesAnchorPoint(true),
- mTransparent(false)
+ mTransparent(false),
+ mUpdateAreaChanged(false)
{
#ifdef DEBUG_ENABLED
gNodeCount++;
flags |= NodePropertyFlags::COLOR;
}
- // Check whether the update area property has changed
- if(!mUpdateAreaHint.IsClean())
- {
- flags |= NodePropertyFlags::TRANSFORM;
- }
-
return flags;
}
void Node::ResetDirtyFlags(BufferIndex updateBufferIndex)
{
mDirtyFlags = NodePropertyFlags::NOTHING;
+
+ mUpdateAreaChanged = false;
}
void Node::UpdateUniformHash(BufferIndex bufferIndex)
}
/**
- * 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;
}
/**
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
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;
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