X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fupdate%2Fmanager%2Fupdate-algorithms.cpp;h=3ff66c41b450639a766fc9dc4d4f4c6f21d4c595;hb=4e2aa476640b5ce5557e062c6349d1fbfd1ae005;hp=40da3346ea62925203022c47fd6effa9bd753be0;hpb=9709e1327f6ca9391863eb6dacf562334a5d6a23;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/update/manager/update-algorithms.cpp b/dali/internal/update/manager/update-algorithms.cpp index 40da334..3ff66c4 100644 --- a/dali/internal/update/manager/update-algorithms.cpp +++ b/dali/internal/update/manager/update-algorithms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -22,28 +22,22 @@ #include // INTERNAL INCLUDES +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include namespace Dali { - namespace Internal { - namespace SceneGraph { - #if defined(DEBUG_ENABLED) Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UPDATE_ALGORITHMS"); #endif @@ -52,490 +46,197 @@ Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UP *********************** Apply Constraints ************************************ ******************************************************************************/ - /** * Constrain the local properties of the PropertyOwner. * @param propertyOwner to constrain * @param updateBufferIndex buffer index to use - * @return The number of constraints that are still being applied */ -unsigned int ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex ) +void ConstrainPropertyOwner(PropertyOwner& propertyOwner, BufferIndex updateBufferIndex) { - unsigned int activeCount = 0; - ConstraintOwnerContainer& constraints = propertyOwner.GetConstraints(); const ConstraintIter endIter = constraints.End(); - for( ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter ) + for(ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter) { ConstraintBase& constraint = **iter; - constraint.Apply( updateBufferIndex ); - - if( constraint.mWeight[updateBufferIndex] < 1.0f ) - { - // this constraint is still being applied - ++activeCount; - } - } - - return activeCount; -} - -/** - * Recursively apply the constraints on the nodes - * @param node to constraint - * @param updateBufferIndex buffer index to use - * @return number of active constraints - */ -unsigned int ConstrainNodes( Node& node, BufferIndex updateBufferIndex ) -{ - unsigned int activeCount = ConstrainPropertyOwner( node, updateBufferIndex ); - - /** - * Constrain the children next - */ - NodeContainer& children = node.GetChildren(); - const NodeIter endIter = children.End(); - for ( NodeIter iter = children.Begin(); iter != endIter; ++iter ) - { - Node& child = **iter; - activeCount += ConstrainNodes( child, updateBufferIndex ); + constraint.Apply(updateBufferIndex); } - return activeCount; } /****************************************************************************** ************************** Update node hierarchy ***************************** ******************************************************************************/ -inline void UpdateRootNodeOpacity( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex ) +inline void UpdateRootNodeOpacity(Layer& rootNode, NodePropertyFlags nodeDirtyFlags, BufferIndex updateBufferIndex) { - if ( nodeDirtyFlags & ColorFlag ) + if(nodeDirtyFlags & NodePropertyFlags::COLOR) { - rootNode.SetWorldColor( rootNode.GetColor( updateBufferIndex ), updateBufferIndex ); + rootNode.SetWorldColor(rootNode.GetColor(updateBufferIndex), updateBufferIndex); } else { // Copy previous value, in case it changed in the previous frame - rootNode.CopyPreviousWorldColor( updateBufferIndex ); + rootNode.CopyPreviousWorldColor(updateBufferIndex); } } -inline void UpdateNodeOpacity( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex ) +inline void UpdateNodeOpacity(Node& node, NodePropertyFlags nodeDirtyFlags, BufferIndex updateBufferIndex) { // If opacity needs to be recalculated - if ( nodeDirtyFlags & ColorFlag ) + if(nodeDirtyFlags & NodePropertyFlags::COLOR) { - node.InheritWorldColor( updateBufferIndex ); + node.InheritWorldColor(updateBufferIndex); } else { // Copy inherited value, if changed in the previous frame - node.CopyPreviousWorldColor( updateBufferIndex ); - } -} - -inline void UpdateNodeGeometry( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex ) -{ - if ( nodeDirtyFlags & SizeFlag ) - { - Vector3 geometryScale( 1.0f, 1.0f, 1.0f ); - - if ( node.GetTransmitGeometryScaling() ) - { - const Vector3& requiredSize = node.GetSize( updateBufferIndex ); - geometryScale = FitKeepAspectRatio( requiredSize, node.GetInitialVolume() ); - } - - if ( node.GetGeometryScale() != geometryScale ) - { - node.SetGeometryScale( geometryScale ); - } - } -} - -inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex ) -{ - // If the transform values need to be reinherited - if ( nodeDirtyFlags & TransformFlag ) - { - rootNode.SetWorldPosition( updateBufferIndex, rootNode.GetPosition( updateBufferIndex ) ); - rootNode.SetWorldRotation( updateBufferIndex, rootNode.GetRotation( updateBufferIndex ) ); - rootNode.SetWorldScale ( updateBufferIndex, rootNode.GetScale ( updateBufferIndex ) ); - } - else - { - // Copy previous value, in case they changed in the previous frame - rootNode.CopyPreviousWorldRotation( updateBufferIndex ); - rootNode.CopyPreviousWorldScale( updateBufferIndex ); - rootNode.CopyPreviousWorldPosition( updateBufferIndex ); + node.CopyPreviousWorldColor(updateBufferIndex); } } /** - * Updates transform values for the given node if the transform flag is dirty. - * This includes applying a new size should the SizeMode require it. - * Note that this will cause the size dirty flag to be set. This is why we pass - * the dirty flags in by reference. - * @param[in] node The node to update - * @param[in,out] nodeDirtyFlags A reference to the dirty flags, these may be modified by this function - * @param[in] updateBufferIndex The current index to use for this frame + * This is called recursively for all children of the root Node */ -inline void UpdateNodeTransformValues( Node& node, int& nodeDirtyFlags, BufferIndex updateBufferIndex ) +inline NodePropertyFlags UpdateNodes(Node& node, + NodePropertyFlags parentFlags, + BufferIndex updateBufferIndex, + RenderQueue& renderQueue, + bool updated) { - // If the transform values need to be reinherited - if( nodeDirtyFlags & TransformFlag ) - { - // Handle size relative to parent modes. - // This must be delt with before rotation/translation as otherwise anything - // anchored to a corner of this child would appear at the wrong position. - // The size dirty flag is modified if the size is being overridden. - // Note: Switch is in order of use-case commonality. - switch( node.GetSizeMode() ) - { - case USE_OWN_SIZE: - { - // Completely ignore the parents size. - break; - } - - case SIZE_EQUAL_TO_PARENT: - { - // Set the nodes size to that of the parent. - node.SetSize( updateBufferIndex, node.GetParent()->GetSize( updateBufferIndex ) ); - nodeDirtyFlags |= SizeFlag; - break; - } - - case SIZE_RELATIVE_TO_PARENT: - { - // Set the nodes size to the parents multiplied by a user defined value. - node.SetSize( updateBufferIndex, node.GetSizeModeFactor() * node.GetParent()->GetSize( updateBufferIndex ) ); - nodeDirtyFlags |= SizeFlag; - break; - } - - case SIZE_FIXED_OFFSET_FROM_PARENT: - { - // Set the nodes size to the parents plus a user defined value. - node.SetSize( updateBufferIndex, node.GetSizeModeFactor() + node.GetParent()->GetSize( updateBufferIndex ) ); - nodeDirtyFlags |= SizeFlag; - break; - } - } - - // With a non-central anchor-point, the world rotation and scale affects the world position. - // Therefore the world rotation & scale must be updated before the world position. - if( node.IsRotationInherited() ) - { - node.InheritWorldRotation( updateBufferIndex ); - } - else - { - node.SetWorldRotation( updateBufferIndex, node.GetRotation( updateBufferIndex ) ); - } - - if( node.IsScaleInherited() ) - { - node.InheritWorldScale( updateBufferIndex ); - } - else - { - node.SetWorldScale( updateBufferIndex, node.GetScale( updateBufferIndex ) ); - } - - node.InheritWorldPosition( updateBufferIndex ); - } - else - { - // Copy inherited values, if those changed in the previous frame - node.CopyPreviousWorldRotation( updateBufferIndex ); - node.CopyPreviousWorldScale( updateBufferIndex ); - node.CopyPreviousWorldPosition( updateBufferIndex ); - node.CopyPreviousSize( updateBufferIndex ); - } -} + // Apply constraints to the node + ConstrainPropertyOwner(node, updateBufferIndex); -inline void UpdateNodeWorldMatrix( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex ) -{ - // If world-matrix needs to be recalculated - if ( nodeDirtyFlags & TransformFlag ) - { - if( node.GetInhibitLocalTransform() ) - { - node.SetWorldMatrix( updateBufferIndex, - node.GetWorldScale(updateBufferIndex), - node.GetWorldRotation(updateBufferIndex) / node.GetRotation(updateBufferIndex), - node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) ); - } - else - { - node.SetWorldMatrix( updateBufferIndex, - node.GetWorldScale(updateBufferIndex), - node.GetWorldRotation(updateBufferIndex), - node.GetWorldPosition(updateBufferIndex) ); - } - } - else - { - node.CopyPreviousWorldMatrix( updateBufferIndex ); - } -} + // Some dirty flags are inherited from parent + NodePropertyFlags nodeDirtyFlags = node.GetDirtyFlags() | node.GetInheritedDirtyFlags(parentFlags); -inline void UpdateNodeWorldMatrix( Node& node, RenderableAttachment& updatedRenderable, int nodeDirtyFlags, BufferIndex updateBufferIndex ) -{ - /** - * If world-matrix needs to be recalculated. - */ - if ( ( nodeDirtyFlags & TransformFlag ) || - updatedRenderable.IsScaleForSizeDirty() ) + NodePropertyFlags cumulativeDirtyFlags = nodeDirtyFlags; + + UpdateNodeOpacity(node, nodeDirtyFlags, updateBufferIndex); + + // Collect uniform maps + node.PrepareRender(updateBufferIndex); + + // For partial update, mark all children of an animating node as updated. + if(updated) // Only set to updated if parent was updated. { - if( updatedRenderable.UsesGeometryScaling() ) - { - // scaling, i.e. Mesh - Vector3 scaling; - updatedRenderable.GetScaleForSize( node.GetSize( updateBufferIndex ), scaling ); - if( node.GetInhibitLocalTransform() ) - { - node.SetWorldMatrix( updateBufferIndex, - node.GetWorldScale(updateBufferIndex) * scaling, - node.GetWorldRotation(updateBufferIndex) / node.GetRotation(updateBufferIndex), - node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) ); - } - else - { - node.SetWorldMatrix( updateBufferIndex, - node.GetWorldScale(updateBufferIndex) * scaling, - node.GetWorldRotation(updateBufferIndex), - node.GetWorldPosition(updateBufferIndex) ); - } - } - else - { - // no scaling, i.e. Image - if( node.GetInhibitLocalTransform() ) - { - node.SetWorldMatrix( updateBufferIndex, - node.GetWorldScale(updateBufferIndex), - node.GetWorldRotation(updateBufferIndex) / node.GetRotation(updateBufferIndex), - node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) ); - } - else - { - node.SetWorldMatrix( updateBufferIndex, - node.GetWorldScale(updateBufferIndex), - node.GetWorldRotation(updateBufferIndex), - node.GetWorldPosition(updateBufferIndex) ); - } - } + node.SetUpdated(true); } - else + else if(node.Updated()) // Only propagate updated==true downwards. { - node.CopyPreviousWorldMatrix( updateBufferIndex ); + updated = true; } -} - -/** - * Update an attachment. - * @return An updated renderable attachment if one was ready. - */ -inline RenderableAttachment* UpdateAttachment( NodeAttachment& attachment, - Node& node, - BufferIndex updateBufferIndex, - ResourceManager& resourceManager, - int nodeDirtyFlags ) -{ - // Allow attachments to do specialised processing during updates - attachment.Update( updateBufferIndex, node, nodeDirtyFlags ); - RenderableAttachment* renderable = attachment.GetRenderable(); // not all scene objects render - if( renderable ) + // recurse children + NodeContainer& children = node.GetChildren(); + const NodeIter endIter = children.End(); + for(NodeIter iter = children.Begin(); iter != endIter; ++iter) { - // Notify renderables when size has changed - // Size can change while node was invisible so we need to check size again if we were previously invisible - if( nodeDirtyFlags & (SizeFlag|VisibleFlag) ) - { - renderable->SizeChanged( updateBufferIndex ); - } - - // check if node is visible - if( renderable->ResolveVisibility( updateBufferIndex ) ) - { - renderable->PrepareResources( updateBufferIndex, resourceManager ); - } + Node& child = **iter; + cumulativeDirtyFlags |= UpdateNodes(child, + nodeDirtyFlags, + updateBufferIndex, + renderQueue, + updated); } - return renderable; -} -inline void AddRenderableToLayer( Layer& layer, - RenderableAttachment& renderable, - BufferIndex updateBufferIndex, - int inheritedDrawMode ) -{ - // The renderables are stored into the opaque list temporarily for PrepareRenderables() - // step. The list is cleared by ProcessRenderTasks(). - layer.opaqueRenderables.push_back( &renderable ); + return cumulativeDirtyFlags; } /** - * This is called recursively for all children of the root Node + * The root node is treated separately; it cannot inherit values since it has no parent */ -inline int UpdateNodesAndAttachments( Node& node, - int parentFlags, - BufferIndex updateBufferIndex, - ResourceManager& resourceManager, - RenderQueue& renderQueue, - Layer& currentLayer, - int inheritedDrawMode ) +NodePropertyFlags UpdateNodeTree(Layer& rootNode, + BufferIndex updateBufferIndex, + RenderQueue& renderQueue) { - Layer* layer = ¤tLayer; + DALI_ASSERT_DEBUG(rootNode.IsRoot()); // Short-circuit for invisible nodes - if ( !node.IsVisible( updateBufferIndex ) ) + if(DALI_UNLIKELY(!rootNode.IsVisible(updateBufferIndex))) // almost never ever true { - return 0; + return NodePropertyFlags::NOTHING; } - // If the node was not previously visible + // If the root node was not previously visible BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u; - if ( !node.IsVisible( previousBuffer ) ) + if(DALI_UNLIKELY(!rootNode.IsVisible(previousBuffer))) // almost never ever true { // The node was skipped in the previous update; it must recalculate everything - node.SetAllDirtyFlags(); + rootNode.SetAllDirtyFlags(); } - // Some dirty flags are inherited from parent - int nodeDirtyFlags( node.GetDirtyFlags() | ( parentFlags & InheritedDirtyFlags ) ); + NodePropertyFlags nodeDirtyFlags(rootNode.GetDirtyFlags()); - int cumulativeDirtyFlags = nodeDirtyFlags; + NodePropertyFlags cumulativeDirtyFlags = nodeDirtyFlags; - if ( node.IsLayer() ) - { - // all childs go to this layer - layer = node.GetLayer(); + UpdateRootNodeOpacity(rootNode, nodeDirtyFlags, updateBufferIndex); - // assume layer is clean to begin with - layer->SetReuseRenderers( updateBufferIndex, true ); + bool updated = rootNode.Updated(); - // Layers do not inherit the DrawMode from their parents - inheritedDrawMode = DrawMode::NORMAL; + // recurse children + NodeContainer& children = rootNode.GetChildren(); + const NodeIter endIter = children.End(); + for(NodeIter iter = children.Begin(); iter != endIter; ++iter) + { + Node& child = **iter; + cumulativeDirtyFlags |= UpdateNodes(child, + nodeDirtyFlags, + updateBufferIndex, + renderQueue, + updated); } - DALI_ASSERT_DEBUG( NULL != layer ); - - UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex ); - - UpdateNodeGeometry( node, nodeDirtyFlags, updateBufferIndex ); - // Note: nodeDirtyFlags are passed in by reference and may be modified by the following function. - // It is important that the modified version of these flags are used by the RenderableAttachment. - UpdateNodeTransformValues( node, nodeDirtyFlags, updateBufferIndex ); + return cumulativeDirtyFlags; +} - // Setting STENCIL will override OVERLAY, if that would otherwise have been inherited. - inheritedDrawMode |= node.GetDrawMode(); +inline void UpdateLayers(Node& node, + NodePropertyFlags parentFlags, + BufferIndex updateBufferIndex, + Layer& currentLayer) +{ + // Some dirty flags are inherited from parent + NodePropertyFlags nodeDirtyFlags = node.GetDirtyFlags() | node.GetInheritedDirtyFlags(parentFlags); + nodeDirtyFlags |= (node.IsLocalMatrixDirty() ? NodePropertyFlags::TRANSFORM : NodePropertyFlags::NOTHING); - if ( node.HasAttachment() ) - { - /* - * Add renderables for the children into the current Layer - */ - RenderableAttachment* renderable = UpdateAttachment( node.GetAttachment(), - node, - updateBufferIndex, - resourceManager, - nodeDirtyFlags ); - - - if( NULL != renderable ) - { - // Update the world matrix after renderable update; the ScaleForSize property should now be calculated - UpdateNodeWorldMatrix( node, *renderable, nodeDirtyFlags, updateBufferIndex ); - - // The attachment is ready to render, so it is added to a set of renderables. - AddRenderableToLayer( *layer, *renderable, updateBufferIndex, inheritedDrawMode ); - } - } - else if( node.IsObserved() ) + Layer* nodeIsLayer(node.GetLayer()); + Layer* layer = nodeIsLayer ? nodeIsLayer : ¤tLayer; + if(nodeIsLayer) { - // This node is being used as a property input for an animation, constraint, - // camera or bone. Ensure it's matrix is updated - UpdateNodeWorldMatrix( node, nodeDirtyFlags, updateBufferIndex ); + layer->SetReuseRenderers(updateBufferIndex, true); } + DALI_ASSERT_DEBUG(nullptr != layer); // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused // also if node has been deleted, dont reuse old render items - if( nodeDirtyFlags & RenderableUpdateFlags ) + if(nodeDirtyFlags != NodePropertyFlags::NOTHING) { - layer->SetReuseRenderers( updateBufferIndex, false ); + layer->SetReuseRenderers(updateBufferIndex, false); } // recurse children NodeContainer& children = node.GetChildren(); - const NodeIter endIter = children.End(); - for ( NodeIter iter = children.Begin(); iter != endIter; ++iter ) + const NodeIter endIter = children.End(); + for(NodeIter iter = children.Begin(); iter != endIter; ++iter) { Node& child = **iter; - cumulativeDirtyFlags |=UpdateNodesAndAttachments( child, - nodeDirtyFlags, - updateBufferIndex, - resourceManager, - renderQueue, - *layer, - inheritedDrawMode ); + UpdateLayers(child, nodeDirtyFlags, updateBufferIndex, *layer); } - - return cumulativeDirtyFlags; } -/** - * The root node is treated separately; it cannot inherit values since it has no parent - */ -int UpdateNodesAndAttachments( Layer& rootNode, - BufferIndex updateBufferIndex, - ResourceManager& resourceManager, - RenderQueue& renderQueue ) +void UpdateLayerTree(Layer& layer, + BufferIndex updateBufferIndex) { - DALI_ASSERT_DEBUG( rootNode.IsRoot() ); - - // Short-circuit for invisible nodes - if ( !rootNode.IsVisible( updateBufferIndex ) ) - { - return 0; - } - - // If the root node was not previously visible - BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u; - if ( !rootNode.IsVisible( previousBuffer ) ) - { - // The node was skipped in the previous update; it must recalculate everything - rootNode.SetAllDirtyFlags(); - } - - int nodeDirtyFlags( rootNode.GetDirtyFlags() ); - - int cumulativeDirtyFlags = nodeDirtyFlags; - - UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex ); - - UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex ); - - DrawMode::Type drawMode( rootNode.GetDrawMode() ); + NodePropertyFlags nodeDirtyFlags = layer.GetDirtyFlags(); + nodeDirtyFlags |= (layer.IsLocalMatrixDirty() ? NodePropertyFlags::TRANSFORM : NodePropertyFlags::NOTHING); // recurse children - NodeContainer& children = rootNode.GetChildren(); - const NodeIter endIter = children.End(); - for ( NodeIter iter = children.Begin(); iter != endIter; ++iter ) + NodeContainer& children = layer.GetChildren(); + const NodeIter endIter = children.End(); + for(NodeIter iter = children.Begin(); iter != endIter; ++iter) { Node& child = **iter; - cumulativeDirtyFlags |= UpdateNodesAndAttachments( child, - nodeDirtyFlags, - updateBufferIndex, - resourceManager, - renderQueue, - rootNode, - drawMode ); + UpdateLayers(child, nodeDirtyFlags, updateBufferIndex, layer); } - - return cumulativeDirtyFlags; } } // namespace SceneGraph