From: Heeyong Song Date: Thu, 19 Dec 2019 10:10:41 +0000 (+0900) Subject: (Vector) Ensure that all animation data is applied at once X-Git-Tag: dali_1.9.16~4^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=65fe4d97a7a58199b2f5ad2d84e26acbb2b6ae39 (Vector) Ensure that all animation data is applied at once Change-Id: I22b285e52062e187a7e2117d8a543dc7f49f82c5 --- diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h index 7d6e853..c3616b2 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor-impl.h @@ -26,6 +26,7 @@ class EglInterface; class DisplayConnection; class ThreadSynchronizationInterface; class Window; +class TestApplication; namespace Integration { @@ -83,6 +84,11 @@ public: void AddWindow( Internal::Adaptor::SceneHolder* window ); void RemoveWindow( Internal::Adaptor::SceneHolder* window ); + void RegisterProcessor( Integration::Processor& processor ); + void UnregisterProcessor( Integration::Processor& processor ); + + void SetApplication( Dali::TestApplication& testApplication ); + Dali::Adaptor::AdaptorSignalType& ResizedSignal(); Dali::Adaptor::AdaptorSignalType& LanguageChangedSignal(); Dali::Adaptor::WindowCreatedSignalType& WindowCreatedSignal(); @@ -97,6 +103,7 @@ private: Dali::Adaptor::AdaptorSignalType mResizedSignal; Dali::Adaptor::AdaptorSignalType mLanguageChangedSignal; Dali::Adaptor::WindowCreatedSignalType mWindowCreatedSignal; + TestApplication* mTestApplication; }; } // namespace Adaptor diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp index 7c50cc7..5dbbe76 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp @@ -195,6 +195,23 @@ void Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* window ) } } +void Adaptor::RegisterProcessor( Integration::Processor& processor ) +{ + Integration::Core& core = mTestApplication->GetCore(); + core.RegisterProcessor( processor ); +} + +void Adaptor::UnregisterProcessor( Integration::Processor& processor ) +{ + Integration::Core& core = mTestApplication->GetCore(); + core.UnregisterProcessor( processor ); +} + +void Adaptor::SetApplication( Dali::TestApplication& testApplication ) +{ + mTestApplication = &testApplication; +} + Dali::Adaptor::AdaptorSignalType& Adaptor::ResizedSignal() { return mResizedSignal; @@ -356,4 +373,14 @@ const LogFactoryInterface& Adaptor::GetLogFactory() return *gLogFactory; } +void Adaptor::RegisterProcessor( Integration::Processor& processor ) +{ + mImpl->RegisterProcessor( processor ); +} + +void Adaptor::UnregisterProcessor( Integration::Processor& processor ) +{ + mImpl->UnregisterProcessor( processor ); +} + } // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp index d3bdd42..3e3a0d2 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp @@ -49,6 +49,7 @@ ToolkitTestApplication::ToolkitTestApplication( size_t surfaceWidth, size_t surf // This will also emit the window created signals AdaptorImpl::GetImpl( *mAdaptor ).Start( *mMainWindow ); + AdaptorImpl::GetImpl( *mAdaptor ).SetApplication( *this ); Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get(); lifecycleController.InitSignal().Emit(); 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 cf52774..b0075d2 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 @@ -19,6 +19,8 @@ #include #include #include +#include +#include namespace Dali { @@ -39,7 +41,8 @@ public: mWidth( 0 ), mHeight( 0 ), mPreviousFrame( 0 ), - mFrameRate( 60.0f ) + mFrameRate( 60.0f ), + mEventThreadCallback( new EventThreadCallback( MakeCallback( this, &VectorAnimationRenderer::OnTriggered ) ) ) { mCount++; @@ -83,6 +86,12 @@ public: bool Render( uint32_t frameNumber ) { + if( mNeedTrigger ) + { + mEventThreadCallback->Trigger(); + mNeedTrigger = false; + } + if( frameNumber == 1 && mPreviousFrame != frameNumber ) { mPreviousFrame = frameNumber; @@ -133,9 +142,14 @@ public: return mUploadCompletedSignal; } + void OnTriggered() + { + } + public: static uint32_t mCount; + static bool mNeedTrigger; std::string mUrl; Dali::Renderer mRenderer; @@ -144,9 +158,11 @@ public: uint32_t mPreviousFrame; float mFrameRate; Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal; + std::unique_ptr< EventThreadCallback > mEventThreadCallback; }; uint32_t VectorAnimationRenderer::mCount = 0; +bool VectorAnimationRenderer::mNeedTrigger = true; inline VectorAnimationRenderer& GetImplementation( Dali::VectorAnimationRenderer& renderer ) { @@ -250,5 +266,18 @@ VectorAnimationRenderer::UploadCompletedSignalType& VectorAnimationRenderer::Upl return Internal::Adaptor::GetImplementation( *this ).UploadCompletedSignal(); } -} // namespace Dali; +} // namespace Dali + +namespace Test +{ +namespace VectorAnimationRenderer +{ + +void RequestTrigger() +{ + Dali::Internal::Adaptor::VectorAnimationRenderer::mNeedTrigger = true; +} + +} // VectorAnimationRenderer +} // Test diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h index 670c5ca..2213465 100755 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.h @@ -20,6 +20,8 @@ namespace Test { +namespace VectorAnimationRenderer +{ #define VECTOR_ANIMATION_TOTAL_FRAME_NUMBER 5 #define VECTOR_ANIMATION_MARKER_NAME_1 "marker1" @@ -29,6 +31,9 @@ namespace Test #define VECTOR_ANIMATION_MARKER_START_FRAME_2 2 #define VECTOR_ANIMATION_MARKER_END_FRAME_2 3 +void RequestTrigger(); + +} // VectorAnimationRenderer } // Test diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index daf21d3..587c7ac 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -347,8 +347,6 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render( 16 ); - std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); // wait for one animation loop (16fps, 5frames, need 80ms) - Property::Map map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); Property::Value* value = map.Find( DevelImageVisual::Property::PLAY_STATE ); DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PLAYING ); @@ -359,8 +357,6 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render(16); - std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run - map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::PLAY_STATE ); DALI_TEST_CHECK( value->Get< int >() == DevelImageVisual::PlayState::PAUSED ); @@ -566,7 +562,7 @@ int UtcDaliAnimatedVectorImageVisualLoopCount(void) application.SendNotification(); application.Render(); - // Trigger count is 1 - animation finished + // Trigger count is 1 - render a frame DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); // renderer is added to actor @@ -610,6 +606,8 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + // renderer is added to actor DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); Renderer renderer = actor.GetRendererAt( 0u ); @@ -638,6 +636,8 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); @@ -658,6 +658,8 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + 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 ); @@ -720,6 +722,8 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + // renderer is added to actor DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); Renderer renderer = actor.GetRendererAt( 0u ); @@ -748,6 +752,8 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); @@ -770,6 +776,8 @@ int UtcDaliAnimatedVectorImageVisualPlayRangeMarker(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); @@ -814,7 +822,7 @@ int UtcDaliAnimatedVectorImageVisualAnimationFinishedSignal(void) application.Render(); // Wait for animation finish - DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION ); Property::Map map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); Property::Value* value = map.Find( DevelImageVisual::Property::PLAY_STATE ); @@ -899,6 +907,8 @@ int UtcDaliAnimatedVectorImageVisualJumpTo(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + 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 ); @@ -919,7 +929,7 @@ int UtcDaliAnimatedVectorImageVisualJumpTo(void) int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) { ToolkitTestApplication application; - tet_infoline( "UtcDaliAnimatedVectorImageVisualJumpToCurrentProgress" ); + tet_infoline( "UtcDaliAnimatedVectorImageVisualUpdateProperty" ); int startFrame = 1, endFrame = 3; Property::Array playRange; @@ -947,6 +957,8 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + Property::Map map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); Property::Value* value = map.Find( DevelImageVisual::Property::LOOP_COUNT ); DALI_TEST_EQUALS( value->Get< int >(), 3, TEST_LOCATION ); @@ -973,6 +985,8 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::LOOP_COUNT ); DALI_TEST_EQUALS( value->Get< int >(), 5, TEST_LOCATION ); @@ -997,6 +1011,8 @@ int UtcDaliAnimatedVectorImageVisualUpdateProperty(void) application.SendNotification(); application.Render(); + std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run + map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); value = map.Find( DevelImageVisual::Property::PLAY_RANGE ); @@ -1057,7 +1073,7 @@ int UtcDaliAnimatedVectorImageVisualStopBehavior(void) application.Render(); // Trigger count is 1 - animation finished - DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION ); Property::Map map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); Property::Value* value = map.Find( DevelImageVisual::Property::CURRENT_FRAME_NUMBER ); @@ -1152,7 +1168,7 @@ int UtcDaliAnimatedVectorImageVisualLoopingMode(void) application.Render(); // Trigger count is 1 - animation finished - DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION ); Property::Map map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); Property::Value* value = map.Find( DevelImageVisual::Property::CURRENT_FRAME_NUMBER ); @@ -1353,6 +1369,9 @@ int UtcDaliAnimatedVectorImageVisualControlVisibilityChanged(void) Property::Map attributes; DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + application.SendNotification(); + application.Render(); + // Check rendering behavior DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); Renderer renderer = actor.GetRendererAt( 0u ); @@ -1397,6 +1416,9 @@ int UtcDaliAnimatedVectorImageVisualWindowVisibilityChanged(void) Property::Map attributes; DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + application.SendNotification(); + application.Render(); + // Check rendering behavior DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); Renderer renderer = actor.GetRendererAt( 0u ); 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 1793fbc..bf3b519 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ #include #include #include +#include #include // INTERNAL INCLUDES @@ -46,19 +47,8 @@ namespace Internal namespace { -constexpr auto LOOP_FOREVER = -1; - const Dali::Vector4 FULL_TEXTURE_RECT( 0.f, 0.f, 1.f, 1.f ); -// Flags for re-sending data to the rasterize thread -enum Flags -{ - RESEND_PLAY_RANGE = 1 << 0, - RESEND_LOOP_COUNT = 1 << 1, - RESEND_STOP_BEHAVIOR = 1 << 2, - RESEND_LOOPING_MODE = 1 << 3 -}; - // stop behavior DALI_ENUM_TO_STRING_TABLE_BEGIN( STOP_BEHAVIOR ) DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME ) @@ -96,18 +86,15 @@ AnimatedVectorImageVisualPtr AnimatedVectorImageVisual::New( VisualFactoryCache& AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl ) : Visual::Base( factoryCache, Visual::FittingMode::FILL ), mUrl( imageUrl ), + mAnimationData(), mVectorAnimationTask( new VectorAnimationTask( factoryCache, imageUrl.GetUrl() ) ), mImageVisualShaderFactory( shaderFactory ), mVisualSize(), mVisualScale( Vector2::ONE ), - mPlayRange(), mPlacementActor(), - mLoopCount( LOOP_FOREVER ), - mResendFlag( 0 ), - mActionStatus( DevelAnimatedVectorImageVisual::Action::STOP ), - mStopBehavior( DevelImageVisual::StopBehavior::CURRENT_FRAME ), - mLoopingMode( DevelImageVisual::LoopingMode::RESTART ), - mRendererAdded( false ) + mPlayState( DevelImageVisual::PlayState::STOPPED ), + mRendererAdded( false ), + mRasterizationTriggered( false ) { // the rasterized image is with pre-multiplied alpha format mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; @@ -118,6 +105,11 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factor AnimatedVectorImageVisual::~AnimatedVectorImageVisual() { + if( mRasterizationTriggered && Adaptor::IsAvailable() ) + { + Adaptor::Get().UnregisterProcessor( *this ); + } + // Finalize animation task and disconnect the signal in the main thread mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); mVectorAnimationTask->Finalize(); @@ -148,7 +140,7 @@ void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const { map.Insert( Toolkit::ImageVisual::Property::URL, mUrl.GetUrl() ); } - map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, mLoopCount ); + map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, mAnimationData.loopCount ); uint32_t startFrame, endFrame; mVectorAnimationTask->GetPlayRange( startFrame, endFrame ); @@ -158,12 +150,12 @@ void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const playRange.PushBack( static_cast< int32_t >( endFrame ) ); 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::PLAY_STATE, static_cast< int32_t >( mPlayState ) ); 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::STOP_BEHAVIOR, mStopBehavior ); - map.Insert( Toolkit::DevelImageVisual::Property::LOOPING_MODE, mLoopingMode ); + map.Insert( Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mAnimationData.stopBehavior ); + map.Insert( Toolkit::DevelImageVisual::Property::LOOPING_MODE, mAnimationData.loopingMode ); Property::Map layerInfo; mVectorAnimationTask->GetLayerInfo( layerInfo ); @@ -205,6 +197,8 @@ void AnimatedVectorImageVisual::DoSetProperties( const Property::Map& propertyMa } } } + + TriggerVectorRasterization(); } void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Property::Value& value ) @@ -216,8 +210,8 @@ void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Prop int32_t loopCount; if( value.Get( loopCount ) ) { - mLoopCount = loopCount; - mResendFlag |= RESEND_LOOP_COUNT; + mAnimationData.loopCount = loopCount; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_LOOP_COUNT; } break; } @@ -226,28 +220,28 @@ void AnimatedVectorImageVisual::DoSetProperty( Property::Index index, const Prop Property::Array* array = value.GetArray(); if( array ) { - mPlayRange = *array; - mResendFlag |= RESEND_PLAY_RANGE; + mAnimationData.playRange = *array; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_RANGE; } break; } case Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR: { - int32_t stopBehavior = mStopBehavior; + int32_t stopBehavior = mAnimationData.stopBehavior; if( Scripting::GetEnumerationProperty( value, STOP_BEHAVIOR_TABLE, STOP_BEHAVIOR_TABLE_COUNT, stopBehavior ) ) { - mStopBehavior = DevelImageVisual::StopBehavior::Type( stopBehavior ); - mResendFlag |= RESEND_STOP_BEHAVIOR; + mAnimationData.stopBehavior = DevelImageVisual::StopBehavior::Type( stopBehavior ); + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_STOP_BEHAVIOR; } break; } case Toolkit::DevelImageVisual::Property::LOOPING_MODE: { - int32_t loopingMode = mLoopingMode; + int32_t loopingMode = mAnimationData.loopingMode; if( Scripting::GetEnumerationProperty( value, LOOPING_MODE_TABLE, LOOPING_MODE_TABLE_COUNT, loopingMode ) ) { - mLoopingMode = DevelImageVisual::LoopingMode::Type( loopingMode ); - mResendFlag |= RESEND_LOOPING_MODE; + mAnimationData.loopingMode = DevelImageVisual::LoopingMode::Type( loopingMode ); + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_LOOPING_MODE; } break; } @@ -309,6 +303,7 @@ void AnimatedVectorImageVisual::DoSetOnStage( Actor& actor ) void AnimatedVectorImageVisual::DoSetOffStage( Actor& actor ) { StopAnimation(); + SendAnimationData(); if( mImpl->mRenderer ) { @@ -351,19 +346,13 @@ void AnimatedVectorImageVisual::OnSetTransform() SetVectorImageSize(); - SendAnimationData(); - - if( mActionStatus == DevelAnimatedVectorImageVisual::Action::PLAY ) + if( mPlayState == DevelImageVisual::PlayState::PLAYING && mAnimationData.playState != DevelImageVisual::PlayState::PLAYING ) { - mVectorAnimationTask->PlayAnimation(); - - mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY ); - } - else - { - // Render one frame - mVectorAnimationTask->RenderFrame(); + mAnimationData.playState = DevelImageVisual::PlayState::PLAYING; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE; } + + SendAnimationData(); } } @@ -376,38 +365,33 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons { if( IsOnStage() && mVisualSize != Vector2::ZERO ) { - mVectorAnimationTask->PlayAnimation(); - - mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY ); + if( mAnimationData.playState != DevelImageVisual::PlayState::PLAYING ) + { + mAnimationData.playState = DevelImageVisual::PlayState::PLAYING; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE; + } } - mActionStatus = DevelAnimatedVectorImageVisual::Action::PLAY; + mPlayState = DevelImageVisual::PlayState::PLAYING; break; } case DevelAnimatedVectorImageVisual::Action::PAUSE: { - mVectorAnimationTask->PauseAnimation(); - - if( mImpl->mRenderer ) + if( mAnimationData.playState == DevelImageVisual::PlayState::PLAYING ) { - mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED ); + mAnimationData.playState = DevelImageVisual::PlayState::PAUSED; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE; } - - mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE; + mPlayState = DevelImageVisual::PlayState::PAUSED; break; } case DevelAnimatedVectorImageVisual::Action::STOP: { - if( mVectorAnimationTask->GetPlayState() != DevelImageVisual::PlayState::STOPPED ) + if( mAnimationData.playState != DevelImageVisual::PlayState::STOPPED ) { - mVectorAnimationTask->StopAnimation(); - } - - if( mImpl->mRenderer ) - { - mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED ); + mAnimationData.playState = DevelImageVisual::PlayState::STOPPED; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE; } - - mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP; + mPlayState = DevelImageVisual::PlayState::STOPPED; break; } case DevelAnimatedVectorImageVisual::Action::JUMP_TO: @@ -415,13 +399,8 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons int32_t frameNumber; if( attributes.Get( frameNumber ) ) { - mVectorAnimationTask->SetCurrentFrameNumber( frameNumber ); - - if( IsOnStage() && mVectorAnimationTask->GetPlayState() != DevelImageVisual::PlayState::PLAYING ) - { - mVectorAnimationTask->RenderFrame(); - Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger rendering - } + mAnimationData.currentFrame = frameNumber; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_CURRENT_FRAME; } break; } @@ -431,12 +410,21 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons if( map ) { DoSetProperties( *map ); - - SendAnimationData(); } break; } } + + TriggerVectorRasterization(); +} + +void AnimatedVectorImageVisual::Process() +{ + SendAnimationData(); + + mRasterizationTriggered = false; + + Adaptor::Get().UnregisterProcessor( *this ); } void AnimatedVectorImageVisual::OnUploadCompleted() @@ -456,11 +444,13 @@ void AnimatedVectorImageVisual::OnUploadCompleted() void AnimatedVectorImageVisual::OnAnimationFinished() { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnAnimationFinished: action state = %d [%p]\n", mActionStatus, this ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnAnimationFinished: action state = %d [%p]\n", mPlayState, this ); - if( mActionStatus != DevelAnimatedVectorImageVisual::Action::STOP ) + if( mPlayState != DevelImageVisual::PlayState::STOPPED ) { - mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP; + mPlayState = DevelImageVisual::PlayState::STOPPED; + + mAnimationData.playState = DevelImageVisual::PlayState::STOPPED; if( mImpl->mEventObserver ) { @@ -476,49 +466,23 @@ void AnimatedVectorImageVisual::OnAnimationFinished() void AnimatedVectorImageVisual::SendAnimationData() { - if( mResendFlag ) + if( mAnimationData.resendFlag ) { - bool isPlaying = false; - if( mVectorAnimationTask->GetPlayState() == DevelImageVisual::PlayState::PLAYING ) - { - mVectorAnimationTask->PauseAnimation(); - isPlaying = true; - } - - if( mResendFlag & RESEND_LOOP_COUNT ) - { - mVectorAnimationTask->SetLoopCount( mLoopCount ); - } - - if( mResendFlag & RESEND_PLAY_RANGE ) - { - mVectorAnimationTask->SetPlayRange( mPlayRange ); - } - - if( mResendFlag & RESEND_STOP_BEHAVIOR ) - { - mVectorAnimationTask->SetStopBehavior( mStopBehavior ); - } - - if( mResendFlag & RESEND_LOOPING_MODE ) - { - mVectorAnimationTask->SetLoopingMode( mLoopingMode ); - } + mVectorAnimationTask->SetAnimationData( mAnimationData ); - if( IsOnStage() ) + if( mImpl->mRenderer ) { - if( isPlaying ) + if( mAnimationData.playState == DevelImageVisual::PlayState::PLAYING ) { - mVectorAnimationTask->PlayAnimation(); + mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY ); } else { - mVectorAnimationTask->RenderFrame(); - Stage::GetCurrent().KeepRendering( 0.0f ); + mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED ); } } - mResendFlag = 0; + mAnimationData.resendFlag = 0; } } @@ -527,27 +491,30 @@ 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 ); + mAnimationData.width = width; + mAnimationData.height = height; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_SIZE; +} - if( IsOnStage() && mVectorAnimationTask->GetPlayState() != DevelImageVisual::PlayState::PLAYING ) +void AnimatedVectorImageVisual::StopAnimation() +{ + if( mAnimationData.playState != DevelImageVisual::PlayState::STOPPED ) { - mVectorAnimationTask->RenderFrame(); - Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger rendering + mAnimationData.playState = DevelImageVisual::PlayState::STOPPED; + mAnimationData.resendFlag |= VectorAnimationTask::RESEND_PLAY_STATE; + + mPlayState = DevelImageVisual::PlayState::STOPPED; } } -void AnimatedVectorImageVisual::StopAnimation() +void AnimatedVectorImageVisual::TriggerVectorRasterization() { - if( mActionStatus != DevelAnimatedVectorImageVisual::Action::STOP ) + if( !mRasterizationTriggered ) { - mVectorAnimationTask->StopAnimation(); + Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing - mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP; - - if( mImpl->mRenderer ) - { - mImpl->mRenderer.SetProperty( DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED ); - } + Adaptor::Get().RegisterProcessor( *this ); + mRasterizationTriggered = true; } } @@ -563,6 +530,9 @@ void AnimatedVectorImageVisual::OnScaleNotification( PropertyNotification& sourc DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnScaleNotification: scale = %f, %f [%p]\n", mVisualScale.width, mVisualScale.height, this ); SetVectorImageSize(); + SendAnimationData(); + + Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing } } @@ -578,6 +548,9 @@ void AnimatedVectorImageVisual::OnSizeNotification( PropertyNotification& source DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnSizeNotification: size = %f, %f [%p]\n", mVisualSize.width, mVisualSize.height, this ); SetVectorImageSize(); + SendAnimationData(); + + Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing } } @@ -586,6 +559,7 @@ void AnimatedVectorImageVisual::OnControlVisibilityChanged( Actor actor, bool vi if( !visible ) { StopAnimation(); + TriggerVectorRasterization(); DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnControlVisibilityChanged: invisibile. Pause animation [%p]\n", this ); } @@ -596,6 +570,7 @@ void AnimatedVectorImageVisual::OnWindowVisibilityChanged( Window window, bool v if( !visible ) { StopAnimation(); + TriggerVectorRasterization(); DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnWindowVisibilityChanged: invisibile. Pause animation [%p]\n", this ); } 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 8aaed9c..6eaead5 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 @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_ANIMATED_VECTOR_IMAGE_VISUAL_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,9 @@ #include #include #include -#include #include +#include +#include // INTERNAL INCLUDES #include @@ -55,7 +56,7 @@ using AnimatedVectorImageVisualPtr = IntrusivePtr< AnimatedVectorImageVisual >; * | url | STRING | * */ -class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker +class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker, public Integration::Processor { public: @@ -138,6 +139,13 @@ protected: */ void OnDoAction( const Property::Index actionId, const Property::Value& attributes ) override; +protected: // Implementation of Processor + + /** + * @copydoc Dali::Integration::Processor::Process() + */ + void Process() override; + private: /** @@ -173,6 +181,11 @@ private: void StopAnimation(); /** + * @brief Trigger rasterization of the vector content. + */ + void TriggerVectorRasterization(); + + /** * @brief Callback when the world scale factor changes. */ void OnScaleNotification( PropertyNotification& source ); @@ -200,20 +213,17 @@ private: private: VisualUrl mUrl; + VectorAnimationTask::AnimationData mAnimationData; VectorAnimationTaskPtr mVectorAnimationTask; ImageVisualShaderFactory& mImageVisualShaderFactory; PropertyNotification mScaleNotification; PropertyNotification mSizeNotification; Vector2 mVisualSize; Vector2 mVisualScale; - Property::Array mPlayRange; WeakHandle< Actor > mPlacementActor; - int32_t mLoopCount; - uint32_t mResendFlag; - DevelAnimatedVectorImageVisual::Action::Type mActionStatus; - DevelImageVisual::StopBehavior::Type mStopBehavior; - DevelImageVisual::LoopingMode::Type mLoopingMode; + DevelImageVisual::PlayState::Type mPlayState; bool mRendererAdded; + bool mRasterizationTriggered; }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index e0c08bd..6072ce5 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -46,22 +46,12 @@ constexpr auto NANOSECONDS_PER_SECOND( 1e+9 ); Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" ); #endif -template< typename T > -inline void ResetValue( bool& updated, T& value, T newValue, ConditionalWait& conditionalWait ) -{ - ConditionalWait::ScopedLock lock( conditionalWait ); - if( !updated ) - { - value = newValue; - updated = true; - } -} - } // unnamed namespace VectorAnimationTask::VectorAnimationTask( VisualFactoryCache& factoryCache, const std::string& url ) : mUrl( url ), mVectorRenderer(), + mAnimationData(), mVectorAnimationThread( factoryCache.GetVectorAnimationThread() ), mConditionalWait(), mAnimationFinishedTrigger(), @@ -77,14 +67,14 @@ VectorAnimationTask::VectorAnimationTask( VisualFactoryCache& factoryCache, cons mEndFrame( 0 ), mWidth( 0 ), mHeight( 0 ), + mAnimationDataIndex( 0 ), mLoopCount( LOOP_FOREVER ), mCurrentLoop( 0 ), mResourceReady( false ), - mCurrentFrameUpdated( false ), - mCurrentLoopUpdated( false ), mForward( true ), mUpdateFrameNumber( false ), - mNeedAnimationFinishedTrigger( true ) + mNeedAnimationFinishedTrigger( true ), + mAnimationDataUpdated( false ) { Initialize(); } @@ -116,11 +106,30 @@ void VectorAnimationTask::SetRenderer( Renderer renderer ) DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", this ); } +void VectorAnimationTask::SetAnimationData( const AnimationData& data ) +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetAnimationData [%p]\n", this ); + + uint32_t index = mAnimationDataIndex == 0 ? 1 : 0; // Use the other buffer + + mAnimationData[index] = data; + mAnimationDataUpdated = true; + + if( data.resendFlag & VectorAnimationTask::RESEND_SIZE ) + { + // The size should be changed in the main thread. + SetSize( data.width, data.height ); + } + + mVectorAnimationThread.AddTask( this ); +} + void VectorAnimationTask::SetSize( uint32_t width, uint32_t height ) { if( mWidth != width || mHeight != height ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mVectorRenderer.SetSize( width, height ); mWidth = width; @@ -134,23 +143,18 @@ void VectorAnimationTask::SetSize( uint32_t width, uint32_t height ) 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 ) + if( mPlayState != PlayState::STOPPING ) { mNeedAnimationFinishedTrigger = false; mPlayState = PlayState::STOPPING; @@ -161,7 +165,6 @@ void VectorAnimationTask::StopAnimation() void VectorAnimationTask::PauseAnimation() { - ConditionalWait::ScopedLock lock( mConditionalWait ); if( mPlayState == PlayState::PLAYING ) { mPlayState = PlayState::PAUSED; @@ -170,18 +173,6 @@ void VectorAnimationTask::PauseAnimation() } } -void VectorAnimationTask::RenderFrame() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - - if( !mResourceReady ) - { - mVectorAnimationThread.AddTask( this ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::RenderFrame: Render [%p]\n", this ); - } -} - void VectorAnimationTask::SetAnimationFinishedCallback( EventThreadCallback* callback ) { ConditionalWait::ScopedLock lock( mConditionalWait ); @@ -195,20 +186,15 @@ 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( Property::Array& playRange ) +void VectorAnimationTask::SetPlayRange( const Property::Array& playRange ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - bool valid = false; uint32_t startFrame = 0, endFrame = 0; size_t count = playRange.Count(); @@ -277,15 +263,11 @@ void VectorAnimationTask::SetPlayRange( Property::Array& playRange ) if( mStartFrame > mCurrentFrame ) { mCurrentFrame = mStartFrame; - - mCurrentFrameUpdated = true; mResourceReady = false; } else if( mEndFrame < mCurrentFrame ) { mCurrentFrame = mEndFrame; - - mCurrentFrameUpdated = true; mResourceReady = false; } @@ -305,37 +287,8 @@ void VectorAnimationTask::GetPlayRange( uint32_t& startFrame, uint32_t& endFrame endFrame = mEndFrame; } -DevelImageVisual::PlayState::Type VectorAnimationTask::GetPlayState() const -{ - DevelImageVisual::PlayState::Type state = DevelImageVisual::PlayState::STOPPED; - - switch( mPlayState ) - { - case PlayState::PLAYING: - { - state = DevelImageVisual::PlayState::PLAYING; - break; - } - case PlayState::PAUSED: - { - state = DevelImageVisual::PlayState::PAUSED; - break; - } - case PlayState::STOPPING: - case PlayState::STOPPED: - { - state = DevelImageVisual::PlayState::STOPPED; - break; - } - } - - return state; -} - void VectorAnimationTask::SetCurrentFrameNumber( uint32_t frameNumber ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mCurrentFrame == frameNumber ) { DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetCurrentFrameNumber: Set same frame [%d] [%p]\n", frameNumber, this ); @@ -345,8 +298,6 @@ void VectorAnimationTask::SetCurrentFrameNumber( uint32_t frameNumber ) if( frameNumber >= mStartFrame && frameNumber <= mEndFrame ) { mCurrentFrame = frameNumber; - mCurrentFrameUpdated = true; - mUpdateFrameNumber = false; mResourceReady = false; @@ -375,7 +326,6 @@ void VectorAnimationTask::GetDefaultSize( uint32_t& width, uint32_t& height ) co void VectorAnimationTask::SetStopBehavior( DevelImageVisual::StopBehavior::Type stopBehavior ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mStopBehavior = stopBehavior; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetStopBehavior: stop behavor = %d [%p]\n", mStopBehavior, this ); @@ -383,7 +333,6 @@ void VectorAnimationTask::SetStopBehavior( DevelImageVisual::StopBehavior::Type void VectorAnimationTask::SetLoopingMode( DevelImageVisual::LoopingMode::Type loopingMode ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mLoopingMode = loopingMode; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetLoopingMode: looping mode = %d [%p]\n", mLoopingMode, this ); @@ -420,48 +369,35 @@ void VectorAnimationTask::Initialize() bool VectorAnimationTask::Rasterize() { - bool stopped = false, needAnimationFinishedTrigger, resourceReady; - uint32_t currentFrame, startFrame, endFrame; - int32_t loopCount, currentLoopCount; - PlayState playState; + bool stopped = false; + uint32_t currentFrame; + + ApplyAnimationData(); + if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); + mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; + Dali::ClampInPlace( mCurrentFrame, mStartFrame, mEndFrame ); + } - if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) - { - mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; - Dali::ClampInPlace( mCurrentFrame, mStartFrame, mEndFrame ); - } + currentFrame = mCurrentFrame; - currentFrame = mCurrentFrame; - startFrame = mStartFrame; - endFrame = mEndFrame; - loopCount = mLoopCount; - currentLoopCount = mCurrentLoop; - needAnimationFinishedTrigger = mNeedAnimationFinishedTrigger; - playState = mPlayState; - resourceReady = mResourceReady; - - mResourceReady = true; - mCurrentFrameUpdated = false; - mCurrentLoopUpdated = false; - mUpdateFrameNumber = true; - mNeedAnimationFinishedTrigger = true; - } + // Reset values + mResourceReady = true; + mUpdateFrameNumber = true; + mNeedAnimationFinishedTrigger = true; - if( playState == PlayState::STOPPING ) + if( mPlayState == PlayState::STOPPING ) { - currentFrame = GetStoppedFrame( startFrame, endFrame, currentFrame ); - ResetValue( mCurrentFrameUpdated, mCurrentFrame, currentFrame, mConditionalWait ); - + mCurrentFrame = GetStoppedFrame( mStartFrame, mEndFrame, mCurrentFrame ); + currentFrame = mCurrentFrame; stopped = true; } - else if( playState == PlayState::PLAYING ) + else if( mPlayState == PlayState::PLAYING ) { bool animationFinished = false; - if( currentFrame >= endFrame ) // last frame + if( currentFrame >= mEndFrame ) // last frame { if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) { @@ -469,21 +405,20 @@ bool VectorAnimationTask::Rasterize() } else { - if( loopCount < 0 || ++currentLoopCount < loopCount ) // repeat forever or before the last loop + if( mLoopCount < 0 || ++mCurrentLoop < mLoopCount ) // repeat forever or before the last loop { - ResetValue( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it. + mCurrentFrame = mStartFrame; mUpdateFrameNumber = false; } else { animationFinished = true; // end of animation } - ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); } } - else if( currentFrame == startFrame && !mForward ) // first frame + else if( currentFrame == mStartFrame && !mForward ) // first frame { - if( loopCount < 0 || ++currentLoopCount < loopCount ) // repeat forever or before the last loop + if( mLoopCount < 0 || ++mCurrentLoop < mLoopCount ) // repeat forever or before the last loop { mForward = true; } @@ -491,7 +426,6 @@ bool VectorAnimationTask::Rasterize() { animationFinished = true; // end of animation } - ResetValue( mCurrentLoopUpdated, mCurrentLoop, currentLoopCount, mConditionalWait ); } if( animationFinished ) @@ -517,9 +451,8 @@ bool VectorAnimationTask::Rasterize() DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Rendering failed. Try again later.[%d] [%p]\n", currentFrame, this ); mUpdateFrameNumber = false; - if( !resourceReady ) + if( !mResourceReady ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); mResourceReady = false; } } @@ -527,23 +460,24 @@ bool VectorAnimationTask::Rasterize() if( stopped && renderSuccess ) { - ConditionalWait::ScopedLock lock( mConditionalWait ); - mPlayState = PlayState::STOPPED; mForward = true; mCurrentLoop = 0; // Animation is finished - if( needAnimationFinishedTrigger && mAnimationFinishedTrigger ) { - mAnimationFinishedTrigger->Trigger(); + ConditionalWait::ScopedLock lock( mConditionalWait ); + if( mNeedAnimationFinishedTrigger && mAnimationFinishedTrigger ) + { + mAnimationFinishedTrigger->Trigger(); + } } DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Animation is finished [current = %d] [%p]\n", currentFrame, this ); } bool keepAnimation = true; - if( playState == PlayState::PAUSED || playState == PlayState::STOPPED ) + if( mPlayState == PlayState::PAUSED || mPlayState == PlayState::STOPPED ) { keepAnimation = false; } @@ -604,6 +538,69 @@ std::chrono::time_point< std::chrono::system_clock > VectorAnimationTask::GetNex return mNextFrameStartTime; } +void VectorAnimationTask::ApplyAnimationData() +{ + uint32_t index; + + { + ConditionalWait::ScopedLock lock( mConditionalWait ); + + if( !mAnimationDataUpdated || mAnimationData[mAnimationDataIndex].resendFlag != 0 ) + { + // Data is not updated or the previous data is not applied yet. + return; + } + + mAnimationDataIndex = mAnimationDataIndex == 0 ? 1 : 0; // Swap index + mAnimationDataUpdated = false; + + index = mAnimationDataIndex; + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_LOOP_COUNT ) + { + SetLoopCount( mAnimationData[index].loopCount ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_RANGE ) + { + SetPlayRange( mAnimationData[index].playRange ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_STOP_BEHAVIOR ) + { + SetStopBehavior( mAnimationData[index].stopBehavior ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_LOOPING_MODE ) + { + SetLoopingMode( mAnimationData[index].loopingMode ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_CURRENT_FRAME ) + { + SetCurrentFrameNumber( mAnimationData[index].currentFrame ); + } + + if( mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE ) + { + if( mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING ) + { + PlayAnimation(); + } + else if( mAnimationData[index].playState == DevelImageVisual::PlayState::PAUSED ) + { + PauseAnimation(); + } + else if( mAnimationData[index].playState == DevelImageVisual::PlayState::STOPPED ) + { + StopAnimation(); + } + } + + mAnimationData[index].resendFlag = 0; +} + } // namespace Internal } // namespace Toolkit 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 index f2e3042..8e91788 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_VECTOR_ANIMATION_TASK_H /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ */ // EXTERNAL INCLUDES +#include #include #include #include @@ -51,6 +52,63 @@ public: using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType; /** + * Flags for re-sending data to the vector animation thread + */ + enum ResendFlags + { + RESEND_PLAY_RANGE = 1 << 0, + RESEND_LOOP_COUNT = 1 << 1, + RESEND_STOP_BEHAVIOR = 1 << 2, + RESEND_LOOPING_MODE = 1 << 3, + RESEND_CURRENT_FRAME = 1 << 4, + RESEND_SIZE = 1 << 5, + RESEND_PLAY_STATE = 1 << 6 + }; + + /** + * @brief Structure used to pass parameters to the vector animation task + */ + struct AnimationData + { + AnimationData() + : resendFlag( 0 ), + playRange(), + playState(), + stopBehavior( DevelImageVisual::StopBehavior::CURRENT_FRAME ), + loopingMode( DevelImageVisual::LoopingMode::RESTART ), + currentFrame( 0 ), + width( 0 ), + height( 0 ), + loopCount( -1 ) + { + } + + AnimationData& operator= ( const AnimationData& rhs ) + { + resendFlag |= rhs.resendFlag; // OR resend flag + playRange = rhs.playRange; + playState = rhs.playState; + stopBehavior = rhs.stopBehavior; + loopingMode = rhs.loopingMode; + currentFrame = rhs.currentFrame; + width = rhs.width; + height = rhs.height; + loopCount = rhs.loopCount; + return *this; + } + + uint32_t resendFlag; + Property::Array playRange; + DevelImageVisual::PlayState::Type playState; + DevelImageVisual::StopBehavior::Type stopBehavior; + DevelImageVisual::LoopingMode::Type loopingMode; + uint32_t currentFrame; + uint32_t width; + uint32_t height; + int32_t loopCount; + }; + + /** * @brief Constructor. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object @@ -76,32 +134,10 @@ public: 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. + * @brief Sets data to specify animation playback. + * @param[in] data The animation data */ - void RenderFrame(); + void SetAnimationData( const AnimationData& data ); /** * @brief This callback is called after the animation is finished. @@ -110,19 +146,6 @@ public: 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] playRange The array to specify minimum and maximum progress. - * The animation will play between those values. - */ - void SetPlayRange( Property::Array& playRange ); - - /** * @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. @@ -130,18 +153,6 @@ public: 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 */ @@ -160,19 +171,6 @@ public: 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 Gets the layer information of all the child layers. * @param[out] map The layer information */ @@ -210,10 +208,70 @@ private: void Initialize(); /** + * @brief Play the vector animation. + */ + void PlayAnimation(); + + /** + * @brief Stop the vector animation. + */ + void StopAnimation(); + + /** + * @brief Pause the vector animation. + */ + void PauseAnimation(); + + /** + * @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 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] playRange The array to specify minimum and maximum progress. + * The animation will play between those values. + */ + void SetPlayRange( const Property::Array& playRange ); + + /** + * @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 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 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 ); + /** + * @brief Applies the animation data set by the main thread. + */ + void ApplyAnimationData(); + // Undefined VectorAnimationTask( const VectorAnimationTask& task ) = delete; @@ -232,10 +290,10 @@ private: std::string mUrl; VectorAnimationRenderer mVectorRenderer; + AnimationData mAnimationData[2]; VectorAnimationThread& mVectorAnimationThread; ConditionalWait mConditionalWait; std::unique_ptr< EventThreadCallback > mAnimationFinishedTrigger; - Vector2 mPlayRange; PlayState mPlayState; DevelImageVisual::StopBehavior::Type mStopBehavior; DevelImageVisual::LoopingMode::Type mLoopingMode; @@ -248,14 +306,14 @@ private: uint32_t mEndFrame; uint32_t mWidth; uint32_t mHeight; + uint32_t mAnimationDataIndex; int32_t mLoopCount; int32_t mCurrentLoop; bool mResourceReady; - bool mCurrentFrameUpdated; - bool mCurrentLoopUpdated; bool mForward; bool mUpdateFrameNumber; bool mNeedAnimationFinishedTrigger; + bool mAnimationDataUpdated; };