[dali_2.3.5] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / toolkit-vector-animation-renderer.cpp
1 /*
2  * Copyright (c) 2023 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 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
19 #include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
20 #include <dali/devel-api/threading/mutex.h>
21 #include <dali/public-api/object/base-object.h>
22 #include <dali/public-api/object/property-array.h>
23 #include <toolkit-application.h>
24 #include <toolkit-event-thread-callback.h>
25 #include <toolkit-vector-animation-renderer.h>
26 #include <chrono>
27 #include <memory>
28 #include <thread>
29
30 namespace Dali
31 {
32 namespace Internal
33 {
34 namespace Adaptor
35 {
36 namespace
37 {
38 Dali::Internal::Adaptor::VectorAnimationRenderer* gVectorAnimationRenderer = nullptr;
39 }
40
41 class VectorAnimationRenderer : public Dali::BaseObject
42 {
43 public:
44   VectorAnimationRenderer()
45   : mUrl(),
46     mRenderer(),
47     mWidth(0),
48     mHeight(0),
49     mDefaultWidth(0),
50     mDefaultHeight(0),
51     mTotalFrameNumber(VECTOR_ANIMATION_TOTAL_FRAME_NUMBER),
52     mPreviousFrame(0),
53     mDelayTime(0),
54     mDroppedFrames(0),
55     mFrameRate(60.0f),
56     mTestFrameDrop(false),
57     mNeedDroppedFrames(false),
58     mEventThreadCallback(new EventThreadCallback(MakeCallback(this, &VectorAnimationRenderer::OnTriggered)))
59   {
60     mCount++;
61
62     if(mCount == 2)
63     {
64       mFrameRate = 0.1f;
65     }
66   }
67
68   ~VectorAnimationRenderer()
69   {
70     mCount--;
71   }
72
73   bool Load(const std::string& url)
74   {
75     Dali::Mutex::ScopedLock lock(mMutex);
76     mUrl = url;
77     if(mUrl == "invalid.json")
78     {
79       mLoadFailed = true;
80       return false;
81     }
82     else if(mUrl == "framedrop.json")
83     {
84       // Change total frame number for test
85       mTotalFrameNumber = 200;
86     }
87
88     mDefaultWidth  = 100;
89     mDefaultHeight = 100;
90
91     return true;
92   }
93
94   bool Load(const Dali::Vector<uint8_t>& data)
95   {
96     Dali::Mutex::ScopedLock lock(mMutex);
97
98     mDefaultWidth  = 100;
99     mDefaultHeight = 100;
100
101     return true;
102   }
103
104   void SetRenderer(Dali::Renderer renderer)
105   {
106     mRenderer = renderer;
107   }
108
109   void SetSize(uint32_t width, uint32_t height)
110   {
111     Dali::Mutex::ScopedLock lock(mMutex);
112     mWidth  = width;
113     mHeight = height;
114
115     if(!mLoadFailed)
116     {
117       mNeedTrigger   = true;
118       mResourceReady = false;
119     }
120   }
121
122   bool Render(uint32_t frameNumber)
123   {
124     Dali::Mutex::ScopedLock lock(mMutex);
125     if(mWidth == 0 || mHeight == 0)
126     {
127       return false;
128     }
129
130     if(mTestFrameDrop)
131     {
132       std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int32_t>(mDelayTime)));
133       mTestFrameDrop     = false;
134       mNeedDroppedFrames = true;
135     }
136     else if(mNeedDroppedFrames)
137     {
138       mDroppedFrames     = (frameNumber > mPreviousFrame) ? frameNumber - mPreviousFrame - 1 : frameNumber + (mTotalFrameNumber - mPreviousFrame) - 1;
139       mNeedTrigger       = true;
140       mNeedDroppedFrames = false;
141     }
142
143     if(mDynamicPropertyCallback)
144     {
145       CallbackBase::ExecuteReturn<Property::Value>(*mDynamicPropertyCallback, 0, 0, frameNumber);
146     }
147
148     if(mNeedTrigger)
149     {
150       mEventThreadCallback->Trigger();
151       mNeedTrigger = false;
152     }
153
154     if(frameNumber == 1 && mPreviousFrame != frameNumber)
155     {
156       mPreviousFrame = frameNumber;
157       // For test corverage
158       return false;
159     }
160     mPreviousFrame = frameNumber;
161     return true;
162   }
163
164   uint32_t GetTotalFrameNumber() const
165   {
166     return mTotalFrameNumber;
167   }
168
169   float GetFrameRate() const
170   {
171     return mFrameRate;
172   }
173
174   void GetDefaultSize(uint32_t& width, uint32_t& height) const
175   {
176     width  = mDefaultWidth;
177     height = mDefaultHeight;
178   }
179
180   bool GetMarkerInfo(const std::string& marker, uint32_t& startFrame, uint32_t& endFrame) const
181   {
182     if(marker.compare(VECTOR_ANIMATION_MARKER_NAME_1) == 0)
183     {
184       startFrame = VECTOR_ANIMATION_MARKER_START_FRAME_1;
185       endFrame   = VECTOR_ANIMATION_MARKER_END_FRAME_1;
186     }
187     else if(marker.compare(VECTOR_ANIMATION_MARKER_NAME_2) == 0)
188     {
189       startFrame = VECTOR_ANIMATION_MARKER_START_FRAME_2;
190       endFrame   = VECTOR_ANIMATION_MARKER_END_FRAME_2;
191     }
192     else
193     {
194       return false;
195     }
196     return true;
197   }
198
199   void InvalidateBuffer()
200   {
201     Dali::Mutex::ScopedLock lock(mMutex);
202     if(mResourceReady)
203     {
204       mNeedTrigger   = true;
205       mResourceReady = false;
206     }
207   }
208
209   void AddPropertyValueCallback(const std::string& keyPath, Dali::VectorAnimationRenderer::VectorProperty property, CallbackBase* callback, int32_t id)
210   {
211     mDynamicPropertyCallback = std::unique_ptr<CallbackBase>(callback);
212   }
213
214   void KeepRasterizedBuffer()
215   {
216     Dali::Mutex::ScopedLock lock(mMutex);
217     mEnableFixedCache = true;
218   }
219
220   Dali::VectorAnimationRenderer::UploadCompletedSignalType& UploadCompletedSignal()
221   {
222     return mUploadCompletedSignal;
223   }
224
225   void OnTriggered()
226   {
227     if(!mResourceReady)
228     {
229       mResourceReady = true;
230
231       Dali::TextureSet textureSet = mRenderer.GetTextures();
232       Dali::Texture    texture    = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, mWidth, mHeight);
233       textureSet.SetTexture(0, texture);
234
235       Devel::PixelBuffer pixelBuffer = Devel::PixelBuffer::New(mWidth, mHeight, Pixel::RGBA8888);
236       Dali::PixelData    pixelData   = Devel::PixelBuffer::Convert(pixelBuffer);
237       texture.Upload(pixelData);
238
239       mUploadCompletedSignal.Emit();
240     }
241   }
242
243 public:
244   static uint32_t mCount;
245
246   std::string                   mUrl;
247   Dali::Renderer                mRenderer;
248   Dali::Mutex                   mMutex;
249   std::unique_ptr<CallbackBase> mDynamicPropertyCallback{nullptr};
250
251   uint32_t mWidth;
252   uint32_t mHeight;
253   uint32_t mDefaultWidth;
254   uint32_t mDefaultHeight;
255   uint32_t mTotalFrameNumber;
256   uint32_t mPreviousFrame;
257   uint32_t mDelayTime;
258   uint32_t mDroppedFrames;
259   float    mFrameRate;
260   bool     mTestFrameDrop;
261   bool     mNeedDroppedFrames;
262   bool     mLoadFailed{false};
263   bool     mResourceReady{false};
264   bool     mNeedTrigger{true};
265   bool     mEnableFixedCache{false};
266
267   Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal;
268   std::unique_ptr<EventThreadCallback>                     mEventThreadCallback;
269 };
270
271 uint32_t VectorAnimationRenderer::mCount = 0;
272
273 inline VectorAnimationRenderer& GetImplementation(Dali::VectorAnimationRenderer& renderer)
274 {
275   DALI_ASSERT_ALWAYS(renderer && "VectorAnimationRenderer handle is empty.");
276   BaseObject& handle = renderer.GetBaseObject();
277   return static_cast<Internal::Adaptor::VectorAnimationRenderer&>(handle);
278 }
279
280 inline const VectorAnimationRenderer& GetImplementation(const Dali::VectorAnimationRenderer& renderer)
281 {
282   DALI_ASSERT_ALWAYS(renderer && "VectorAnimationRenderer handle is empty.");
283   const BaseObject& handle = renderer.GetBaseObject();
284   return static_cast<const Internal::Adaptor::VectorAnimationRenderer&>(handle);
285 }
286
287 } // namespace Adaptor
288
289 } // namespace Internal
290
291 /********************************************************************************/
292 /*********************************  PUBLIC CLASS  *******************************/
293 /********************************************************************************/
294
295 VectorAnimationRenderer VectorAnimationRenderer::New()
296 {
297   Internal::Adaptor::VectorAnimationRenderer* animationRenderer = new Internal::Adaptor::VectorAnimationRenderer();
298
299   Internal::Adaptor::gVectorAnimationRenderer = animationRenderer;
300
301   return VectorAnimationRenderer(animationRenderer);
302 }
303
304 VectorAnimationRenderer::VectorAnimationRenderer()
305 {
306 }
307
308 VectorAnimationRenderer::~VectorAnimationRenderer()
309 {
310 }
311
312 VectorAnimationRenderer::VectorAnimationRenderer(Internal::Adaptor::VectorAnimationRenderer* internal)
313 : BaseHandle(internal)
314 {
315 }
316
317 VectorAnimationRenderer::VectorAnimationRenderer(const VectorAnimationRenderer& handle)
318 : BaseHandle(handle)
319 {
320 }
321
322 VectorAnimationRenderer& VectorAnimationRenderer::operator=(const VectorAnimationRenderer& rhs)
323 {
324   BaseHandle::operator=(rhs);
325   return *this;
326 }
327
328 void VectorAnimationRenderer::Finalize()
329 {
330 }
331
332 bool VectorAnimationRenderer::Load(const std::string& url)
333 {
334   return Internal::Adaptor::GetImplementation(*this).Load(url);
335 }
336
337 bool VectorAnimationRenderer::Load(const Dali::Vector<uint8_t>& data)
338 {
339   return Internal::Adaptor::GetImplementation(*this).Load(data);
340 }
341
342 void VectorAnimationRenderer::SetRenderer(Renderer renderer)
343 {
344   Internal::Adaptor::GetImplementation(*this).SetRenderer(renderer);
345 }
346
347 void VectorAnimationRenderer::SetSize(uint32_t width, uint32_t height)
348 {
349   Internal::Adaptor::GetImplementation(*this).SetSize(width, height);
350 }
351
352 bool VectorAnimationRenderer::Render(uint32_t frameNumber)
353 {
354   return Internal::Adaptor::GetImplementation(*this).Render(frameNumber);
355 }
356
357 void VectorAnimationRenderer::RenderStopped()
358 {
359 }
360
361 uint32_t VectorAnimationRenderer::GetTotalFrameNumber() const
362 {
363   return Internal::Adaptor::GetImplementation(*this).GetTotalFrameNumber();
364 }
365
366 float VectorAnimationRenderer::GetFrameRate() const
367 {
368   return Internal::Adaptor::GetImplementation(*this).GetFrameRate();
369 }
370
371 void VectorAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
372 {
373   Internal::Adaptor::GetImplementation(*this).GetDefaultSize(width, height);
374 }
375
376 void VectorAnimationRenderer::GetLayerInfo(Property::Map& map) const
377 {
378 }
379
380 bool VectorAnimationRenderer::GetMarkerInfo(const std::string& marker, uint32_t& startFrame, uint32_t& endFrame) const
381 {
382   return Internal::Adaptor::GetImplementation(*this).GetMarkerInfo(marker, startFrame, endFrame);
383 }
384
385 void VectorAnimationRenderer::GetMarkerInfo(Property::Map& map) const
386 {
387   map.Add(VECTOR_ANIMATION_MARKER_NAME_1, Property::Array({VECTOR_ANIMATION_MARKER_START_FRAME_1, VECTOR_ANIMATION_MARKER_END_FRAME_1}));
388   map.Add(VECTOR_ANIMATION_MARKER_NAME_2, Property::Array({VECTOR_ANIMATION_MARKER_START_FRAME_2, VECTOR_ANIMATION_MARKER_END_FRAME_2}));
389 }
390
391 void VectorAnimationRenderer::InvalidateBuffer()
392 {
393   return Internal::Adaptor::GetImplementation(*this).InvalidateBuffer();
394 }
395
396 void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPath, VectorProperty property, CallbackBase* callback, int32_t id)
397 {
398   Internal::Adaptor::GetImplementation(*this).AddPropertyValueCallback(keyPath, property, callback, id);
399 }
400
401 void VectorAnimationRenderer::KeepRasterizedBuffer()
402 {
403   Internal::Adaptor::GetImplementation(*this).KeepRasterizedBuffer();
404 }
405
406
407 VectorAnimationRenderer::UploadCompletedSignalType& VectorAnimationRenderer::UploadCompletedSignal()
408 {
409   return Internal::Adaptor::GetImplementation(*this).UploadCompletedSignal();
410 }
411
412 } // namespace Dali
413
414 namespace Test
415 {
416 namespace VectorAnimationRenderer
417 {
418 void DelayRendering(uint32_t delay)
419 {
420   Dali::Internal::Adaptor::gVectorAnimationRenderer->mDelayTime     = delay;
421   Dali::Internal::Adaptor::gVectorAnimationRenderer->mTestFrameDrop = true;
422 }
423
424 uint32_t GetDroppedFrames()
425 {
426   return Dali::Internal::Adaptor::gVectorAnimationRenderer->mDroppedFrames;
427 }
428
429 } // namespace VectorAnimationRenderer
430 } // namespace Test