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-rasterize-thread.cpp;h=a640b19cccb819063e6c3c40879294a4beca9313;hp=25d0743afc48957e61cebedc2750365ee51fdc53;hb=2c6a6697e24d39ef061f134b39f30acc5c47b0cb;hpb=e1f3e2cd23303685a5cb9e8babf4ea11d58c95e9 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 25d0743..a640b19 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -37,50 +37,20 @@ namespace Internal namespace { -constexpr auto LOOP_FOREVER = -1; -constexpr auto NANOSECONDS_PER_SECOND( 1e+9 ); - #if defined(DEBUG_ENABLED) 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(), +VectorRasterizeThread::VectorRasterizeThread() +: mRasterizeTasks(), mConditionalWait(), - mResourceReadyTrigger(), - mAnimationFinishedTrigger(), - mPlayRange( 0.0f, 1.0f ), - mPlayState( DevelImageVisual::PlayState::STOPPED ), - mFrameDurationNanoSeconds( 0 ), - mProgress( 0.0f ), - mFrameRate( 60.0f ), - mCurrentFrame( 0 ), - mTotalFrame( 0 ), - mStartFrame( 0 ), - mEndFrame( 0 ), - mWidth( 0 ), - mHeight( 0 ), - mLoopCount( LOOP_FOREVER ), - mCurrentLoop( 0 ), - mNeedRender( false ), + mCompletedCallback(), mDestroyThread( false ), - mResourceReady( false ), - mCurrentFrameUpdated( false ), + mIsThreadStarted( false ), mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) { - mVectorRenderer = VectorAnimationRenderer::New( mUrl ); } VectorRasterizeThread::~VectorRasterizeThread() @@ -90,319 +60,82 @@ VectorRasterizeThread::~VectorRasterizeThread() ConditionalWait::ScopedLock lock( mConditionalWait ); mDestroyThread = true; mConditionalWait.Notify( lock ); - - // This should be called in the main thread to stop waiting for the dequeuable buffer. - mVectorRenderer.StopRender(); } - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join [%p]\n", this ); Join(); } -void VectorRasterizeThread::Run() -{ - SetThreadName( "VectorImageThread" ); - mLogFactory.InstallLogFunction(); - - //TODO: check the return value - StartRender(); - - while( !mDestroyThread ) - { - Rasterize(); - } -} - -void VectorRasterizeThread::SetRenderer( Renderer renderer ) +void VectorRasterizeThread::SetCompletedCallback( CallbackBase* callback ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - mVectorRenderer.SetRenderer( renderer ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer\n" ); + mCompletedCallback = std::unique_ptr< CallbackBase >( callback ); } -void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height ) +void VectorRasterizeThread::AddTask( VectorAnimationTaskPtr task ) { - if( mWidth != width || mHeight != height ) + if( !mIsThreadStarted ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mVectorRenderer.SetSize( width, height ); - - mWidth = width; - mHeight = height; - - mResourceReady = false; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height ); + Start(); + mIsThreadStarted = true; } -} -void VectorRasterizeThread::PlayAnimation() -{ + // Lock while adding task to the queue ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::PLAYING ) - { - mPlayState = DevelImageVisual::PlayState::PLAYING; - mConditionalWait.Notify( lock ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Start\n" ); - } -} -void VectorRasterizeThread::StopAnimation() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::STOPPED ) + if( mRasterizeTasks.end() == std::find( mRasterizeTasks.begin(), mRasterizeTasks.end(), task ) ) { - mPlayState = DevelImageVisual::PlayState::STOPPED; - - mCurrentFrame = mStartFrame; - mCurrentFrameUpdated = true; + mRasterizeTasks.push_back( task ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" ); - } -} - -void VectorRasterizeThread::PauseAnimation() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState == DevelImageVisual::PlayState::PLAYING ) - { - mPlayState = DevelImageVisual::PlayState::PAUSED; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" ); - } -} - -void VectorRasterizeThread::RenderFrame() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( !mResourceReady ) - { - mNeedRender = true; + // wake up the animation thread mConditionalWait.Notify( lock ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" ); - } -} - -void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback ) -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - mResourceReadyTrigger = std::unique_ptr< EventThreadCallback >( callback ); -} - -void VectorRasterizeThread::SetAnimationFinishedCallback( EventThreadCallback* callback ) -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback ); -} - -void VectorRasterizeThread::SetLoopCount( int32_t count ) -{ - if( mLoopCount != count ) - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - - mLoopCount = count; - } -} - -int32_t VectorRasterizeThread::GetLoopCount() const -{ - return mLoopCount; -} - -void VectorRasterizeThread::SetPlayRange( Vector2 range ) -{ - // Make sure the range specified is between 0.0 and 1.0 - if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f ) - { - Vector2 orderedRange( range ); - // If the range is not in order swap values - if( range.x > range.y ) - { - orderedRange = Vector2( range.y, range.x ); - } - - if( mPlayRange != orderedRange ) - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - - mPlayRange = orderedRange; - - if( mTotalFrame != 0 ) - { - mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f ); - mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f ); - - // If the current frame is out of the range, change the current frame also. - if( mStartFrame > mCurrentFrame ) - { - mCurrentFrame = mStartFrame; - - mCurrentFrameUpdated = true; - mResourceReady = false; - } - else if( mEndFrame < mCurrentFrame ) - { - mCurrentFrame = mEndFrame; - - mCurrentFrameUpdated = true; - mResourceReady = false; - } - } - } } } -Vector2 VectorRasterizeThread::GetPlayRange() const -{ - return mPlayRange; -} - -void VectorRasterizeThread::SetCurrentProgress( float progress ) +void VectorRasterizeThread::Run() { - ConditionalWait::ScopedLock lock( mConditionalWait ); + SetThreadName( "VectorRasterizeThread" ); + mLogFactory.InstallLogFunction(); - if( progress >= mPlayRange.x && progress <= mPlayRange.y ) + while( !mDestroyThread ) { - mProgress = progress; - - if( mTotalFrame != 0 ) - { - mCurrentFrame = static_cast< uint32_t >( mTotalFrame * progress + 0.5f ); - mCurrentFrameUpdated = true; - } - - mResourceReady = false; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentProgress: progress = %f (%d)\n", progress, mCurrentFrame ); + Rasterize(); } } -float VectorRasterizeThread::GetCurrentProgress() const -{ - return ( static_cast< float >( mCurrentFrame ) / static_cast< float >( mTotalFrame ) ); -} - -DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() const -{ - return mPlayState; -} - -bool VectorRasterizeThread::IsResourceReady() const -{ - return mResourceReady; -} - -bool VectorRasterizeThread::StartRender() -{ - //TODO: check the return value - mVectorRenderer.StartRender(); - - mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); - - mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f ); - mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f ); - - mCurrentFrame = std::max( static_cast< uint32_t >( mTotalFrame * mProgress + 0.5f ), mStartFrame ); - - mFrameRate = mVectorRenderer.GetFrameRate(); - mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d, %f fps]\n", mTotalFrame, mFrameRate ); - - return true; -} - void VectorRasterizeThread::Rasterize() { - bool resourceReady; - uint32_t currentFrame, startFrame, endFrame; - int32_t loopCount; - DevelImageVisual::PlayState playState; - + VectorAnimationTaskPtr nextTask; { + // Lock while popping task out from the queue ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread ) + // conditional wait + if( mRasterizeTasks.empty() ) { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Wait\n" ); - - if( mPlayState == DevelImageVisual::PlayState::STOPPED ) - { - // Reset the current loop - 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( currentFrame ); - - if( playState == DevelImageVisual::PlayState::PLAYING ) - { - if( currentFrame >= endFrame ) + // pop out the next task from the queue + if( !mRasterizeTasks.empty() ) { - if( loopCount < 0 ) - { - // repeat forever - ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it. - } - else - { - mCurrentLoop++; - if( mCurrentLoop >= loopCount ) - { - mPlayState = DevelImageVisual::PlayState::STOPPED; - - // Animation is finished - mAnimationFinishedTrigger->Trigger(); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" ); - } - else - { - ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); - } - } + std::vector< VectorAnimationTaskPtr >::iterator next = mRasterizeTasks.begin(); + nextTask = *next; + mRasterizeTasks.erase( next ); } } - if( !resourceReady ) + if( nextTask ) { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" ); + bool keepAnimation = nextTask->Rasterize(); - mResourceReadyTrigger->Trigger(); + if( mCompletedCallback ) + { + CallbackBase::Execute( *mCompletedCallback, nextTask, keepAnimation ); + } } - - auto timeToSleepUntil = currentFrameStartTime + std::chrono::nanoseconds( mFrameDurationNanoSeconds ); - -#if defined(DEBUG_ENABLED) - auto sleepDuration = std::chrono::duration_cast< std::chrono::milliseconds >( timeToSleepUntil - std::chrono::system_clock::now() ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [current = %d, sleep duration = %lld]\n", mCurrentFrame, sleepDuration.count() ); -#endif - - std::this_thread::sleep_until( timeToSleepUntil ); } } // namespace Internal