[Tizen] Clear previous textures when event triggered
[platform/core/uifw/dali-extension.git] / dali-extension / vector-animation-renderer / 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 // CLASS HEADER
19 #include <dali-extension/vector-animation-renderer/vector-animation-renderer.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/common/hash.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/integration-api/texture-integ.h>
25 #include <dali/public-api/object/property-array.h>
26
27 #include <cstring> // for strlen()
28
29 // INTERNAL INCLUDES
30 #include <dali-extension/vector-animation-renderer/vector-animation-plugin-manager.h>
31
32 namespace Dali
33 {
34 namespace Plugin
35 {
36 namespace
37 {
38 const char* const PIXEL_AREA_UNIFORM_NAME("pixelArea");
39 const Vector4     FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
40
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION");
43 #endif
44 } // unnamed namespace
45
46 VectorAnimationRenderer::VectorAnimationRenderer()
47 : mUrl(),
48   mMutex(),
49   mRenderer(),
50   mTexture(),
51   mVectorRenderer(),
52   mUploadCompletedSignal(),
53   mTotalFrameNumber(0),
54   mWidth(0),
55   mHeight(0),
56   mDefaultWidth(0),
57   mDefaultHeight(0),
58   mFrameRate(60.0f),
59   mLoadFailed(false),
60   mResourceReady(false),
61   mShaderChanged(false),
62   mResourceReadyTriggered(false),
63   mEnableFixedCache(false)
64 {
65   VectorAnimationPluginManager::Get().AddEventHandler(*this);
66 }
67
68 VectorAnimationRenderer::~VectorAnimationRenderer()
69 {
70 }
71
72 void VectorAnimationRenderer::Finalize()
73 {
74   Dali::Mutex::ScopedLock lock(mMutex);
75
76   VectorAnimationPluginManager::Get().RemoveEventHandler(*this);
77
78   mRenderer.Reset();
79   mTexture.Reset();
80   mVectorRenderer.reset();
81   mPropertyCallbacks.clear();
82
83   OnFinalize();
84
85   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "[%p]\n", this);
86 }
87
88 bool VectorAnimationRenderer::Load(const std::string& url)
89 {
90   Dali::Mutex::ScopedLock lock(mMutex);
91
92   mUrl = url;
93
94   mVectorRenderer = rlottie::Animation::loadFromFile(mUrl);
95   if(!mVectorRenderer)
96   {
97     DALI_LOG_ERROR("Failed to load a Lottie file [%s] [%p]\n", mUrl.c_str(), this);
98     mLoadFailed = true;
99     return false;
100   }
101
102   mTotalFrameNumber = static_cast<uint32_t>(mVectorRenderer->totalFrame());
103   mFrameRate        = static_cast<float>(mVectorRenderer->frameRate());
104
105   size_t w, h;
106   mVectorRenderer->size(w, h);
107   mDefaultWidth  = static_cast<uint32_t>(w);
108   mDefaultHeight = static_cast<uint32_t>(h);
109
110   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "file [%s] [%p]\n", url.c_str(), this);
111
112   return true;
113 }
114
115 bool VectorAnimationRenderer::Load(const Dali::Vector<uint8_t>& data)
116 {
117   Dali::Mutex::ScopedLock lock(mMutex);
118
119   std::string jsonData(data.Begin(), data.End());    ///< Convert from raw buffer to string.
120   auto        hashValue = Dali::CalculateHash(data); ///< Will be used for rlottie internal cache system.
121
122   mVectorRenderer = rlottie::Animation::loadFromData(std::move(jsonData), std::to_string(hashValue));
123   if(!mVectorRenderer)
124   {
125     DALI_LOG_ERROR("Failed to load a Lottie data [data size : %zu byte] [%p]\n", data.Size(), this);
126     mLoadFailed = true;
127     return false;
128   }
129
130   mTotalFrameNumber = static_cast<uint32_t>(mVectorRenderer->totalFrame());
131   mFrameRate        = static_cast<float>(mVectorRenderer->frameRate());
132
133   size_t w, h;
134   mVectorRenderer->size(w, h);
135   mDefaultWidth  = static_cast<uint32_t>(w);
136   mDefaultHeight = static_cast<uint32_t>(h);
137
138   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "data [data size : %zu byte] [%p]\n", data.Size(), this);
139
140   return true;
141 }
142
143 void VectorAnimationRenderer::SetRenderer(Renderer renderer)
144 {
145   mRenderer      = renderer;
146   mShaderChanged = false;
147
148   if(IsTargetPrepared())
149   {
150     Dali::Mutex::ScopedLock lock(mMutex);
151
152     if(IsRenderReady())
153     {
154       TextureSet textureSet = renderer.GetTextures();
155
156       textureSet.SetTexture(0, GetTargetTexture());
157
158       mUploadCompletedSignal.Emit();
159     }
160
161     SetShader();
162   }
163 }
164
165 void VectorAnimationRenderer::SetSize(uint32_t width, uint32_t height)
166 {
167   Dali::Mutex::ScopedLock lock(mMutex);
168
169   if(mWidth == width && mHeight == height)
170   {
171     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Same size (%d, %d) [%p]\n", mWidth, mHeight, this);
172     return;
173   }
174
175   if(mLoadFailed)
176   {
177     DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Load is failed. Do not make texture [%p]\n", this);
178     return;
179   }
180
181   mWidth  = width;
182   mHeight = height;
183
184   PrepareTarget();
185
186   if(mRenderer)
187   {
188     SetShader();
189   }
190
191   mResourceReady = false;
192
193   OnSetSize();
194
195   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "width = %d, height = %d [%p]\n", mWidth, mHeight, this);
196 }
197
198 uint32_t VectorAnimationRenderer::GetTotalFrameNumber() const
199 {
200   return mTotalFrameNumber;
201 }
202
203 float VectorAnimationRenderer::GetFrameRate() const
204 {
205   return mFrameRate;
206 }
207
208 void VectorAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
209 {
210   width  = mDefaultWidth;
211   height = mDefaultHeight;
212 }
213
214 void VectorAnimationRenderer::GetLayerInfo(Property::Map& map) const
215 {
216   Dali::Mutex::ScopedLock lock(mMutex);
217
218   if(mVectorRenderer)
219   {
220     auto layerInfo = mVectorRenderer->layers();
221
222     for(auto&& iter : layerInfo)
223     {
224       Property::Array frames;
225       frames.PushBack(std::get<1>(iter));
226       frames.PushBack(std::get<2>(iter));
227       map.Add(std::get<0>(iter), frames);
228     }
229   }
230 }
231
232 bool VectorAnimationRenderer::GetMarkerInfo(const std::string& marker, uint32_t& startFrame, uint32_t& endFrame) const
233 {
234   Dali::Mutex::ScopedLock lock(mMutex);
235
236   if(mVectorRenderer)
237   {
238     auto markerList = mVectorRenderer->markers();
239     for(auto&& iter : markerList)
240     {
241       if(std::get<0>(iter).compare(marker) == 0)
242       {
243         startFrame = static_cast<uint32_t>(std::get<1>(iter));
244         endFrame   = static_cast<uint32_t>(std::get<2>(iter));
245         return true;
246       }
247     }
248   }
249   return false;
250 }
251
252 void VectorAnimationRenderer::GetMarkerInfo(Property::Map& map) const
253 {
254   Dali::Mutex::ScopedLock lock(mMutex);
255
256   if(mVectorRenderer)
257   {
258     auto markerList = mVectorRenderer->markers();
259     for(auto&& iter : markerList)
260     {
261       Property::Array frames;
262       frames.PushBack(std::get<1>(iter));
263       frames.PushBack(std::get<2>(iter));
264       map.Add(std::get<0>(iter), frames);
265     }
266   }
267 }
268
269 void VectorAnimationRenderer::InvalidateBuffer()
270 {
271   Dali::Mutex::ScopedLock lock(mMutex);
272   mResourceReady = false;
273 }
274
275 void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPath, VectorProperty property, CallbackBase* callback, int32_t id)
276 {
277   Dali::Mutex::ScopedLock lock(mMutex);
278
279   mPropertyCallbacks.push_back(std::unique_ptr<CallbackBase>(callback));
280
281   switch(property)
282   {
283     case VectorProperty::FILL_COLOR:
284     {
285       mVectorRenderer->setValue<rlottie::Property::FillColor>(keyPath,
286                                                               [property, callback, id](const rlottie::FrameInfo& info) {
287                                                                 Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
288                                                                 Vector3         color;
289                                                                 if(value.Get(color))
290                                                                 {
291                                                                   return rlottie::Color(color.r, color.g, color.b);
292                                                                 }
293                                                                 return rlottie::Color(1.0f, 1.0f, 1.0f);
294                                                               });
295       break;
296     }
297     case VectorProperty::FILL_OPACITY:
298     {
299       mVectorRenderer->setValue<rlottie::Property::FillOpacity>(keyPath,
300                                                                 [property, callback, id](const rlottie::FrameInfo& info) {
301                                                                   Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
302                                                                   float           opacity;
303                                                                   if(value.Get(opacity))
304                                                                   {
305                                                                     return opacity * 100;
306                                                                   }
307                                                                   return 100.0f;
308                                                                 });
309       break;
310     }
311     case VectorProperty::STROKE_COLOR:
312     {
313       mVectorRenderer->setValue<rlottie::Property::StrokeColor>(keyPath,
314                                                                 [property, callback, id](const rlottie::FrameInfo& info) {
315                                                                   Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
316                                                                   Vector3         color;
317                                                                   if(value.Get(color))
318                                                                   {
319                                                                     return rlottie::Color(color.r, color.g, color.b);
320                                                                   }
321                                                                   return rlottie::Color(1.0f, 1.0f, 1.0f);
322                                                                 });
323       break;
324     }
325     case VectorProperty::STROKE_OPACITY:
326     {
327       mVectorRenderer->setValue<rlottie::Property::StrokeOpacity>(keyPath,
328                                                                   [property, callback, id](const rlottie::FrameInfo& info) {
329                                                                     Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
330                                                                     float           opacity;
331                                                                     if(value.Get(opacity))
332                                                                     {
333                                                                       return opacity * 100;
334                                                                     }
335                                                                     return 100.0f;
336                                                                   });
337       break;
338     }
339     case VectorProperty::STROKE_WIDTH:
340     {
341       mVectorRenderer->setValue<rlottie::Property::StrokeWidth>(keyPath,
342                                                                 [property, callback, id](const rlottie::FrameInfo& info) {
343                                                                   Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
344                                                                   float           width;
345                                                                   if(value.Get(width))
346                                                                   {
347                                                                     return width;
348                                                                   }
349                                                                   return 1.0f;
350                                                                 });
351       break;
352     }
353     case VectorProperty::TRANSFORM_ANCHOR:
354     {
355       mVectorRenderer->setValue<rlottie::Property::TrAnchor>(keyPath,
356                                                              [property, callback, id](const rlottie::FrameInfo& info) {
357                                                                Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
358                                                                Vector2         point;
359                                                                if(value.Get(point))
360                                                                {
361                                                                  return rlottie::Point(point.x, point.y);
362                                                                }
363                                                                return rlottie::Point(0.0f, 0.0f);
364                                                              });
365       break;
366     }
367     case VectorProperty::TRANSFORM_POSITION:
368     {
369       mVectorRenderer->setValue<rlottie::Property::TrPosition>(keyPath,
370                                                                [property, callback, id](const rlottie::FrameInfo& info) {
371                                                                  Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
372                                                                  Vector2         position;
373                                                                  if(value.Get(position))
374                                                                  {
375                                                                    return rlottie::Point(position.x, position.y);
376                                                                  }
377                                                                  return rlottie::Point(0.0f, 0.0f);
378                                                                });
379       break;
380     }
381     case VectorProperty::TRANSFORM_SCALE:
382     {
383       mVectorRenderer->setValue<rlottie::Property::TrScale>(keyPath,
384                                                             [property, callback, id](const rlottie::FrameInfo& info) {
385                                                               Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
386                                                               Vector2         scale;
387                                                               if(value.Get(scale))
388                                                               {
389                                                                 return rlottie::Size(scale.x, scale.y);
390                                                               }
391                                                               return rlottie::Size(100.0f, 100.0f);
392                                                             });
393       break;
394     }
395     case VectorProperty::TRANSFORM_ROTATION:
396     {
397       mVectorRenderer->setValue<rlottie::Property::TrRotation>(keyPath,
398                                                                [property, callback, id](const rlottie::FrameInfo& info) {
399                                                                  Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
400                                                                  float           rotation;
401                                                                  if(value.Get(rotation))
402                                                                  {
403                                                                    return rotation;
404                                                                  }
405                                                                  return 0.0f;
406                                                                });
407       break;
408     }
409     case VectorProperty::TRANSFORM_OPACITY:
410     {
411       mVectorRenderer->setValue<rlottie::Property::TrOpacity>(keyPath,
412                                                               [property, callback, id](const rlottie::FrameInfo& info) {
413                                                                 Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
414                                                                 float           opacity;
415                                                                 if(value.Get(opacity))
416                                                                 {
417                                                                   return opacity * 100;
418                                                                 }
419                                                                 return 100.0f;
420                                                               });
421       break;
422     }
423   }
424 }
425
426 void VectorAnimationRenderer::KeepRasterizedBuffer()
427 {
428   Dali::Mutex::ScopedLock lock(mMutex);
429   mEnableFixedCache = true;
430   mDecodedBuffers.clear();
431 }
432
433 VectorAnimationRendererPlugin::UploadCompletedSignalType& VectorAnimationRenderer::UploadCompletedSignal()
434 {
435   return mUploadCompletedSignal;
436 }
437
438 void VectorAnimationRenderer::NotifyEvent()
439 {
440   bool emitSignal = false;
441   {
442     Dali::Mutex::ScopedLock lock(mMutex);
443
444     if(mResourceReadyTriggered)
445     {
446       DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Set Texture [%p]\n", this);
447
448       // Set texture
449       if(mRenderer && GetTargetTexture())
450       {
451         TextureSet textureSet = mRenderer.GetTextures();
452         textureSet.SetTexture(0, GetTargetTexture());
453       }
454
455       mResourceReadyTriggered = false;
456       emitSignal              = true;
457     }
458
459     OnNotify();
460   }
461   if(emitSignal)
462   {
463     mUploadCompletedSignal.Emit();
464   }
465 }
466
467 } // namespace Plugin
468
469 } // namespace Dali