X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-vector-image%2Fvector-animation-task.cpp;h=55968e10111f1a6907e938d5126c99c5482a45a4;hb=HEAD;hp=a746ba24dfabf201b3ea40b3f39e805ea3d1fa31;hpb=11b582e09858be2ea67299ca1b69449022c28d86;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index a746ba2..ac448c0 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -31,7 +31,10 @@ #include #ifdef TRACE_ENABLED +#include +#include #include +#include #endif namespace Dali @@ -51,6 +54,16 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false); +#ifdef TRACE_ENABLED +uint64_t GetNanoseconds() +{ + // Get the time of a monotonic clock since its epoch. + auto epoch = std::chrono::steady_clock::now().time_since_epoch(); + auto duration = std::chrono::duration_cast(epoch); + return static_cast(duration.count()); +} +#endif + } // unnamed namespace VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) @@ -60,7 +73,7 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) mVectorRenderer(VectorAnimationRenderer::New()), mAnimationData(), mVectorAnimationThread(factoryCache.GetVectorAnimationManager().GetVectorAnimationThread()), - mConditionalWait(), + mMutex(), mResourceReadySignal(), mLoadCompletedCallback(MakeCallback(this, &VectorAnimationTask::OnLoadCompleted)), mCachedLayerInfo(), @@ -79,11 +92,13 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) mWidth(0), mHeight(0), mAnimationDataIndex(0), + mAppliedPlayStateId(0u), mLoopCount(LOOP_FOREVER), mCurrentLoop(0), mForward(true), mUpdateFrameNumber(false), mNeedAnimationFinishedTrigger(true), + mNeedForceRenderOnceTrigger(false), mAnimationDataUpdated(false), mDestroyTask(false), mLoadRequest(false), @@ -93,6 +108,7 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) mLayerInfoCached(false), mMarkerInfoCached(false), mEnableFrameCache(false), + mNotifyAfterRasterization(false), mSizeUpdated(false) { mVectorRenderer.UploadCompletedSignal().Connect(this, &VectorAnimationTask::OnUploadCompleted); @@ -115,23 +131,25 @@ bool VectorAnimationTask::IsReady() void VectorAnimationTask::Finalize() { - ConditionalWait::ScopedLock lock(mConditionalWait); - - // Release some objects in the main thread - if(mAnimationFinishedCallback) - { - mVectorAnimationThread.RemoveEventTriggerCallbacks(mAnimationFinishedCallback.get()); - mAnimationFinishedCallback.reset(); - } - if(mLoadCompletedCallback) { - mVectorAnimationThread.RemoveEventTriggerCallbacks(mLoadCompletedCallback.get()); - mLoadCompletedCallback.reset(); + Mutex::ScopedLock lock(mMutex); + + // Release some objects in the main thread + if(mAnimationFinishedCallback) + { + mVectorAnimationThread.RemoveEventTriggerCallbacks(mAnimationFinishedCallback.get()); + mAnimationFinishedCallback.reset(); + } + if(mLoadCompletedCallback) + { + mVectorAnimationThread.RemoveEventTriggerCallbacks(mLoadCompletedCallback.get()); + mLoadCompletedCallback.reset(); + } + + mDestroyTask = true; } mVectorRenderer.Finalize(); - - mDestroyTask = true; } void VectorAnimationTask::TaskCompleted(VectorAnimationTaskPtr task) @@ -152,8 +170,11 @@ bool VectorAnimationTask::IsAnimating() bool VectorAnimationTask::Load(bool synchronousLoading) { #ifdef TRACE_ENABLED + uint64_t mStartTimeNanoSceonds = 0; + uint64_t mEndTimeNanoSceonds = 0; if(gTraceFilter && gTraceFilter->IsTraceEnabled()) { + mStartTimeNanoSceonds = GetNanoseconds(); std::ostringstream oss; oss << "[u:" << mImageUrl.GetEllipsedUrl() << "]"; // DALI_TRACE_BEGIN(gTraceFilter, "DALI_LOTTIE_LOADING_TASK"); ///< TODO : Open it if we can control trace log level @@ -193,17 +214,21 @@ bool VectorAnimationTask::Load(bool synchronousLoading) DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mImageUrl.GetUrl().c_str()); mLoadRequest = false; { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); if(!synchronousLoading && mLoadCompletedCallback) { - mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get()); + mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get(), 0u); } } #ifdef TRACE_ENABLED if(gTraceFilter && gTraceFilter->IsTraceEnabled()) { + mEndTimeNanoSceonds = GetNanoseconds(); std::ostringstream oss; - oss << "[u:" << mImageUrl.GetEllipsedUrl() << "]"; + oss << std::fixed << std::setprecision(3); + oss << "["; + oss << "d:" << static_cast(mEndTimeNanoSceonds - mStartTimeNanoSceonds) / 1000000.0f << "ms "; + oss << "u:" << mImageUrl.GetEllipsedUrl() << "]"; // DALI_TRACE_END(gTraceFilter, "DALI_LOTTIE_LOADING_TASK"); ///< TODO : Open it if we can control trace log level DALI_LOG_RELEASE_INFO("END: DALI_LOTTIE_LOADING_TASK %s", oss.str().c_str()); } @@ -220,10 +245,10 @@ bool VectorAnimationTask::Load(bool synchronousLoading) mLoadRequest = false; { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); if(!synchronousLoading && mLoadCompletedCallback) { - mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get()); + mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get(), 0u); } } @@ -232,8 +257,12 @@ bool VectorAnimationTask::Load(bool synchronousLoading) #ifdef TRACE_ENABLED if(gTraceFilter && gTraceFilter->IsTraceEnabled()) { + mEndTimeNanoSceonds = GetNanoseconds(); std::ostringstream oss; - oss << "[u:" << mImageUrl.GetEllipsedUrl() << "]"; + oss << std::fixed << std::setprecision(3); + oss << "["; + oss << "d:" << static_cast(mEndTimeNanoSceonds - mStartTimeNanoSceonds) / 1000000.0f << "ms "; + oss << "u:" << mImageUrl.GetEllipsedUrl() << "]"; // DALI_TRACE_END(gTraceFilter, "DALI_LOTTIE_LOADING_TASK"); ///< TODO : Open it if we can control trace log level DALI_LOG_RELEASE_INFO("END: DALI_LOTTIE_LOADING_TASK %s", oss.str().c_str()); } @@ -244,8 +273,6 @@ bool VectorAnimationTask::Load(bool synchronousLoading) void VectorAnimationTask::SetRenderer(Renderer renderer) { - ConditionalWait::ScopedLock lock(mConditionalWait); - mVectorRenderer.SetRenderer(renderer); DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", this); @@ -266,7 +293,7 @@ void VectorAnimationTask::RequestLoad(const VisualUrl& url, EncodedImageBuffer e { Load(true); - OnLoadCompleted(); + OnLoadCompleted(0u); } } @@ -277,7 +304,7 @@ bool VectorAnimationTask::IsLoadRequested() const void VectorAnimationTask::SetAnimationData(const AnimationData& data) { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetAnimationData [%p]\n", this); @@ -351,13 +378,16 @@ void VectorAnimationTask::PauseAnimation() { mPlayState = PlayState::PAUSED; + // Ensure to render paused frame. + mNeedForceRenderOnceTrigger = true; + DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::PauseAnimation: Pause [%p]\n", this); } } void VectorAnimationTask::SetAnimationFinishedCallback(CallbackBase* callback) { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); mAnimationFinishedCallback = std::unique_ptr(callback); } @@ -442,10 +472,22 @@ void VectorAnimationTask::SetPlayRange(const Property::Array& playRange) if(mStartFrame > mCurrentFrame) { mCurrentFrame = mStartFrame; + + if(mPlayState != PlayState::PLAYING) + { + // Ensure to render current frame. + mNeedForceRenderOnceTrigger = true; + } } else if(mEndFrame < mCurrentFrame) { mCurrentFrame = mEndFrame; + + if(mPlayState != PlayState::PLAYING) + { + // Ensure to render current frame. + mNeedForceRenderOnceTrigger = true; + } } DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%s] [%p]\n", mStartFrame, mEndFrame, mImageUrl.GetUrl().c_str(), this); @@ -471,6 +513,12 @@ void VectorAnimationTask::SetCurrentFrameNumber(uint32_t frameNumber) mCurrentFrame = frameNumber; mUpdateFrameNumber = false; + if(mPlayState != PlayState::PLAYING) + { + // Ensure to render current frame. + mNeedForceRenderOnceTrigger = true; + } + DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetCurrentFrameNumber: frame number = %d [%p]\n", mCurrentFrame, this); } else @@ -556,7 +604,7 @@ bool VectorAnimationTask::Rasterize() mKeepAnimation = false; { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); if(mDestroyTask) { // The task will be destroyed. We don't need rasterization. @@ -574,7 +622,12 @@ bool VectorAnimationTask::Rasterize() return false; } +#ifdef TRACE_ENABLED + uint64_t mStartTimeNanoSceonds = 0; + uint64_t mEndTimeNanoSceonds = 0; +#endif DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_LOTTIE_RASTERIZE_TASK", [&](std::ostringstream& oss) { + mStartTimeNanoSceonds = GetNanoseconds(); oss << "[s:" << mWidth << "x" << mHeight << " "; oss << "u:" << mImageUrl.GetEllipsedUrl() << "]"; }); @@ -663,6 +716,8 @@ bool VectorAnimationTask::Rasterize() mForward = true; mCurrentLoop = 0; + mNeedForceRenderOnceTrigger = true; + if(mVectorRenderer) { // Notify the Renderer that rendering is stopped. @@ -671,23 +726,35 @@ bool VectorAnimationTask::Rasterize() // Animation is finished { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); if(mNeedAnimationFinishedTrigger && mAnimationFinishedCallback) { - mVectorAnimationThread.AddEventTriggerCallback(mAnimationFinishedCallback.get()); + mVectorAnimationThread.AddEventTriggerCallback(mAnimationFinishedCallback.get(), mAppliedPlayStateId); } } DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Animation is finished [current = %d] [%p]\n", currentFrame, this); } + // Forcely trigger render once if need. + if(mNotifyAfterRasterization || mNeedForceRenderOnceTrigger) + { + Mutex::ScopedLock lock(mMutex); + mVectorAnimationThread.RequestForceRenderOnce(); + mNeedForceRenderOnceTrigger = false; + } + if(mPlayState != PlayState::PAUSED && mPlayState != PlayState::STOPPED) { mKeepAnimation = true; } DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_LOTTIE_RASTERIZE_TASK", [&](std::ostringstream& oss) { - oss << "[s:" << mWidth << "x" << mHeight << " "; + mEndTimeNanoSceonds = GetNanoseconds(); + oss << std::fixed << std::setprecision(3); + oss << "["; + oss << "d:" << static_cast(mEndTimeNanoSceonds - mStartTimeNanoSceonds) / 1000000.0f << "ms "; + oss << "s:" << mWidth << "x" << mHeight << " "; oss << "f:" << mCurrentFrame << " "; oss << "l:" << mCurrentLoop << " "; oss << "p:" << mPlayState << " "; @@ -770,7 +837,7 @@ void VectorAnimationTask::ApplyAnimationData() uint32_t index; { - ConditionalWait::ScopedLock lock(mConditionalWait); + Mutex::ScopedLock lock(mMutex); if(!mAnimationDataUpdated || mAnimationData[mAnimationDataIndex].size() != 0) { @@ -811,6 +878,11 @@ void VectorAnimationTask::ApplyAnimationData() SetCurrentFrameNumber(animationData.currentFrame); } + if(animationData.resendFlag & VectorAnimationTask::RESEND_NOTIFY_AFTER_RASTERIZATION) + { + mNotifyAfterRasterization = animationData.notifyAfterRasterization; + } + if(animationData.resendFlag & VectorAnimationTask::RESEND_NEED_RESOURCE_READY) { mVectorRenderer.InvalidateBuffer(); @@ -826,6 +898,7 @@ void VectorAnimationTask::ApplyAnimationData() if(animationData.resendFlag & VectorAnimationTask::RESEND_PLAY_STATE) { + mAppliedPlayStateId = animationData.playStateId; if(animationData.playState == DevelImageVisual::PlayState::PLAYING) { PlayAnimation(); @@ -850,7 +923,7 @@ void VectorAnimationTask::OnUploadCompleted() mResourceReadySignal.Emit(ResourceStatus::READY); } -void VectorAnimationTask::OnLoadCompleted() +void VectorAnimationTask::OnLoadCompleted(uint32_t /* not used */) { if(!mLoadFailed) {