2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-extension/internal/rive-animation-view/animation-renderer/rive-animation-renderer.h>
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>
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>
38 #include <dali-extension/internal/rive-animation-view/animation-renderer/rive-animation-renderer-manager.h>
48 const char* const PIXEL_AREA_UNIFORM_NAME("pixelArea");
50 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
52 #if defined(DEBUG_ENABLED)
53 Debug::Filter* gRiveAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RIVE_ANIMATION");
55 } // unnamed namespace
57 RiveAnimationRenderer::RiveAnimationRenderer()
65 mUploadCompletedSignal(),
76 mResourceReady(false),
77 mShaderChanged(false),
78 mResourceReadyTriggered(false),
79 mRiveTizenAdapter(nullptr)
81 mRiveTizenAdapter = new RiveTizen();
84 RiveAnimationRenderer::~RiveAnimationRenderer()
86 Dali::Mutex::ScopedLock lock(mMutex);
87 ClearRiveAnimations();
91 delete mRiveTizenAdapter;
94 mRiveTizenAdapter = nullptr;
96 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::~RiveAnimationRenderer: this = %p\n", this);
99 void RiveAnimationRenderer::ClearRiveAnimations()
104 void RiveAnimationRenderer::LoadRiveFile(const std::string& filename)
106 std::streampos length = 0;
107 Dali::Vector<uint8_t> bytes;
109 if(!Dali::FileLoader::ReadFile(filename, bytes))
111 DALI_LOG_ERROR("Failed to read all of %s", filename.c_str());
115 if(bytes.Size() == 0)
117 DALI_LOG_ERROR("Failed to load: empty file %s", filename.c_str());
121 ClearRiveAnimations();
122 if(!mRiveTizenAdapter->loadRiveResource(&bytes[0], bytes.Size()))
124 DALI_LOG_ERROR("Failed to load resource file %s", filename.c_str());
128 mArtboard = mRiveTizenAdapter->getArtboard();
130 for(unsigned int i = 0; i < mArtboard->animationCount(); i++)
132 auto animation = mArtboard->animation(i);
133 const std::string& name = animation->name();
134 mAnimations.emplace_back(Animation(mRiveTizenAdapter->createLinearAnimationInstance(i), name, false));
137 mAnimation = mArtboard->firstAnimation();
140 mStartFrameNumber = mAnimation->enableWorkArea() ? mAnimation->workStart() : 0;
141 mTotalFrameNumber = mAnimation->enableWorkArea() ? mAnimation->workEnd() : mAnimation->duration();
142 mTotalFrameNumber -= mStartFrameNumber;
146 bool RiveAnimationRenderer::Load(const std::string& url)
150 RiveAnimationRendererManager::Get().AddEventHandler(*this);
152 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Initialize: file [%s] [%p]\n", url.c_str(), this);
157 void RiveAnimationRenderer::Finalize()
159 Dali::Mutex::ScopedLock lock(mMutex);
161 RiveAnimationRendererManager::Get().RemoveEventHandler(*this);
165 mRenderedTexture.Reset();
166 mPreviousTexture.Reset();
168 mTargetSurface = nullptr;
171 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Finalize: [%p]\n", this);
174 void RiveAnimationRenderer::SetRenderer(Renderer renderer)
176 mRenderer = renderer;
177 mShaderChanged = false;
181 Dali::Mutex::ScopedLock lock(mMutex);
183 if(mResourceReady && mRenderedTexture)
185 TextureSet textureSet = renderer.GetTextures();
187 textureSet.SetTexture(0, mRenderedTexture);
189 mUploadCompletedSignal.Emit();
196 void RiveAnimationRenderer::SetSize(uint32_t width, uint32_t height)
198 Dali::Mutex::ScopedLock lock(mMutex);
200 if(mWidth == width && mHeight == height)
202 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::SetSize: Same size (%d, %d) [%p]\n", mWidth, mHeight, this);
206 mTargetSurface = NativeImageSourceQueue::New(width, height, NativeImageSourceQueue::ColorFormat::RGBA8888);
208 mTexture = Texture::New(*mTargetSurface);
215 mTbmQueue = AnyCast<tbm_surface_queue_h>(mTargetSurface->GetNativeImageSourceQueue());
220 mResourceReady = false;
222 // Reset the previous texture to destroy it in the main thread
223 mPreviousTexture.Reset();
225 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::SetSize: width = %d, height = %d [%p]\n", mWidth, mHeight, this);
228 bool RiveAnimationRenderer::Render(double elapsed)
230 Dali::Mutex::ScopedLock lock(mMutex);
231 if(!mTbmQueue || !mTargetSurface || mAnimations.empty())
236 int canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
239 // Ignore the previous image which is inserted to the queue.
240 mTargetSurface->IgnoreSourceImage();
243 canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
250 tbm_surface_h tbmSurface;
252 if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
254 DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", this);
258 tbm_surface_info_s info;
259 int ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
260 if(ret != TBM_SURFACE_ERROR_NONE)
262 DALI_LOG_ERROR("RiveAnimationRenderer::Render: tbm_surface_map is failed! [%d] [%p]\n", ret, this);
263 tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
267 unsigned char* buffer = info.planes[0].ptr;
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);
276 tbm_surface_internal_ref(tbmSurface);
278 mRiveTizenAdapter->createCanvas(buffer, info.width, info.height, info.planes[0].stride / 4);
280 // Render Rive animation by elapsed time
281 for(auto& animation : mAnimations)
283 if(animation.instance)
287 mRiveTizenAdapter->animationAdvanceApply(animation.instance.get(), elapsed);
289 else if(animation.elapsed >= 0.0f)
291 mRiveTizenAdapter->animationApply(animation.instance.get(), animation.elapsed);
296 if(!mRiveTizenAdapter->render(elapsed, info.width, info.height))
298 tbm_surface_unmap(tbmSurface);
299 tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
303 tbm_surface_unmap(tbmSurface);
305 tbm_surface_queue_enqueue(mTbmQueue, tbmSurface);
309 mPreviousTexture = mRenderedTexture; // It is used to destroy the object in the main thread.
310 mRenderedTexture = mTexture;
311 mResourceReady = true;
312 mResourceReadyTriggered = true;
314 RiveAnimationRendererManager::Get().TriggerEvent(*this);
316 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Render: Resource ready [%p]\n", this);
322 uint32_t RiveAnimationRenderer::GetTotalFrameNumber() const
324 return mTotalFrameNumber;
327 float RiveAnimationRenderer::GetFrameRate() const
332 void RiveAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
334 width = mDefaultWidth;
335 height = mDefaultHeight;
338 void RiveAnimationRenderer::EnableAnimation(const std::string& animationName, bool enable)
340 Dali::Mutex::ScopedLock lock(mMutex);
342 for(unsigned int i = 0; i < mAnimations.size(); i++)
344 if(mAnimations[i].name == animationName)
346 if(mAnimations[i].instance)
348 mAnimations[i].instance.reset(mRiveTizenAdapter->createLinearAnimationInstance(i));
350 mAnimations[i].enable = enable;
356 void RiveAnimationRenderer::SetAnimationElapsedTime(const std::string& animationName, float elapsed)
358 Dali::Mutex::ScopedLock lock(mMutex);
360 for(auto& animation : mAnimations)
362 if(animation.name == animationName)
364 animation.elapsed = elapsed;
370 void RiveAnimationRenderer::SetShapeFillColor(const std::string& fillName, Vector4 color)
372 Dali::Mutex::ScopedLock lock(mMutex);
373 mRiveTizenAdapter->setShapeFillColor(fillName, color.a, color.r, color.g, color.b);
376 void RiveAnimationRenderer::SetShapeStrokeColor(const std::string& strokeName, Vector4 color)
378 Dali::Mutex::ScopedLock lock(mMutex);
379 mRiveTizenAdapter->setShapeStrokeColor(strokeName, color.a, color.r, color.g, color.b);
382 void RiveAnimationRenderer::SetNodeOpacity(const std::string& nodeName, float opacity)
384 Dali::Mutex::ScopedLock lock(mMutex);
385 mRiveTizenAdapter->setNodeOpacity(nodeName, opacity);
388 void RiveAnimationRenderer::SetNodeScale(const std::string& nodeName, Vector2 scale)
390 Dali::Mutex::ScopedLock lock(mMutex);
391 mRiveTizenAdapter->setNodeScale(nodeName, scale.x, scale.y);
394 void RiveAnimationRenderer::SetNodeRotation(const std::string& nodeName, Degree degree)
396 Dali::Mutex::ScopedLock lock(mMutex);
397 mRiveTizenAdapter->setNodeRotation(nodeName, degree.degree);
400 void RiveAnimationRenderer::SetNodePosition(const std::string& nodeName, Vector2 position)
402 Dali::Mutex::ScopedLock lock(mMutex);
403 mRiveTizenAdapter->setNodePosition(nodeName, position.x, position.y);
406 void RiveAnimationRenderer::PointerMove(float x, float y)
408 #if !defined(OS_TIZEN_TV)
409 Dali::Mutex::ScopedLock lock(mMutex);
410 mRiveTizenAdapter->pointerMove(x, y);
414 void RiveAnimationRenderer::PointerDown(float x, float y)
416 #if !defined(OS_TIZEN_TV)
417 Dali::Mutex::ScopedLock lock(mMutex);
418 mRiveTizenAdapter->pointerDown(x, y);
422 void RiveAnimationRenderer::PointerUp(float x, float y)
424 #if !defined(OS_TIZEN_TV)
425 Dali::Mutex::ScopedLock lock(mMutex);
426 mRiveTizenAdapter->pointerUp(x, y);
430 bool RiveAnimationRenderer::SetNumberState(const std::string& stateMachineName, const std::string& inputName, float value)
432 #if !defined(OS_TIZEN_TV)
433 Dali::Mutex::ScopedLock lock(mMutex);
434 return mRiveTizenAdapter->setNumberState(stateMachineName, inputName, value);
440 bool RiveAnimationRenderer::SetBooleanState(const std::string& stateMachineName, const std::string& inputName, bool value)
442 #if !defined(OS_TIZEN_TV)
443 Dali::Mutex::ScopedLock lock(mMutex);
444 return mRiveTizenAdapter->setBooleanState(stateMachineName, inputName, value);
450 bool RiveAnimationRenderer::FireState(const std::string& stateMachineName, const std::string& inputName)
452 #if !defined(OS_TIZEN_TV)
453 Dali::Mutex::ScopedLock lock(mMutex);
454 return mRiveTizenAdapter->fireState(stateMachineName, inputName);
460 void RiveAnimationRenderer::IgnoreRenderedFrame()
462 Dali::Mutex::ScopedLock lock(mMutex);
466 mTargetSurface->IgnoreSourceImage();
470 RiveAnimationRenderer::UploadCompletedSignalType& RiveAnimationRenderer::UploadCompletedSignal()
472 return mUploadCompletedSignal;
475 void RiveAnimationRenderer::NotifyEvent()
477 Dali::Mutex::ScopedLock lock(mMutex);
479 if(mResourceReadyTriggered)
481 DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::NotifyEvent: Set Texture [%p]\n", this);
484 if(mRenderer && mRenderedTexture)
486 TextureSet textureSet = mRenderer.GetTextures();
487 textureSet.SetTexture(0, mRenderedTexture);
490 mResourceReadyTriggered = false;
492 mUploadCompletedSignal.Emit();
495 mPreviousTexture.Reset();
498 void RiveAnimationRenderer::SetShader()
505 Shader shader = mRenderer.GetShader();
507 std::string fragmentShader;
508 std::string vertexShader;
510 // Get the current fragment shader source
511 Property::Value program = shader.GetProperty(Shader::Property::PROGRAM);
512 Property::Map* map = program.GetMap();
515 Property::Value* fragment = map->Find("fragment");
518 fragmentShader = fragment->Get<std::string>();
521 Property::Value* vertex = map->Find("vertex");
524 vertexShader = vertex->Get<std::string>();
528 // Get custom fragment shader prefix
529 mTargetSurface->ApplyNativeFragmentShader(fragmentShader);
531 // Set the modified shader again
532 Shader newShader = Shader::New(vertexShader, fragmentShader);
533 newShader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
535 mRenderer.SetShader(newShader);
537 mShaderChanged = true;
540 } // namespace Internal
542 } // namespace Extension