X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-vector-image%2Fvector-rasterize-thread.cpp;h=2794c14d41778451bcf2c5d9dc841d07cfa08393;hb=5b7c9a175a97de10a004943526f07a1413b3c83c;hp=9e0645bb8b1c3c7ffebf9869e5d3c0a257a7993f;hpb=683bf0c0ed06950ec3eef64fb564104b6311c9bf;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git 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 9e0645b..2794c14 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 @@ -21,8 +21,8 @@ // EXTERNAL INCLUDES #include #include - -// INTERNAL INCLUDES +#include +#include namespace Dali { @@ -37,22 +37,34 @@ 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(), mConditionalWait(), - mMutex(), - mResourceReadyTrigger( NULL ), - mAnimationFinishedTrigger( NULL ), + 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 ), @@ -64,9 +76,10 @@ VectorRasterizeThread::VectorRasterizeThread( const std::string& url ) mNeedRender( false ), mDestroyThread( false ), mResourceReady( false ), + mCurrentFrameUpdated( false ), mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) { - mVectorRenderer = VectorAnimationRenderer::New( mUrl ); + Initialize(); } VectorRasterizeThread::~VectorRasterizeThread() @@ -84,19 +97,13 @@ VectorRasterizeThread::~VectorRasterizeThread() DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join\n" ); Join(); - - delete mResourceReadyTrigger; - delete mAnimationFinishedTrigger; } void VectorRasterizeThread::Run() { mLogFactory.InstallLogFunction(); - //TODO: check the return value - StartRender(); - - while( IsThreadReady() ) + while( !mDestroyThread ) { Rasterize(); } @@ -108,36 +115,34 @@ void VectorRasterizeThread::SetRenderer( Renderer renderer ) mVectorRenderer.SetRenderer( renderer ); - // Need to trigger resource ready again - mResourceReady = false; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer\n" ); } void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mVectorRenderer.SetSize( width, 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, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height ); + } } -void VectorRasterizeThread::StartAnimation() +void VectorRasterizeThread::PlayAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); if( mPlayState != DevelImageVisual::PlayState::PLAYING ) { - if( mPlayState == DevelImageVisual::PlayState::STOPPED ) - { - // Reset the current frame and the current loop - mCurrentFrame = mStartFrame; - mCurrentLoop = 0; - } - mPlayState = DevelImageVisual::PlayState::PLAYING; mConditionalWait.Notify( lock ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartAnimation: Start\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Start\n" ); } } @@ -148,6 +153,9 @@ void VectorRasterizeThread::StopAnimation() { mPlayState = DevelImageVisual::PlayState::STOPPED; + mCurrentFrame = mStartFrame; + mCurrentFrameUpdated = true; + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" ); } } @@ -166,130 +174,226 @@ void VectorRasterizeThread::PauseAnimation() void VectorRasterizeThread::RenderFrame() { ConditionalWait::ScopedLock lock( mConditionalWait ); - mNeedRender = true; - mConditionalWait.Notify( lock ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" ); + if( !mResourceReady ) + { + mNeedRender = true; + mConditionalWait.Notify( lock ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" ); + } } void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - mResourceReadyTrigger = callback; + mResourceReadyTrigger = std::unique_ptr< EventThreadCallback >( callback ); } void VectorRasterizeThread::SetAnimationFinishedCallback( EventThreadCallback* callback ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - mAnimationFinishedTrigger = callback; + mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback ); } -void VectorRasterizeThread::SetLoopCount( int16_t count ) +void VectorRasterizeThread::SetLoopCount( int32_t count ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); + if( mLoopCount != count ) + { + ConditionalWait::ScopedLock lock( mConditionalWait ); - mLoopCount = count; + mLoopCount = count; + } +} - // Reset progress - mCurrentLoop = 0; - mCurrentFrame = mStartFrame; +int32_t VectorRasterizeThread::GetLoopCount() const +{ + return mLoopCount; } void VectorRasterizeThread::SetPlayRange( Vector2 range ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); + // 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 ); + } - mPlayRange = range; + if( mPlayRange != orderedRange ) + { + ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mTotalFrame != 0 ) - { - mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f ); - mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f ); + mPlayRange = orderedRange; + + 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; + } + } } } -DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() +Vector2 VectorRasterizeThread::GetPlayRange() const { - return mPlayState; + return mPlayRange; } -bool VectorRasterizeThread::IsThreadReady() +void VectorRasterizeThread::SetCurrentProgress( float progress ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread ) + if( progress >= mPlayRange.x && progress <= mPlayRange.y ) { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" ); + mProgress = progress; - mConditionalWait.Wait( lock ); + 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 ); } +} - // Keep the thread alive if this thread is NOT to be destroyed - return !mDestroyThread; +float VectorRasterizeThread::GetCurrentProgress() const +{ + return ( static_cast< float >( mCurrentFrame ) / static_cast< float >( mTotalFrame ) ); +} + +void VectorRasterizeThread::GetDefaultSize( uint32_t& width, uint32_t& height ) const +{ + mVectorRenderer.GetDefaultSize( width, height ); } -bool VectorRasterizeThread::StartRender() +DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() const { - //TODO: check the return value - mVectorRenderer.StartRender(); + return mPlayState; +} + +bool VectorRasterizeThread::IsResourceReady() const +{ + return mResourceReady; +} + +void VectorRasterizeThread::Initialize() +{ + mVectorRenderer = VectorAnimationRenderer::New( mUrl ); mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f ); mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f ); - mCurrentFrame = mStartFrame; + mCurrentFrame = std::max( static_cast< uint32_t >( mTotalFrame * mProgress + 0.5f ), mStartFrame ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame ); + mFrameRate = mVectorRenderer.GetFrameRate(); + mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; - return true; + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Initialize: file = %s [%d frames, %f fps]\n", mUrl.c_str(), mTotalFrame, mFrameRate ); } void VectorRasterizeThread::Rasterize() { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [%d]\n", mCurrentFrame ); + bool resourceReady; + uint32_t currentFrame, startFrame, endFrame; + int32_t loopCount; + DevelImageVisual::PlayState playState; + + { + ConditionalWait::ScopedLock lock( mConditionalWait ); + + 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 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( 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; + // 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 ); } } } } - mNeedRender = false; - - if( !mResourceReady ) + 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 ); + +#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