// This is a clipping node. We generate the AABB for this node and intersect it with the previous intersection further up the tree.
// Get the AABB bounding box for the current render item.
- const ClippingBox scissorBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3::ZERO, item.mSize, mViewportRectangle.width, mViewportRectangle.height));
+ const ClippingBox scissorBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3::ZERO, item.GetPartialRenderingDataNodeInfomations().size, mViewportRectangle.width, mViewportRectangle.height));
// Get the AABB for the parent item that we must intersect with.
const ClippingBox& parentBox(mScissorStack.back());
{
// store clipping box inside the render callback input structure
auto& input = item.mRenderer->GetRenderCallbackInput();
- input.clippingBox = ClippingBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3::ZERO, item.mSize, mViewportRectangle.width, mViewportRectangle.height));
+ input.clippingBox = ClippingBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3::ZERO, item.GetPartialRenderingDataNodeInfomations().size, mViewportRectangle.width, mViewportRectangle.height));
}
}
}
// Prepare Render::Renderer Render for this secondary command buffer.
Renderer::PrepareCommandBuffer();
+ const SceneGraph::Node* lastRenderedNode = nullptr;
+ Vector3 nodeScale = Vector3::ONE;
+
// Modify by the clip matrix if necessary (transforms from GL clip space to alternative clip space)
Matrix clippedProjectionMatrix(projectionMatrix);
if(mGraphicsController.HasClipMatrix())
{
const RenderItem& item = renderList.GetItem(index);
+ // Get NodeInformation as const l-value, to reduce memory access operations.
+ const SceneGraph::PartialRenderingData::NodeInfomations& nodeInfo = item.GetPartialRenderingDataNodeInfomations();
+
// Discard renderers outside the root clipping rect
bool skip = true;
if(!rootClippingRect.IsEmpty())
{
- Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(bufferIndex, item.mUpdateArea) : item.mUpdateArea;
+ Vector4 updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(bufferIndex, nodeInfo.updatedPositionSize) : nodeInfo.updatedPositionSize;
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))
// It is similar to the multi-pass rendering.
if(!skip)
{
+ if(lastRenderedNode != item.mNode)
+ {
+ lastRenderedNode = item.mNode;
+
+ nodeScale = nodeInfo.modelMatrix.GetScale();
+ }
+
auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX;
for(auto queue = 0u; queue < MAX_QUEUE; ++queue)
{
// Render the item. It will write into the command buffer everything it has to render
- item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, clippedProjectionMatrix, item.mScale, item.mSize, !item.mIsOpaque, instruction, renderTarget, queue);
+ item.mRenderer->Render(secondaryCommandBuffer, bufferIndex, *item.mNode, nodeInfo.modelMatrix, item.mModelViewMatrix, viewMatrix, clippedProjectionMatrix, nodeInfo.worldColor, nodeScale, nodeInfo.size, !item.mIsOpaque, instruction, renderTarget, queue);
}
}
}
Graphics::RenderTarget* renderTarget,
Graphics::CommandBuffer* commandBuffer)
{
- DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_INSTRUCTION_PROCESS", [&](std::ostringstream& oss)
- { oss << "[" << instruction.RenderListCount() << "]"; });
+ DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_INSTRUCTION_PROCESS", [&](std::ostringstream& oss) { oss << "[" << instruction.RenderListCount() << "]"; });
DALI_PRINT_RENDER_INSTRUCTION(instruction, bufferIndex);
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
}
RenderItem::RenderItem()
-: mModelMatrix(false),
- mModelViewMatrix(false),
- mScale(),
- mSize(),
+: mModelViewMatrix(false),
mRenderer{},
mNode(nullptr),
mTextureSet(nullptr),
return enableDepthTest || enableDepthWrite;
}
-bool RenderItem::UsesStencilBuffer()
+bool RenderItem::UsesStencilBuffer() const
{
RenderMode::Type renderMode = RenderMode::AUTO;
bool usesStencil = false;
#define DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
* @brief Returns true if this node/renderer uses the stencil buffer (read or write)
* @return true if this node/renderer pair uses the stencil buffer
*/
- bool UsesStencilBuffer();
+ bool UsesStencilBuffer() const;
+
+ /**
+ * @brief Get PartialRenderingData::NodeInfomations from node
+ * @return Node infomations from node's partial rendering data.
+ */
+ const PartialRenderingData::NodeInfomations& GetPartialRenderingDataNodeInfomations() const
+ {
+ return mNode->GetPartialRenderingData().mNodeInfomations;
+ }
/**
* Overriden delete operator.
*/
void operator delete(void* ptr);
- Matrix mModelMatrix;
Matrix mModelViewMatrix;
- Vector3 mScale;
- Vector3 mSize;
- Vector4 mUpdateArea; ///< Update area hint is provided for damaged area calculation. (x, y, width, height)
Render::RendererKey mRenderer;
- Node* mNode;
+ const Node* mNode;
const void* mTextureSet; ///< Used for sorting only
int mDepthIndex;
- bool mIsOpaque : 1;
- bool mIsUpdated : 1;
+
+ bool mIsOpaque : 1;
+ bool mIsUpdated : 1;
/**
* Get the capacity of the global pool.
RenderItem();
// RenderItems should not be copied as they are heavy
- RenderItem(const RenderItem& item) = delete;
+ RenderItem(const RenderItem& item) = delete;
RenderItem& operator=(const RenderItem& item) = delete;
};
return newScissorArea;
}
-inline Rect<int32_t> CalculateUpdateArea(RenderItem& item, BufferIndex renderBufferIndex, const Rect<int32_t>& viewportRect)
+inline Rect<int32_t> CalculateUpdateArea(const RenderItem& item, const Vector4& updatedPositionSize, BufferIndex renderBufferIndex, const Rect<int32_t>& viewportRect)
{
Vector4 updateArea;
if(item.mNode && item.mNode->IsTextureUpdateAreaUsed() && item.mRenderer)
}
else
{
- updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(renderBufferIndex, item.mUpdateArea) : item.mUpdateArea;
+ updateArea = item.mRenderer ? item.mRenderer->GetVisualTransformedUpdateArea(renderBufferIndex, updatedPositionSize) : updatedPositionSize;
}
return RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, Vector3(updateArea.x, updateArea.y, 0.0f), Vector3(updateArea.z, updateArea.w, 0.0f), viewportRect.width, viewportRect.height);
for(uint32_t listIndex = 0u; listIndex < listCount; ++listIndex)
{
RenderItem& item = renderList->GetItem(listIndex);
+
+ // Get NodeInformation as const l-value, to reduce memory access operations.
+ const SceneGraph::PartialRenderingData::NodeInfomations& nodeInfo = item.GetPartialRenderingDataNodeInfomations();
+
// If the item does 3D transformation, make full update
- if(item.mUpdateArea == Vector4::ZERO)
+ if(nodeInfo.updatedPositionSize == Vector4::ZERO)
{
cleanDamagedRect = true;
(item.mNode &&
(item.mNode->Updated() || (item.mRenderer && item.mRenderer->Updated()))))
{
- item.mIsUpdated = false;
+ item.mIsUpdated = false; /// DevNote : Reset flag here, since RenderItem could be reused by renderList.ReuseCachedItems().
- rect = CalculateUpdateArea(item, mImpl->renderBufferIndex, viewportRect);
+ rect = CalculateUpdateArea(item, nodeInfo.updatedPositionSize, mImpl->renderBufferIndex, viewportRect);
if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
{
AlignDamagedRect(rect);
else
{
// The item is not in the list for some reason. Add the current rect!
- rect = CalculateUpdateArea(item, mImpl->renderBufferIndex, viewportRect);
+ rect = CalculateUpdateArea(item, nodeInfo.updatedPositionSize, mImpl->renderBufferIndex, viewportRect);
if(rect.IsValid() && rect.Intersect(viewportRect) && !rect.IsEmpty())
{
AlignDamagedRect(rect);
bool usesStencilBuffer = false;
for(auto k = 0u; k < renderList->Count(); ++k)
{
- auto& item = renderList->GetItem(k);
- usesStencilBuffer |= item.UsesStencilBuffer();
+ auto& item = renderList->GetItem(k);
+ usesStencilBuffer = usesStencilBuffer || item.UsesStencilBuffer();
if(item.mRenderer && item.mRenderer->NeedsProgram())
{
- usesDepthBuffer |= item.UsesDepthBuffer(autoDepthTestMode);
+ usesDepthBuffer = usesDepthBuffer || item.UsesDepthBuffer(autoDepthTestMode);
// Prepare and store used programs for further processing
auto program = item.mRenderer->PrepareProgram(instruction);
const Matrix& modelViewMatrix,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
+ const Vector4& worldColor,
const Vector3& scale,
const Vector3& size,
bool blend,
if(queueIndex == 0)
{
std::size_t nodeIndex = BuildUniformIndexMap(bufferIndex, node, *program);
- WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, scale, size, nodeIndex);
+ WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, worldColor, scale, size, nodeIndex);
}
// @todo We should detect this case much earlier to prevent unnecessary work
// Reuse latest bound vertex attributes location, or Bind buffers to attribute locations.
Graphics::CommandBuffer& commandBuffer,
Program* program,
const SceneGraph::RenderInstruction& instruction,
- const SceneGraph::NodeDataProvider& node,
const Matrix& modelMatrix,
const Matrix& modelViewMatrix,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
+ const Vector4& worldColor,
const Vector3& scale,
const Vector3& size,
std::size_t nodeIndex)
WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::SCALE), uboViews, scale);
- const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color
const Vector4& mixColor = mRenderDataProvider->GetMixColor(bufferIndex); ///< Renderer's mix color
- Vector4 finalColor = color * mixColor; ///< Applied renderer's mix color
+ Vector4 finalColor = worldColor * mixColor; ///< Applied Actor's original color to renderer's mix color
if(mPremultipliedAlphaEnabled)
{
const float alpha = finalColor.a;
finalColor.b *= alpha;
}
WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), uboViews, finalColor);
- WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), uboViews, color);
+ WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), uboViews, worldColor);
// Write uniforms from the uniform map
FillUniformBuffer(*program, instruction, uboViews, bufferIndex, nodeIndex);
#define DALI_INTERNAL_RENDER_RENDERER_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
* @param[in] modelViewMatrix The model-view matrix.
* @param[in] viewMatrix The view matrix.
* @param[in] projectionMatrix The projection matrix.
+ * @param[in] worldColor The world color of the node.
* @param[in] scale Scale factor of the render item
* @param[in] size Size of the render item
* @param[in] blend If true, blending is enabled
const Matrix& modelViewMatrix,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
+ const Vector4& worldColor,
const Vector3& scale,
const Vector3& size,
bool blend,
* @param[in] modelViewMatrix The model-view matrix.
* @param[in] viewMatrix The view matrix.
* @param[in] projectionMatrix The projection matrix.
+ * @param[in] worldColor The world color of the node.
* @param[in] scale Scale factor of the render item
* @param[in] size Size of the render item
* @param[in] blend If true, blending is enabled
Graphics::CommandBuffer& commandBuffer,
Program* program,
const SceneGraph::RenderInstruction& instruction,
- const SceneGraph::NodeDataProvider& node,
const Matrix& modelMatrix,
const Matrix& modelViewMatrix,
const Matrix& viewMatrix,
const Matrix& projectionMatrix,
+ const Vector4& worldColor,
const Vector3& scale,
const Vector3& size,
std::size_t nodeIndex);
struct DirtyRectKey
{
- DirtyRectKey(Node* node, Render::RendererKey renderer)
+ DirtyRectKey(const Node* node, Render::RendererKey renderer)
: node(node),
renderer(renderer)
{
};
#endif
- Node* node{nullptr};
+ const Node* node{nullptr};
Render::RendererKey renderer{};
};
return lhs.renderItem->mNode->mClippingSortModifier < rhs.renderItem->mNode->mClippingSortModifier;
}
-/**
- * Set the update area of the node
- * @param[in] node The node of the renderer
- * @param[in] isLayer3d Whether we are processing a 3D layer or not
- * @param[in,out] nodeWorldMatrix The world matrix of the node
- * @param[in,out] nodeSize The size of the node
- * @param[in,out] nodeUpdateArea The update area of the node
- *
- * @return True if node use it's own UpdateAreaHint, or z transform occured. False if we use nodeUpdateArea equal with Vector4(0, 0, nodeSize.width, nodeSize.height).
- */
-inline bool SetNodeUpdateArea(Node* node, bool isLayer3d, Matrix& nodeWorldMatrix, Vector3& nodeSize, Vector4& nodeUpdateArea)
-{
- node->GetWorldMatrixAndSize(nodeWorldMatrix, nodeSize);
-
- if(node->GetUpdateAreaHint() == Vector4::ZERO)
- {
- if(isLayer3d)
- {
- return true;
- }
- // RenderItem::CalculateViewportSpaceAABB cannot cope with z transform
- // I don't use item.mModelMatrix.GetTransformComponents() for z transform, would be too slow
- Vector3 zaxis = nodeWorldMatrix.GetZAxis();
- if(EqualsZero(zaxis.x) && EqualsZero(zaxis.y))
- {
- nodeUpdateArea = Vector4(0.0f, 0.0f, nodeSize.width, nodeSize.height);
- return false;
- }
- // Keep nodeUpdateArea as Vector4::ZERO, and return true.
- return true;
- }
- else
- {
- nodeUpdateArea = node->GetUpdateAreaHint();
- return true;
- }
-}
-
/**
* Add a renderer to the list
* @param updateBufferIndex to read the model matrix from
bool cullingEnabled,
Node* stopperNode)
{
- bool inside(true);
- Node* node = renderable.mNode;
- Matrix nodeWorldMatrix(false);
- Vector3 nodeScale;
- Vector3 nodeSize;
- Vector4 nodeUpdateArea;
- bool nodeUpdateAreaSet(false);
- Matrix nodeModelViewMatrix(false);
- bool nodeModelViewMatrixSet(false);
+ bool inside(true);
+ Node* node = renderable.mNode;
+
+ bool nodePartialRenderingDataUpdateChecked(false);
+
+ Matrix nodeModelViewMatrix(false);
+ bool nodeModelViewMatrixSet(false);
+
+ auto& nodePartialRenderingData = node->GetPartialRenderingData();
const bool rendererExist(renderable.mRenderer);
if(inside && !isLayer3d && viewportSet)
{
- SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
- nodeUpdateAreaSet = true;
+ node->UpdatePartialRenderingData(updateBufferIndex, isLayer3d);
+
+ const Vector4& nodeUpdateArea = nodePartialRenderingData.mNodeInfomations.updatedPositionSize;
+ const Vector3& nodeScale = nodePartialRenderingData.mNodeInfomations.modelMatrix.GetScale();
- nodeScale = nodeWorldMatrix.GetScale();
+ nodePartialRenderingDataUpdateChecked = true;
const Vector3& size = Vector3(nodeUpdateArea.z, nodeUpdateArea.w, 0.0f) * nodeScale;
if(size.LengthSquared() > Math::MACHINE_EPSILON_1000)
{
- MatrixUtils::MultiplyTransformMatrix(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
+ MatrixUtils::MultiplyTransformMatrix(nodeModelViewMatrix, nodePartialRenderingData.mNodeInfomations.modelMatrix, viewMatrix);
nodeModelViewMatrixSet = true;
// Assume actors are at z=0, compute AABB in view space & test rect intersection
// - If then, It must use math calculate like tan(fov) internally. So, we might need calculate it only one times, and cache.
ClippingBox boundingBox = RenderItem::CalculateTransformSpaceAABB(nodeModelViewMatrix, Vector3(nodeUpdateArea.x, nodeUpdateArea.y, 0.0f), Vector3(nodeUpdateArea.z, nodeUpdateArea.w, 0.0f));
ClippingBox clippingBox = camera.GetOrthographicClippingBox(updateBufferIndex);
- inside = clippingBox.Intersects(boundingBox);
+
+ inside = clippingBox.Intersects(boundingBox);
}
}
/*
// Get the next free RenderItem.
RenderItem& item = renderList.GetNextFreeItem();
- item.mNode = node;
+ item.mNode = static_cast<const Node*>(node);
item.mIsOpaque = isOpaque;
item.mDepthIndex = isLayer3d ? 0 : node->GetDepthIndex();
item.mIsUpdated = (viewMatrixChanged || isLayer3d);
- if(!nodeUpdateAreaSet)
+ if(!nodePartialRenderingDataUpdateChecked)
{
- SetNodeUpdateArea(node, isLayer3d, nodeWorldMatrix, nodeSize, nodeUpdateArea);
- nodeScale = nodeWorldMatrix.GetScale();
+ node->UpdatePartialRenderingData(updateBufferIndex, isLayer3d);
}
if(!nodeModelViewMatrixSet)
{
- MatrixUtils::MultiplyTransformMatrix(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
+ MatrixUtils::MultiplyTransformMatrix(nodeModelViewMatrix, nodePartialRenderingData.mNodeInfomations.modelMatrix, viewMatrix);
}
- item.mScale = nodeScale;
- item.mSize = nodeSize;
- item.mUpdateArea = nodeUpdateArea;
- item.mModelMatrix = std::move(nodeWorldMatrix);
item.mModelViewMatrix = std::move(nodeModelViewMatrix);
- auto& nodePartialRenderingData = node->GetPartialRenderingData();
-
- if(nodePartialRenderingData.mUpdateDecay == PartialRenderingData::Decay::UPDATED_CURRENT_FRAME)
- {
- item.mIsUpdated = nodePartialRenderingData.mUpdated;
- }
- else
- {
- // Update current node's partial update data as latest.
- if(nodePartialRenderingData.UpdateNodeInfomations(item.mModelMatrix, node->GetWorldColor(updateBufferIndex), item.mUpdateArea, item.mSize))
- {
- item.mIsUpdated = true;
- }
- }
+ item.mIsUpdated = item.mIsUpdated || nodePartialRenderingData.mUpdated;
}
node->SetCulled(updateBufferIndex, false);
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
mPositionUsesAnchorPoint(true),
mTransparent(false),
mUpdateAreaChanged(false),
+ mUpdateAreaUseSize(true),
mUseTextureUpdateArea(false)
{
#ifdef DEBUG_ENABLED
return GetNodeMemoryPool().GetCapacity();
}
+void Node::UpdatePartialRenderingData(BufferIndex updateBufferIndex, bool isLayer3d)
+{
+ if(mPartialRenderingData.mUpdateDecay == PartialRenderingData::Decay::UPDATED_CURRENT_FRAME)
+ {
+ // Fast-out if we're already updated this frame
+ return;
+ }
+
+ if(Updated())
+ {
+ // If the node was updated, then mark the partial rendering data as expired
+ // So we can skip data comparision.
+ mPartialRenderingData.MakeExpired();
+ }
+
+ const Vector4& worldColor = GetWorldColor(updateBufferIndex);
+
+ // TODO : Can't we get modelMatrix and size as const l-value at onces?
+ const auto& transformId = mTransformManagerData.Id();
+ const Matrix& modelMatrix = transformId == INVALID_TRANSFORM_ID ? Matrix::IDENTITY : mWorldMatrix.Get(0);
+ const Vector3& size = transformId == INVALID_TRANSFORM_ID ? Vector3::ZERO : mSize.Get(0);
+
+ const Vector4& updatedPositionSize = CalculateNodeUpdateArea(isLayer3d, modelMatrix, size);
+
+ mPartialRenderingData.UpdateNodeInfomations(modelMatrix, worldColor, updatedPositionSize, size);
+}
+
+Vector4 Node::CalculateNodeUpdateArea(bool isLayer3d, const Matrix& nodeWorldMatrix, const Vector3& nodeSize) const
+{
+ if(DALI_LIKELY(mUpdateAreaUseSize))
+ {
+ if(isLayer3d)
+ {
+ return Vector4::ZERO;
+ }
+ // RenderItem::CalculateViewportSpaceAABB cannot cope with z transform
+ // I don't use item.mModelMatrix.GetTransformComponents() for z transform, would be too slow
+ // Instead, use [8] and [9] of world matrix, which are z-axis's x and z-axis's y value.
+ if(EqualsZero(nodeWorldMatrix.AsFloat()[8]) && EqualsZero(nodeWorldMatrix.AsFloat()[9]))
+ {
+ return Vector4(0.0f, 0.0f, nodeSize.width, nodeSize.height);
+ }
+ // Keep nodeUpdateArea as Vector4::ZERO.
+ return Vector4::ZERO;
+ }
+ else
+ {
+ return GetUpdateAreaHint();
+ }
+}
+
} // namespace SceneGraph
} // namespace Internal
#define DALI_INTERNAL_SCENE_GRAPH_NODE_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
mUpdateAreaHint = updateAreaHint;
mUpdateAreaChanged = true;
}
+
+ mUpdateAreaUseSize = (mUpdateAreaHint == Vector4::ZERO);
mDirtyFlags |= NodePropertyFlags::TRANSFORM;
}
*/
static uint32_t GetMemoryPoolCapacity();
+ /**
+ * @brief Update partial rendering data from the latest node infomations.
+ */
+ void UpdatePartialRenderingData(BufferIndex bufferIndex, bool isLayer3d);
+
/**
* @brief Returns partial rendering data associated with the node.
* @return The partial rendering data
return mPartialRenderingData;
}
+ /**
+ * @brief Returns partial rendering data associated with the node.
+ * @return The partial rendering data
+ */
+ const PartialRenderingData& GetPartialRenderingData() const
+ {
+ return mPartialRenderingData;
+ }
+
public:
/**
* @copydoc Dali::Internal::SceneGraph::PropertyOwner::IsAnimationPossible
*/
void RecursiveDisconnectFromSceneGraph(BufferIndex updateBufferIndex);
+ /**
+ * @brief Calculates the update area of the node. Or Vector4::ZERO if partial update area is not 2D scale.
+ * @param[in] isLayer3d Whether we are processing a 3D layer or not
+ * @param[in] nodeWorldMatrix The world matrix of the node
+ * @param[in] nodeSize The size of the node
+ *
+ * @return It's own UpdateAreaHint, or if we use nodeUpdateArea equal with Vector4(0, 0, nodeSize.width, nodeSize.height),
+ * or Vector4::ZERO if z transform occured.
+ */
+ Vector4 CalculateNodeUpdateArea(bool isLayer3d, const Matrix& nodeWorldMatrix, const Vector3& nodeSize) const;
+
public: // Default properties
// Define a base offset for the following wrappers. The wrapper macros calculate offsets from the previous
// element such that each wrapper type generates a compile time offset to the transform manager data.
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.
+ bool mUpdateAreaUseSize : 1; ///< True if the update area of the node is same as node size.
bool mUseTextureUpdateArea : 1; ///< Whether the actor uses the update area of the texture instead of its own.
// Changes scope, should be at end of class
*/
struct PartialRenderingData
{
+ struct NodeInfomations
+ {
+ Matrix modelMatrix{}; /// Model matrix
+ Vector4 worldColor{}; /// World Color
+ Vector4 updatedPositionSize{}; /// Updated position/size (x, y, width, height)
+ Vector3 size{}; /// Size
+
+ mutable size_t hash{0u}; /// Last frame's hash
+
+ static size_t CalculateHash(const Vector4& worldColor, const Vector4& updatedPositionSize, const Vector3& size, const Matrix& matrix)
+ {
+ size_t hash = Dali::Internal::HashUtils::INITIAL_HASH_VALUE;
+ Dali::Internal::HashUtils::HashRawBuffer<float>(worldColor.AsFloat(), 4, hash);
+ Dali::Internal::HashUtils::HashRawBuffer<float>(updatedPositionSize.AsFloat(), 4, hash);
+ Dali::Internal::HashUtils::HashRawBuffer<float>(size.AsFloat(), 3, hash);
+ Dali::Internal::HashUtils::HashRawBuffer<float>(matrix.AsFloat(), 16, hash);
+ return hash;
+ }
+
+ size_t GetHash() const
+ {
+ if(hash == 0u)
+ {
+ hash = CalculateHash(worldColor, updatedPositionSize, size, modelMatrix);
+ }
+ return hash;
+ }
+
+ public:
+ NodeInfomations() = default; // Default constructor
+
+ NodeInfomations(const Matrix& modelMatrix, const Vector4& worldColor, const Vector4& updatedPositionSize, const Vector3& size, size_t hash = 0u)
+ : modelMatrix(modelMatrix),
+ worldColor(worldColor),
+ updatedPositionSize(updatedPositionSize),
+ size(size),
+ hash(hash)
+ {
+ }
+ NodeInfomations(NodeInfomations&& rhs)
+ {
+ (*this) = std::move(rhs);
+ }
+
+ NodeInfomations& operator=(NodeInfomations&& rhs)
+ {
+ if(this != &rhs)
+ {
+ modelMatrix = std::move(rhs.modelMatrix);
+ worldColor = std::move(rhs.worldColor);
+ updatedPositionSize = std::move(rhs.updatedPositionSize);
+ size = std::move(rhs.size);
+
+ hash = rhs.hash;
+ rhs.hash = 0u;
+ }
+ return *this;
+ }
+
+ private:
+ // Let we don't allow to copy the matrix values.
+ NodeInfomations(const NodeInfomations&) = delete;
+ NodeInfomations& operator=(const NodeInfomations&) = delete;
+ } mNodeInfomations;
+
bool mVisible : 1; /// Visible state. It is depends on node's visibility (Not hashed)
bool mUpdated : 1; /// IsUpdated return true at this frame. Will be reset at UpdateNodes time. (Not hashed)
{
mUpdated = true;
- mNodeInfomations = {modelMatrix, worldColor, updatedPositionSize, size, 0u, 0u};
+ mNodeInfomations = NodeInfomations(modelMatrix, worldColor, updatedPositionSize, size, 0u);
}
else
{
- mUpdated = true;
+ size_t hash = NodeInfomations::CalculateHash(worldColor, updatedPositionSize, size, modelMatrix);
- size_t hash1 = NodeInfomations::CalculateHash1(worldColor, updatedPositionSize, size);
- size_t hash2 = 0u;
- if(mNodeInfomations.GetHash1() == hash1)
- {
- hash2 = NodeInfomations::CalculateHash2(modelMatrix); // Hash2 is expensive, so we calculate it only when necessary
- if(mNodeInfomations.GetHash2() == hash2)
- {
- // Full comparision one more time.
- mUpdated = !(mNodeInfomations.matrix == modelMatrix &&
- mNodeInfomations.color == worldColor &&
- mNodeInfomations.updatedPositionSize == updatedPositionSize &&
- mNodeInfomations.size == size);
- }
- }
+ mUpdated = !(mNodeInfomations.GetHash() == hash && ///< Hash comparision first
+ mNodeInfomations.worldColor == worldColor && ///< Full comparision one more time.
+ mNodeInfomations.updatedPositionSize == updatedPositionSize &&
+ mNodeInfomations.size == size &&
+ mNodeInfomations.modelMatrix == modelMatrix); ///< Compare matrix last order
if(mUpdated)
{
- mNodeInfomations = {modelMatrix, worldColor, updatedPositionSize, size, hash1, hash2};
-
- // Don't change mVisible.
+ mNodeInfomations = NodeInfomations(modelMatrix, worldColor, updatedPositionSize, size, hash);
}
}
mUpdateDecay = Decay::UPDATED_CURRENT_FRAME;
+ // Don't change mVisible.
return mUpdated;
}
{
mUpdateDecay = Decay::EXPIRED;
}
-
-private:
- struct NodeInfomations
- {
- Matrix matrix{}; /// Model matrix
- Vector4 color{}; /// Color
- Vector4 updatedPositionSize{}; /// Updated position/size (x, y, width, height)
- Vector3 size{}; /// Size
-
- mutable size_t hash1{0u}; /// Last frame's hash for non-matrix
- mutable size_t hash2{0u}; /// Last frame's hash for matrix
-
- static size_t CalculateHash1(const Vector4& color, const Vector4& updatedPositionSize, const Vector3& size)
- {
- size_t hash = Dali::Internal::HashUtils::INITIAL_HASH_VALUE;
- Dali::Internal::HashUtils::HashRawBuffer<float>(color.AsFloat(), 4, hash);
- Dali::Internal::HashUtils::HashRawBuffer<float>(updatedPositionSize.AsFloat(), 4, hash);
- Dali::Internal::HashUtils::HashRawBuffer<float>(size.AsFloat(), 3, hash);
- return hash;
- }
-
- static size_t CalculateHash2(const Matrix& matrix)
- {
- size_t hash = Dali::Internal::HashUtils::INITIAL_HASH_VALUE;
- Dali::Internal::HashUtils::HashRawBuffer<float>(matrix.AsFloat(), 16, hash);
- return hash;
- }
-
- size_t GetHash1() const
- {
- if(hash1 == 0u)
- {
- hash1 = CalculateHash1(color, updatedPositionSize, size);
- }
- return hash1;
- }
- size_t GetHash2() const
- {
- if(hash2 == 0u)
- {
- hash2 = CalculateHash2(matrix);
- }
- return hash2;
- }
- } mNodeInfomations;
};
} // namespace Dali::Internal::SceneGraph
// const float decoratedBorderlineWidth = std::max((1.0f + Dali::Clamp(borderlineOffset, -1.0f, 1.0f)) * borderlineWidth, 2.0f * blurRadius);
// const Vector2 decoratedVisualSize = visualSize + Vector2(decoratedBorderlineWidth, decoratedBorderlineWidth);
- // Note : vertexPositoin.xy = aPosition * decoratedVisualSize
+ // Note : vertexPosition.xy = aPosition * decoratedVisualSize
// + anchorPoint * visualSize
// + origin * uSize.xy
// + visualOffset;