From 0246a6acf4875d1c4fa37b7c8f942548de583166 Mon Sep 17 00:00:00 2001 From: Richard Huang Date: Wed, 23 Sep 2020 16:00:31 +0100 Subject: [PATCH] Skip rendering if no animation is currently active Change-Id: Ie14194eeee047d908f36ec4c509e3863cc227cb8 --- dali/internal/event/actors/actor-impl.cpp | 12 +++++ .../update/animation/scene-graph-animation.cpp | 12 ++++- .../update/animation/scene-graph-animation.h | 13 +++++- dali/internal/update/manager/transform-manager.cpp | 15 +++---- dali/internal/update/manager/transform-manager.h | 5 ++- dali/internal/update/manager/update-manager.cpp | 52 ++++++++++++++++------ dali/internal/update/manager/update-manager.h | 22 ++++++++- .../update/rendering/scene-graph-renderer.cpp | 8 +++- .../update/rendering/scene-graph-renderer.h | 5 ++- 9 files changed, 112 insertions(+), 32 deletions(-) diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index 321b111..4b95320 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -836,6 +836,8 @@ void Actor::SetOpacity( float opacity ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeW, opacity ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } float Actor::GetCurrentOpacity() const @@ -855,6 +857,8 @@ void Actor::SetColor( const Vector4& color ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::Bake, color ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } void Actor::SetColorRed( float red ) @@ -863,6 +867,8 @@ void Actor::SetColorRed( float red ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeX, red ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } void Actor::SetColorGreen( float green ) @@ -871,6 +877,8 @@ void Actor::SetColorGreen( float green ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeY, green ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } void Actor::SetColorBlue( float blue ) @@ -879,6 +887,8 @@ void Actor::SetColorBlue( float blue ) // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty::BakeZ, blue ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } const Vector4& Actor::GetCurrentColor() const @@ -2492,6 +2502,8 @@ void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage ) { // node is being used in a separate thread; queue a message to set the value & base value SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty::Bake, visible ); + + RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() ); } mVisible = visible; diff --git a/dali/internal/update/animation/scene-graph-animation.cpp b/dali/internal/update/animation/scene-graph-animation.cpp index f0d961d..bd4656f 100644 --- a/dali/internal/update/animation/scene-graph-animation.cpp +++ b/dali/internal/update/animation/scene-graph-animation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -78,7 +78,8 @@ Animation::Animation( float durationSeconds, float speedFactor, const Vector2& p mDisconnectAction(disconnectAction), mState(Stopped), mProgressReachedSignalRequired( false ), - mAutoReverseEnabled( false ) + mAutoReverseEnabled( false ), + mIsActive{ false } { } @@ -426,6 +427,8 @@ void Animation::Update( BufferIndex bufferIndex, float elapsedSeconds, bool& loo void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished ) { + mIsActive[bufferIndex] = false; + const Vector2 playRange( mPlayRange * mDurationSeconds ); float elapsedSecondsClamped = Clamp( mElapsedSeconds, playRange.x, playRange.y ); @@ -456,6 +459,11 @@ void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animat progress = Clamp((elapsedSecondsClamped - intervalDelay) / animatorDuration, 0.0f , 1.0f ); } animator->Update(bufferIndex, progress, bake); + + if (animatorDuration > 0.0f && (elapsedSecondsClamped - intervalDelay) <= animatorDuration) + { + mIsActive[bufferIndex] = true; + } } applied = true; } diff --git a/dali/internal/update/animation/scene-graph-animation.h b/dali/internal/update/animation/scene-graph-animation.h index a4e309f..0617041 100644 --- a/dali/internal/update/animation/scene-graph-animation.h +++ b/dali/internal/update/animation/scene-graph-animation.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -259,6 +259,16 @@ public: } /** + * Query whether the animation is currently active (i.e. at least one of the animators has been updated in either frame) + * @return True if the animation is currently active + */ + bool IsActive() const + { + // As we have double buffering, if animator is updated in either frame, it needs to be rendered. + return mIsActive[0] || mIsActive[1]; + } + + /** * @brief Sets the looping mode. * * Animation plays forwards and then restarts from the beginning or runs backwards again. @@ -349,6 +359,7 @@ protected: bool mProgressReachedSignalRequired; // Flag to indicate the progress marker was hit bool mAutoReverseEnabled; // Flag to identify that the looping mode is auto reverse. + bool mIsActive[2]; // Flag to indicate whether the animation is active in the current frame (which is double buffered) }; }; //namespace SceneGraph diff --git a/dali/internal/update/manager/transform-manager.cpp b/dali/internal/update/manager/transform-manager.cpp index c2cc4bb..7951e32 100644 --- a/dali/internal/update/manager/transform-manager.cpp +++ b/dali/internal/update/manager/transform-manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -229,8 +229,10 @@ void TransformManager::ResetToBaseValue() } } -void TransformManager::Update() +bool TransformManager::Update() { + bool componentsChanged = false; + if( mReorder ) { //If some transform component has change its parent or has been removed since last update @@ -322,8 +324,11 @@ void TransformManager::Update() mBoundingSpheres[i] = mWorld[i].GetTranslation(); mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace ); + componentsChanged = componentsChanged || mComponentDirty[i]; mComponentDirty[i] = false; } + + return componentsChanged; } void TransformManager::SwapComponents( unsigned int i, unsigned int j ) @@ -382,31 +387,26 @@ Vector3& TransformManager::GetVector3PropertyValue( TransformId id, TransformMan case TRANSFORM_PROPERTY_POSITION: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentAnimatable[ index ].mPosition; } case TRANSFORM_PROPERTY_SCALE: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentAnimatable[ index ].mScale; } case TRANSFORM_PROPERTY_PARENT_ORIGIN: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentStatic[ index ].mParentOrigin; } case TRANSFORM_PROPERTY_ANCHOR_POINT: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentStatic[ index ].mAnchorPoint; } case TRANSFORM_PROPERTY_SIZE: { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mSize[ index ]; } default: @@ -835,7 +835,6 @@ void TransformManager::BakeZVector3PropertyValue( TransformId id, TransformManag Quaternion& TransformManager::GetQuaternionPropertyValue( TransformId id ) { TransformId index( mIds[id] ); - mComponentDirty[ index ] = true; return mTxComponentAnimatable[ index ].mOrientation; } diff --git a/dali/internal/update/manager/transform-manager.h b/dali/internal/update/manager/transform-manager.h index d003f57..068c39ff 100644 --- a/dali/internal/update/manager/transform-manager.h +++ b/dali/internal/update/manager/transform-manager.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_TRANSFORM_MANAGER_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -192,8 +192,9 @@ public: /** * Recomputes all world transform matrices + * @return true if any component has been changed in this frame, false otherwise */ - void Update(); + bool Update(); /** * Resets all the animatable properties to its base value diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 58fb0bc..a7ca327 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -189,7 +189,8 @@ struct UpdateManager::Impl previousUpdateScene( false ), renderTaskWaiting( false ), renderersAdded( false ), - surfaceRectChanged( false ) + surfaceRectChanged( false ), + renderingRequired( false ) { sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue ); @@ -298,6 +299,7 @@ struct UpdateManager::Impl bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing bool surfaceRectChanged; ///< True if the default surface rect is changed + bool renderingRequired; ///< True if required to render the current frame private: @@ -734,8 +736,10 @@ bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSync return gestureUpdated; } -void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) +bool UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) { + bool animationActive = false; + auto&& iter = mImpl->animations.Begin(); bool animationLooped = false; @@ -747,6 +751,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) bool progressMarkerReached = false; animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached ); + animationActive = animationActive || animation->IsActive(); + if ( progressMarkerReached ) { mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) ); @@ -772,6 +778,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds ) // The application should be notified by NotificationManager, in another thread mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist ); } + + return animationActive; } void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex ) @@ -852,7 +860,7 @@ void UpdateManager::UpdateRenderers( BufferIndex bufferIndex ) //Apply constraints ConstrainPropertyOwner( *renderer, bufferIndex ); - renderer->PrepareRender( bufferIndex ); + mImpl->renderingRequired = renderer->PrepareRender( bufferIndex ) || mImpl->renderingRequired; } } @@ -884,17 +892,20 @@ uint32_t UpdateManager::Update( float elapsedSeconds, //Clear nodes/resources which were previously discarded mImpl->discardQueue.Clear( bufferIndex ); + bool isAnimationRunning = IsAnimationRunning(); + //Process Touches & Gestures const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds ); bool updateScene = // The scene-graph requires an update if.. (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR - IsAnimationRunning() || // ..at least one animation is running OR + isAnimationRunning || // ..at least one animation is running OR mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR mImpl->frameCallbackProcessor || // ..a frame callback processor is existed OR gestureUpdated; // ..a gesture property was updated bool keepRendererRendering = false; + mImpl->renderingRequired = false; // Although the scene-graph may not require an update, we still need to synchronize double-buffered // values if the scene was updated in the previous frame. @@ -919,7 +930,7 @@ uint32_t UpdateManager::Update( float elapsedSeconds, if( updateScene || mImpl->previousUpdateScene ) { //Animate - Animate( bufferIndex, elapsedSeconds ); + bool animationActive = Animate( bufferIndex, elapsedSeconds ); //Constraint custom objects ConstrainCustomObjects( bufferIndex ); @@ -957,7 +968,10 @@ uint32_t UpdateManager::Update( float elapsedSeconds, UpdateRenderers( bufferIndex ); //Update the transformations of all the nodes - mImpl->transformManager.Update(); + if ( mImpl->transformManager.Update() ) + { + mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM; + } //Process Property Notifications ProcessPropertyNotifications( bufferIndex ); @@ -982,7 +996,6 @@ uint32_t UpdateManager::Update( float elapsedSeconds, } } - std::size_t numberOfRenderInstructions = 0; for ( auto&& scene : mImpl->scenes ) { @@ -991,13 +1004,19 @@ uint32_t UpdateManager::Update( float elapsedSeconds, scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex, static_cast( scene->taskList->GetTasks().Count() ) ); - keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex, - *scene->taskList, - *scene->root, - scene->sortedLayerList, - scene->scene->GetRenderInstructions(), - renderToFboEnabled, - isRenderingToFbo ); + // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed) + // or the nodes are dirty + if ( !isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) ) + { + keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex, + *scene->taskList, + *scene->root, + scene->sortedLayerList, + scene->scene->GetRenderInstructions(), + renderToFboEnabled, + isRenderingToFbo ); + + } numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex ); } @@ -1139,6 +1158,11 @@ void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavio mImpl->renderingBehavior = renderingBehavior; } +void UpdateManager::RequestRendering() +{ + mImpl->renderingRequired = true; +} + void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer ) { for ( auto&& scene : mImpl->scenes ) diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index bf5d3e4..3368970 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -646,6 +646,14 @@ public: void SetRenderingBehavior( DevelStage::Rendering renderingBehavior ); /** + * Request to render the current frame + * @note This is a temporary workaround (to be removed in the future) to request the rendering of + * the current frame if the color or visibility of any actor is updated. It MUST NOT be used + * for any other purposes. + */ + void RequestRendering(); + + /** * Sets the depths of all layers. * @param layers The layers in depth order. * @param[in] rootLayer The root layer of the sorted layers. @@ -711,8 +719,9 @@ private: * Perform animation updates * @param[in] bufferIndex to use * @param[in] elapsedSeconds time since last frame + * @return true if at least one animations is currently active or false otherwise */ - void Animate( BufferIndex bufferIndex, float elapsedSeconds ); + bool Animate( BufferIndex bufferIndex, float elapsedSeconds ); /** * Applies constraints to CustomObjects @@ -1110,6 +1119,17 @@ inline void SetRenderingBehaviorMessage( UpdateManager& manager, DevelStage::Ren new (slot) LocalType( &manager, &UpdateManager::SetRenderingBehavior, renderingBehavior ); } +inline void RequestRenderingMessage( UpdateManager& manager ) +{ + using LocalType = Message; + + // Reserve some memory inside the message queue + uint32_t* slot = manager.ReserveMessageSlot( sizeof( LocalType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) LocalType( &manager, &UpdateManager::RequestRendering ); +} + /** * Create a message for setting the depth of a layer * @param[in] manager The update manager diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index e821f6e..cce7464 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -181,7 +181,7 @@ void Renderer::operator delete( void* ptr ) } -void Renderer::PrepareRender( BufferIndex updateBufferIndex ) +bool Renderer::PrepareRender( BufferIndex updateBufferIndex ) { if( mRegenerateUniformMap == UNIFORM_MAP_READY ) { @@ -221,6 +221,8 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex ) mRegenerateUniformMap--; } + bool rendererUpdated = mUniformMapChanged[updateBufferIndex] || mResendFlag; + if( mResendFlag != 0 ) { if( mResendFlag & RESEND_GEOMETRY ) @@ -365,6 +367,8 @@ void Renderer::PrepareRender( BufferIndex updateBufferIndex ) mResendFlag = 0; } + + return rendererUpdated; } void Renderer::SetTextures( TextureSet* textureSet ) diff --git a/dali/internal/update/rendering/scene-graph-renderer.h b/dali/internal/update/rendering/scene-graph-renderer.h index b3ab63e..a06fa2a 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.h +++ b/dali/internal/update/rendering/scene-graph-renderer.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDERER_H /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -339,8 +339,9 @@ public: * Prepare the object for rendering. * This is called by the UpdateManager when an object is due to be rendered in the current frame. * @param[in] updateBufferIndex The current update buffer index. + * @return Whether this renderer has been updated in the current frame */ - void PrepareRender( BufferIndex updateBufferIndex ); + bool PrepareRender( BufferIndex updateBufferIndex ); /** * Retrieve the Render thread renderer -- 2.7.4