# Todo Evas plugin separation
libdali2_extension_la_SOURCES = \
$(evas_plugin_devel_src_files) \
- $(evas_plugin_internal_src_files) \
+ $(evas_plugin_internal_src_files)
+
+if SUPPORT_RIVE
+libdali2_extension_la_SOURCES += \
$(rive_animation_view_devel_src_files) \
$(rive_animation_view_internal_src_files)
+endif
libdali2_extension_la_DEPENDENCIES =
$(EVAS_LIBS) \
$(WAYLAND_LIBS)
+if SUPPORT_RIVE
+libdali2_extension_la_CXXFLAGS += \
+ -I$(includedir)/rive \
+ $(THORVG_CFLAGS) \
+ $(RIVE_TIZEN_CFLAGS)
+
+libdali2_extension_la_LIBADD += \
+ $(THORVG_LIBS) \
+ $(RIVE_TIZEN_LIBS)
+endif
+
libdali2_extension_la_LDFLAGS = \
-rdynamic
PKG_CHECK_MODULES(EVAS, evas)
PKG_CHECK_MODULES(WAYLAND, [ecore-wl2])
+# For rive animation
+if test "x$with_tizen_65_or_greater" = "xyes"; then
+ PKG_CHECK_MODULES(THORVG, thorvg)
+ PKG_CHECK_MODULES(RIVE_TIZEN, rive_tizen)
+ AM_CONDITIONAL([SUPPORT_RIVE], [true])
+else
+ AM_CONDITIONAL([SUPPORT_RIVE], [false])
+fi
+
devincludepath=${includedir}
AC_SUBST(devincludepath)
AC_SUBST(DALI_CFLAGS)
libdali2_vector_animation_renderer_plugin_la_LDFLAGS = \
-rdynamic
-if RIVE
-
-lib_LTLIBRARIES += libdali2-rive-animation-renderer-plugin.la
-
-libdali2_rive_animation_renderer_plugin_la_SOURCES = \
- $(rive_animation_renderer_plugin_src_files)
-
-libdali2_rive_animation_renderer_plugin_la_DEPENDENCIES =
-
-libdali2_rive_animation_renderer_plugin_la_CXXFLAGS = \
- -I../../../ \
- -I$(includedir)/rive \
- $(DALI_CFLAGS) \
- $(THORVG_CFLAGS) \
- $(RIVE_TIZEN_CFLAGS) \
- -Werror -Wall
-
-libdali2_rive_animation_renderer_plugin_la_LIBADD = \
- $(DALI_LIBS) \
- $(THORVG_LIBS) \
- $(RIVE_TIZEN_LIBS)
-
-libdali2_rive_animation_renderer_plugin_la_LDFLAGS = \
- -rdynamic
-
-endif
PKG_CHECK_MODULES([DALI], [dali2-core dali2-adaptor dali2-toolkit])
PKG_CHECK_MODULES(RLOTTIE, rlottie)
-if test "x$with_tizen_65_or_greater" = "xyes"; then
- PKG_CHECK_MODULES(THORVG, thorvg)
- PKG_CHECK_MODULES(RIVE_TIZEN, rive_tizen)
- AM_CONDITIONAL([RIVE], [true])
-else
- AM_CONDITIONAL([RIVE], [false])
-fi
-
devincludepath=${includedir}
AC_SUBST(devincludepath)
AC_SUBST(DALI_CFLAGS)
--- /dev/null
+#ifndef DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_EVENT_HANDLER_H
+#define DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_EVENT_HANDLER_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.
+ *
+ */
+
+namespace Dali
+{
+namespace Extension
+{
+namespace Internal
+{
+
+/**
+ * @brief Rive animation renderer event handler
+ */
+class RiveAnimationRendererEventHandler
+{
+public:
+
+ /**
+ * @brief Notify events
+ */
+ virtual void NotifyEvent() = 0;
+
+protected:
+
+ /**
+ * constructor
+ */
+ RiveAnimationRendererEventHandler()
+ {
+ }
+
+ /**
+ * virtual destructor
+ */
+ virtual ~RiveAnimationRendererEventHandler()
+ {
+ }
+
+ // Undefined copy constructor.
+ RiveAnimationRendererEventHandler(const RiveAnimationRendererEventHandler&) = delete;
+
+ // Undefined assignment operator.
+ RiveAnimationRendererEventHandler& operator=(const RiveAnimationRendererEventHandler&) = delete;
+};
+
+} // namespace Internal
+
+} // namespace Extension
+
+} // namespace Dali
+
+#endif // DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_EVENT_HANDLER_H
--- /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/internal/rive-animation-view/animation-renderer/rive-animation-renderer-manager.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+
+namespace Dali
+{
+namespace Extension
+{
+namespace Internal
+{
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gRiveAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RIVE_ANIMATION");
+#endif
+} // unnamed namespace
+
+RiveAnimationRendererManager& RiveAnimationRendererManager::Get()
+{
+ static RiveAnimationRendererManager animationManager;
+ return animationManager;
+}
+
+RiveAnimationRendererManager::RiveAnimationRendererManager()
+: mEventHandlers(),
+ mTriggeredHandlers(),
+ mMutex(),
+ mEventTrigger()
+{
+}
+
+RiveAnimationRendererManager::~RiveAnimationRendererManager()
+{
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRendererManager::~RiveAnimationRendererManager: this = %p\n", this);
+}
+
+void RiveAnimationRendererManager::AddEventHandler( RiveAnimationRendererEventHandler& handler )
+{
+ if( mEventHandlers.end() == std::find( mEventHandlers.begin(), mEventHandlers.end(), &handler ) )
+ {
+ if( mEventHandlers.empty() )
+ {
+ Adaptor::Get().RegisterProcessor( *this );
+ }
+
+ mEventHandlers.push_back( &handler );
+
+ {
+ Dali::Mutex::ScopedLock lock( mMutex );
+
+ if( !mEventTrigger )
+ {
+ mEventTrigger = std::unique_ptr< EventThreadCallback >( new EventThreadCallback( MakeCallback( this, &RiveAnimationRendererManager::OnEventTriggered ) ) );
+ }
+ }
+ }
+}
+
+void RiveAnimationRendererManager::RemoveEventHandler( RiveAnimationRendererEventHandler& handler )
+{
+ auto iter = std::find( mEventHandlers.begin(), mEventHandlers.end(), &handler );
+ if( iter != mEventHandlers.end() )
+ {
+ mEventHandlers.erase( iter );
+ }
+
+ bool releaseEventTrigger = false;
+
+ if( mEventHandlers.empty() )
+ {
+ if( Adaptor::IsAvailable() )
+ {
+ Adaptor::Get().UnregisterProcessor( *this );
+ }
+
+ releaseEventTrigger = true;
+ }
+
+ {
+ Dali::Mutex::ScopedLock lock( mMutex );
+
+ auto triggeredHandler = std::find( mTriggeredHandlers.begin(), mTriggeredHandlers.end(), &handler );
+ if( triggeredHandler != mTriggeredHandlers.end() )
+ {
+ mTriggeredHandlers.erase( triggeredHandler );
+ }
+
+ if( releaseEventTrigger )
+ {
+ mEventTrigger.reset();
+ }
+ }
+}
+
+void RiveAnimationRendererManager::TriggerEvent( RiveAnimationRendererEventHandler& handler )
+{
+ Dali::Mutex::ScopedLock lock( mMutex );
+
+ if( mTriggeredHandlers.end() == std::find( mTriggeredHandlers.begin(), mTriggeredHandlers.end(), &handler ) )
+ {
+ mTriggeredHandlers.push_back( &handler );
+
+ if( mEventTrigger )
+ {
+ mEventTrigger->Trigger();
+ }
+ }
+}
+
+void RiveAnimationRendererManager::Process(bool postProcessor)
+{
+ OnEventTriggered();
+}
+
+// This function is called in the main thread.
+void RiveAnimationRendererManager::OnEventTriggered()
+{
+ std::vector< RiveAnimationRendererEventHandler* > handlers;
+
+ {
+ Dali::Mutex::ScopedLock lock( mMutex );
+
+ // Copy the list to the local variable and clear
+ handlers = mTriggeredHandlers;
+ mTriggeredHandlers.clear();
+ }
+
+ for( auto&& iter : handlers )
+ {
+ // Check if it is valid
+ auto handler = std::find( mEventHandlers.begin(), mEventHandlers.end(), iter );
+ if( handler != mEventHandlers.end() )
+ {
+ iter->NotifyEvent();
+ }
+ }
+}
+
+} // namespace Internal
+
+} // namespace Extension
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_MANAGER_H
+#define DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_MANAGER_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/event-thread-callback.h>
+#include <dali/integration-api/processor-interface.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-extension/internal/rive-animation-view/animation-renderer/rive-animation-renderer-event-handler.h>
+
+namespace Dali
+{
+namespace Extension
+{
+namespace Internal
+{
+
+/**
+ * @brief Rive animation renderer manager
+ */
+class RiveAnimationRendererManager : public Integration::Processor
+{
+public:
+
+ /**
+ * @brief Create or retrieve RiveAnimationRendererManager singleton.
+ *
+ * @return A reference to the RiveAnimationRendererManager.
+ */
+ static RiveAnimationRendererManager& Get();
+
+ /**
+ * @brief Add the event handler.
+ *
+ * @param handler The event handler to add.
+ */
+ void AddEventHandler(RiveAnimationRendererEventHandler& handler);
+
+ /**
+ * @brief Remove the event handler.
+ *
+ * @param handler The event handler to remove.
+ */
+ void RemoveEventHandler(RiveAnimationRendererEventHandler& handler);
+
+ /**
+ * @brief Trigger the event.
+ */
+ void TriggerEvent(RiveAnimationRendererEventHandler& handler);
+
+protected: // Implementation of Processor
+
+ /**
+ * @copydoc Dali::Integration::Processor::Process()
+ */
+ void Process(bool postProcessor) override;
+
+private:
+
+ /**
+ * @brief Event callback to process events.
+ */
+ void OnEventTriggered();
+
+private:
+
+ /**
+ * @brief Constructor.
+ */
+ RiveAnimationRendererManager();
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~RiveAnimationRendererManager();
+
+ // Undefined
+ RiveAnimationRendererManager(const RiveAnimationRendererManager&) = delete;
+
+ // Undefined
+ RiveAnimationRendererManager& operator=(const RiveAnimationRendererManager&) = delete;
+
+private:
+
+ std::vector<RiveAnimationRendererEventHandler*> mEventHandlers;
+ std::vector<RiveAnimationRendererEventHandler*> mTriggeredHandlers;
+ Dali::Mutex mMutex;
+ std::unique_ptr<EventThreadCallback> mEventTrigger;
+};
+
+} // namespace Internal
+
+} // namespace Extension
+
+} // namespace Dali
+
+#endif // DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_MANAGER_H
--- /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/internal/rive-animation-view/animation-renderer/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/internal/rive-animation-view/animation-renderer/rive-animation-renderer-manager.h>
+
+namespace Dali
+{
+namespace Extension
+{
+namespace Internal
+{
+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);
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gRiveAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RIVE_ANIMATION");
+#endif
+} // unnamed namespace
+
+RiveAnimationRenderer::RiveAnimationRenderer()
+: 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);
+}
+
+RiveAnimationRenderer::~RiveAnimationRenderer()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mAnimationInstance)
+ {
+ delete mAnimationInstance;
+ }
+
+ if(mFile)
+ {
+ delete mFile;
+ }
+
+ mSwCanvas->clear();
+ tvg::Initializer::term(tvg::CanvasEngine::Sw);
+
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::~RiveAnimationRenderer: this = %p\n", this);
+}
+
+void RiveAnimationRenderer::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 RiveAnimationRenderer::Load(const std::string& url)
+{
+ mUrl = url;
+ LoadRiveFile(mUrl);
+ RiveAnimationRendererManager::Get().AddEventHandler(*this);
+
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Initialize: file [%s] [%p]\n", url.c_str(), this);
+
+ return true;
+}
+
+void RiveAnimationRenderer::Finalize()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ RiveAnimationRendererManager::Get().RemoveEventHandler(*this);
+
+ mRenderer.Reset();
+ mTexture.Reset();
+ mRenderedTexture.Reset();
+ mPreviousTexture.Reset();
+
+ mTargetSurface = nullptr;
+ mTbmQueue = nullptr;
+
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Finalize: [%p]\n", this);
+}
+
+void RiveAnimationRenderer::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 RiveAnimationRenderer::SetSize(uint32_t width, uint32_t height)
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mWidth == width && mHeight == height)
+ {
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::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_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::SetSize: width = %d, height = %d [%p]\n", mWidth, mHeight, this);
+}
+
+bool RiveAnimationRenderer::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("RiveAnimationRenderer::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("RiveAnimationRenderer::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->mempool(tvg::SwCanvas::MempoolPolicy::Individual);
+
+ }
+ mSwCanvas->clear();
+ mSwCanvas->target((uint32_t*)buffer, info.planes[0].stride / 4, info.width, info.height, tvg::SwCanvas::ARGB8888);
+
+ // 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;
+
+ RiveAnimationRendererManager::Get().TriggerEvent(*this);
+
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::Render: Resource ready [current = %d] [%p]\n", frameNumber, this);
+ }
+
+ return true;
+}
+
+uint32_t RiveAnimationRenderer::GetTotalFrameNumber() const
+{
+ return mTotalFrameNumber;
+}
+
+float RiveAnimationRenderer::GetFrameRate() const
+{
+ return mFrameRate;
+}
+
+void RiveAnimationRenderer::GetDefaultSize(uint32_t& width, uint32_t& height) const
+{
+ width = mDefaultWidth;
+ height = mDefaultHeight;
+}
+
+void RiveAnimationRenderer::IgnoreRenderedFrame()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mTargetSurface)
+ {
+ mTargetSurface->IgnoreSourceImage();
+ }
+}
+
+RiveAnimationRenderer::UploadCompletedSignalType& RiveAnimationRenderer::UploadCompletedSignal()
+{
+ return mUploadCompletedSignal;
+}
+
+void RiveAnimationRenderer::NotifyEvent()
+{
+ Dali::Mutex::ScopedLock lock(mMutex);
+
+ if(mResourceReadyTriggered)
+ {
+ DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationRenderer::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();
+}
+
+void RiveAnimationRenderer::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 Internal
+
+} // namespace Extension
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_H
+#define DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_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/public-api/rendering/renderer.h>
+#include <dali/devel-api/threading/mutex.h>
+#include <dali/devel-api/adaptor-framework/native-image-source-queue.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/internal/rive-animation-view/animation-renderer/rive-animation-renderer-event-handler.h>
+
+namespace Dali
+{
+namespace Extension
+{
+namespace Internal
+{
+class RiveAnimationRenderer;
+using RiveAnimationRendererPtr = IntrusivePtr<RiveAnimationRenderer>;
+
+/**
+ * @brief Implementation of the Rive animation renderer class which has Tizen platform dependency.
+ */
+class RiveAnimationRenderer : public RefObject, public RiveAnimationRendererEventHandler
+{
+public:
+ /**
+ * @brief UploadCompleted signal type.
+ */
+ using UploadCompletedSignalType = Signal<void()>;
+
+ /**
+ * @brief Constructor.
+ */
+ RiveAnimationRenderer();
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~RiveAnimationRenderer();
+
+ /**
+ * @brief Loads the animation file.
+ *
+ * @param[in] url The url of the vector animation file
+ * @return True if loading success, false otherwise.
+ */
+ bool Load(const std::string& url);
+
+ /**
+ * @brief Finalizes the renderer. It will be called in the main thread.
+ */
+ void Finalize();
+
+ /**
+ * @brief Sets the renderer used to display the result image.
+ *
+ * @param[in] renderer The renderer used to display the result image
+ */
+ void SetRenderer(Renderer renderer);
+
+ /**
+ * @brief Sets the target image size.
+ *
+ * @param[in] width The target image width
+ * @param[in] height The target image height
+ */
+ void SetSize(uint32_t width, uint32_t height);
+
+ /**
+ * @brief Renders the content to the target buffer synchronously.
+ *
+ * @param[in] frameNumber The frame number to be rendered
+ * @return True if the rendering success, false otherwise.
+ */
+ bool Render(uint32_t frameNumber);
+
+ /**
+ * @brief Gets the total number of frames of the file.
+ *
+ * @return The total number of frames
+ */
+ uint32_t GetTotalFrameNumber() const;
+
+ /**
+ * @brief Gets the frame rate of the file.
+ *
+ * @return The frame rate of the file
+ */
+ float GetFrameRate() const;
+
+ /**
+ * @brief Gets the default size of the file.
+ *
+ * @param[out] width The default width of the file
+ * @param[out] height The default height of the file
+ */
+ void GetDefaultSize(uint32_t& width, uint32_t& height) const;
+
+ /**
+ * @brief Ignores a rendered frame which is not shown yet.
+ */
+ void IgnoreRenderedFrame();
+
+ /**
+ * @brief Connect to this signal to be notified when the texture upload is completed.
+ *
+ * @return The signal to connect to.
+ */
+ UploadCompletedSignalType& UploadCompletedSignal();
+
+protected: // Implementation of RiveAnimationRendererEventHandler
+
+ /**
+ * @copydoc Dali::Plugin::RiveAnimationRendererEventHandler::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 Internal
+
+} // namespace Extension
+
+} // namespace Dali
+
+#endif // DALI_EXTENSION_INTERNAL_RIVE_ANIMATION_RENDERER_H
$(extension_src_dir)/internal/rive-animation-view/rive-animation-thread.h \
$(extension_src_dir)/internal/rive-animation-view/rive-animation-view-impl.h \
$(extension_src_dir)/internal/rive-animation-view/rive-rasterize-thread.h \
- $(extension_src_dir)/internal/rive-animation-view/round-robin-container-view.h
+ $(extension_src_dir)/internal/rive-animation-view/round-robin-container-view.h \
+ $(extension_src_dir)/internal/rive-animation-view/animation-renderer/rive-animation-renderer.h \
+ $(extension_src_dir)/internal/rive-animation-view/animation-renderer/rive-animation-renderer-event-handler.h \
+ $(extension_src_dir)/internal/rive-animation-view/animation-renderer/rive-animation-renderer-manager.h
rive_animation_view_internal_src_files = \
$(extension_src_dir)/internal/rive-animation-view/rive-animation-manager.cpp \
$(extension_src_dir)/internal/rive-animation-view/rive-animation-task.cpp \
$(extension_src_dir)/internal/rive-animation-view/rive-animation-thread.cpp \
$(extension_src_dir)/internal/rive-animation-view/rive-animation-view-impl.cpp \
- $(extension_src_dir)/internal/rive-animation-view/rive-rasterize-thread.cpp
+ $(extension_src_dir)/internal/rive-animation-view/rive-rasterize-thread.cpp \
+ $(extension_src_dir)/internal/rive-animation-view/animation-renderer/rive-animation-renderer.cpp \
+ $(extension_src_dir)/internal/rive-animation-view/animation-renderer/rive-animation-renderer-manager.cpp
{
namespace
{
-constexpr auto LOOP_FOREVER = -1;
constexpr auto MICROSECONDS_PER_SECOND(1e+6);
#if defined(DEBUG_ENABLED)
Debug::Filter* gRiveAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RIVE_ANIMATION");
#endif
-
} // unnamed namespace
RiveAnimationTask::RiveAnimationTask()
: mUrl(),
- mVectorRenderer(VectorAnimationRenderer::New()),
+ mVectorRenderer(new RiveAnimationRenderer()),
mAnimationData(),
mRiveAnimationThread(RiveAnimationManager::GetInstance().GetRiveAnimationThread()),
mConditionalWait(),
mAnimationFinishedTrigger.reset();
}
- mVectorRenderer.Finalize();
+ mVectorRenderer->Finalize();
mDestroyTask = true;
}
{
mUrl = url;
- if(!mVectorRenderer.Load(mUrl))
+ if(!mVectorRenderer->Load(mUrl))
{
DALI_LOG_ERROR("RiveAnimationTask::Load: Load failed [%s]\n", mUrl.c_str());
return false;
}
- mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
+ mTotalFrame = mVectorRenderer->GetTotalFrameNumber();
mEndFrame = mTotalFrame - 1;
- mFrameRate = mVectorRenderer.GetFrameRate();
+ mFrameRate = mVectorRenderer->GetFrameRate();
mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate;
uint32_t width, height;
- mVectorRenderer.GetDefaultSize(width, height);
+ mVectorRenderer->GetDefaultSize(width, height);
SetSize(width, height);
{
ConditionalWait::ScopedLock lock(mConditionalWait);
- mVectorRenderer.SetRenderer(renderer);
+ mVectorRenderer->SetRenderer(renderer);
DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationTask::SetRenderer [%p]\n", this);
}
{
if(mWidth != width || mHeight != height)
{
- mVectorRenderer.SetSize(width, height);
+ mVectorRenderer->SetSize(width, height);
mWidth = width;
mHeight = height;
void RiveAnimationTask::GetDefaultSize(uint32_t& width, uint32_t& height) const
{
- mVectorRenderer.GetDefaultSize(width, height);
+ mVectorRenderer->GetDefaultSize(width, height);
}
RiveAnimationTask::UploadCompletedSignalType& RiveAnimationTask::UploadCompletedSignal()
{
- return mVectorRenderer.UploadCompletedSignal();
+ return mVectorRenderer->UploadCompletedSignal();
}
bool RiveAnimationTask::Rasterize()
bool renderSuccess = false;
if(mVectorRenderer)
{
- renderSuccess = mVectorRenderer.Render(currentFrame);
+ renderSuccess = mVectorRenderer->Render(currentFrame);
if(!renderSuccess)
{
DALI_LOG_INFO(gRiveAnimationLogFilter, Debug::Verbose, "RiveAnimationTask::Rasterize: Rendering failed. Try again later.[%d] [%p]\n", currentFrame, this);
// EXTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/event-thread-callback.h>
-#include <dali/devel-api/adaptor-framework/vector-animation-renderer.h>
#include <dali/devel-api/threading/conditional-wait.h>
#include <dali/public-api/object/property-array.h>
#include <chrono>
// INTERNAL INCLUDES
#include <dali-extension/devel-api/rive-animation-view/rive-animation-view.h>
+#include <dali-extension/internal/rive-animation-view/animation-renderer/rive-animation-renderer.h>
namespace Dali
{
class RiveAnimationTask : public RefObject
{
public:
- using UploadCompletedSignalType = Dali::VectorAnimationRenderer::UploadCompletedSignalType;
+ using UploadCompletedSignalType = RiveAnimationRenderer::UploadCompletedSignalType;
using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
};
std::string mUrl;
- VectorAnimationRenderer mVectorRenderer;
+ RiveAnimationRendererPtr mVectorRenderer;
AnimationData mAnimationData[2];
RiveAnimationThread& mRiveAnimationThread;
ConditionalWait mConditionalWait;
$(extension_src_dir)/vector-animation-renderer/tizen-vector-animation-renderer.cpp \
$(extension_src_dir)/vector-animation-renderer/tizen-vector-animation-manager.cpp
-rive_animation_renderer_plugin_src_files = \
- $(extension_src_dir)/vector-animation-renderer/tizen-rive-animation-renderer.cpp \
- $(extension_src_dir)/vector-animation-renderer/tizen-vector-animation-manager.cpp
-
+++ /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->mempool(tvg::SwCanvas::MempoolPolicy::Individual);
-
- }
- mSwCanvas->clear();
- mSwCanvas->target((uint32_t*)buffer, info.planes[0].stride / 4, info.width, info.height, tvg::SwCanvas::ARGB8888);
-
- // 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
URL: https://review.tizen.org/git/?p=platform/core/uifw/dali-extensions.git;a=summary
Source0: %{name}-%{version}.tar.gz
+%if 0%{?tizen_version_major} >= 4
+%define tizen_40_or_greater 1
+%endif
+
+%if 0%{?tizen_version_major} >= 5
+%define tizen_50_or_greater 1
+%endif
+
+%if ( 0%{?tizen_version_major} == 5 && 0%{?tizen_version_minor} >= 5 ) || 0%{?tizen_version_major} >= 6
+%define tizen_55_or_greater 1
+%endif
+
+%if ( 0%{?tizen_version_major} == 6 && 0%{?tizen_version_minor} >= 5 ) || 0%{?tizen_version_major} >= 7
+%define tizen_65_or_greater 1
+%endif
+
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig
BuildRequires: pkgconfig(evas)
BuildRequires: pkgconfig(ecore-wl2)
-%description
-dali-extension
-
-%if 0%{?tizen_version_major} >= 4
-%define tizen_40_or_greater 1
-%endif
-
-%if 0%{?tizen_version_major} >= 5
-%define tizen_50_or_greater 1
+%if 0%{?tizen_65_or_greater}
+BuildRequires: pkgconfig(rive_tizen)
%endif
-%if ( 0%{?tizen_version_major} == 5 && 0%{?tizen_version_minor} >= 5 ) || 0%{?tizen_version_major} >= 6
-%define tizen_55_or_greater 1
-%endif
+%description
+dali-extension
-%if ( 0%{?tizen_version_major} == 6 && 0%{?tizen_version_minor} >= 5 ) || 0%{?tizen_version_major} >= 7
-%define tizen_65_or_greater 1
-%endif
#############################
# devel
%description vector-animation-renderer-plugin
Plugin to render a vector animation
-####################################
-# Rive Animation Renderer Plugin
-####################################
-%package rive-animation-renderer-plugin
-Summary: Plugin to render a rive animation
-Group: System/Libraries
-%if 0%{?tizen_65_or_greater}
-BuildRequires: pkgconfig(rive_tizen)
-%endif
-%description rive-animation-renderer-plugin
-
####################################
# Vector Image Renderer Plugin
####################################
%license LICENSE
%endif
-%if 0%{?tizen_65_or_greater}
-%files rive-animation-renderer-plugin
-%manifest dali-extension.manifest
-%defattr(-,root,root,-)
-%{_libdir}/libdali2-rive-animation-renderer-plugin.so*
-%license LICENSE
-%endif
-
%files color-controller-plugin
%manifest dali-extension.manifest
%defattr(-,root,root,-)