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/devel-api/adaptor-framework/thread-settings.h>
23 #include <dali/integration-api/adaptors/adaptor.h>
24 #include <dali/integration-api/debug.h>
40 constexpr auto LOOP_FOREVER = -1;
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" );
46 } // unnamed namespace
48 VectorRasterizeThread::VectorRasterizeThread( const std::string& url )
53 mResourceReadyTrigger(),
54 mAnimationFinishedTrigger(),
55 mPlayRange( 0.0f, 1.0f ),
56 mPlayState( DevelImageVisual::PlayState::STOPPED ),
64 mLoopCount( LOOP_FOREVER ),
67 mDestroyThread( false ),
68 mResourceReady( false ),
69 mLogFactory( Dali::Adaptor::Get().GetLogFactory() )
71 mVectorRenderer = VectorAnimationRenderer::New( mUrl );
74 VectorRasterizeThread::~VectorRasterizeThread()
78 ConditionalWait::ScopedLock lock( mConditionalWait );
79 mDestroyThread = true;
80 mConditionalWait.Notify( lock );
82 // This should be called in the main thread to stop waiting for the dequeuable buffer.
83 mVectorRenderer.StopRender();
86 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join\n" );
91 void VectorRasterizeThread::Run()
93 SetThreadName( "VectorImageThread" );
94 mLogFactory.InstallLogFunction();
96 //TODO: check the return value
99 while( IsThreadReady() )
105 void VectorRasterizeThread::SetRenderer( Renderer renderer )
107 ConditionalWait::ScopedLock lock( mConditionalWait );
109 mVectorRenderer.SetRenderer( renderer );
111 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer\n" );
114 void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
116 if( mWidth != width || mHeight != height )
118 ConditionalWait::ScopedLock lock( mConditionalWait );
119 mVectorRenderer.SetSize( width, height );
124 mResourceReady = false;
126 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
130 void VectorRasterizeThread::PlayAnimation()
132 ConditionalWait::ScopedLock lock( mConditionalWait );
133 if( mPlayState != DevelImageVisual::PlayState::PLAYING )
135 mPlayState = DevelImageVisual::PlayState::PLAYING;
136 mConditionalWait.Notify( lock );
138 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Start\n" );
142 void VectorRasterizeThread::StopAnimation()
144 ConditionalWait::ScopedLock lock( mConditionalWait );
145 if( mPlayState != DevelImageVisual::PlayState::STOPPED )
147 mPlayState = DevelImageVisual::PlayState::STOPPED;
149 // Reset the current frame and the current loop
150 mCurrentFrame = mStartFrame;
153 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" );
157 void VectorRasterizeThread::PauseAnimation()
159 ConditionalWait::ScopedLock lock( mConditionalWait );
160 if( mPlayState == DevelImageVisual::PlayState::PLAYING )
162 mPlayState = DevelImageVisual::PlayState::PAUSED;
164 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" );
168 void VectorRasterizeThread::RenderFrame()
170 ConditionalWait::ScopedLock lock( mConditionalWait );
172 if( !mResourceReady )
175 mConditionalWait.Notify( lock );
177 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" );
181 void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback )
183 ConditionalWait::ScopedLock lock( mConditionalWait );
184 mResourceReadyTrigger = std::unique_ptr< EventThreadCallback >( callback );
187 void VectorRasterizeThread::SetAnimationFinishedCallback( EventThreadCallback* callback )
189 ConditionalWait::ScopedLock lock( mConditionalWait );
190 mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback );
193 void VectorRasterizeThread::SetLoopCount( int32_t count )
195 if( mLoopCount != count )
197 ConditionalWait::ScopedLock lock( mConditionalWait );
206 int32_t VectorRasterizeThread::GetLoopCount() const
211 void VectorRasterizeThread::SetPlayRange( Vector2 range )
213 // Make sure the range specified is between 0.0 and 1.0
214 if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
216 Vector2 orderedRange( range );
217 // If the range is not in order swap values
218 if( range.x > range.y )
220 orderedRange = Vector2( range.y, range.x );
223 if( mPlayRange != orderedRange )
225 ConditionalWait::ScopedLock lock( mConditionalWait );
227 mPlayRange = orderedRange;
229 if( mTotalFrame != 0 )
231 mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
232 mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
234 // If the current frame is out of the range, change the current frame also.
235 if( mStartFrame > mCurrentFrame )
237 mCurrentFrame = mStartFrame;
239 mResourceReady = false;
241 else if( mEndFrame < mCurrentFrame )
243 mCurrentFrame = mEndFrame;
245 mResourceReady = false;
252 Vector2 VectorRasterizeThread::GetPlayRange() const
257 void VectorRasterizeThread::SetCurrentProgress( float progress )
259 ConditionalWait::ScopedLock lock( mConditionalWait );
261 if( progress >= mPlayRange.x && progress <= mPlayRange.y )
263 mProgress = progress;
265 if( mTotalFrame != 0 )
267 mCurrentFrame = static_cast< uint32_t >( mTotalFrame * progress + 0.5f );
270 mResourceReady = false;
272 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentProgress: progress = %f (%d)\n", progress, mCurrentFrame );
276 float VectorRasterizeThread::GetCurrentProgress() const
278 return ( static_cast< float >( mCurrentFrame ) / static_cast< float >( mTotalFrame ) );
281 DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() const
286 bool VectorRasterizeThread::IsResourceReady() const
288 return mResourceReady;
291 bool VectorRasterizeThread::IsThreadReady()
293 ConditionalWait::ScopedLock lock( mConditionalWait );
295 if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread )
297 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" );
299 mConditionalWait.Wait( lock );
302 // Keep the thread alive if this thread is NOT to be destroyed
303 return !mDestroyThread;
306 bool VectorRasterizeThread::StartRender()
308 //TODO: check the return value
309 mVectorRenderer.StartRender();
311 mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
313 mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
314 mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
316 mCurrentFrame = std::max( static_cast< uint32_t >( mTotalFrame * mProgress + 0.5f ), mStartFrame );
318 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame );
323 void VectorRasterizeThread::Rasterize()
325 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [%d]\n", mCurrentFrame );
327 bool needRender, resourceReady;
330 ConditionalWait::ScopedLock lock( mConditionalWait );
331 needRender = mNeedRender;
332 resourceReady = mResourceReady;
336 mVectorRenderer.Render( mCurrentFrame );
338 if( mPlayState == DevelImageVisual::PlayState::PLAYING )
340 if( ++mCurrentFrame >= mEndFrame )
345 mCurrentFrame = mStartFrame;
350 if( mCurrentLoop >= mLoopCount )
352 // Animation is finished
353 mPlayState = DevelImageVisual::PlayState::STOPPED;
355 // Reset the current frame and the current loop
356 mCurrentFrame = mStartFrame;
359 mAnimationFinishedTrigger->Trigger();
361 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" );
365 mCurrentFrame = mStartFrame;
378 DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" );
380 mResourceReadyTrigger->Trigger();
381 mResourceReady = true;
385 } // namespace Internal
387 } // namespace Toolkit