[dali_1.3.54] Merge branch '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( NULL ),
54   mPlayRange( 0.0f, 1.0f ),
55   mCurrentFrame( 0 ),
56   mTotalFrame( 0 ),
57   mStartFrame( 0 ),
58   mEndFrame( 0 ),
59   mWidth( width ),
60   mHeight( height ),
61   mLoopCount( LOOP_FOREVER ),
62   mCurrentLoop( 0 ),
63   mNeedRender( false ),
64   mPlaying( false ),
65   mPaused( 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   delete mResourceReadyTrigger;
90 }
91
92 void VectorRasterizeThread::Run()
93 {
94   SetThreadName( "VectorImageThread" );
95   mLogFactory.InstallLogFunction();
96
97   //TODO: check the return value
98   StartRender();
99
100   while( IsThreadReady() )
101   {
102     Rasterize();
103   }
104 }
105
106 void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height )
107 {
108   ConditionalWait::ScopedLock lock( mConditionalWait );
109   mVectorRenderer.SetSize( width, height );
110
111   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height );
112 }
113
114 void VectorRasterizeThread::StartAnimation()
115 {
116   ConditionalWait::ScopedLock lock( mConditionalWait );
117   if( !mPlaying )
118   {
119     mPlaying = true;
120     mPaused = false;
121     mConditionalWait.Notify( lock );
122
123     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartAnimation: Start\n" );
124   }
125 }
126
127 void VectorRasterizeThread::StopAnimation()
128 {
129   ConditionalWait::ScopedLock lock( mConditionalWait );
130   if( mPlaying )
131   {
132     mPlaying = false;
133     mPaused = false;
134
135     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" );
136   }
137 }
138
139 void VectorRasterizeThread::PauseAnimation()
140 {
141   ConditionalWait::ScopedLock lock( mConditionalWait );
142   if( mPlaying && !mPaused )
143   {
144     mPaused = true;
145
146     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" );
147   }
148 }
149
150 void VectorRasterizeThread::ResumeAnimation()
151 {
152   ConditionalWait::ScopedLock lock( mConditionalWait );
153   if( mPlaying && mPaused )
154   {
155     mPaused = false;
156     mConditionalWait.Notify( lock );
157
158     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::ResumeAnimation: Resume\n" );
159   }
160 }
161
162 void VectorRasterizeThread::RenderFrame()
163 {
164   ConditionalWait::ScopedLock lock( mConditionalWait );
165   mNeedRender = true;
166   mConditionalWait.Notify( lock );
167
168   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" );
169 }
170
171 void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callback )
172 {
173   ConditionalWait::ScopedLock lock( mConditionalWait );
174   mResourceReadyTrigger = callback;
175 }
176
177 void VectorRasterizeThread::SetLoopCount( int16_t count )
178 {
179   ConditionalWait::ScopedLock lock( mConditionalWait );
180
181   mLoopCount = count;
182
183   // Reset progress
184   mCurrentLoop = 0;
185   mCurrentFrame = mStartFrame;
186 }
187
188 void VectorRasterizeThread::SetPlayRange( Vector2 range )
189 {
190   ConditionalWait::ScopedLock lock( mConditionalWait );
191
192   mPlayRange = range;
193
194   if( mTotalFrame != 0 )
195   {
196     mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
197     mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
198   }
199 }
200
201 bool VectorRasterizeThread::IsThreadReady()
202 {
203   ConditionalWait::ScopedLock lock( mConditionalWait );
204
205   if( ( !mPlaying || mPaused ) && !mNeedRender && !mDestroyThread )
206   {
207     DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" );
208
209     if( !mPlaying )
210     {
211       mCurrentFrame = mStartFrame;
212       mCurrentLoop = 0;
213     }
214
215     mConditionalWait.Wait( lock );
216   }
217
218   // Keep the thread alive if this thread is NOT to be destroyed
219   return !mDestroyThread;
220 }
221
222 bool VectorRasterizeThread::StartRender()
223 {
224   //TODO: check the return value
225   mVectorRenderer.StartRender();
226
227   mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
228
229   mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f );
230   mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f );
231
232   mCurrentFrame = mStartFrame;
233
234   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame );
235
236   return true;
237 }
238
239 void VectorRasterizeThread::Rasterize()
240 {
241   DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [%d]\n", mCurrentFrame );
242
243   // Rasterize
244   mVectorRenderer.Render( mCurrentFrame );
245
246   if( mPlaying && !mPaused )
247   {
248     if( ++mCurrentFrame >= mEndFrame )
249     {
250       if( mLoopCount < 0 )
251       {
252         // repeat forever
253         mCurrentFrame = mStartFrame;
254       }
255       else
256       {
257         mCurrentLoop++;
258         if( mCurrentLoop >= mLoopCount )
259         {
260           // Animation is finished
261           mPlaying = false;
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