+++ /dev/null
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-extension/vector-animation-renderer/tizen-rive-animation-renderer.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/file-loader.h>
-#include <dali/devel-api/adaptor-framework/native-image-source-queue.h>
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/object/property-array.h>
-#include <tbm_surface_internal.h>
-#include <time.h>
-#include <cmath>
-#include <cstring> // for strlen()
-#include <rive/file.hpp>
-#include <rive/tvg_renderer.hpp>
-
-// INTERNAL INCLUDES
-#include <dali-extension/vector-animation-renderer/tizen-vector-animation-manager.h>
-
-// The plugin factories
-extern "C" DALI_EXPORT_API Dali::VectorAnimationRendererPlugin* CreateVectorAnimationRendererPlugin(void)
-{
- return new Dali::Plugin::TizenRiveAnimationRenderer;
-}
-
-namespace Dali
-{
-namespace Plugin
-{
-namespace
-{
-const char* const DEFAULT_SAMPLER_TYPENAME("sampler2D");
-const char* const PIXEL_AREA_UNIFORM_NAME("pixelArea");
-
-const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
-
-} // unnamed namespace
-
-TizenRiveAnimationRenderer::TizenRiveAnimationRenderer()
-: mUrl(),
- mMutex(),
- mRenderer(),
- mTexture(),
- mRenderedTexture(),
- mPreviousTexture(),
- mTargetSurface(),
- mUploadCompletedSignal(),
- mTbmQueue(NULL),
- mSwCanvas(nullptr),
- mFile(nullptr),
- mArtboard(nullptr),
- mAnimation(nullptr),
- mAnimationInstance(nullptr),
- mStartFrameNumber(0),
- mTotalFrameNumber(0),
- mWidth(0),
- mHeight(0),
- mDefaultWidth(0),
- mDefaultHeight(0),
- mFrameRate(60.0f),
- mResourceReady(false),
- mShaderChanged(false),
- mResourceReadyTriggered(false)
-{
- tvg::Initializer::init(tvg::CanvasEngine::Sw, 0);
-}
-
-TizenRiveAnimationRenderer::~TizenRiveAnimationRenderer()
-{
- Dali::Mutex::ScopedLock lock(mMutex);
-
- if(mAnimationInstance)
- {
- delete mAnimationInstance;
- }
-
- if(mFile)
- {
- delete mFile;
- }
-
- mSwCanvas->clear();
- tvg::Initializer::term(tvg::CanvasEngine::Sw);
-
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::~TizenRiveAnimationRenderer: this = %p\n", this);
-}
-
-void TizenRiveAnimationRenderer::LoadRiveFile(const std::string& filename)
-{
- std::streampos length = 0;
- Dali::Vector<uint8_t> bytes;
-
- if(!Dali::FileLoader::ReadFile(filename, bytes))
- {
- DALI_LOG_ERROR("Failed to read all of %s", filename.c_str());
- return;
- }
-
- auto reader = rive::BinaryReader(&bytes[0], bytes.Size());
-
- if(mFile)
- {
- delete mFile;
- }
-
- auto result = rive::File::import(reader, &mFile);
- if(result != rive::ImportResult::success)
- {
- DALI_LOG_ERROR("Failed to import %s", filename.c_str());
- return;
- }
-
- mArtboard = mFile->artboard();
- mArtboard->advance(0.0f);
-
- if(mAnimationInstance)
- {
- delete mAnimationInstance;
- mAnimationInstance = nullptr;
- }
-
- mAnimation = mArtboard->firstAnimation();
- if(mAnimation)
- {
- mAnimationInstance = new rive::LinearAnimationInstance(mAnimation);
- }
-
- mStartFrameNumber = mAnimation->enableWorkArea() ? mAnimation->workStart() : 0;
- mTotalFrameNumber = mAnimation->enableWorkArea() ? mAnimation->workEnd() : mAnimation->duration();
- mTotalFrameNumber -= mStartFrameNumber;
-}
-
-bool TizenRiveAnimationRenderer::Load(const std::string& url)
-{
- mUrl = url;
- LoadRiveFile(mUrl);
- TizenVectorAnimationManager::Get().AddEventHandler(*this);
-
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::Initialize: file [%s] [%p]\n", url.c_str(), this);
-
- return true;
-}
-
-void TizenRiveAnimationRenderer::Finalize()
-{
- Dali::Mutex::ScopedLock lock(mMutex);
-
- TizenVectorAnimationManager::Get().RemoveEventHandler(*this);
-
- mRenderer.Reset();
- mTexture.Reset();
- mRenderedTexture.Reset();
- mPreviousTexture.Reset();
-
- mTargetSurface = nullptr;
- mTbmQueue = nullptr;
-
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::Finalize: [%p]\n", this);
-}
-
-void TizenRiveAnimationRenderer::SetRenderer(Renderer renderer)
-{
- mRenderer = renderer;
- mShaderChanged = false;
-
- if(mTargetSurface)
- {
- Dali::Mutex::ScopedLock lock(mMutex);
-
- if(mResourceReady && mRenderedTexture)
- {
- TextureSet textureSet = renderer.GetTextures();
-
- textureSet.SetTexture(0, mRenderedTexture);
-
- mUploadCompletedSignal.Emit();
- }
-
- SetShader();
- }
-}
-
-void TizenRiveAnimationRenderer::SetSize(uint32_t width, uint32_t height)
-{
- Dali::Mutex::ScopedLock lock(mMutex);
-
- if(mWidth == width && mHeight == height)
- {
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::SetSize: Same size (%d, %d) [%p]\n", mWidth, mHeight, this);
- return;
- }
-
- mTargetSurface = NativeImageSourceQueue::New(width, height, NativeImageSourceQueue::COLOR_DEPTH_DEFAULT);
-
- mTexture = Texture::New(*mTargetSurface);
-
- if(mRenderer)
- {
- SetShader();
- }
-
- mTbmQueue = AnyCast<tbm_surface_queue_h>(mTargetSurface->GetNativeImageSourceQueue());
-
- mWidth = width;
- mHeight = height;
-
- mResourceReady = false;
-
- // Reset the previous texture to destroy it in the main thread
- mPreviousTexture.Reset();
-
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::SetSize: width = %d, height = %d [%p]\n", mWidth, mHeight, this);
-}
-
-bool TizenRiveAnimationRenderer::Render(uint32_t frameNumber)
-{
- Dali::Mutex::ScopedLock lock(mMutex);
- if(!mTbmQueue || !mTargetSurface || !mArtboard || !mAnimationInstance)
- {
- return false;
- }
-
- int canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
- if(!canDequeue)
- {
- // Ignore the previous image which is inserted to the queue.
- mTargetSurface->IgnoreSourceImage();
-
- // Check again
- canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
- if(!canDequeue)
- {
- return false;
- }
- }
-
- tbm_surface_h tbmSurface;
-
- if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
- {
- DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", this);
- return false;
- }
-
- tbm_surface_info_s info;
- int ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
- if(ret != TBM_SURFACE_ERROR_NONE)
- {
- DALI_LOG_ERROR("TizenRiveAnimationRenderer::Render: tbm_surface_map is failed! [%d] [%p]\n", ret, this);
- tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
- return false;
- }
-
- unsigned char* buffer = info.planes[0].ptr;
- if(!buffer)
- {
- DALI_LOG_ERROR("TizenRiveAnimationRenderer::Render: tbm buffer pointer is null! [%p]\n", this);
- tbm_surface_unmap(tbmSurface);
- tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
- return false;
- }
-
- tbm_surface_internal_ref(tbmSurface);
-
- if(!mSwCanvas)
- {
- mSwCanvas = tvg::SwCanvas::gen();
- }
- mSwCanvas->target((uint32_t*)buffer, info.planes[0].stride / 4, info.width, info.height, tvg::SwCanvas::ARGB8888);
- mSwCanvas->clear();
-
- // Render Rive Frame
- frameNumber = mStartFrameNumber + frameNumber;
- double elapsed = (float)frameNumber / 60.0f;
-
- mAnimationInstance->time(elapsed);
- mAnimationInstance->advance(0.0);
- mAnimationInstance->apply(mArtboard);
-
- mArtboard->advance(0.0);
-
- rive::TvgRenderer renderer(mSwCanvas.get());
- renderer.save();
- renderer.align(rive::Fit::contain,
- rive::Alignment::center,
- rive::AABB(0, 0, info.width, info.height),
- mArtboard->bounds());
- mArtboard->draw(&renderer);
- renderer.restore();
-
- if(mSwCanvas->draw() == tvg::Result::Success)
- {
- mSwCanvas->sync();
- }
- else
- {
- tbm_surface_unmap(tbmSurface);
- tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
- return false;
- }
-
- tbm_surface_unmap(tbmSurface);
-
- tbm_surface_queue_enqueue(mTbmQueue, tbmSurface);
-
- if(!mResourceReady)
- {
- mPreviousTexture = mRenderedTexture; // It is used to destroy the object in the main thread.
- mRenderedTexture = mTexture;
- mResourceReady = true;
- mResourceReadyTriggered = true;
-
- TizenVectorAnimationManager::Get().TriggerEvent(*this);
-
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::Render: Resource ready [current = %d] [%p]\n", frameNumber, this);
- }
-
- return true;
-}
-
-uint32_t TizenRiveAnimationRenderer::GetTotalFrameNumber() const
-{
- return mTotalFrameNumber;
-}
-
-float TizenRiveAnimationRenderer::GetFrameRate() const
-{
- return mFrameRate;
-}
-
-void TizenRiveAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
-{
- width = mDefaultWidth;
- height = mDefaultHeight;
-}
-
-void TizenRiveAnimationRenderer::GetLayerInfo(Property::Map& map) const
-{
- return;
-}
-
-//TODO: This should be modified later, GetMarkerInfo is not proper interface name
-bool TizenRiveAnimationRenderer::GetMarkerInfo(const std::string& marker, uint32_t& startFrame, uint32_t& endFrame) const
-{
- Dali::Mutex::ScopedLock lock(mMutex);
-
- if(!mAnimation)
- {
- return false;
- }
-
- startFrame = mStartFrameNumber;
- endFrame = mTotalFrameNumber;
-
- return true;
-}
-
-void TizenRiveAnimationRenderer::IgnoreRenderedFrame()
-{
- Dali::Mutex::ScopedLock lock(mMutex);
-
- if(mTargetSurface)
- {
- mTargetSurface->IgnoreSourceImage();
- }
-}
-
-VectorAnimationRendererPlugin::UploadCompletedSignalType& TizenRiveAnimationRenderer::UploadCompletedSignal()
-{
- return mUploadCompletedSignal;
-}
-
-void TizenRiveAnimationRenderer::NotifyEvent()
-{
- Dali::Mutex::ScopedLock lock(mMutex);
-
- if(mResourceReadyTriggered)
- {
- DALI_LOG_RELEASE_INFO("TizenRiveAnimationRenderer::NotifyEvent: Set Texture [%p]\n", this);
-
- // Set texture
- if(mRenderer && mRenderedTexture)
- {
- TextureSet textureSet = mRenderer.GetTextures();
- textureSet.SetTexture(0, mRenderedTexture);
- }
-
- mResourceReadyTriggered = false;
-
- mUploadCompletedSignal.Emit();
- }
-
- mPreviousTexture.Reset();
-}
-
-//TODO: unify SetShader with tizen-vector-animation-renderer's since code are totally identical
-void TizenRiveAnimationRenderer::SetShader()
-{
- if(mShaderChanged)
- {
- return;
- }
-
- Shader shader = mRenderer.GetShader();
-
- std::string fragmentShader;
- std::string vertexShader;
-
- // Get the current fragment shader source
- Property::Value program = shader.GetProperty(Shader::Property::PROGRAM);
- Property::Map* map = program.GetMap();
- if(map)
- {
- Property::Value* fragment = map->Find("fragment");
- if(fragment)
- {
- fragmentShader = fragment->Get<std::string>();
- }
-
- Property::Value* vertex = map->Find("vertex");
- if(vertex)
- {
- vertexShader = vertex->Get<std::string>();
- }
- }
-
- // Get custom fragment shader prefix
- const char* fragmentPrefix = mTargetSurface->GetCustomFragmentPrefix();
-
- size_t prefixIndex = fragmentShader.find(Dali::Shader::GetShaderVersionPrefix());
- if(fragmentPrefix)
- {
- if(prefixIndex == std::string::npos)
- {
- fragmentShader = fragmentPrefix + fragmentShader;
- }
- else
- {
- fragmentShader.insert(prefixIndex + Dali::Shader::GetShaderVersionPrefix().length(), std::string(fragmentPrefix) + "\n");
- }
- }
-
- // Get custom sampler type name
- const char* customSamplerTypename = mTargetSurface->GetCustomSamplerTypename();
- if(customSamplerTypename)
- {
- size_t position = fragmentShader.find(DEFAULT_SAMPLER_TYPENAME);
- if(position != std::string::npos)
- {
- fragmentShader.replace(position, strlen(DEFAULT_SAMPLER_TYPENAME), customSamplerTypename);
- }
- }
-
- // Set the modified shader again
- Shader newShader = Shader::New(vertexShader, fragmentShader);
- newShader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-
- mRenderer.SetShader(newShader);
-
- mShaderChanged = true;
-}
-
-} // namespace Plugin
-
-} // namespace Dali
+++ /dev/null
-#ifndef DALI_TIZEN_RIVE_ANIMATION_RENDERER_PLUGIN_H
-#define DALI_TIZEN_RIVE_ANIMATION_RENDERER_PLUGIN_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/devel-api/threading/mutex.h>
-#include <dali/devel-api/adaptor-framework/native-image-source-queue.h>
-#include <dali/devel-api/adaptor-framework/vector-animation-renderer-plugin.h>
-#include <memory>
-#include <tbm_surface.h>
-#include <tbm_surface_queue.h>
-
-// RIVE - THORVG INCLUDES
-#include <thorvg.h>
-#include <rive/animation/linear_animation_instance.hpp>
-#include <rive/artboard.hpp>
-//
-
-// INTERNAL INCLUDES
-#include <dali-extension/vector-animation-renderer/tizen-vector-animation-event-handler.h>
-
-namespace Dali
-{
-
-namespace Plugin
-{
-
-/**
- * @brief Implementation of the Tizen vector animation renderer class which has Tizen platform dependency.
- */
-class TizenRiveAnimationRenderer : public Dali::VectorAnimationRendererPlugin, public TizenVectorAnimationEventHandler
-{
-public:
-
- /**
- * @brief Constructor.
- */
- TizenRiveAnimationRenderer();
-
- /**
- * @brief Destructor.
- */
- virtual ~TizenRiveAnimationRenderer();
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::Initialize()
- */
- bool Load( const std::string& url ) override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::Finalize()
- */
- void Finalize() override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::SetRenderer()
- */
- void SetRenderer( Renderer renderer ) override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::SetSize()
- */
- void SetSize( uint32_t width, uint32_t height ) override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::Render()
- */
- bool Render( uint32_t frameNumber) override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::GetTotalFrameNumber()
- */
- uint32_t GetTotalFrameNumber() const override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::GetFrameRate()
- */
- float GetFrameRate() const override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::GetDefaultSize()
- */
- void GetDefaultSize( uint32_t& width, uint32_t& height ) const override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::GetLayerInfo()
- */
- void GetLayerInfo( Property::Map& map ) const override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::GetMarkerInfo()
- */
- bool GetMarkerInfo( const std::string& marker, uint32_t& startFrame, uint32_t& endFrame ) const override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::IgnoreRenderedFrame()
- */
- void IgnoreRenderedFrame() override;
-
- /**
- * @copydoc Dali::VectorAnimationRendererPlugin::UploadCompletedSignal()
- */
- UploadCompletedSignalType& UploadCompletedSignal() override;
-
-protected: // Implementation of TizenVectorAnimationEventHandler
-
- /**
- * @copydoc Dali::Plugin::TizenVectorAnimationEventHandler::NotifyEvent()
- */
- void NotifyEvent() override;
-
-private:
-
- /**
- * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
- */
- void SetShader();
-
- /**
- * @brief Reset buffer list.
- */
- void ResetBuffers();
-
- /**
- * @brief Load rive resource file for artboard.
- */
- void LoadRiveFile(const std::string& filename);
-
-private:
-
- std::string mUrl; ///< The content file path
- mutable Dali::Mutex mMutex; ///< Mutex
- Dali::Renderer mRenderer; ///< Renderer
- Dali::Texture mTexture; ///< Texture
- Dali::Texture mRenderedTexture; ///< Rendered Texture
- Dali::Texture mPreviousTexture; ///< Previous rendered texture
- NativeImageSourceQueuePtr mTargetSurface; ///< The target surface
- UploadCompletedSignalType mUploadCompletedSignal; ///< Upload completed signal
- tbm_surface_queue_h mTbmQueue; ///< Tbm surface queue handle
- std::unique_ptr<tvg::SwCanvas> mSwCanvas; ///< ThorVG SW canvas handle
- rive::File *mFile; ///< Rive file handle
- rive::Artboard *mArtboard; ///< Rive artboard handle
- rive::LinearAnimation *mAnimation; ///< Rive animation handle
- rive::LinearAnimationInstance *mAnimationInstance; ///< Rive animation instance
- uint32_t mStartFrameNumber; ///< The start frame number
- uint32_t mTotalFrameNumber; ///< The total frame number
- uint32_t mWidth; ///< The width of the surface
- uint32_t mHeight; ///< The height of the surface
- uint32_t mDefaultWidth; ///< The width of the surface
- uint32_t mDefaultHeight; ///< The height of the surface
- float mFrameRate; ///< The frame rate of the content
- bool mResourceReady; ///< Whether the resource is ready
- bool mShaderChanged; ///< Whether the shader is changed to support native image
- bool mResourceReadyTriggered;///< Whether the resource ready is triggered
-};
-
-} // namespace Plugin
-
-} // namespace Dali;
-
-#endif // DALI_TIZEN_RIVE_ANIMATION_RENDERER_PLUGIN_H