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