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