2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
22 #include <dali/integration-api/adaptors/adaptor.h>
23 #include <dali/integration-api/debug.h>
39 constexpr auto LOOP_FOREVER = -1;
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" );
45 } // unnamed namespace
47 VectorRasterizeThread::VectorRasterizeThread( const std::string& url )
52 mResourceReadyTrigger(),
53 mAnimationFinishedTrigger(),
54 mPlayRange( 0.0f, 1.0f ),
55 mPlayState( DevelImageVisual::PlayState::STOPPED ),
63 mLoopCount( LOOP_FOREVER ),
66 mDestroyThread( false ),
67 mResourceReady( false ),
68 mLogFactory( Dali::Adaptor::Get().GetLogFactory() )
70 mVectorRenderer = VectorAnimationRenderer::New( mUrl );
73 VectorRasterizeThread::~VectorRasterizeThread()
77 ConditionalWait::ScopedLock lock( mConditionalWait );
78 mDestroyThread = true;
79 mConditionalWait.Notify( lock );
81 // This should be called in the main thread to stop waiting for the dequeuable buffer.
82 mVectorRenderer.StopRender();
85 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join\n" );
90 void VectorRasterizeThread::Run()
92 mLogFactory.InstallLogFunction();
94 //TODO: check the return value
97 while( IsThreadReady() )
103 void VectorRasterizeThread::SetRenderer( Renderer renderer )
105 ConditionalWait::ScopedLock lock( mConditionalWait );
107 mVectorRenderer.SetRenderer( renderer );
109 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer\n" );
112 void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
114 if( mWidth != width || mHeight != height )
116 ConditionalWait::ScopedLock lock( mConditionalWait );
117 mVectorRenderer.SetSize( width, height );
122 mResourceReady = false;
124 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
128 void VectorRasterizeThread::PlayAnimation()
130 ConditionalWait::ScopedLock lock( mConditionalWait );
131 if( mPlayState != DevelImageVisual::PlayState::PLAYING )
133 mPlayState = DevelImageVisual::PlayState::PLAYING;
134 mConditionalWait.Notify( lock );
136 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Start\n" );
140 void VectorRasterizeThread::StopAnimation()
142 ConditionalWait::ScopedLock lock( mConditionalWait );
143 if( mPlayState != DevelImageVisual::PlayState::STOPPED )
145 mPlayState = DevelImageVisual::PlayState::STOPPED;
147 // Reset the current frame and the current loop
148 mCurrentFrame = mStartFrame;
151 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" );
155 void VectorRasterizeThread::PauseAnimation()
157 ConditionalWait::ScopedLock lock( mConditionalWait );
158 if( mPlayState == DevelImageVisual::PlayState::PLAYING )
160 mPlayState = DevelImageVisual::PlayState::PAUSED;
162 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" );
166 void VectorRasterizeThread::RenderFrame()
168 ConditionalWait::ScopedLock lock( mConditionalWait );
170 if( !mResourceReady )
173 mConditionalWait.Notify( lock );
175 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" );
179 void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback )
181 ConditionalWait::ScopedLock lock( mConditionalWait );
182 mResourceReadyTrigger = std::unique_ptr< EventThreadCallback >( callback );
185 void VectorRasterizeThread::SetAnimationFinishedCallback( EventThreadCallback* callback )
187 ConditionalWait::ScopedLock lock( mConditionalWait );
188 mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback );
191 void VectorRasterizeThread::SetLoopCount( int32_t count )
193 if( mLoopCount != count )
195 ConditionalWait::ScopedLock lock( mConditionalWait );
204 int32_t VectorRasterizeThread::GetLoopCount() const
209 void VectorRasterizeThread::SetPlayRange( Vector2 range )
211 // Make sure the range specified is between 0.0 and 1.0
212 if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
214 Vector2 orderedRange( range );
215 // If the range is not in order swap values
216 if( range.x > range.y )
218 orderedRange = Vector2( range.y, range.x );
221 if( mPlayRange != orderedRange )
223 ConditionalWait::ScopedLock lock( mConditionalWait );
225 mPlayRange = orderedRange;
227 if( mTotalFrame != 0 )
229 mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
230 mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
232 // If the current frame is out of the range, change the current frame also.
233 if( mStartFrame > mCurrentFrame )
235 mCurrentFrame = mStartFrame;
237 mResourceReady = false;
239 else if( mEndFrame < mCurrentFrame )
241 mCurrentFrame = mEndFrame;
243 mResourceReady = false;
250 Vector2 VectorRasterizeThread::GetPlayRange() const
255 void VectorRasterizeThread::SetCurrentProgress( float progress )
257 ConditionalWait::ScopedLock lock( mConditionalWait );
259 if( progress >= mPlayRange.x && progress <= mPlayRange.y )
261 mProgress = progress;
263 if( mTotalFrame != 0 )
265 mCurrentFrame = static_cast< uint32_t >( mTotalFrame * progress + 0.5f );
268 mResourceReady = false;
270 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentProgress: progress = %f (%d)\n", progress, mCurrentFrame );
274 float VectorRasterizeThread::GetCurrentProgress() const
276 return ( static_cast< float >( mCurrentFrame ) / static_cast< float >( mTotalFrame ) );
279 DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() const
284 bool VectorRasterizeThread::IsResourceReady() const
286 return mResourceReady;
289 bool VectorRasterizeThread::IsThreadReady()
291 ConditionalWait::ScopedLock lock( mConditionalWait );
293 if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread )
295 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" );
297 mConditionalWait.Wait( lock );
300 // Keep the thread alive if this thread is NOT to be destroyed
301 return !mDestroyThread;
304 bool VectorRasterizeThread::StartRender()
306 //TODO: check the return value
307 mVectorRenderer.StartRender();
309 mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
311 mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
312 mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
314 mCurrentFrame = std::max( static_cast< uint32_t >( mTotalFrame * mProgress + 0.5f ), mStartFrame );
316 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame );
321 void VectorRasterizeThread::Rasterize()
323 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [%d]\n", mCurrentFrame );
325 bool needRender, resourceReady;
328 ConditionalWait::ScopedLock lock( mConditionalWait );
329 needRender = mNeedRender;
330 resourceReady = mResourceReady;
334 mVectorRenderer.Render( mCurrentFrame );
336 if( mPlayState == DevelImageVisual::PlayState::PLAYING )
338 if( ++mCurrentFrame >= mEndFrame )
343 mCurrentFrame = mStartFrame;
348 if( mCurrentLoop >= mLoopCount )
350 // Animation is finished
351 mPlayState = DevelImageVisual::PlayState::STOPPED;
353 // Reset the current frame and the current loop
354 mCurrentFrame = mStartFrame;
357 mAnimationFinishedTrigger->Trigger();
359 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" );
363 mCurrentFrame = mStartFrame;
376 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" );
378 mResourceReadyTrigger->Trigger();
379 mResourceReady = true;
383 } // namespace Internal
385 } // namespace Toolkit