X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-vector-image%2Fvector-animation-task.cpp;h=bae4fbc15c83ad5d7cd899d689ec7cfde4599ad4;hp=8258fb7e5ffb42025b45c8c2b5b703f4ca411767;hb=bf58973c37b31d52707463a1e9cdecdbe91099f6;hpb=55e1976335d0098eff26d44a245de161a6a2a231 diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index 8258fb7..bae4fbc 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.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. @@ -20,6 +20,8 @@ // EXTERNAL INCLUDES #include +#include +#include // INTERNAL INCLUDES #include @@ -44,22 +46,12 @@ constexpr auto NANOSECONDS_PER_SECOND( 1e+9 ); Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" ); #endif -template< typename T > -inline void ResetValue( bool& updated, T& value, T newValue, ConditionalWait& conditionalWait ) -{ - ConditionalWait::ScopedLock lock( conditionalWait ); - if( !updated ) - { - value = newValue; - updated = true; - } -} - } // unnamed namespace VectorAnimationTask::VectorAnimationTask( VisualFactoryCache& factoryCache, const std::string& url ) : mUrl( url ), mVectorRenderer(), + mAnimationData(), mVectorAnimationThread( factoryCache.GetVectorAnimationThread() ), mConditionalWait(), mAnimationFinishedTrigger(), @@ -75,14 +67,14 @@ VectorAnimationTask::VectorAnimationTask( VisualFactoryCache& factoryCache, cons mEndFrame( 0 ), mWidth( 0 ), mHeight( 0 ), + mAnimationDataIndex( 0 ), mLoopCount( LOOP_FOREVER ), mCurrentLoop( 0 ), - mResourceReady( false ), - mCurrentFrameUpdated( false ), - mCurrentLoopUpdated( false ), mForward( true ), mUpdateFrameNumber( false ), - mNeedAnimationFinishedTrigger( true ) + mNeedAnimationFinishedTrigger( true ), + mAnimationDataUpdated( false ), + mDestroyTask( false ) { Initialize(); } @@ -94,6 +86,8 @@ VectorAnimationTask::~VectorAnimationTask() void VectorAnimationTask::Finalize() { + ConditionalWait::ScopedLock lock( mConditionalWait ); + // Release some objects in the main thread if( mAnimationFinishedTrigger ) { @@ -101,6 +95,8 @@ void VectorAnimationTask::Finalize() } mVectorRenderer.Finalize(); + + mDestroyTask = true; } void VectorAnimationTask::SetRenderer( Renderer renderer ) @@ -112,41 +108,54 @@ void VectorAnimationTask::SetRenderer( Renderer renderer ) DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", this ); } +void VectorAnimationTask::SetAnimationData( const AnimationData& data ) +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetAnimationData [%p]\n", this ); + + uint32_t index = mAnimationDataIndex == 0 ? 1 : 0; // Use the other buffer + + mAnimationData[index] = data; + mAnimationDataUpdated = true; + + if( data.resendFlag & VectorAnimationTask::RESEND_SIZE ) + { + // The size should be changed in the main thread. + SetSize( data.width, data.height ); + } + + mVectorAnimationThread.AddTask( this ); +} + void VectorAnimationTask::SetSize( uint32_t width, uint32_t height ) { if( mWidth != width || mHeight != height ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mVectorRenderer.SetSize( width, height ); mWidth = width; mHeight = height; - mResourceReady = false; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetSize: width = %d, height = %d [%p]\n", width, height, this ); } } void VectorAnimationTask::PlayAnimation() { - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != PlayState::PLAYING ) { + mNeedAnimationFinishedTrigger = true; mUpdateFrameNumber = false; mPlayState = PlayState::PLAYING; - mVectorAnimationThread.AddTask( this ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::PlayAnimation: Play [%p]\n", this ); } } void VectorAnimationTask::StopAnimation() { - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != PlayState::STOPPED && mPlayState != PlayState::STOPPING ) + if( mPlayState != PlayState::STOPPING ) { mNeedAnimationFinishedTrigger = false; mPlayState = PlayState::STOPPING; @@ -157,7 +166,6 @@ void VectorAnimationTask::StopAnimation() void VectorAnimationTask::PauseAnimation() { - ConditionalWait::ScopedLock lock( mConditionalWait ); if( mPlayState == PlayState::PLAYING ) { mPlayState = PlayState::PAUSED; @@ -166,18 +174,6 @@ void VectorAnimationTask::PauseAnimation() } } -void VectorAnimationTask::RenderFrame() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( !mResourceReady ) - { - mVectorAnimationThread.AddTask( this ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::RenderFrame: Render [%p]\n", this ); - } -} - void VectorAnimationTask::SetAnimationFinishedCallback( EventThreadCallback* callback ) { ConditionalWait::ScopedLock lock( mConditionalWait ); @@ -191,20 +187,65 @@ void VectorAnimationTask::SetLoopCount( int32_t count ) { if( mLoopCount != count ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mLoopCount = count; mCurrentLoop = 0; - mCurrentLoopUpdated = true; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetLoopCount: [%d] [%p]\n", count, this ); } } -void VectorAnimationTask::SetPlayRange( uint32_t startFrame, uint32_t endFrame ) +void VectorAnimationTask::SetPlayRange( const Property::Array& playRange ) { + bool valid = false; + uint32_t startFrame = 0, endFrame = 0; + size_t count = playRange.Count(); + + if( count >= 2 ) + { + int32_t start = 0, end = 0; + if( playRange.GetElementAt( 0 ).Get( start ) && playRange.GetElementAt( 1 ).Get( end ) ) + { + startFrame = static_cast< uint32_t >( start ); + endFrame = static_cast< uint32_t >( end ); + valid = true; + } + else + { + std::string startMarker, endMarker; + if( playRange.GetElementAt( 0 ).Get( startMarker ) && playRange.GetElementAt( 1 ).Get( endMarker ) ) + { + if( mVectorRenderer ) + { + uint32_t frame; // We don't use this later + if( mVectorRenderer.GetMarkerInfo( startMarker, startFrame, frame ) && mVectorRenderer.GetMarkerInfo( endMarker, frame, endFrame ) ) + { + valid = true; + } + } + } + } + } + else if( count == 1 ) + { + std::string marker; + if( playRange.GetElementAt( 0 ).Get( marker ) ) + { + if( mVectorRenderer ) + { + mVectorRenderer.GetMarkerInfo( marker, startFrame, endFrame ); + valid = true; + } + } + } + + if( !valid ) + { + DALI_LOG_ERROR( "VectorAnimationTask::SetPlayRange: Invalid range [%p]\n", this ); + return; + } + // Make sure the range specified is between 0 and the total frame number - if( ( startFrame < mTotalFrame ) && ( endFrame < mTotalFrame ) ) + if( startFrame < mTotalFrame && endFrame < mTotalFrame ) { // If the range is not in order swap values if( startFrame > endFrame ) @@ -216,8 +257,6 @@ void VectorAnimationTask::SetPlayRange( uint32_t startFrame, uint32_t endFrame ) if( startFrame != mStartFrame || endFrame != mEndFrame ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mStartFrame = startFrame; mEndFrame = endFrame; @@ -225,21 +264,20 @@ void VectorAnimationTask::SetPlayRange( uint32_t startFrame, uint32_t endFrame ) if( mStartFrame > mCurrentFrame ) { mCurrentFrame = mStartFrame; - - mCurrentFrameUpdated = true; - mResourceReady = false; } else if( mEndFrame < mCurrentFrame ) { mCurrentFrame = mEndFrame; - - mCurrentFrameUpdated = true; - mResourceReady = false; } DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%p]\n", mStartFrame, mEndFrame, this ); } } + else + { + DALI_LOG_ERROR( "VectorAnimationTask::SetPlayRange: Invalid range (%d, %d) [%p]\n", startFrame, endFrame, this ); + return; + } } void VectorAnimationTask::GetPlayRange( uint32_t& startFrame, uint32_t& endFrame ) @@ -248,37 +286,8 @@ void VectorAnimationTask::GetPlayRange( uint32_t& startFrame, uint32_t& endFrame endFrame = mEndFrame; } -DevelImageVisual::PlayState::Type VectorAnimationTask::GetPlayState() const -{ - DevelImageVisual::PlayState::Type state = DevelImageVisual::PlayState::STOPPED; - - switch( mPlayState ) - { - case PlayState::PLAYING: - { - state = DevelImageVisual::PlayState::PLAYING; - break; - } - case PlayState::PAUSED: - { - state = DevelImageVisual::PlayState::PAUSED; - break; - } - case PlayState::STOPPING: - case PlayState::STOPPED: - { - state = DevelImageVisual::PlayState::STOPPED; - break; - } - } - - return state; -} - void VectorAnimationTask::SetCurrentFrameNumber( uint32_t frameNumber ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mCurrentFrame == frameNumber ) { DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetCurrentFrameNumber: Set same frame [%d] [%p]\n", frameNumber, this ); @@ -288,10 +297,7 @@ void VectorAnimationTask::SetCurrentFrameNumber( uint32_t frameNumber ) if( frameNumber >= mStartFrame && frameNumber <= mEndFrame ) { mCurrentFrame = frameNumber; - mCurrentFrameUpdated = true; - mUpdateFrameNumber = false; - mResourceReady = false; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetCurrentFrameNumber: frame number = %d [%p]\n", mCurrentFrame, this ); } @@ -318,7 +324,6 @@ void VectorAnimationTask::GetDefaultSize( uint32_t& width, uint32_t& height ) co void VectorAnimationTask::SetStopBehavior( DevelImageVisual::StopBehavior::Type stopBehavior ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mStopBehavior = stopBehavior; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetStopBehavior: stop behavor = %d [%p]\n", mStopBehavior, this ); @@ -326,7 +331,6 @@ void VectorAnimationTask::SetStopBehavior( DevelImageVisual::StopBehavior::Type void VectorAnimationTask::SetLoopingMode( DevelImageVisual::LoopingMode::Type loopingMode ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mLoopingMode = loopingMode; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetLoopingMode: looping mode = %d [%p]\n", mLoopingMode, this ); @@ -363,46 +367,41 @@ void VectorAnimationTask::Initialize() bool VectorAnimationTask::Rasterize() { - bool stopped = false, needAnimationFinishedTrigger; - uint32_t currentFrame, startFrame, endFrame; - int32_t loopCount, currentLoopCount; - PlayState playState; + bool stopped = false; + uint32_t currentFrame; { ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) + if( mDestroyTask ) { - mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; + // The task will be destroyed. We don't need rasterization. + return false; } - - currentFrame = mCurrentFrame; - startFrame = mStartFrame; - endFrame = mEndFrame; - loopCount = mLoopCount; - currentLoopCount = mCurrentLoop; - needAnimationFinishedTrigger = mNeedAnimationFinishedTrigger; - playState = mPlayState; - - mResourceReady = true; - mCurrentFrameUpdated = false; - mCurrentLoopUpdated = false; - mUpdateFrameNumber = true; - mNeedAnimationFinishedTrigger = true; } - if( playState == PlayState::STOPPING ) + ApplyAnimationData(); + + if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) { - currentFrame = GetStoppedFrame( startFrame, endFrame, currentFrame ); - ResetValue( mCurrentFrameUpdated, mCurrentFrame, currentFrame, mConditionalWait ); + mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; + Dali::ClampInPlace( mCurrentFrame, mStartFrame, mEndFrame ); + } + + currentFrame = mCurrentFrame; + + mUpdateFrameNumber = true; + if( mPlayState == PlayState::STOPPING ) + { + mCurrentFrame = GetStoppedFrame( mStartFrame, mEndFrame, mCurrentFrame ); + currentFrame = mCurrentFrame; stopped = true; } - else if( playState == PlayState::PLAYING ) + else if( mPlayState == PlayState::PLAYING ) { bool animationFinished = false; - if( currentFrame >= endFrame ) // last frame + if( currentFrame >= mEndFrame ) // last frame { if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) { @@ -410,21 +409,20 @@ bool VectorAnimationTask::Rasterize() } else { - if( loopCount < 0 || ++currentLoopCount < loopCount ) // repeat forever or before the last loop + if( mLoopCount < 0 || ++mCurrentLoop < mLoopCount ) // repeat forever or before the last loop { - ResetValue( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it. + mCurrentFrame = mStartFrame; mUpdateFrameNumber = false; } else { animationFinished = true; // end of animation } - ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); } } - else if( currentFrame == startFrame && !mForward ) // first frame + else if( currentFrame == mStartFrame && !mForward ) // first frame { - if( loopCount < 0 || ++currentLoopCount < loopCount ) // repeat forever or before the last loop + if( mLoopCount < 0 || ++mCurrentLoop < mLoopCount ) // repeat forever or before the last loop { mForward = true; } @@ -432,7 +430,6 @@ bool VectorAnimationTask::Rasterize() { animationFinished = true; // end of animation } - ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); } if( animationFinished ) @@ -467,16 +464,19 @@ bool VectorAnimationTask::Rasterize() mCurrentLoop = 0; // Animation is finished - if( needAnimationFinishedTrigger && mAnimationFinishedTrigger ) { - mAnimationFinishedTrigger->Trigger(); + ConditionalWait::ScopedLock lock( mConditionalWait ); + if( mNeedAnimationFinishedTrigger && mAnimationFinishedTrigger ) + { + mAnimationFinishedTrigger->Trigger(); + } } DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Animation is finished [current = %d] [%p]\n", currentFrame, this ); } bool keepAnimation = true; - if( playState == PlayState::PAUSED || playState == PlayState::STOPPED ) + if( mPlayState == PlayState::PAUSED || mPlayState == PlayState::STOPPED ) { keepAnimation = false; } @@ -537,6 +537,69 @@ std::chrono::time_point< std::chrono::system_clock > VectorAnimationTask::GetNex return mNextFrameStartTime; } +void VectorAnimationTask::ApplyAnimationData() +{ + uint32_t index; + + { + ConditionalWait::ScopedLock lock( mConditionalWait ); + + if( !mAnimationDataUpdated || mAnimationData[mAnimationDataIndex].resendFlag != 0 ) + { + // Data is not updated or the previous data is not applied yet. + return; + } + + mAnimationDataIndex = mAnimationDataIndex == 0 ? 1 : 0; // Swap index + mAnimationDataUpdated = false; + + index = mAnimationDataIndex; + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_LOOP_COUNT ) + { + SetLoopCount( mAnimationData[index].loopCount ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_RANGE ) + { + SetPlayRange( mAnimationData[index].playRange ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_STOP_BEHAVIOR ) + { + SetStopBehavior( mAnimationData[index].stopBehavior ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_LOOPING_MODE ) + { + SetLoopingMode( mAnimationData[index].loopingMode ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_CURRENT_FRAME ) + { + SetCurrentFrameNumber( mAnimationData[index].currentFrame ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE ) + { + if( mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING ) + { + PlayAnimation(); + } + else if( mAnimationData[index].playState == DevelImageVisual::PlayState::PAUSED ) + { + PauseAnimation(); + } + else if( mAnimationData[index].playState == DevelImageVisual::PlayState::STOPPED ) + { + StopAnimation(); + } + } + + mAnimationData[index].resendFlag = 0; +} + } // namespace Internal } // namespace Toolkit