Fix Rive build errors in Tizen 7.0 TV
[platform/core/uifw/dali-extension.git] / dali-extension / internal / rive-animation-view / animation-renderer / rive-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/internal/rive-animation-view/animation-renderer/rive-animation-renderer.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/file-loader.h>
23 #include <dali/devel-api/adaptor-framework/native-image-source-queue.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/object/property-array.h>
26 #include <tbm_surface_internal.h>
27 #include <time.h>
28 #include <cmath>
29 #include <cstring> // for strlen()
30 #include <rive/file.hpp>
31 #include <rive/node.hpp>
32 #include <rive/shapes/paint/color.hpp>
33 #include <rive/shapes/paint/fill.hpp>
34 #include <rive/shapes/paint/solid_color.hpp>
35 #include <rive/shapes/paint/stroke.hpp>
36
37 // INTERNAL INCLUDES
38 #include <dali-extension/internal/rive-animation-view/animation-renderer/rive-animation-renderer-manager.h>
39
40 namespace Dali
41 {
42 namespace Extension
43 {
44 namespace Internal
45 {
46 namespace
47 {
48 const char* const PIXEL_AREA_UNIFORM_NAME("pixelArea");
49
50 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
51
52 #if defined(DEBUG_ENABLED)
53 Debug::Filter* gRiveAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RIVE_ANIMATION");
54 #endif
55 } // unnamed namespace
56
57 RiveAnimationRenderer::RiveAnimationRenderer()
58 : mUrl(),
59   mMutex(),
60   mRenderer(),
61   mTexture(),
62   mRenderedTexture(),
63   mPreviousTexture(),
64   mTargetSurface(),
65   mUploadCompletedSignal(),
66   mTbmQueue(NULL),
67   mArtboard(nullptr),
68   mAnimation(nullptr),
69   mStartFrameNumber(0),
70   mTotalFrameNumber(0),
71   mWidth(0),
72   mHeight(0),
73   mDefaultWidth(0),
74   mDefaultHeight(0),
75   mFrameRate(60.0f),
76   mResourceReady(false),
77   mShaderChanged(false),
78   mResourceReadyTriggered(false),
79   mRiveTizenAdapter(nullptr)
80 {
81   mRiveTizenAdapter = new RiveTizen();
82 }
83
84 RiveAnimationRenderer::~RiveAnimationRenderer()
85 {
86   Dali::Mutex::ScopedLock lock(mMutex);
87   ClearRiveAnimations();
88
89   if(mRiveTizenAdapter)
90   {
91     delete mRiveTizenAdapter;
92   }
93
94   mRiveTizenAdapter = nullptr;
95
96   DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::~RiveAnimationRenderer: this = %p\n", this);
97 }
98
99 void RiveAnimationRenderer::ClearRiveAnimations()
100 {
101   mAnimations.clear();
102 }
103
104 void RiveAnimationRenderer::LoadRiveFile(const std::string& filename)
105 {
106   std::streampos        length = 0;
107   Dali::Vector<uint8_t> bytes;
108
109   if(!Dali::FileLoader::ReadFile(filename, bytes))
110   {
111     DALI_LOG_ERROR("Failed to read all of %s", filename.c_str());
112     return;
113   }
114
115   if(bytes.Size() == 0)
116   {
117     DALI_LOG_ERROR("Failed to load: empty file %s", filename.c_str());
118     return;
119   }
120
121   ClearRiveAnimations();
122   if(!mRiveTizenAdapter->loadRiveResource(&bytes[0], bytes.Size()))
123   {
124     DALI_LOG_ERROR("Failed to load resource file %s", filename.c_str());
125     return;
126   }
127
128   mArtboard = mRiveTizenAdapter->getArtboard();
129
130   for(unsigned int i = 0; i < mArtboard->animationCount(); i++)
131   {
132     auto               animation = mArtboard->animation(i);
133     const std::string& name      = animation->name();
134     mAnimations.emplace_back(Animation(mRiveTizenAdapter->createLinearAnimationInstance(i), name, false));
135   }
136
137   mAnimation = mArtboard->firstAnimation();
138   if(mAnimation)
139   {
140     mStartFrameNumber = mAnimation->enableWorkArea() ? mAnimation->workStart() : 0;
141     mTotalFrameNumber = mAnimation->enableWorkArea() ? mAnimation->workEnd() : mAnimation->duration();
142     mTotalFrameNumber -= mStartFrameNumber;
143   }
144 }
145
146 bool RiveAnimationRenderer::Load(const std::string& url)
147 {
148   mUrl = url;
149   LoadRiveFile(mUrl);
150   RiveAnimationRendererManager::Get().AddEventHandler(*this);
151
152   DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Initialize: file [%s] [%p]\n", url.c_str(), this);
153
154   return true;
155 }
156
157 void RiveAnimationRenderer::Finalize()
158 {
159   Dali::Mutex::ScopedLock lock(mMutex);
160
161   RiveAnimationRendererManager::Get().RemoveEventHandler(*this);
162
163   mRenderer.Reset();
164   mTexture.Reset();
165   mRenderedTexture.Reset();
166   mPreviousTexture.Reset();
167
168   mTargetSurface = nullptr;
169   mTbmQueue      = nullptr;
170
171   DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Finalize: [%p]\n", this);
172 }
173
174 void RiveAnimationRenderer::SetRenderer(Renderer renderer)
175 {
176   mRenderer      = renderer;
177   mShaderChanged = false;
178
179   if(mTargetSurface)
180   {
181     Dali::Mutex::ScopedLock lock(mMutex);
182
183     if(mResourceReady && mRenderedTexture)
184     {
185       TextureSet textureSet = renderer.GetTextures();
186
187       textureSet.SetTexture(0, mRenderedTexture);
188
189       mUploadCompletedSignal.Emit();
190     }
191
192     SetShader();
193   }
194 }
195
196 void RiveAnimationRenderer::SetSize(uint32_t width, uint32_t height)
197 {
198   Dali::Mutex::ScopedLock lock(mMutex);
199
200   if(mWidth == width && mHeight == height)
201   {
202     DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::SetSize: Same size (%d, %d) [%p]\n", mWidth, mHeight, this);
203     return;
204   }
205
206   mTargetSurface = NativeImageSourceQueue::New(width, height, NativeImageSourceQueue::ColorFormat::RGBA8888);
207
208   mTexture = Texture::New(*mTargetSurface);
209
210   if(mRenderer)
211   {
212     SetShader();
213   }
214
215   mTbmQueue = AnyCast<tbm_surface_queue_h>(mTargetSurface->GetNativeImageSourceQueue());
216
217   mWidth  = width;
218   mHeight = height;
219
220   mResourceReady = false;
221
222   // Reset the previous texture to destroy it in the main thread
223   mPreviousTexture.Reset();
224
225   DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::SetSize: width = %d, height = %d [%p]\n", mWidth, mHeight, this);
226 }
227
228 bool RiveAnimationRenderer::Render(double elapsed)
229 {
230   Dali::Mutex::ScopedLock lock(mMutex);
231   if(!mTbmQueue || !mTargetSurface || mAnimations.empty())
232   {
233     return false;
234   }
235
236   int canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
237   if(!canDequeue)
238   {
239     // Ignore the previous image which is inserted to the queue.
240     mTargetSurface->IgnoreSourceImage();
241
242     // Check again
243     canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
244     if(!canDequeue)
245     {
246       return false;
247     }
248   }
249
250   tbm_surface_h tbmSurface;
251
252   if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
253   {
254     DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", this);
255     return false;
256   }
257
258   tbm_surface_info_s info;
259   int                ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
260   if(ret != TBM_SURFACE_ERROR_NONE)
261   {
262     DALI_LOG_ERROR("RiveAnimationRenderer::Render: tbm_surface_map is failed! [%d] [%p]\n", ret, this);
263     tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
264     return false;
265   }
266
267   unsigned char* buffer = info.planes[0].ptr;
268   if(!buffer)
269   {
270     DALI_LOG_ERROR("RiveAnimationRenderer::Render: tbm buffer pointer is null! [%p]\n", this);
271     tbm_surface_unmap(tbmSurface);
272     tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
273     return false;
274   }
275
276   tbm_surface_internal_ref(tbmSurface);
277
278   mRiveTizenAdapter->createCanvas(buffer, info.width, info.height, info.planes[0].stride / 4);
279
280   // Render Rive animation by elapsed time
281   for(auto& animation : mAnimations)
282   {
283     if(animation.instance)
284     {
285       if(animation.enable)
286       {
287         mRiveTizenAdapter->animationAdvanceApply(animation.instance.get(), elapsed);
288       }
289       else if(animation.elapsed >= 0.0f)
290       {
291         mRiveTizenAdapter->animationApply(animation.instance.get(), animation.elapsed);
292       }
293     }
294   }
295
296   if(!mRiveTizenAdapter->render(elapsed, info.width, info.height))
297   {
298     tbm_surface_unmap(tbmSurface);
299     tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
300     return false;
301   }
302
303   tbm_surface_unmap(tbmSurface);
304
305   tbm_surface_queue_enqueue(mTbmQueue, tbmSurface);
306
307   if(!mResourceReady)
308   {
309     mPreviousTexture        = mRenderedTexture; // It is used to destroy the object in the main thread.
310     mRenderedTexture        = mTexture;
311     mResourceReady          = true;
312     mResourceReadyTriggered = true;
313
314     RiveAnimationRendererManager::Get().TriggerEvent(*this);
315
316     DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Render: Resource ready [%p]\n", this);
317   }
318
319   return true;
320 }
321
322 uint32_t RiveAnimationRenderer::GetTotalFrameNumber() const
323 {
324   return mTotalFrameNumber;
325 }
326
327 float RiveAnimationRenderer::GetFrameRate() const
328 {
329   return mFrameRate;
330 }
331
332 void RiveAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
333 {
334   width  = mDefaultWidth;
335   height = mDefaultHeight;
336 }
337
338 void RiveAnimationRenderer::EnableAnimation(const std::string& animationName, bool enable)
339 {
340   Dali::Mutex::ScopedLock lock(mMutex);
341
342   for(unsigned int i = 0; i < mAnimations.size(); i++)
343   {
344     if(mAnimations[i].name == animationName)
345     {
346       if(mAnimations[i].instance)
347       {
348         mAnimations[i].instance.reset(mRiveTizenAdapter->createLinearAnimationInstance(i));
349       }
350       mAnimations[i].enable = enable;
351       return;
352     }
353   }
354 }
355
356 void RiveAnimationRenderer::SetAnimationElapsedTime(const std::string& animationName, float elapsed)
357 {
358   Dali::Mutex::ScopedLock lock(mMutex);
359
360   for(auto& animation : mAnimations)
361   {
362     if(animation.name == animationName)
363     {
364       animation.elapsed = elapsed;
365       return;
366     }
367   }
368 }
369
370 void RiveAnimationRenderer::SetShapeFillColor(const std::string& fillName, Vector4 color)
371 {
372   Dali::Mutex::ScopedLock lock(mMutex);
373   mRiveTizenAdapter->setShapeFillColor(fillName, color.a, color.r, color.g, color.b);
374 }
375
376 void RiveAnimationRenderer::SetShapeStrokeColor(const std::string& strokeName, Vector4 color)
377 {
378   Dali::Mutex::ScopedLock lock(mMutex);
379   mRiveTizenAdapter->setShapeStrokeColor(strokeName, color.a, color.r, color.g, color.b);
380 }
381
382 void RiveAnimationRenderer::SetNodeOpacity(const std::string& nodeName, float opacity)
383 {
384   Dali::Mutex::ScopedLock lock(mMutex);
385   mRiveTizenAdapter->setNodeOpacity(nodeName, opacity);
386 }
387
388 void RiveAnimationRenderer::SetNodeScale(const std::string& nodeName, Vector2 scale)
389 {
390   Dali::Mutex::ScopedLock lock(mMutex);
391   mRiveTizenAdapter->setNodeScale(nodeName, scale.x, scale.y);
392 }
393
394 void RiveAnimationRenderer::SetNodeRotation(const std::string& nodeName, Degree degree)
395 {
396   Dali::Mutex::ScopedLock lock(mMutex);
397   mRiveTizenAdapter->setNodeRotation(nodeName, degree.degree);
398 }
399
400 void RiveAnimationRenderer::SetNodePosition(const std::string& nodeName, Vector2 position)
401 {
402   Dali::Mutex::ScopedLock lock(mMutex);
403   mRiveTizenAdapter->setNodePosition(nodeName, position.x, position.y);
404 }
405
406 void RiveAnimationRenderer::PointerMove(float x, float y)
407 {
408 #if !defined(OS_TIZEN_TV)
409   Dali::Mutex::ScopedLock lock(mMutex);
410   mRiveTizenAdapter->pointerMove(x, y);
411 #endif
412 }
413
414 void RiveAnimationRenderer::PointerDown(float x, float y)
415 {
416 #if !defined(OS_TIZEN_TV)
417   Dali::Mutex::ScopedLock lock(mMutex);
418   mRiveTizenAdapter->pointerDown(x, y);
419 #endif
420 }
421
422 void RiveAnimationRenderer::PointerUp(float x, float y)
423 {
424 #if !defined(OS_TIZEN_TV)
425   Dali::Mutex::ScopedLock lock(mMutex);
426   mRiveTizenAdapter->pointerUp(x, y);
427 #endif
428 }
429
430 bool RiveAnimationRenderer::SetNumberState(const std::string& stateMachineName, const std::string& inputName, float value)
431 {
432 #if !defined(OS_TIZEN_TV)
433   Dali::Mutex::ScopedLock lock(mMutex);
434   return mRiveTizenAdapter->setNumberState(stateMachineName, inputName, value);
435 #else
436   return false;
437 #endif
438 }
439
440 bool RiveAnimationRenderer::SetBooleanState(const std::string& stateMachineName, const std::string& inputName, bool value)
441 {
442 #if !defined(OS_TIZEN_TV)
443   Dali::Mutex::ScopedLock lock(mMutex);
444   return mRiveTizenAdapter->setBooleanState(stateMachineName, inputName, value);
445 #else
446   return false;
447 #endif
448 }
449
450 bool RiveAnimationRenderer::FireState(const std::string& stateMachineName, const std::string& inputName)
451 {
452 #if !defined(OS_TIZEN_TV)
453   Dali::Mutex::ScopedLock lock(mMutex);
454   return mRiveTizenAdapter->fireState(stateMachineName, inputName);
455 #else
456   return false;
457 #endif
458 }
459
460 void RiveAnimationRenderer::IgnoreRenderedFrame()
461 {
462   Dali::Mutex::ScopedLock lock(mMutex);
463
464   if(mTargetSurface)
465   {
466     mTargetSurface->IgnoreSourceImage();
467   }
468 }
469
470 RiveAnimationRenderer::UploadCompletedSignalType& RiveAnimationRenderer::UploadCompletedSignal()
471 {
472   return mUploadCompletedSignal;
473 }
474
475 void RiveAnimationRenderer::NotifyEvent()
476 {
477   Dali::Mutex::ScopedLock lock(mMutex);
478
479   if(mResourceReadyTriggered)
480   {
481     DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::NotifyEvent: Set Texture [%p]\n", this);
482
483     // Set texture
484     if(mRenderer && mRenderedTexture)
485     {
486       TextureSet textureSet = mRenderer.GetTextures();
487       textureSet.SetTexture(0, mRenderedTexture);
488     }
489
490     mResourceReadyTriggered = false;
491
492     mUploadCompletedSignal.Emit();
493   }
494
495   mPreviousTexture.Reset();
496 }
497
498 void RiveAnimationRenderer::SetShader()
499 {
500   if(mShaderChanged)
501   {
502     return;
503   }
504
505   Shader shader = mRenderer.GetShader();
506
507   std::string fragmentShader;
508   std::string vertexShader;
509
510   // Get the current fragment shader source
511   Property::Value program = shader.GetProperty(Shader::Property::PROGRAM);
512   Property::Map*  map     = program.GetMap();
513   if(map)
514   {
515     Property::Value* fragment = map->Find("fragment");
516     if(fragment)
517     {
518       fragmentShader = fragment->Get<std::string>();
519     }
520
521     Property::Value* vertex = map->Find("vertex");
522     if(vertex)
523     {
524       vertexShader = vertex->Get<std::string>();
525     }
526   }
527
528   // Get custom fragment shader prefix
529   mTargetSurface->ApplyNativeFragmentShader(fragmentShader);
530
531   // Set the modified shader again
532   Shader newShader = Shader::New(vertexShader, fragmentShader);
533   newShader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
534
535   mRenderer.SetShader(newShader);
536
537   mShaderChanged = true;
538 }
539
540 } // namespace Internal
541
542 } // namespace Extension
543
544 } // namespace Dali