From 07c47ae1945fa29711f592e2e78b0cb87434ae3d Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Tue, 12 Nov 2019 15:43:30 +0900 Subject: [PATCH] Revert "(Vector) Refactor vector to use thread pool" This reverts commit d1b15cdf7040a24f74cd5a0601eec61c9e65b47c. Change-Id: Id457b929701068aa941caea587a558c9e2c098ff --- .../toolkit-vector-animation-renderer.cpp | 21 +- .../utc-Dali-AnimatedVectorImageVisual.cpp | 140 +----- dali-toolkit/internal/file.list | 2 - .../animated-vector-image-visual.cpp | 71 ++- .../animated-vector-image-visual.h | 11 +- .../vector-animation-task.cpp | 516 --------------------- .../animated-vector-image/vector-animation-task.h | 258 ----------- .../vector-animation-thread.cpp | 330 ------------- .../vector-animation-thread.h | 201 -------- .../vector-rasterize-thread.cpp | 452 ++++++++++++++++-- .../vector-rasterize-thread.h | 179 ++++++- .../internal/visuals/visual-factory-cache.cpp | 11 - .../internal/visuals/visual-factory-cache.h | 20 +- 13 files changed, 632 insertions(+), 1580 deletions(-) delete mode 100644 dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp delete mode 100644 dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h delete mode 100644 dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp delete mode 100755 dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp index 344280a..558cdec 100755 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp @@ -37,20 +37,8 @@ public: mRenderer(), mWidth( 0 ), mHeight( 0 ), - mPreviousFrame( 0 ), - mFrameRate( 60.0f ) + mPreviousFrame( 0 ) { - mCount++; - - if( mCount == 2 ) - { - mFrameRate = 0.1f; - } - } - - ~VectorAnimationRenderer() - { - mCount--; } void SetRenderer( Dali::Renderer renderer ) @@ -99,7 +87,7 @@ public: float GetFrameRate() const { - return mFrameRate; + return 60.0f; } void GetDefaultSize( uint32_t& width, uint32_t& height ) const @@ -115,19 +103,14 @@ public: public: - static uint32_t mCount; - std::string mUrl; Dali::Renderer mRenderer; uint32_t mWidth; uint32_t mHeight; uint32_t mPreviousFrame; - float mFrameRate; Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal; }; -uint32_t VectorAnimationRenderer::mCount = 0; - inline VectorAnimationRenderer& GetImplementation( Dali::VectorAnimationRenderer& renderer ) { DALI_ASSERT_ALWAYS( renderer && "VectorAnimationRenderer handle is empty." ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index 98a2d3d..87ff376 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -251,20 +251,8 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) VisualFactory factory = VisualFactory::Get(); Visual::Base visual = factory.CreateVisual( propertyMap ); - DummyControl actor = DummyControl::New( true ); - DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() ); - dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); - - Vector2 controlSize( 20.f, 30.f ); - actor.SetSize( controlSize ); - - Stage::GetCurrent().Add( actor ); - - application.SendNotification(); - application.Render(); - Property::Map resultMap; - resultMap = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + visual.CreatePropertyMap( resultMap ); // check the property values from the returned map from a visual Property::Value* value = resultMap.Find( Toolkit::Visual::Property::TYPE, Property::INTEGER ); @@ -576,10 +564,10 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) ToolkitTestApplication application; tet_infoline( "UtcDaliAnimatedVectorImageVisualPlayRange" ); - int startFrame = 1, endFrame = 3; + int startFrame = 3, endFrame = 1; Property::Array array; - array.PushBack( endFrame ); array.PushBack( startFrame ); + array.PushBack( endFrame ); Property::Map propertyMap; propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE ) @@ -622,7 +610,7 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) // Set invalid play range array.Clear(); - array.PushBack( 1 ); + array.PushBack( -1 ); array.PushBack( 100 ); attributes.Clear(); @@ -642,44 +630,6 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) DALI_TEST_EQUALS( startFrame, resultStartFrame, TEST_LOCATION ); // Should not be changed DALI_TEST_EQUALS( endFrame, resultEndFrame, TEST_LOCATION ); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PAUSE, Property::Map() ); - - application.SendNotification(); - application.Render(); - - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3 ); - - application.SendNotification(); - application.Render(); - - map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); - value = map.Find( DevelImageVisual::Property::CURRENT_FRAME_NUMBER ); - DALI_TEST_EQUALS( value->Get< int >(), 3, TEST_LOCATION ); - - array.Clear(); - array.PushBack( 0 ); - array.PushBack( 2 ); - - attributes.Clear(); - attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array ); - 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 ); - - result = value->GetArray(); - result->GetElementAt( 0 ).Get( resultStartFrame ); - result->GetElementAt( 1 ).Get( resultEndFrame ); - - DALI_TEST_EQUALS( 0, resultStartFrame, TEST_LOCATION ); - DALI_TEST_EQUALS( 2, resultEndFrame, TEST_LOCATION ); - - value = map.Find( DevelImageVisual::Property::CURRENT_FRAME_NUMBER ); - DALI_TEST_EQUALS( value->Get< int >(), 2, TEST_LOCATION ); // CURRENT_FRAME_NUMBER should be changed also. - END_TEST; } @@ -906,24 +856,6 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) DALI_TEST_CHECK( result->GetElementAt( 0 ).Get< int >() == startFrame ); DALI_TEST_CHECK( result->GetElementAt( 1 ).Get< int >() == endFrame ); - // Play and update property - attributes.Clear(); - DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); - - application.SendNotification(); - application.Render(); - - attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 10 ); - - 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::LOOP_COUNT ); - DALI_TEST_EQUALS( value->Get< int >(), 10, TEST_LOCATION ); - END_TEST; } @@ -1161,67 +1093,3 @@ int UtcDaliAnimatedVectorImageVisualPropertyNotification(void) END_TEST; } - -int UtcDaliAnimatedVectorImageVisualMultipleInstances(void) -{ - ToolkitTestApplication application; - tet_infoline( "UtcDaliAnimatedVectorImageVisualMultipleInstances" ); - - Property::Map propertyMap; - propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE ) - .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME ); - - Visual::Base visual1 = VisualFactory::Get().CreateVisual( propertyMap ); - DALI_TEST_CHECK( visual1 ); - - DummyControl actor1 = DummyControl::New( true ); - DummyControlImpl& dummyImpl1 = static_cast< DummyControlImpl& >( actor1.GetImplementation() ); - dummyImpl1.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual1 ); - - Vector2 controlSize( 20.f, 30.f ); - actor1.SetSize( controlSize ); - - Stage::GetCurrent().Add( actor1 ); - - propertyMap.Clear(); - propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE ) - .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME ); - - Visual::Base visual2 = VisualFactory::Get().CreateVisual( propertyMap ); - DALI_TEST_CHECK( visual2 ); - - DummyControl actor2 = DummyControl::New( true ); - DummyControlImpl& dummyImpl2 = static_cast< DummyControlImpl& >( actor2.GetImplementation() ); - dummyImpl2.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual2 ); - - actor2.SetSize( controlSize ); - - Stage::GetCurrent().Add( actor2 ); - - DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, Property::Map() ); - - application.SendNotification(); - application.Render(); - - std::this_thread::sleep_for( std::chrono::milliseconds( 200 ) ); - - Property::Map attributes; - attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME ); - - DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); - DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes ); - - DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, Property::Map() ); - - // renderer is added to actor - DALI_TEST_CHECK( actor1.GetRendererCount() == 1u ); - Renderer renderer1 = actor1.GetRendererAt( 0u ); - DALI_TEST_CHECK( renderer1 ); - - // renderer is added to actor - DALI_TEST_CHECK( actor2.GetRendererCount() == 1u ); - Renderer renderer2 = actor2.GetRendererAt( 0u ); - DALI_TEST_CHECK( renderer2 ); - - END_TEST; -} diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 9642ef8..a7b1b78 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -19,8 +19,6 @@ SET( toolkit_src_files ${toolkit_src_dir}/visuals/animated-image/rolling-image-cache.cpp ${toolkit_src_dir}/visuals/animated-image/rolling-gif-image-cache.cpp ${toolkit_src_dir}/visuals/animated-vector-image/animated-vector-image-visual.cpp - ${toolkit_src_dir}/visuals/animated-vector-image/vector-animation-task.cpp - ${toolkit_src_dir}/visuals/animated-vector-image/vector-animation-thread.cpp ${toolkit_src_dir}/visuals/animated-vector-image/vector-rasterize-thread.cpp ${toolkit_src_dir}/visuals/border/border-visual.cpp ${toolkit_src_dir}/visuals/color/color-visual.cpp 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 070836c..5b0c1c4 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 @@ -94,9 +94,9 @@ AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl ) : Visual::Base( factoryCache, Visual::FittingMode::FILL ), - mUrl( imageUrl ), - mVectorAnimationTask( new VectorAnimationTask( factoryCache, imageUrl.GetUrl() ) ), mImageVisualShaderFactory( shaderFactory ), + mUrl( imageUrl ), + mVectorRasterizeThread( imageUrl.GetUrl() ), mVisualSize(), mVisualScale( Vector2::ONE ), mPlacementActor(), @@ -112,8 +112,10 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factor // the rasterized image is with pre-multiplied alpha format mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; - mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); - mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) ); + mVectorRasterizeThread.UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); + mVectorRasterizeThread.SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) ); + + mVectorRasterizeThread.Start(); } AnimatedVectorImageVisual::~AnimatedVectorImageVisual() @@ -129,7 +131,7 @@ void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize ) else { uint32_t width, height; - mVectorAnimationTask->GetDefaultSize( width, height ); + mVectorRasterizeThread.GetDefaultSize( width, height ); naturalSize.x = width; naturalSize.y = height; } @@ -147,17 +149,14 @@ void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const } map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, mLoopCount ); - uint32_t startFrame, endFrame; - mVectorAnimationTask->GetPlayRange( startFrame, endFrame ); - Property::Array playRange; - playRange.PushBack( static_cast< int32_t >( startFrame ) ); - playRange.PushBack( static_cast< int32_t >( endFrame ) ); + playRange.PushBack( mStartFrame ); + playRange.PushBack( mEndFrame ); map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, playRange ); - map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int32_t >( mVectorAnimationTask->GetPlayState() ) ); - map.Insert( Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, static_cast< int32_t >( mVectorAnimationTask->GetCurrentFrameNumber() ) ); - map.Insert( Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, static_cast< int32_t >( mVectorAnimationTask->GetTotalFrameNumber() ) ); + map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread.GetPlayState() ) ); + map.Insert( Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, static_cast< int32_t >( mVectorRasterizeThread.GetCurrentFrameNumber() ) ); + map.Insert( Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, static_cast< int32_t >( mVectorRasterizeThread.GetTotalFrameNumber() ) ); map.Insert( Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mStopBehavior ); map.Insert( Toolkit::DevelImageVisual::Property::LOOPING_MODE, mLoopingMode ); @@ -223,7 +222,7 @@ void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Prop if( count >= 2 ) { int startFrame, endFrame; - int totalFrame = mVectorAnimationTask->GetTotalFrameNumber(); + int totalFrame = mVectorRasterizeThread.GetTotalFrameNumber(); array->GetElementAt( 0 ).Get( startFrame ); array->GetElementAt( 1 ).Get( endFrame ); @@ -296,7 +295,7 @@ void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor ) // Hold the weak handle of the placement actor and delay the adding of renderer until the rasterization is finished. mPlacementActor = actor; - mVectorAnimationTask->SetRenderer( mImpl->mRenderer ); + mVectorRasterizeThread.SetRenderer( mImpl->mRenderer ); // Add property notification for scaling & size mScaleNotification = actor.AddPropertyNotification( Actor::Property::WORLD_SCALE, StepCondition( 0.1f, 1.0f ) ); @@ -310,7 +309,7 @@ void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor ) void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor ) { - mVectorAnimationTask->PauseAnimation(); + mVectorRasterizeThread.PauseAnimation(); mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE; @@ -353,14 +352,14 @@ void AnimatedVectorImageVisual::OnSetTransform() if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY ) { - mVectorAnimationTask->PlayAnimation(); + mVectorRasterizeThread.PlayAnimation(); mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY ); } else { // Render one frame - mVectorAnimationTask->RenderFrame(); + mVectorRasterizeThread.RenderFrame(); } } } @@ -374,7 +373,7 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons { if( IsOnStage() && mVisualSize != Vector2::ZERO ) { - mVectorAnimationTask->PlayAnimation(); + mVectorRasterizeThread.PlayAnimation(); mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY ); } @@ -383,7 +382,7 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons } case DevelAnimatedVectorImageVisual::Action::PAUSE: { - mVectorAnimationTask->PauseAnimation(); + mVectorRasterizeThread.PauseAnimation(); if( mImpl->mRenderer ) { @@ -395,9 +394,9 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons } case DevelAnimatedVectorImageVisual::Action::STOP: { - if( mVectorAnimationTask->GetPlayState() != DevelImageVisual::PlayState::STOPPED ) + if( mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::STOPPED ) { - mVectorAnimationTask->StopAnimation(); + mVectorRasterizeThread.StopAnimation(); } if( mImpl->mRenderer ) @@ -413,11 +412,11 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons int32_t frameNumber; if( attributes.Get( frameNumber ) ) { - mVectorAnimationTask->SetCurrentFrameNumber( frameNumber ); + mVectorRasterizeThread.SetCurrentFrameNumber( frameNumber ); - if( IsOnStage() && mVectorAnimationTask->GetPlayState() != DevelImageVisual::PlayState::PLAYING ) + if( IsOnStage() && mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::PLAYING ) { - mVectorAnimationTask->RenderFrame(); + mVectorRasterizeThread.RenderFrame(); Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger rendering } } @@ -477,41 +476,41 @@ void AnimatedVectorImageVisual::SendAnimationData() if( mResendFlag ) { bool isPlaying = false; - if( mVectorAnimationTask->GetPlayState() == DevelImageVisual::PlayState::PLAYING ) + if( mVectorRasterizeThread.GetPlayState() == DevelImageVisual::PlayState::PLAYING ) { - mVectorAnimationTask->PauseAnimation(); + mVectorRasterizeThread.PauseAnimation(); isPlaying = true; } if( mResendFlag & RESEND_LOOP_COUNT ) { - mVectorAnimationTask->SetLoopCount( mLoopCount ); + mVectorRasterizeThread.SetLoopCount( mLoopCount ); } if( mResendFlag & RESEND_PLAY_RANGE ) { - mVectorAnimationTask->SetPlayRange( mStartFrame, mEndFrame ); + mVectorRasterizeThread.SetPlayRange( mStartFrame, mEndFrame ); } if( mResendFlag & RESEND_STOP_BEHAVIOR ) { - mVectorAnimationTask->SetStopBehavior( mStopBehavior ); + mVectorRasterizeThread.SetStopBehavior( mStopBehavior ); } if( mResendFlag & RESEND_LOOPING_MODE ) { - mVectorAnimationTask->SetLoopingMode( mLoopingMode ); + mVectorRasterizeThread.SetLoopingMode( mLoopingMode ); } if( IsOnStage() ) { if( isPlaying ) { - mVectorAnimationTask->PlayAnimation(); + mVectorRasterizeThread.PlayAnimation(); } else { - mVectorAnimationTask->RenderFrame(); + mVectorRasterizeThread.RenderFrame(); Stage::GetCurrent().KeepRendering( 0.0f ); } } @@ -525,11 +524,11 @@ void AnimatedVectorImageVisual::SetVectorImageSize() uint32_t width = static_cast< uint32_t >( mVisualSize.width * mVisualScale.width ); uint32_t height = static_cast< uint32_t >( mVisualSize.height * mVisualScale.height ); - mVectorAnimationTask->SetSize( width, height ); + mVectorRasterizeThread.SetSize( width, height ); - if( IsOnStage() && mVectorAnimationTask->GetPlayState() != DevelImageVisual::PlayState::PLAYING ) + if( IsOnStage() && mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::PLAYING ) { - mVectorAnimationTask->RenderFrame(); + mVectorRasterizeThread.RenderFrame(); Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger rendering } } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h index 674cb1b..b6837b5 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include namespace Dali { @@ -39,6 +39,7 @@ namespace Internal { class ImageVisualShaderFactory; +class VectorRasterizeThread; class AnimatedVectorImageVisual; using AnimatedVectorImageVisualPtr = IntrusivePtr< AnimatedVectorImageVisual >; @@ -182,17 +183,17 @@ private: AnimatedVectorImageVisual& operator=( const AnimatedVectorImageVisual& visual ) = delete; private: - VisualUrl mUrl; - VectorAnimationTaskPtr mVectorAnimationTask; ImageVisualShaderFactory& mImageVisualShaderFactory; + VisualUrl mUrl; + VectorRasterizeThread mVectorRasterizeThread; PropertyNotification mScaleNotification; PropertyNotification mSizeNotification; Vector2 mVisualSize; Vector2 mVisualScale; WeakHandle< Actor > mPlacementActor; int32_t mLoopCount; - uint32_t mStartFrame; - uint32_t mEndFrame; + int32_t mStartFrame; + int32_t mEndFrame; uint32_t mResendFlag; DevelAnimatedVectorImageVisual::Action::Type mActionStatus; DevelImageVisual::StopBehavior::Type mStopBehavior; 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 deleted file mode 100644 index 0445df7..0000000 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ /dev/null @@ -1,516 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -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 - -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(), - mVectorAnimationThread( factoryCache.GetVectorAnimationThread() ), - mConditionalWait(), - mAnimationFinishedTrigger(), - mPlayState( PlayState::STOPPED ), - mStopBehavior( DevelImageVisual::StopBehavior::CURRENT_FRAME ), - mLoopingMode( DevelImageVisual::LoopingMode::RESTART ), - mNextFrameStartTime(), - mFrameDurationNanoSeconds( 0 ), - mFrameRate( 60.0f ), - mCurrentFrame( 0 ), - mTotalFrame( 0 ), - mStartFrame( 0 ), - mEndFrame( 0 ), - mWidth( 0 ), - mHeight( 0 ), - mLoopCount( LOOP_FOREVER ), - mCurrentLoop( 0 ), - mResourceReady( false ), - mCurrentFrameUpdated( false ), - mCurrentLoopUpdated( false ), - mForward( true ), - mUpdateFrameNumber( false ), - mNeedAnimationFinishedTrigger( true ) -{ - Initialize(); -} - -VectorAnimationTask::~VectorAnimationTask() -{ - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::~VectorAnimationTask: destructor [%p]\n", this ); -} - -void VectorAnimationTask::SetRenderer( Renderer renderer ) -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - - mVectorRenderer.SetRenderer( renderer ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", 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 ) - { - 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 ) - { - mNeedAnimationFinishedTrigger = false; - mPlayState = PlayState::STOPPING; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::StopAnimation: Stop [%p]\n", this ); - } -} - -void VectorAnimationTask::PauseAnimation() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState == PlayState::PLAYING ) - { - mPlayState = PlayState::PAUSED; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::PauseAnimation: Pause [%p]\n", this ); - } -} - -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 ); - mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback ); -} - -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 ) -{ - // Make sure the range specified is between 0 and the total frame number - if( ( startFrame < mTotalFrame ) && ( endFrame < mTotalFrame ) ) - { - // If the range is not in order swap values - if( startFrame > endFrame ) - { - uint32_t temp = startFrame; - startFrame = endFrame; - endFrame = temp; - } - - if( startFrame != mStartFrame || endFrame != mEndFrame ) - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - - mStartFrame = startFrame; - mEndFrame = endFrame; - - // 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; - } - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%p]\n", mStartFrame, mEndFrame, this ); - } - } -} - -void VectorAnimationTask::GetPlayRange( uint32_t& startFrame, uint32_t& endFrame ) -{ - startFrame = mStartFrame; - 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 ); - return; - } - - if( frameNumber >= mStartFrame && frameNumber <= mEndFrame ) - { - mCurrentFrame = frameNumber; - mCurrentFrameUpdated = true; - - mResourceReady = false; - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetCurrentFrameNumber: frame number = %d [%p]\n", mCurrentFrame, this ); - } - else - { - DALI_LOG_ERROR( "Invalid frame number [%d (%d, %d)]\n", frameNumber, mStartFrame, mEndFrame ); - } -} - -uint32_t VectorAnimationTask::GetCurrentFrameNumber() const -{ - return mCurrentFrame; -} - -uint32_t VectorAnimationTask::GetTotalFrameNumber() const -{ - return mTotalFrame; -} - -void VectorAnimationTask::GetDefaultSize( uint32_t& width, uint32_t& height ) const -{ - mVectorRenderer.GetDefaultSize( width, height ); -} - -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 ); -} - -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 ); -} - -VectorAnimationTask::UploadCompletedSignalType& VectorAnimationTask::UploadCompletedSignal() -{ - return mVectorRenderer.UploadCompletedSignal(); -} - -void VectorAnimationTask::Initialize() -{ - mVectorRenderer = VectorAnimationRenderer::New( mUrl ); - - mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); - - mEndFrame = mTotalFrame - 1; - - mFrameRate = mVectorRenderer.GetFrameRate(); - mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; - - uint32_t width, height; - mVectorRenderer.GetDefaultSize( width, height ); - - SetSize( width, height ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Initialize: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this ); -} - -bool VectorAnimationTask::Rasterize() -{ - bool stopped = false, needAnimationFinishedTrigger; - uint32_t currentFrame, startFrame, endFrame; - int32_t loopCount, currentLoopCount; - PlayState playState; - - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) - { - mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; - } - - 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 ) - { - currentFrame = GetStoppedFrame( startFrame, endFrame, currentFrame ); - ResetValue( mCurrentFrameUpdated, mCurrentFrame, currentFrame, mConditionalWait ); - - stopped = true; - } - else if( playState == PlayState::PLAYING ) - { - bool animationFinished = false; - - if( currentFrame >= endFrame ) // last frame - { - if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) - { - mForward = false; - } - else - { - if( loopCount < 0 || ++currentLoopCount < loopCount ) // 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. - mUpdateFrameNumber = false; - } - else - { - animationFinished = true; // end of animation - } - ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); - } - } - else if( currentFrame == startFrame && !mForward ) // first frame - { - if( loopCount < 0 || ++currentLoopCount < loopCount ) // repeat forever or before the last loop - { - mForward = true; - } - else - { - animationFinished = true; // end of animation - } - ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); - } - - if( animationFinished ) - { - if( mStopBehavior == DevelImageVisual::StopBehavior::CURRENT_FRAME ) - { - stopped = true; - } - else - { - mPlayState = PlayState::STOPPING; - } - } - } - - // Rasterize - bool renderSuccess = mVectorRenderer.Render( currentFrame ); - if( !renderSuccess ) - { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Rendering failed. Try again later.[%d] [%p]\n", currentFrame, this ); - mUpdateFrameNumber = false; - } - - if( stopped && renderSuccess ) - { - mPlayState = PlayState::STOPPED; - mForward = true; - mCurrentLoop = 0; - - // Animation is finished - if( needAnimationFinishedTrigger && 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 ) - { - keepAnimation = false; - } - - return keepAnimation; -} - -uint32_t VectorAnimationTask::GetStoppedFrame( uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame ) -{ - uint32_t frame = currentFrame; - - switch( mStopBehavior ) - { - case DevelImageVisual::StopBehavior::FIRST_FRAME: - { - frame = startFrame; - break; - } - case DevelImageVisual::StopBehavior::LAST_FRAME: - { - if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) - { - frame = startFrame; - } - else - { - frame = endFrame; - } - break; - } - case DevelImageVisual::StopBehavior::CURRENT_FRAME: - { - frame = currentFrame; - break; - } - } - - return frame; -} - -std::chrono::time_point< std::chrono::system_clock > VectorAnimationTask::CalculateNextFrameTime( bool renderNow ) -{ - mNextFrameStartTime = mNextFrameStartTime + std::chrono::nanoseconds( mFrameDurationNanoSeconds ); - auto current = std::chrono::system_clock::now(); - if( renderNow || mNextFrameStartTime < current ) - { - mNextFrameStartTime = current; - } - return mNextFrameStartTime; -} - -std::chrono::time_point< std::chrono::system_clock > VectorAnimationTask::GetNextFrameTime() -{ - return mNextFrameStartTime; -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h deleted file mode 100644 index c13b4d3..0000000 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ /dev/null @@ -1,258 +0,0 @@ -#ifndef DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H -#define DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H - -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class VisualFactoryCache; -class VectorAnimationThread; -class VectorAnimationTask; -typedef IntrusivePtr< VectorAnimationTask > VectorAnimationTaskPtr; - -/** - * The task of the vector animation. - */ -class VectorAnimationTask : public RefObject -{ -public: - - using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType; - - /** - * @brief Constructor. - * - * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object - * @param[in] url The url of the vector animation file - */ - VectorAnimationTask( VisualFactoryCache& factoryCache, const std::string& url ); - - /** - * @brief Destructor. - */ - virtual ~VectorAnimationTask(); - - /** - * @brief Sets the renderer used to display the result image. - * - * @param[in] renderer The renderer used to display the result image - */ - void SetRenderer( Renderer renderer ); - - /** - * @brief Sets the target image size. - * - * @param[in] width The target image width - * @param[in] height The target image height - */ - void SetSize( uint32_t width, uint32_t height ); - - /** - * @brief Play the vector animation. - */ - void PlayAnimation(); - - /** - * @brief Stop the vector animation. - */ - void StopAnimation(); - - /** - * @brief Pause the vector animation. - */ - void PauseAnimation(); - - /** - * @brief Render one frame. The current frame number will be increased. - */ - void RenderFrame(); - - /** - * @brief This callback is called after the animation is finished. - * @param[in] callback The animation finished callback - */ - void SetAnimationFinishedCallback( EventThreadCallback* callback ); - - /** - * @brief Enable looping for 'count' repeats. -1 means to repeat forever. - * @param[in] count The number of times to loop - */ - void SetLoopCount( int32_t count ); - - /** - * @brief Set the playing range in frame number. - * @param[in] startFrame The frame number to specify minimum progress. - * @param[in] endFrame The frame number to specify maximum progress. - * The animation will play between those values. - */ - void SetPlayRange( uint32_t startFrame, uint32_t endFrame ); - - /** - * @brief Gets the playing range in frame number. - * @param[out] startFrame The frame number to specify minimum progress. - * @param[out] endFrame The frame number to specify maximum progress. - */ - void GetPlayRange( uint32_t& startFrame, uint32_t& endFrame ); - - /** - * @brief Get the play state - * @return The play state - */ - DevelImageVisual::PlayState::Type GetPlayState() const; - - /** - * @brief Sets the current frame number of the animation. - * @param[in] frameNumber The new frame number between [0, the maximum frame number] or between the play range if specified. - */ - void SetCurrentFrameNumber( uint32_t frameNumber ); - - /** - * @brief Retrieves the current frame number of the animation. - * @return The current frame number - */ - uint32_t GetCurrentFrameNumber() const; - - /** - * @brief Retrieves the total frame number of the animation. - * @return The total frame number - */ - uint32_t GetTotalFrameNumber() const; - - /** - * @brief Gets the default size of the file,. - * @return The default size of the file - */ - void GetDefaultSize( uint32_t& width, uint32_t& height ) const; - - /** - * @brief Sets the stop behavior of the animation. This is performed when the animation is stopped. - * @param[in] stopBehavior The stop behavior - */ - void SetStopBehavior( DevelImageVisual::StopBehavior::Type stopBehavior ); - - /** - * @brief Sets the looping mode. - * Animation plays forwards and then restarts from the beginning or runs backwards again. - * @param[in] loopingMode The looping mode - */ - void SetLoopingMode( DevelImageVisual::LoopingMode::Type loopingMode ); - - /** - * @brief Connect to this signal to be notified when the texture upload is completed. - * @return The signal to connect to. - */ - UploadCompletedSignalType& UploadCompletedSignal(); - - /** - * @brief Rasterizes the current frame. - * @return true if the animation is running, false otherwise. - */ - bool Rasterize(); - - /** - * @brief Calculates the time for the next frame rasterization. - * @return The time for the next frame rasterization. - */ - std::chrono::time_point< std::chrono::system_clock > CalculateNextFrameTime( bool renderNow ); - - /** - * @brief Gets the time for the next frame rasterization. - * @return The time for the next frame rasterization. - */ - std::chrono::time_point< std::chrono::system_clock > GetNextFrameTime(); - -private: - - /** - * @brief Initializes the vector renderer. - */ - void Initialize(); - - /** - * @brief Gets the frame number when the animation is stopped according to the stop behavior. - */ - uint32_t GetStoppedFrame( uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame ); - - // Undefined - VectorAnimationTask( const VectorAnimationTask& task ) = delete; - - // Undefined - VectorAnimationTask& operator=( const VectorAnimationTask& task ) = delete; - -private: - - enum class PlayState - { - STOPPING, ///< The animation is stopping - STOPPED, ///< The animation has stopped - PLAYING, ///< The animation is playing - PAUSED ///< The animation is paused - }; - - std::string mUrl; - VectorAnimationRenderer mVectorRenderer; - VectorAnimationThread& mVectorAnimationThread; - ConditionalWait mConditionalWait; - std::unique_ptr< EventThreadCallback > mAnimationFinishedTrigger; - Vector2 mPlayRange; - PlayState mPlayState; - DevelImageVisual::StopBehavior::Type mStopBehavior; - DevelImageVisual::LoopingMode::Type mLoopingMode; - std::chrono::time_point< std::chrono::system_clock > mNextFrameStartTime; - int64_t mFrameDurationNanoSeconds; - float mFrameRate; - uint32_t mCurrentFrame; - uint32_t mTotalFrame; - uint32_t mStartFrame; - uint32_t mEndFrame; - uint32_t mWidth; - uint32_t mHeight; - int32_t mLoopCount; - int32_t mCurrentLoop; - bool mResourceReady; - bool mCurrentFrameUpdated; - bool mCurrentLoopUpdated; - bool mForward; - bool mUpdateFrameNumber; - bool mNeedAnimationFinishedTrigger; - -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp deleted file mode 100644 index a4a2a16..0000000 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace -{ - -constexpr auto DEFAULT_NUMBER_OF_RASTERIZE_THREADS = size_t{ 4u }; -constexpr auto NUMBER_OF_RASTERIZE_THREADS_ENV = "DALI_VECTOR_RASTERIZE_THREADS"; - -size_t GetNumberOfThreads( const char* environmentVariable, size_t defaultValue ) -{ - using Dali::EnvironmentVariable::GetEnvironmentVariable; - auto numberString = GetEnvironmentVariable( environmentVariable ); - auto numberOfThreads = numberString ? std::strtoul( numberString, nullptr, 10 ) : 0; - constexpr auto MAX_NUMBER_OF_THREADS = 100u; - DALI_ASSERT_DEBUG( numberOfThreads < MAX_NUMBER_OF_THREADS ); - return ( numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS ) ? numberOfThreads : defaultValue; -} - -#if defined(DEBUG_ENABLED) -Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" ); -#endif - -} // unnamed namespace - -VectorAnimationThread::VectorAnimationThread() -: mAnimationTasks(), - mCompletedTasks(), - mRasterizers( GetNumberOfThreads( NUMBER_OF_RASTERIZE_THREADS_ENV, DEFAULT_NUMBER_OF_RASTERIZE_THREADS ), [&]() { return RasterizeHelper( *this ); } ), - mSleepThread( MakeCallback( this, &VectorAnimationThread::OnAwakeFromSleep ) ), - mConditionalWait(), - mNeedToSleep( false ), - mDestroyThread( false ), - mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) -{ - mSleepThread.Start(); -} - -VectorAnimationThread::~VectorAnimationThread() -{ - // Stop the thread - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mDestroyThread = true; - mConditionalWait.Notify( lock ); - } - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::~VectorAnimationThread: Join [%p]\n", this ); - - Join(); -} - -void VectorAnimationThread::AddTask( VectorAnimationTaskPtr task ) -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( mAnimationTasks.end() == std::find( mAnimationTasks.begin(), mAnimationTasks.end(), task ) ) - { - auto currentTime = task->CalculateNextFrameTime( true ); // Rasterize as soon as possible - - bool inserted = false; - for( auto iter = mAnimationTasks.begin(); iter != mAnimationTasks.end(); ++iter ) - { - auto nextTime = (*iter)->GetNextFrameTime(); - if( nextTime > currentTime ) - { - mAnimationTasks.insert( iter, task ); - inserted = true; - break; - } - } - - if( !inserted ) - { - mAnimationTasks.push_back( task ); - } - - // wake up the animation thread - mConditionalWait.Notify( lock ); - } -} - -void VectorAnimationThread::OnTaskCompleted( VectorAnimationTaskPtr task, bool keepAnimation ) -{ - if( keepAnimation && !mDestroyThread ) - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( mAnimationTasks.end() == std::find( mAnimationTasks.begin(), mAnimationTasks.end(), task ) ) - { - mCompletedTasks.push_back( task ); - - // wake up the animation thread - mConditionalWait.Notify( lock ); - } - } -} - -void VectorAnimationThread::OnAwakeFromSleep() -{ - if( !mDestroyThread ) - { - mNeedToSleep = false; - // wake up the animation thread - mConditionalWait.Notify(); - } -} - -void VectorAnimationThread::Run() -{ - SetThreadName( "VectorAnimationThread" ); - mLogFactory.InstallLogFunction(); - - while( !mDestroyThread ) - { - Rasterize(); - } -} - -void VectorAnimationThread::Rasterize() -{ - // Lock while popping task out from the queue - ConditionalWait::ScopedLock lock( mConditionalWait ); - - // conditional wait - if( (mAnimationTasks.empty() && mCompletedTasks.empty() ) || mNeedToSleep ) - { - mConditionalWait.Wait( lock ); - } - - mNeedToSleep = false; - - // Process completed tasks - for( auto&& task : mCompletedTasks ) - { - if( mAnimationTasks.end() == std::find( mAnimationTasks.begin(), mAnimationTasks.end(), task ) ) - { - // Should use the frame rate of the animation file - auto nextFrameTime = task->CalculateNextFrameTime( false ); - - bool inserted = false; - for( auto iter = mAnimationTasks.begin(); iter != mAnimationTasks.end(); ++iter ) - { - auto time = (*iter)->GetNextFrameTime(); - if( time > nextFrameTime ) - { - mAnimationTasks.insert( iter, task ); - inserted = true; - break; - } - } - - if( !inserted ) - { - mAnimationTasks.push_back( task ); - } - } - } - mCompletedTasks.clear(); - - // pop out the next task from the queue - if( !mAnimationTasks.empty() && !mNeedToSleep ) - { - std::vector< VectorAnimationTaskPtr >::iterator next = mAnimationTasks.begin(); - VectorAnimationTaskPtr nextTask = *next; - - auto currentTime = std::chrono::system_clock::now(); - auto nextFrameTime = nextTask->GetNextFrameTime(); - -#if defined(DEBUG_ENABLED) - auto duration = std::chrono::duration_cast< std::chrono::milliseconds >( nextFrameTime - currentTime ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::Rasterize: [next time = %lld]\n", duration.count() ); -#endif - - if( nextFrameTime <= currentTime ) - { - mAnimationTasks.erase( next ); - - auto rasterizerHelperIt = mRasterizers.GetNext(); - DALI_ASSERT_ALWAYS( rasterizerHelperIt != mRasterizers.End() ); - - rasterizerHelperIt->Rasterize( nextTask ); - } - else - { - mNeedToSleep = true; - mSleepThread.SleepUntil( nextFrameTime ); - } - } -} - -VectorAnimationThread::RasterizeHelper::RasterizeHelper( VectorAnimationThread& animationThread ) -: RasterizeHelper( std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread() ), animationThread ) -{ -} - -VectorAnimationThread::RasterizeHelper::RasterizeHelper( RasterizeHelper&& rhs ) -: RasterizeHelper( std::move( rhs.mRasterizer ), rhs.mAnimationThread ) -{ -} - -VectorAnimationThread::RasterizeHelper::RasterizeHelper( std::unique_ptr< VectorRasterizeThread > rasterizer, VectorAnimationThread& animationThread ) -: mRasterizer( std::move( rasterizer ) ), - mAnimationThread( animationThread ) -{ - mRasterizer->SetCompletedCallback( MakeCallback( &mAnimationThread, &VectorAnimationThread::OnTaskCompleted ) ); -} - -void VectorAnimationThread::RasterizeHelper::Rasterize( VectorAnimationTaskPtr task ) -{ - if( task ) - { - mRasterizer->AddTask( task ); - } -} - -VectorAnimationThread::SleepThread::SleepThread( CallbackBase* callback ) -: mConditionalWait(), - mAwakeCallback( std::unique_ptr< CallbackBase >( callback ) ), - mSleepTimePoint(), - mLogFactory( Dali::Adaptor::Get().GetLogFactory() ), - mNeedToSleep( false ), - mDestroyThread( false ) -{ -} - -VectorAnimationThread::SleepThread::~SleepThread() -{ - // Stop the thread - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mDestroyThread = true; - mConditionalWait.Notify( lock ); - } - - Join(); -} - -void VectorAnimationThread::SleepThread::SleepUntil( std::chrono::time_point< std::chrono::system_clock > timeToSleepUntil ) -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - mSleepTimePoint = timeToSleepUntil; - mNeedToSleep = true; - mConditionalWait.Notify( lock ); -} - -void VectorAnimationThread::SleepThread::Run() -{ - SetThreadName( "VectorSleepThread" ); - mLogFactory.InstallLogFunction(); - - while( !mDestroyThread ) - { - bool needToSleep; - std::chrono::time_point< std::chrono::system_clock > sleepTimePoint; - - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - - needToSleep = mNeedToSleep; - sleepTimePoint = mSleepTimePoint; - - mNeedToSleep = false; - } - - if( needToSleep ) - { -#if defined(DEBUG_ENABLED) - auto sleepDuration = std::chrono::duration_cast< std::chrono::milliseconds >( mSleepTimePoint - std::chrono::system_clock::now() ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::SleepThread::Run: [sleep duration = %lld]\n", sleepDuration.count() ); -#endif - - std::this_thread::sleep_until( sleepTimePoint ); - - if( mAwakeCallback ) - { - CallbackBase::Execute( *mAwakeCallback ); - } - } - - { - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( !mDestroyThread && !mNeedToSleep ) - { - mConditionalWait.Wait( lock ); - } - } - } -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h deleted file mode 100755 index 63e3525..0000000 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef DALI_TOOLKIT_VECTOR_ANIMATION_THREAD_H -#define DALI_TOOLKIT_VECTOR_ANIMATION_THREAD_H - -/* - * 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * The main animation thread for vector animations - */ -class VectorAnimationThread : public Thread -{ -public: - - /** - * @brief Constructor. - */ - VectorAnimationThread(); - - /** - * @brief Destructor. - */ - virtual ~VectorAnimationThread(); - - /** - * Add a animation task into the vector animation thread, called by main thread. - * - * @param[in] task The task added to the thread. - */ - void AddTask( VectorAnimationTaskPtr task ); - - /** - * @brief Called when the rasterization is completed from the rasterize thread. - * @param task The completed task - */ - void OnTaskCompleted( VectorAnimationTaskPtr task, bool stopped ); - - /** - * @brief Called when the sleep thread is awaken. - */ - void OnAwakeFromSleep(); - -protected: - - /** - * @brief The entry function of the animation thread. - */ - void Run() override; - -private: - - /** - * Rasterizes the tasks. - */ - void Rasterize(); - -private: - - /** - * @brief Helper class to keep the relation between VectorRasterizeThread and corresponding container - */ - class RasterizeHelper : public ConnectionTracker - { - public: - /** - * @brief Create an RasterizeHelper. - * - * @param[in] animationThread Reference to the VectorAnimationThread - */ - RasterizeHelper( VectorAnimationThread& animationThread ); - - /** - * @brief Rasterizes the task. - * - * @param[in] task The task to rasterize. - */ - void Rasterize( VectorAnimationTaskPtr task ); - - public: - RasterizeHelper( const RasterizeHelper& ) = delete; - RasterizeHelper& operator=( const RasterizeHelper& ) = delete; - - RasterizeHelper( RasterizeHelper&& rhs ); - RasterizeHelper& operator=( RasterizeHelper&& rhs ) = delete; - - private: - - /** - * @brief Main constructor that used by all other constructors - */ - RasterizeHelper( std::unique_ptr< VectorRasterizeThread > rasterizer, VectorAnimationThread& animationThread ); - - private: - std::unique_ptr< VectorRasterizeThread > mRasterizer; - VectorAnimationThread& mAnimationThread; - }; - - /** - * @brief The thread to sleep until the next frame time. - */ - class SleepThread : public Thread - { - public: - - /** - * @brief Constructor. - */ - SleepThread( CallbackBase* callback ); - - /** - * @brief Destructor. - */ - virtual ~SleepThread(); - - /** - * @brief Sleeps untile the specified time point. - */ - void SleepUntil( std::chrono::time_point< std::chrono::system_clock > timeToSleepUntil ); - - protected: - - /** - * @brief The entry function of the animation thread. - */ - void Run() override; - - private: - - SleepThread( const SleepThread& thread ) = delete; - SleepThread& operator=( const SleepThread& thread ) = delete; - - private: - ConditionalWait mConditionalWait; - std::unique_ptr< CallbackBase > mAwakeCallback; - std::chrono::time_point< std::chrono::system_clock > mSleepTimePoint; - const Dali::LogFactoryInterface& mLogFactory; - bool mNeedToSleep; - bool mDestroyThread; - }; - -private: - - // Undefined - VectorAnimationThread( const VectorAnimationThread& thread ) = delete; - - // Undefined - VectorAnimationThread& operator=( const VectorAnimationThread& thread ) = delete; - -private: - - std::vector< VectorAnimationTaskPtr > mAnimationTasks; - std::vector< VectorAnimationTaskPtr > mCompletedTasks; - RoundRobinContainerView< RasterizeHelper > mRasterizers; - SleepThread mSleepThread; - ConditionalWait mConditionalWait; - bool mNeedToSleep; - bool mDestroyThread; - const Dali::LogFactoryInterface& mLogFactory; - -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // #endif // DALI_TOOLKIT_VECTOR_ANIMATION_THREAD_H 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 a640b19..2c39333 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 @@ -37,20 +37,55 @@ 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 +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 -VectorRasterizeThread::VectorRasterizeThread() -: mRasterizeTasks(), +VectorRasterizeThread::VectorRasterizeThread( const std::string& url ) +: mUrl( url ), + mVectorRenderer(), mConditionalWait(), - mCompletedCallback(), + mAnimationFinishedTrigger(), + mPlayState( PlayState::STOPPED ), + mStopBehavior( DevelImageVisual::StopBehavior::CURRENT_FRAME ), + mLoopingMode( DevelImageVisual::LoopingMode::RESTART ), + mFrameDurationNanoSeconds( 0 ), + mFrameRate( 60.0f ), + mCurrentFrame( 0 ), + mTotalFrame( 0 ), + mStartFrame( 0 ), + mEndFrame( 0 ), + mWidth( 0 ), + mHeight( 0 ), + mLoopCount( LOOP_FOREVER ), + mCurrentLoop( 0 ), + mNeedRender( false ), mDestroyThread( false ), - mIsThreadStarted( false ), + mResourceReady( false ), + mCurrentFrameUpdated( false ), + mCurrentLoopUpdated( false ), + mForward( true ), + mUpdateFrameNumber( false ), + mNeedAnimationFinishedTrigger( true ), mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) { + Initialize(); } VectorRasterizeThread::~VectorRasterizeThread() @@ -67,75 +102,428 @@ VectorRasterizeThread::~VectorRasterizeThread() Join(); } -void VectorRasterizeThread::SetCompletedCallback( CallbackBase* callback ) +void VectorRasterizeThread::Run() +{ + SetThreadName( "VectorImageThread" ); + mLogFactory.InstallLogFunction(); + + while( !mDestroyThread ) + { + Rasterize(); + } + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Run: End of thread [%p]\n", this ); +} + +void VectorRasterizeThread::SetRenderer( Renderer renderer ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - mCompletedCallback = std::unique_ptr< CallbackBase >( callback ); + mVectorRenderer.SetRenderer( renderer ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer [%p]\n", this ); } -void VectorRasterizeThread::AddTask( VectorAnimationTaskPtr task ) +void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height ) { - if( !mIsThreadStarted ) + if( mWidth != width || mHeight != height ) { - Start(); - mIsThreadStarted = true; + 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 [%p]\n", width, height, this ); } +} - // Lock while adding task to the queue +void VectorRasterizeThread::PlayAnimation() +{ ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mRasterizeTasks.end() == std::find( mRasterizeTasks.begin(), mRasterizeTasks.end(), task ) ) + if( mPlayState != PlayState::PLAYING ) { - mRasterizeTasks.push_back( task ); + mNeedRender = true; + mUpdateFrameNumber = false; + mPlayState = PlayState::PLAYING; + mConditionalWait.Notify( lock ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Play [%p]\n", this ); + } +} - // wake up the animation thread +void VectorRasterizeThread::StopAnimation() +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + if( mPlayState != PlayState::STOPPED && mPlayState != PlayState::STOPPING ) + { + mNeedRender = true; + mNeedAnimationFinishedTrigger = false; + mPlayState = PlayState::STOPPING; mConditionalWait.Notify( lock ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop [%p]\n", this ); } } -void VectorRasterizeThread::Run() +void VectorRasterizeThread::PauseAnimation() { - SetThreadName( "VectorRasterizeThread" ); - mLogFactory.InstallLogFunction(); + ConditionalWait::ScopedLock lock( mConditionalWait ); + if( mPlayState == PlayState::PLAYING ) + { + mPlayState = PlayState::PAUSED; - while( !mDestroyThread ) + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause [%p]\n", this ); + } +} + +void VectorRasterizeThread::RenderFrame() +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + + if( !mResourceReady ) { - Rasterize(); + mNeedRender = true; + mConditionalWait.Notify( lock ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render [%p]\n", this ); + } +} + +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; + mCurrentLoop = 0; + mCurrentLoopUpdated = true; + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetLoopCount: [%d] [%p]\n", count, this ); + } +} + +void VectorRasterizeThread::SetPlayRange( uint32_t startFrame, uint32_t endFrame ) +{ + // Make sure the range specified is between 0 and the total frame number + if( ( startFrame < mTotalFrame ) && ( endFrame < mTotalFrame ) ) + { + // If the range is not in order swap values + if( startFrame > endFrame ) + { + uint32_t temp = startFrame; + startFrame = endFrame; + endFrame = temp; + } + + if( startFrame != mStartFrame || endFrame != mEndFrame ) + { + ConditionalWait::ScopedLock lock( mConditionalWait ); + + mStartFrame = startFrame; + mEndFrame = endFrame; + + // 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; + } + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetPlayRange: [%d, %d] [%p]\n", mStartFrame, mEndFrame, this ); + } + } +} + +DevelImageVisual::PlayState::Type VectorRasterizeThread::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; +} + +bool VectorRasterizeThread::IsResourceReady() const +{ + return mResourceReady; +} + +void VectorRasterizeThread::SetCurrentFrameNumber( uint32_t frameNumber ) +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + + if( mCurrentFrame == frameNumber ) + { + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentFrameNumber: Set same frame [%d] [%p]\n", frameNumber, this ); + return; + } + + if( frameNumber >= mStartFrame && frameNumber <= mEndFrame ) + { + mCurrentFrame = frameNumber; + mCurrentFrameUpdated = true; + + mResourceReady = false; + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentFrameNumber: frame number = %d [%p]\n", mCurrentFrame, this ); + } + else + { + DALI_LOG_ERROR( "Invalid frame number [%d (%d, %d)]\n", frameNumber, mStartFrame, mEndFrame ); + } +} + +uint32_t VectorRasterizeThread::GetCurrentFrameNumber() const +{ + return mCurrentFrame; +} + +uint32_t VectorRasterizeThread::GetTotalFrameNumber() const +{ + return mTotalFrame; +} + +void VectorRasterizeThread::GetDefaultSize( uint32_t& width, uint32_t& height ) const +{ + mVectorRenderer.GetDefaultSize( width, height ); +} + +void VectorRasterizeThread::SetStopBehavior( DevelImageVisual::StopBehavior::Type stopBehavior ) +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + mStopBehavior = stopBehavior; + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetStopBehavior: stop behavor = %d [%p]\n", mStopBehavior, this ); +} + +void VectorRasterizeThread::SetLoopingMode( DevelImageVisual::LoopingMode::Type loopingMode ) +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + mLoopingMode = loopingMode; + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetLoopingMode: looping mode = %d [%p]\n", mLoopingMode, this ); +} + +VectorRasterizeThread::UploadCompletedSignalType& VectorRasterizeThread::UploadCompletedSignal() +{ + return mVectorRenderer.UploadCompletedSignal(); +} + +void VectorRasterizeThread::Initialize() +{ + mVectorRenderer = VectorAnimationRenderer::New( mUrl ); + + mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); + + mEndFrame = mTotalFrame - 1; + + mFrameRate = mVectorRenderer.GetFrameRate(); + mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; + + uint32_t width, height; + mVectorRenderer.GetDefaultSize( width, height ); + + SetSize( width, height ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Initialize: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this ); } void VectorRasterizeThread::Rasterize() { - VectorAnimationTaskPtr nextTask; + bool stopped = false, needAnimationFinishedTrigger; + uint32_t currentFrame, startFrame, endFrame; + int32_t loopCount, currentLoopCount; + { - // Lock while popping task out from the queue ConditionalWait::ScopedLock lock( mConditionalWait ); - // conditional wait - if( mRasterizeTasks.empty() ) + if( ( mPlayState == PlayState::PAUSED || mPlayState == PlayState::STOPPED ) && !mNeedRender && !mDestroyThread ) { + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Wait [%p]\n", this ); mConditionalWait.Wait( lock ); } - // pop out the next task from the queue - if( !mRasterizeTasks.empty() ) + if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) { - std::vector< VectorAnimationTaskPtr >::iterator next = mRasterizeTasks.begin(); - nextTask = *next; - mRasterizeTasks.erase( next ); + mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; } + + currentFrame = mCurrentFrame; + startFrame = mStartFrame; + endFrame = mEndFrame; + loopCount = mLoopCount; + currentLoopCount = mCurrentLoop; + needAnimationFinishedTrigger = mNeedAnimationFinishedTrigger; + + mResourceReady = true; + mNeedRender = false; + mCurrentFrameUpdated = false; + mCurrentLoopUpdated = false; + mUpdateFrameNumber = true; + mNeedAnimationFinishedTrigger = true; } - if( nextTask ) + auto currentFrameStartTime = std::chrono::system_clock::now(); + + if( mPlayState == PlayState::STOPPING ) { - bool keepAnimation = nextTask->Rasterize(); + currentFrame = GetStoppedFrame( startFrame, endFrame, currentFrame ); + ResetValue( mCurrentFrameUpdated, mCurrentFrame, currentFrame, mConditionalWait ); + + stopped = true; + } + else if( mPlayState == PlayState::PLAYING ) + { + bool animationFinished = false; + + if( currentFrame >= endFrame ) // last frame + { + if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) + { + mForward = false; + } + else + { + if( loopCount < 0 || ++currentLoopCount < loopCount ) // 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. + mUpdateFrameNumber = false; + } + else + { + animationFinished = true; // end of animation + } + ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); + } + } + else if( currentFrame == startFrame && !mForward ) // first frame + { + if( loopCount < 0 || ++currentLoopCount < loopCount ) // repeat forever or before the last loop + { + mForward = true; + } + else + { + animationFinished = true; // end of animation + } + ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); + } - if( mCompletedCallback ) + if( animationFinished ) { - CallbackBase::Execute( *mCompletedCallback, nextTask, keepAnimation ); + if( mStopBehavior == DevelImageVisual::StopBehavior::CURRENT_FRAME ) + { + stopped = true; + } + else + { + mPlayState = PlayState::STOPPING; + } } } + + // Rasterize + if( !mVectorRenderer.Render( currentFrame ) ) + { + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Rendering failed. Try again later.[%d] [%p]\n", currentFrame, this ); + mUpdateFrameNumber = false; + } + + if( stopped ) + { + mPlayState = PlayState::STOPPED; + mForward = true; + mCurrentLoop = 0; + + // Animation is finished + if( needAnimationFinishedTrigger ) + { + mAnimationFinishedTrigger->Trigger(); + } + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished [current = %d] [%p]\n", currentFrame, this ); + } + + 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] [%p]\n", currentFrame, sleepDuration.count(), this ); +#endif + + std::this_thread::sleep_until( timeToSleepUntil ); +} + +uint32_t VectorRasterizeThread::GetStoppedFrame( uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame ) +{ + uint32_t frame = currentFrame; + + switch( mStopBehavior ) + { + case DevelImageVisual::StopBehavior::FIRST_FRAME: + { + frame = startFrame; + break; + } + case DevelImageVisual::StopBehavior::LAST_FRAME: + { + if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) + { + frame = startFrame; + } + else + { + frame = endFrame; + } + break; + } + case DevelImageVisual::StopBehavior::CURRENT_FRAME: + { + frame = currentFrame; + break; + } + } + + return frame; } } // namespace Internal 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 e21809e..f50a66d 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 @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_VECTOR_IMAGE_RASTERIZE_THREAD_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 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. @@ -18,16 +18,17 @@ */ // EXTERNAL INCLUDES -//#include +#include +#include #include +#include #include #include -#include +#include #include -//#include // INTERNAL INCLUDES -#include +#include namespace Dali { @@ -45,10 +46,14 @@ class VectorRasterizeThread : public Thread { public: + using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType; + /** * @brief Constructor. + * + * @param[in] url The url of the vector animation file */ - VectorRasterizeThread(); + VectorRasterizeThread( const std::string& url ); /** * @brief Destructor. @@ -56,17 +61,114 @@ public: virtual ~VectorRasterizeThread(); /** - * The callback is called from the rasterize thread after the rasterization is completed. - * @param[in] callBack The function to call. + * @brief Sets the renderer used to display the result image. + * + * @param[in] renderer The renderer used to display the result image */ - void SetCompletedCallback( CallbackBase* callback ); + void SetRenderer( Renderer renderer ); /** - * Add a task to rasterize. + * @brief Sets the target image size. * - * @param[in] task The task to rasterize + * @param[in] width The target image width + * @param[in] height The target image height + */ + void SetSize( uint32_t width, uint32_t height ); + + /** + * @brief Play the vector animation. + */ + void PlayAnimation(); + + /** + * @brief Stop the vector animation. + */ + void StopAnimation(); + + /** + * @brief Pause the vector animation. + */ + void PauseAnimation(); + + /** + * @brief Render one frame. The current frame number will be increased. */ - void AddTask( VectorAnimationTaskPtr task ); + void RenderFrame(); + + /** + * @brief This callback is called after the animation is finished. + * @param[in] callback The animation finished callback + */ + void SetAnimationFinishedCallback( EventThreadCallback* callback ); + + /** + * @brief Enable looping for 'count' repeats. -1 means to repeat forever. + * @param[in] count The number of times to loop + */ + void SetLoopCount( int32_t count ); + + /** + * @brief Set the playing range in frame number. + * @param[in] startFrame The frame number to specify minimum progress. + * @param[in] endFrame The frame number to specify maximum progress. + * The animation will play between those values. + */ + void SetPlayRange( uint32_t startFrame, uint32_t endFrame ); + + /** + * @brief Get the play state + * @return The play state + */ + DevelImageVisual::PlayState::Type GetPlayState() const; + + /** + * @brief Queries whether the resource is ready. + * @return true if ready, false otherwise + */ + bool IsResourceReady() const; + + /** + * @brief Sets the current frame number of the animation. + * @param[in] frameNumber The new frame number between [0, the maximum frame number] or between the play range if specified. + */ + void SetCurrentFrameNumber( uint32_t frameNumber ); + + /** + * @brief Retrieves the current frame number of the animation. + * @return The current frame number + */ + uint32_t GetCurrentFrameNumber() const; + + /** + * @brief Retrieves the total frame number of the animation. + * @return The total frame number + */ + uint32_t GetTotalFrameNumber() const; + + /** + * @brief Gets the default size of the file,. + * @return The default size of the file + */ + void GetDefaultSize( uint32_t& width, uint32_t& height ) const; + + /** + * @brief Sets the stop behavior of the animation. This is performed when the animation is stopped. + * @param[in] stopBehavior The stop behavior + */ + void SetStopBehavior( DevelImageVisual::StopBehavior::Type stopBehavior ); + + /** + * @brief Sets the looping mode. + * Animation plays forwards and then restarts from the beginning or runs backwards again. + * @param[in] loopingMode The looping mode + */ + void SetLoopingMode( DevelImageVisual::LoopingMode::Type loopingMode ); + + /** + * @brief Connect to this signal to be notified when the texture upload is completed. + * @return The signal to connect to. + */ + UploadCompletedSignalType& UploadCompletedSignal(); protected: @@ -79,11 +181,19 @@ protected: private: /** - * Rasterizes the tasks. + * @brief Initializes the vector renderer. + */ + void Initialize(); + + /** + * @brief Rasterizes the current frame. */ void Rasterize(); -private: + /** + * @brief Gets the frame number when the animation is stopped according to the stop behavior. + */ + uint32_t GetStoppedFrame( uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame ); // Undefined VectorRasterizeThread( const VectorRasterizeThread& thread ) = delete; @@ -93,12 +203,41 @@ private: private: - std::vector< VectorAnimationTaskPtr > mRasterizeTasks; - ConditionalWait mConditionalWait; - std::unique_ptr< CallbackBase > mCompletedCallback; - bool mDestroyThread; ///< Whether the thread be destroyed - bool mIsThreadStarted; - const Dali::LogFactoryInterface& mLogFactory; ///< The log factory + enum class PlayState + { + STOPPING, ///< The animation is stopping + STOPPED, ///< The animation has stopped + PLAYING, ///< The animation is playing + PAUSED ///< The animation is paused + }; + + std::string mUrl; + VectorAnimationRenderer mVectorRenderer; + ConditionalWait mConditionalWait; + std::unique_ptr< EventThreadCallback > mAnimationFinishedTrigger; + Vector2 mPlayRange; + PlayState mPlayState; + DevelImageVisual::StopBehavior::Type mStopBehavior; + DevelImageVisual::LoopingMode::Type mLoopingMode; + int64_t mFrameDurationNanoSeconds; + float mFrameRate; + uint32_t mCurrentFrame; + uint32_t mTotalFrame; + uint32_t mStartFrame; + uint32_t mEndFrame; + uint32_t mWidth; + uint32_t mHeight; + int32_t mLoopCount; + int32_t mCurrentLoop; + bool mNeedRender; + bool mDestroyThread; ///< Whether the thread be destroyed + bool mResourceReady; + bool mCurrentFrameUpdated; + bool mCurrentLoopUpdated; + bool mForward; + bool mUpdateFrameNumber; + bool mNeedAnimationFinishedTrigger; + const Dali::LogFactoryInterface& mLogFactory; ///< The log factory }; diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.cpp b/dali-toolkit/internal/visuals/visual-factory-cache.cpp index 3852361..101e696 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-cache.cpp @@ -43,7 +43,6 @@ namespace Internal VisualFactoryCache::VisualFactoryCache( bool preMultiplyOnLoad ) : mSvgRasterizeThread( NULL ), - mVectorAnimationThread(), mBrokenImageUrl(""), mPreMultiplyOnLoad( preMultiplyOnLoad ) { @@ -136,16 +135,6 @@ SvgRasterizeThread* VisualFactoryCache::GetSVGRasterizationThread() return mSvgRasterizeThread; } -VectorAnimationThread& VisualFactoryCache::GetVectorAnimationThread() -{ - if( !mVectorAnimationThread ) - { - mVectorAnimationThread = std::unique_ptr< VectorAnimationThread >( new VectorAnimationThread() ); - mVectorAnimationThread->Start(); - } - return *mVectorAnimationThread; -} - void VisualFactoryCache::ApplyRasterizedSVGToSampler() { while( RasterizingTaskPtr task = mSvgRasterizeThread->NextCompletedTask() ) diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index e080d52..f2c8120 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -28,7 +28,6 @@ #include #include #include -#include namespace Dali { @@ -204,12 +203,6 @@ public: */ SvgRasterizeThread* GetSVGRasterizationThread(); - /** - * Get the vector animation thread. - * @return A raw pointer pointing to the vector animation thread. - */ - VectorAnimationThread& GetVectorAnimationThread(); - private: // for svg rasterization thread /** @@ -233,13 +226,12 @@ private: Geometry mGeometry[GEOMETRY_TYPE_MAX+1]; Shader mShader[SHADER_TYPE_MAX+1]; - ImageAtlasManagerPtr mAtlasManager; - TextureManager mTextureManager; - NPatchLoader mNPatchLoader; - SvgRasterizeThread* mSvgRasterizeThread; - std::unique_ptr< VectorAnimationThread > mVectorAnimationThread; - std::string mBrokenImageUrl; - bool mPreMultiplyOnLoad; + ImageAtlasManagerPtr mAtlasManager; + TextureManager mTextureManager; + NPatchLoader mNPatchLoader; + SvgRasterizeThread* mSvgRasterizeThread; + std::string mBrokenImageUrl; + bool mPreMultiplyOnLoad; }; } // namespace Internal -- 2.7.4