From: Heeyong Song Date: Mon, 11 Mar 2019 08:06:01 +0000 (+0900) Subject: (AnimatedVectorImageVisual) Prevent properties from being updated during rendering X-Git-Tag: dali_1.4.13~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=a30390f12a3730156a9872d5a2b90b50a795aeb7 (AnimatedVectorImageVisual) Prevent properties from being updated during rendering Change-Id: I9f68e3ad2d116f2a6d92422c864f72479f7e6b07 --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index bda987d..d2e6332 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -282,6 +284,8 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render( 16 ); + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); // wait for one animation loop (16fps, 5frames, need 80ms) + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); Property::Map map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); @@ -294,6 +298,8 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render(16); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::PLAY_STATE ); DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PAUSED ) ); @@ -650,7 +656,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) ToolkitTestApplication application; tet_infoline( "UtcDaliAnimatedVectorImageVisualJumpToCurrentProgress" ); - Vector2 playRange( 0.2f, 0.8f ); + Vector2 playRange( 0.2f, 0.5f ); Property::Map propertyMap; propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE ) @@ -682,7 +688,7 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); DALI_TEST_EQUALS( value->Get< Vector2 >(), playRange, TEST_LOCATION ); - Vector2 newPlayRange( 0.4f, 1.0f ); + Vector2 newPlayRange( 0.6f, 1.0f ); Property::Map attributes; attributes.Add( DevelImageVisual::Property::PLAY_RANGE, newPlayRange ); @@ -700,5 +706,17 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); DALI_TEST_EQUALS( value->Get< Vector2 >(), newPlayRange, TEST_LOCATION ); + attributes.Clear(); + attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange ); + + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); + + application.SendNotification(); + application.Render(); + + map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); + DALI_TEST_EQUALS( value->Get< Vector2 >(), playRange, TEST_LOCATION ); + END_TEST; } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index aed37a2..35fd8aa 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -317,6 +317,12 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons if( attributes.Get( progress ) ) { mVectorRasterizeThread.SetCurrentProgress( progress ); + + if( mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::PLAYING ) + { + mVectorRasterizeThread.RenderFrame(); + Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger rendering + } } break; } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp index a5de71a..da46e1e 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp @@ -44,13 +44,21 @@ constexpr auto NANOSECONDS_PER_SECOND( 1e+9 ); Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" ); #endif +inline void ResetToStart( bool& updated, uint32_t& value, uint32_t startValue, ConditionalWait& conditionalWait ) +{ + ConditionalWait::ScopedLock lock( conditionalWait ); + if( !updated ) + { + value = startValue; + } +} + } // unnamed namespace VectorRasterizeThread::VectorRasterizeThread( const std::string& url ) : mUrl( url ), mVectorRenderer(), mConditionalWait(), - mMutex(), mResourceReadyTrigger(), mAnimationFinishedTrigger(), mPlayRange( 0.0f, 1.0f ), @@ -69,6 +77,7 @@ VectorRasterizeThread::VectorRasterizeThread( const std::string& url ) mNeedRender( false ), mDestroyThread( false ), mResourceReady( false ), + mCurrentFrameUpdated( false ), mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) { mVectorRenderer = VectorAnimationRenderer::New( mUrl ); @@ -99,7 +108,7 @@ void VectorRasterizeThread::Run() //TODO: check the return value StartRender(); - while( IsThreadReady() ) + while( !mDestroyThread ) { Rasterize(); } @@ -149,10 +158,6 @@ void VectorRasterizeThread::StopAnimation() { mPlayState = DevelImageVisual::PlayState::STOPPED; - // Reset the current frame and the current loop - mCurrentFrame = mStartFrame; - mCurrentLoop = 0; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" ); } } @@ -200,9 +205,6 @@ void VectorRasterizeThread::SetLoopCount( int32_t count ) ConditionalWait::ScopedLock lock( mConditionalWait ); mLoopCount = count; - - // Reset progress - mCurrentLoop = 0; } } @@ -239,12 +241,14 @@ void VectorRasterizeThread::SetPlayRange( Vector2 range ) { mCurrentFrame = mStartFrame; + mCurrentFrameUpdated = true; mResourceReady = false; } else if( mEndFrame < mCurrentFrame ) { mCurrentFrame = mEndFrame; + mCurrentFrameUpdated = true; mResourceReady = false; } } @@ -268,6 +272,7 @@ void VectorRasterizeThread::SetCurrentProgress( float progress ) if( mTotalFrame != 0 ) { mCurrentFrame = static_cast< uint32_t >( mTotalFrame * progress + 0.5f ); + mCurrentFrameUpdated = true; } mResourceReady = false; @@ -291,21 +296,6 @@ bool VectorRasterizeThread::IsResourceReady() const return mResourceReady; } -bool VectorRasterizeThread::IsThreadReady() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread ) - { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" ); - - mConditionalWait.Wait( lock ); - } - - // Keep the thread alive if this thread is NOT to be destroyed - return !mDestroyThread; -} - bool VectorRasterizeThread::StartRender() { //TODO: check the return value @@ -328,63 +318,78 @@ bool VectorRasterizeThread::StartRender() void VectorRasterizeThread::Rasterize() { - bool needRender, resourceReady; + bool resourceReady; + uint32_t currentFrame, startFrame, endFrame; + int32_t loopCount; + DevelImageVisual::PlayState playState; { ConditionalWait::ScopedLock lock( mConditionalWait ); - needRender = mNeedRender; + + if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread ) + { + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Wait\n" ); + + if( mPlayState == DevelImageVisual::PlayState::STOPPED ) + { + // Reset the current frame and the current loop + mCurrentFrame = mStartFrame; + mCurrentLoop = 0; + } + mConditionalWait.Wait( lock ); + } + resourceReady = mResourceReady; + currentFrame = mCurrentFrame++; + startFrame = mStartFrame; + endFrame = mEndFrame; + loopCount = mLoopCount; + playState = mPlayState; + + mNeedRender = false; + mResourceReady = true; + mCurrentFrameUpdated = false; } auto currentFrameStartTime = std::chrono::system_clock::now(); // Rasterize - mVectorRenderer.Render( mCurrentFrame ); + mVectorRenderer.Render( currentFrame ); - if( mPlayState == DevelImageVisual::PlayState::PLAYING ) + if( playState == DevelImageVisual::PlayState::PLAYING ) { - if( ++mCurrentFrame >= mEndFrame ) + if( currentFrame >= endFrame ) { - if( mLoopCount < 0 ) + if( loopCount < 0 ) { // repeat forever - mCurrentFrame = mStartFrame; + ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it. } else { mCurrentLoop++; - if( mCurrentLoop >= mLoopCount ) + if( mCurrentLoop >= loopCount ) { - // Animation is finished mPlayState = DevelImageVisual::PlayState::STOPPED; - // Reset the current frame and the current loop - mCurrentFrame = mStartFrame; - mCurrentLoop = 0; - + // Animation is finished mAnimationFinishedTrigger->Trigger(); DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" ); } else { - mCurrentFrame = mStartFrame; + ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); } } } } - if( needRender ) - { - mNeedRender = false; - } - if( !resourceReady ) { DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" ); mResourceReadyTrigger->Trigger(); - mResourceReady = true; } auto timeToSleepUntil = currentFrameStartTime + std::chrono::nanoseconds( mFrameDurationNanoSeconds ); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h index 3c8879e..cb5220d 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h @@ -165,12 +165,6 @@ protected: private: /** - * @brief Called by the rasterize thread which ensures a wait if required. - * @return false if the thread should stop. - */ - bool IsThreadReady(); - - /** * @brief Start rendering */ bool StartRender(); @@ -191,7 +185,6 @@ private: std::string mUrl; VectorAnimationRenderer mVectorRenderer; ConditionalWait mConditionalWait; - Dali::Mutex mMutex; std::unique_ptr< EventThreadCallback > mResourceReadyTrigger; std::unique_ptr< EventThreadCallback > mAnimationFinishedTrigger; Vector2 mPlayRange; @@ -210,6 +203,7 @@ private: bool mNeedRender; bool mDestroyThread; ///< Whether the thread be destroyed bool mResourceReady; + bool mCurrentFrameUpdated; const Dali::LogFactoryInterface& mLogFactory; ///< The log factory };