Merge "Add the logical key to Integration::KeyEvent" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-vector-image / vector-rasterize-thread.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h>
20
21 // EXTERNAL INCLUDES
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>
25
26 // INTERNAL INCLUDES
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 constexpr auto LOOP_FOREVER = -1;
41
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" );
44 #endif
45
46 } // unnamed namespace
47
48 VectorRasterizeThread::VectorRasterizeThread( const std::string& url, Renderer renderer, uint32_t width, uint32_t height )
49 : mUrl( url ),
50   mVectorRenderer(),
51   mConditionalWait(),
52   mMutex(),
53   mResourceReadyTrigger(),
54   mAnimationFinishedTrigger(),
55   mPlayRange( 0.0f, 1.0f ),
56   mPlayState( DevelImageVisual::PlayState::STOPPED ),
57   mCurrentFrame( 0 ),
58   mTotalFrame( 0 ),
59   mStartFrame( 0 ),
60   mEndFrame( 0 ),
61   mWidth( width ),
62   mHeight( height ),
63   mLoopCount( LOOP_FOREVER ),
64   mCurrentLoop( 0 ),
65   mNeedRender( false ),
66   mDestroyThread( false ),
67   mResourceReady( false ),
68   mLogFactory( Dali::Adaptor::Get().GetLogFactory() )
69 {
70   mVectorRenderer = VectorAnimationRenderer::New( mUrl, renderer, width, height );
71 }
72
73 VectorRasterizeThread::~VectorRasterizeThread()
74 {
75   // Stop the thread
76   {
77     ConditionalWait::ScopedLock lock( mConditionalWait );
78     mDestroyThread = true;
79     mConditionalWait.Notify( lock );
80
81     // This should be called in the main thread to stop waiting for the dequeuable buffer.
82     mVectorRenderer.StopRender();
83   }
84
85   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join\n" );
86
87   Join();
88 }
89
90 void VectorRasterizeThread::Run()
91 {
92   SetThreadName( "VectorImageThread" );
93   mLogFactory.InstallLogFunction();
94
95   //TODO: check the return value
96   StartRender();
97
98   while( IsThreadReady() )
99   {
100     Rasterize();
101   }
102 }
103
104 void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
105 {
106   ConditionalWait::ScopedLock lock( mConditionalWait );
107   mVectorRenderer.SetSize( width, height );
108
109   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
110 }
111
112 void VectorRasterizeThread::StartAnimation()
113 {
114   ConditionalWait::ScopedLock lock( mConditionalWait );
115   if( mPlayState != DevelImageVisual::PlayState::PLAYING )
116   {
117     if( mPlayState == DevelImageVisual::PlayState::STOPPED )
118     {
119       // Reset the current frame and the current loop
120       mCurrentFrame = mStartFrame;
121       mCurrentLoop = 0;
122     }
123
124     mPlayState = DevelImageVisual::PlayState::PLAYING;
125     mConditionalWait.Notify( lock );
126
127     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartAnimation: Start\n" );
128   }
129 }
130
131 void VectorRasterizeThread::StopAnimation()
132 {
133   ConditionalWait::ScopedLock lock( mConditionalWait );
134   if( mPlayState != DevelImageVisual::PlayState::STOPPED )
135   {
136     mPlayState = DevelImageVisual::PlayState::STOPPED;
137
138     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" );
139   }
140 }
141
142 void VectorRasterizeThread::PauseAnimation()
143 {
144   ConditionalWait::ScopedLock lock( mConditionalWait );
145   if( mPlayState == DevelImageVisual::PlayState::PLAYING )
146   {
147     mPlayState = DevelImageVisual::PlayState::PAUSED;
148
149     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" );
150   }
151 }
152
153 void VectorRasterizeThread::RenderFrame()
154 {
155   ConditionalWait::ScopedLock lock( mConditionalWait );
156   mNeedRender = true;
157   mConditionalWait.Notify( lock );
158
159   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" );
160 }
161
162 void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback )
163 {
164   ConditionalWait::ScopedLock lock( mConditionalWait );
165   mResourceReadyTrigger = std::unique_ptr< EventThreadCallback >( callback );
166 }
167
168 void VectorRasterizeThread::SetAnimationFinishedCallback( EventThreadCallback* callback )
169 {
170   ConditionalWait::ScopedLock lock( mConditionalWait );
171   mAnimationFinishedTrigger = std::unique_ptr< EventThreadCallback >( callback );
172 }
173
174 void VectorRasterizeThread::SetLoopCount( int16_t count )
175 {
176   ConditionalWait::ScopedLock lock( mConditionalWait );
177
178   mLoopCount = count;
179
180   // Reset progress
181   mCurrentLoop = 0;
182   mCurrentFrame = mStartFrame;
183 }
184
185 void VectorRasterizeThread::SetPlayRange( Vector2 range )
186 {
187   ConditionalWait::ScopedLock lock( mConditionalWait );
188
189   mPlayRange = range;
190
191   if( mTotalFrame != 0 )
192   {
193     mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
194     mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
195   }
196 }
197
198 DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState()
199 {
200   return mPlayState;
201 }
202
203 bool VectorRasterizeThread::IsThreadReady()
204 {
205   ConditionalWait::ScopedLock lock( mConditionalWait );
206
207   if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread )
208   {
209     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" );
210
211     mConditionalWait.Wait( lock );
212   }
213
214   // Keep the thread alive if this thread is NOT to be destroyed
215   return !mDestroyThread;
216 }
217
218 bool VectorRasterizeThread::StartRender()
219 {
220   //TODO: check the return value
221   mVectorRenderer.StartRender();
222
223   mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
224
225   mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
226   mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
227
228   mCurrentFrame = mStartFrame;
229
230   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame );
231
232   return true;
233 }
234
235 void VectorRasterizeThread::Rasterize()
236 {
237   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [%d]\n", mCurrentFrame );
238
239   // Rasterize
240   mVectorRenderer.Render( mCurrentFrame );
241
242   if( mPlayState == DevelImageVisual::PlayState::PLAYING )
243   {
244     if( ++mCurrentFrame >= mEndFrame )
245     {
246       if( mLoopCount < 0 )
247       {
248         // repeat forever
249         mCurrentFrame = mStartFrame;
250       }
251       else
252       {
253         mCurrentLoop++;
254         if( mCurrentLoop >= mLoopCount )
255         {
256           // Animation is finished
257           mPlayState = DevelImageVisual::PlayState::STOPPED;
258
259           mAnimationFinishedTrigger->Trigger();
260
261           DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" );
262         }
263         else
264         {
265           mCurrentFrame = mStartFrame;
266         }
267       }
268     }
269   }
270
271   mNeedRender = false;
272
273   if( !mResourceReady )
274   {
275     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" );
276
277     mResourceReadyTrigger->Trigger();
278     mResourceReady = true;
279   }
280 }
281
282 } // namespace Internal
283
284 } // namespace Toolkit
285
286 } // namespace Dali