From: Subhransu Mohanty Date: Fri, 10 Dec 2021 04:30:07 +0000 (+0900) Subject: Add lottie_init() and lottie_shutdown() c api. X-Git-Tag: submit/tizen_6.5/20220624.031255~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f6931097c040d9ec7d2b4fac4b1cd67f20cc77c7;p=platform%2Fcore%2Fuifw%2Flottie-player.git Add lottie_init() and lottie_shutdown() c api. To support dynamic loading and unloading of rlottie library safely we need to deallocate the resource cache as well as safely shutdown all the worker threads. current patch only stops the Render and Rle task schedulers when lottie_shutdown is called. Things yet to be implemented during shutdown phase - Unload image loader if loaded dynamically. - Check if we can release some cache resources. - Currently multiple load and unload of rlottie library will not work as we are not starting the scheduler again when lottie_init() called multiple time in the same process. Change-Id: Ifacf3882c4aec3ce87e9840d76f445e727a74f58 Signed-off-by: jykeon --- diff --git a/inc/rlottie_capi.h b/inc/rlottie_capi.h index 7c883fa..50daeeb 100644 --- a/inc/rlottie_capi.h +++ b/inc/rlottie_capi.h @@ -46,6 +46,36 @@ typedef enum { typedef struct Lottie_Animation_S Lottie_Animation; +/** + * @brief Runs lottie initialization code when rlottie library is loaded + * dynamically. + * + * + * This api should be called before any other api when rlottie library + * is loaded using dlopen() or equivalent. + * + * @see lottie_shutdown() + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API void lottie_init(); + +/** + * @brief Runs lottie teardown code when rlottie library is loaded + * dynamically. + * + * This api should be called before unloading the rlottie library for + * proper cleanup of the resource without doing so will result in undefined + * behaviour. + * + * @see lottie_init() + * + * @ingroup Lottie_Animation + * @internal + */ +RLOTTIE_API void lottie_shutdown(); + /** * @brief Constructs an animation object from file path. * diff --git a/src/binding/c/lottieanimation_capi.cpp b/src/binding/c/lottieanimation_capi.cpp index a54dac5..abbe2ba 100644 --- a/src/binding/c/lottieanimation_capi.cpp +++ b/src/binding/c/lottieanimation_capi.cpp @@ -26,6 +26,9 @@ using namespace rlottie; +extern void lottie_init_impl(); +extern void lottie_shutdown_impl(); + extern "C" { #include #include @@ -38,6 +41,34 @@ struct Lottie_Animation_S LOTMarkerList *mMarkerList; }; +static uint32_t _lottie_lib_ref_count = 0; + +RLOTTIE_API void lottie_init() +{ + if (_lottie_lib_ref_count > 0) { + _lottie_lib_ref_count++; + return; + } + lottie_init_impl(); + + _lottie_lib_ref_count = 1; +} + +RLOTTIE_API void lottie_shutdown() +{ + if (_lottie_lib_ref_count <= 0) { + // lottie_init() is not called before lottie_shutdown() + // or multiple shutdown is getting called. + return; + } + + _lottie_lib_ref_count--; + + if (_lottie_lib_ref_count == 0) { + lottie_shutdown_impl(); + } +} + RLOTTIE_API Lottie_Animation_S *lottie_animation_from_file(const char *path) { if (auto animation = Animation::loadFromFile(path) ) { diff --git a/src/lottie/lottieanimation.cpp b/src/lottie/lottieanimation.cpp index 601c065..afcc400 100644 --- a/src/lottie/lottieanimation.cpp +++ b/src/lottie/lottieanimation.cpp @@ -178,20 +178,29 @@ class RenderTaskScheduler { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n] { run(n); }); } + + IsRunning = true; } public: + static bool IsRunning; + static RenderTaskScheduler &instance() { static RenderTaskScheduler singleton; return singleton; } - ~RenderTaskScheduler() + ~RenderTaskScheduler() { stop(); } + + void stop() { - for (auto &e : _q) e.done(); + if (IsRunning) { + IsRunning = false; - for (auto &e : _threads) e.join(); + for (auto &e : _q) e.done(); + for (auto &e : _threads) e.join(); + } } std::future process(SharedRenderTask task) @@ -214,12 +223,16 @@ public: #else class RenderTaskScheduler { public: + static bool IsRunning; + static RenderTaskScheduler &instance() { static RenderTaskScheduler singleton; return singleton; } + void stop() {} + std::future process(SharedRenderTask task) { auto result = task->playerImpl->render(task->frameNo, task->surface, @@ -228,8 +241,11 @@ public: return std::move(task->receiver); } }; + #endif +bool RenderTaskScheduler::IsRunning{false}; + std::future AnimationImpl::renderAsync(size_t frameNo, Surface &&surface, bool keepAspectRatio) @@ -441,6 +457,29 @@ void Surface::setDrawRegion(size_t x, size_t y, size_t width, size_t height) mDrawArea.h = height; } +namespace { +void lottieShutdownRenderTaskScheduler() +{ + if (RenderTaskScheduler::IsRunning) { + RenderTaskScheduler::instance().stop(); + } +} +} // namespace + +// private apis exposed to c interface +void lottie_init_impl() +{ + // do nothing for now. +} + +extern void lottieShutdownRasterTaskScheduler(); + +void lottie_shutdown_impl() +{ + lottieShutdownRenderTaskScheduler(); + lottieShutdownRasterTaskScheduler(); +} + #ifdef LOTTIE_LOGGING_SUPPORT void initLogging() { diff --git a/src/vector/vraster.cpp b/src/vector/vraster.cpp index d64c0a6..fdf66fb 100644 --- a/src/vector/vraster.cpp +++ b/src/vector/vraster.cpp @@ -461,20 +461,29 @@ class RleTaskScheduler { for (unsigned n = 0; n != _count; ++n) { _threads.emplace_back([&, n] { run(n); }); } + + IsRunning = true; } public: + static bool IsRunning; + static RleTaskScheduler &instance() { static RleTaskScheduler singleton; return singleton; } - ~RleTaskScheduler() + ~RleTaskScheduler() { stop(); } + + void stop() { - for (auto &e : _q) e.done(); + if (IsRunning) { + IsRunning = false; - for (auto &e : _threads) e.join(); + for (auto &e : _q) e.done(); + for (auto &e : _threads) e.join(); + } } void process(VTask task) @@ -499,12 +508,16 @@ public: SW_FT_Stroker stroker; public: + static bool IsRunning; + static RleTaskScheduler &instance() { static RleTaskScheduler singleton; return singleton; } + void stop() {} + RleTaskScheduler() { SW_FT_Stroker_New(&stroker); } ~RleTaskScheduler() { SW_FT_Stroker_Done(stroker); } @@ -513,6 +526,8 @@ public: }; #endif +bool RleTaskScheduler::IsRunning{false}; + struct VRasterizer::VRasterizerImpl { VRleTask mTask; @@ -560,4 +575,11 @@ void VRasterizer::rasterize(VPath path, CapStyle cap, JoinStyle join, updateRequest(); } +void lottieShutdownRasterTaskScheduler() +{ + if (RleTaskScheduler::IsRunning) { + RleTaskScheduler::instance().stop(); + } +} + V_END_NAMESPACE