Fix Segfault issue on lottie 37/306837/10
authorseungho baek <sbsh.baek@samsung.com>
Wed, 28 Feb 2024 06:42:37 +0000 (15:42 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Wed, 28 Feb 2024 09:23:33 +0000 (18:23 +0900)
Change-Id: Ie615835324c84cd936316d4ba65d76598a881965
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
dali-extension/vector-animation-renderer/vector-animation-renderer-tizen.cpp
dali-extension/vector-animation-renderer/vector-animation-renderer-tizen.h
dali-extension/vector-animation-renderer/vector-animation-renderer-x.cpp
dali-extension/vector-animation-renderer/vector-animation-renderer-x.h
dali-extension/vector-animation-renderer/vector-animation-renderer.cpp
dali-extension/vector-animation-renderer/vector-animation-renderer.h

index f242fcecfade1091a8dc61c61aaddb6a5da44aac..f15e0a7e980cd0cc4269c9ebe32389608bda4269 100644 (file)
@@ -61,10 +61,6 @@ VectorAnimationRendererTizen::VectorAnimationRendererTizen()
   mRenderedTexture(),
   mPreviousTextures()
 {
-  mRenderingDataImpl[0] = std::make_shared<RenderingDataImpl>();
-  mRenderingDataImpl[1] = std::make_shared<RenderingDataImpl>();
-  mRenderingData[0]     = mRenderingDataImpl[0];
-  mRenderingData[1]     = mRenderingDataImpl[1];
 }
 
 VectorAnimationRendererTizen::~VectorAnimationRendererTizen()
@@ -78,14 +74,22 @@ VectorAnimationRendererTizen::~VectorAnimationRendererTizen()
 // Called by VectorAnimationTaskThread
 bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 {
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
   {
     Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
-    mCurrentRenderingData = mRenderingDataImpl[mCurrentDataIndex];
-    if(IsRenderingDataUpdated())
+    if(mPreparedRenderingData)
     {
+      mPreviousRenderingData.push_back(mCurrentRenderingData);
+      mCurrentRenderingData = mPreparedRenderingData;
+      mPreparedRenderingData.reset();
       mResourceReady = false;
-      mIsDataActivated = true;
     }
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mCurrentRenderingData);
+  }
+
+  if(!renderingDataImpl)
+  {
+    return false;
   }
 
   Dali::Mutex::ScopedLock lock(mMutex);
@@ -98,19 +102,19 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
     }
   }
 
-  if(!mCurrentRenderingData->mTbmQueue || !mVectorRenderer || !mCurrentRenderingData->mTargetSurface)
+  if(!renderingDataImpl->mTbmQueue || !mVectorRenderer || !renderingDataImpl->mTargetSurface)
   {
     return false;
   }
 
-  int canDequeue = tbm_surface_queue_can_dequeue(mCurrentRenderingData->mTbmQueue, 0);
+  int canDequeue = tbm_surface_queue_can_dequeue(renderingDataImpl->mTbmQueue, 0);
   if(!canDequeue)
   {
     // Ignore the previous image which is inserted to the queue.
-    mCurrentRenderingData->mTargetSurface->IgnoreSourceImage();
+    renderingDataImpl->mTargetSurface->IgnoreSourceImage();
 
     // Check again
-    canDequeue = tbm_surface_queue_can_dequeue(mCurrentRenderingData->mTbmQueue, 0);
+    canDequeue = tbm_surface_queue_can_dequeue(renderingDataImpl->mTbmQueue, 0);
     if(!canDequeue)
     {
       return false;
@@ -119,7 +123,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
   tbm_surface_h tbmSurface;
 
-  if(tbm_surface_queue_dequeue(mCurrentRenderingData->mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
+  if(tbm_surface_queue_dequeue(renderingDataImpl->mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
   {
     DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", this);
     return false;
@@ -139,16 +143,16 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
   if(ret != TBM_SURFACE_ERROR_NONE)
   {
     DALI_LOG_ERROR("VectorAnimationRendererTizen::Render: tbm_surface_map is failed! [%d] [%p]\n", ret, this);
-    tbm_surface_queue_cancel_dequeue(mCurrentRenderingData->mTbmQueue, tbmSurface);
+    tbm_surface_queue_cancel_dequeue(renderingDataImpl->mTbmQueue, tbmSurface);
     return false;
   }
 
   unsigned char* buffer = info.planes[0].ptr;
-  if(info.width != mCurrentRenderingData->mWidth || info.height != mCurrentRenderingData->mHeight || !buffer)
+  if(info.width != renderingDataImpl->mWidth || info.height != renderingDataImpl->mHeight || !buffer)
   {
     DALI_LOG_ERROR("VectorAnimationRendererTizen::Render: Invalid tbm surface! [%d, %d, %p] [%p]\n", info.width, info.height, buffer, this);
     tbm_surface_unmap(tbmSurface);
-    tbm_surface_queue_cancel_dequeue(mCurrentRenderingData->mTbmQueue, tbmSurface);
+    tbm_surface_queue_cancel_dequeue(renderingDataImpl->mTbmQueue, tbmSurface);
     return false;
   }
 
@@ -176,7 +180,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
   if(mEnableFixedCache && (frameNumber < mDecodedBuffers.size()) && mDecodedBuffers[frameNumber].second)
   {
-    const int bufferSize = mCurrentRenderingData->mWidth * mCurrentRenderingData->mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
+    const int bufferSize = renderingDataImpl->mWidth * renderingDataImpl->mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
     memcpy(buffer, &mDecodedBuffers[frameNumber].first[0], bufferSize);
   }
   else
@@ -186,7 +190,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
       tbm_surface_internal_ref(tbmSurface);
 
       // Create Surface object
-      surface = rlottie::Surface(reinterpret_cast<uint32_t*>(buffer), mCurrentRenderingData->mWidth, mCurrentRenderingData->mHeight, static_cast<size_t>(info.planes[0].stride));
+      surface = rlottie::Surface(reinterpret_cast<uint32_t*>(buffer), renderingDataImpl->mWidth, renderingDataImpl->mHeight, static_cast<size_t>(info.planes[0].stride));
 
       // Push the buffer
       mBuffers.push_back(SurfacePair(tbmSurface, surface));
@@ -197,7 +201,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
     if(mEnableFixedCache && (frameNumber < mDecodedBuffers.size()))
     {
-      const uint32_t       bufferSize = mCurrentRenderingData->mWidth * mCurrentRenderingData->mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
+      const uint32_t       bufferSize = renderingDataImpl->mWidth * renderingDataImpl->mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
       std::vector<uint8_t> rasterizeBuffer(buffer, buffer + bufferSize);
       mDecodedBuffers[frameNumber].first  = std::move(rasterizeBuffer);
       mDecodedBuffers[frameNumber].second = true;
@@ -206,13 +210,13 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
   tbm_surface_unmap(tbmSurface);
 
-  tbm_surface_queue_enqueue(mCurrentRenderingData->mTbmQueue, tbmSurface);
+  tbm_surface_queue_enqueue(renderingDataImpl->mTbmQueue, tbmSurface);
 
   if(!mResourceReady)
   {
     mPreviousTextures.push_back(mRenderedTexture); // It is used to destroy the object in the main thread.
 
-    mRenderedTexture        = mCurrentRenderingData->mTexture;
+    mRenderedTexture        = renderingDataImpl->mTexture;
     mResourceReady          = true;
     mResourceReadyTriggered = true;
 
@@ -226,10 +230,16 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
 void VectorAnimationRendererTizen::RenderStopped()
 {
-  if(mCurrentRenderingData->mTargetSurface)
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mCurrentRenderingData);
+  }
+
+  if(renderingDataImpl && renderingDataImpl->mTargetSurface)
   {
     // Animation is stopped. Free empty buffers
-    mCurrentRenderingData->mTargetSurface->FreeReleasedBuffers();
+    renderingDataImpl->mTargetSurface->FreeReleasedBuffers();
 
     {
       Dali::Mutex::ScopedLock lock(mMutex);
@@ -238,6 +248,7 @@ void VectorAnimationRendererTizen::RenderStopped()
   }
 }
 
+// This Method is called inside mMutex
 void VectorAnimationRendererTizen::ResetBuffers()
 {
   for(auto&& iter : mBuffers)
@@ -247,40 +258,30 @@ void VectorAnimationRendererTizen::ResetBuffers()
   mBuffers.clear();
 }
 
+// This Method is called inside mRenderingDataMutex
 void VectorAnimationRendererTizen::OnFinalize()
 {
   mRenderedTexture.Reset();
   mPreviousTextures.clear();
-
-  for(auto&& renderingData : mRenderingDataImpl)
-  {
-    renderingData->mTargetSurface = nullptr;
-    renderingData->mTbmQueue      = nullptr;
-  }
 }
 
+// This Method is called inside mMutex
 void VectorAnimationRendererTizen::OnNotify()
 {
   // Reset the previous texture to destroy it in the main thread
   mPreviousTextures.clear();
-
-  // If RenderingData is updated, then clear previous renderingData
-  if(IsRenderingDataUpdated())
-  {
-    std::shared_ptr<RenderingDataImpl> oldRenderingData = mRenderingDataImpl[1u - mCurrentDataIndex];
-    oldRenderingData->mTargetSurface                    = nullptr;
-    oldRenderingData->mTbmQueue                         = nullptr;
-    SetRenderingDataUpdated(false);
-  }
 }
 
-void VectorAnimationRendererTizen::PrepareTarget(uint32_t updatedDataIndex)
+// This Method is called inside mRenderingDataMutex
+void VectorAnimationRendererTizen::PrepareTarget(std::shared_ptr<RenderingData> renderingData)
 {
-  mRenderingDataImpl[updatedDataIndex]->mTargetSurface = NativeImageSourceQueue::New(mRenderingDataImpl[updatedDataIndex]->mWidth, mRenderingDataImpl[updatedDataIndex]->mHeight, NativeImageSourceQueue::ColorFormat::RGBA8888);
-  mRenderingDataImpl[updatedDataIndex]->mTexture       = Texture::New(*mRenderingDataImpl[updatedDataIndex]->mTargetSurface);
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(renderingData);
+  renderingDataImpl->mTargetSurface = NativeImageSourceQueue::New(renderingDataImpl->mWidth, renderingDataImpl->mHeight, NativeImageSourceQueue::ColorFormat::BGRA8888);
+  renderingDataImpl->mTexture       = Texture::New(*renderingDataImpl->mTargetSurface);
 }
 
-void VectorAnimationRendererTizen::SetShader(uint32_t updatedDataIndex)
+// This Method is called inside mRenderingDataMutex
+void VectorAnimationRendererTizen::SetShader(std::shared_ptr<RenderingData> renderingData)
 {
   if(mShaderChanged)
   {
@@ -311,7 +312,12 @@ void VectorAnimationRendererTizen::SetShader(uint32_t updatedDataIndex)
   }
 
   // Get custom fragment shader prefix
-  mRenderingDataImpl[updatedDataIndex]->mTargetSurface->ApplyNativeFragmentShader(fragmentShader);
+  if(!renderingData)
+  {
+    DALI_LOG_ERROR("Target Surface is not yet prepared.\n");
+  }
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(renderingData);
+  renderingDataImpl->mTargetSurface->ApplyNativeFragmentShader(fragmentShader);
 
   // Set the modified shader again
   Shader newShader = Shader::New(vertexShader, fragmentShader);
@@ -322,27 +328,41 @@ void VectorAnimationRendererTizen::SetShader(uint32_t updatedDataIndex)
   mShaderChanged = true;
 }
 
-void VectorAnimationRendererTizen::OnSetSize(uint32_t updatedDataIndex)
+// This Method is called inside mRenderingDataMutex
+void VectorAnimationRendererTizen::OnSetSize(std::shared_ptr<RenderingData> renderingData)
 {
-  std::shared_ptr<RenderingDataImpl> renderingData = mRenderingDataImpl[updatedDataIndex];
-  renderingData->mTbmQueue                         = AnyCast<tbm_surface_queue_h>(renderingData->mTargetSurface->GetNativeImageSourceQueue());
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(renderingData);
+  renderingDataImpl->mTbmQueue                         = AnyCast<tbm_surface_queue_h>(renderingDataImpl->mTargetSurface->GetNativeImageSourceQueue());
 }
 
 bool VectorAnimationRendererTizen::IsTargetPrepared()
 {
-  return (mCurrentRenderingData) ? !!mCurrentRenderingData->mTargetSurface : false;
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mPreparedRenderingData ? mPreparedRenderingData : mCurrentRenderingData);
+  }
+  return (renderingDataImpl) ? !!renderingDataImpl->mTargetSurface : false;
 }
 
+// This Method is called inside mMutex
 bool VectorAnimationRendererTizen::IsRenderReady()
 {
   return (mResourceReady && mRenderedTexture);
 }
 
+// This Method is called inside mMutex
 Dali::Texture VectorAnimationRendererTizen::GetTargetTexture()
 {
   return mRenderedTexture;
 }
 
+// This Method is called inside mRenderingDataMutex
+std::shared_ptr<VectorAnimationRenderer::RenderingData> VectorAnimationRendererTizen::CreateRenderingData()
+{
+  return std::make_shared<RenderingDataImpl>();
+}
+
 } // namespace Plugin
 
 } // namespace Dali
index 6c0e97c871fd919f45e1390c2420537c3bffb9d8..3b87cd1a8657e98ca7d4030227982ab4389554a3 100644 (file)
@@ -84,17 +84,17 @@ private:
   /**
    * @copydoc VectorAnimationRenderer::PrepareTarget()
    */
-  void PrepareTarget(uint32_t updatedDataIndex) override;
+  void PrepareTarget(std::shared_ptr<RenderingData> renderingData) override;
 
   /**
    * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
    */
-  void SetShader(uint32_t updatedDataIndex) override;
+  void SetShader(std::shared_ptr<RenderingData> renderingData) override;
 
   /**
    * @copydoc VectorAnimationRenderer::OnSetSize()
    */
-  void OnSetSize(uint32_t updatedDataIndex) override;
+  void OnSetSize(std::shared_ptr<RenderingData> renderingData) override;
 
   /**
    * @copydoc VectorAnimationRenderer::IsTargetPrepared()
@@ -111,13 +111,16 @@ private:
    */
   Dali::Texture GetTargetTexture() override;
 
+  /**
+   * @copydoc VectorAnimationRenderer::CreateRenderingData()
+   */
+  std::shared_ptr<RenderingData> CreateRenderingData() override;
+
 private:
   using SurfacePair = std::pair<tbm_surface_h, rlottie::Surface>;
 
   std::vector<SurfacePair> mBuffers; ///< EGL Image vector
 
-  std::shared_ptr<RenderingDataImpl> mRenderingDataImpl[2];
-  std::shared_ptr<RenderingDataImpl> mCurrentRenderingData;
   Dali::Texture                      mRenderedTexture;  ///< Rendered Texture
   std::vector<Dali::Texture>         mPreviousTextures; ///< Previous rendered texture
 };
index 50070fd2ac1fb980c54f66e005584e91009e9496..7c55bdb45752185beb8c32af41950f852f865423 100644 (file)
@@ -56,10 +56,6 @@ public:
 VectorAnimationRendererX::VectorAnimationRendererX()
 : mRenderCallback(std::unique_ptr<EventThreadCallback>(new EventThreadCallback(MakeCallback(this, &VectorAnimationRendererX::OnLottieRendered))))
 {
-  mRenderingDataImpl[0] = std::make_shared<RenderingDataImpl>();
-  mRenderingDataImpl[1] = std::make_shared<RenderingDataImpl>();
-  mRenderingData[0] = mRenderingDataImpl[0];
-  mRenderingData[1] = mRenderingDataImpl[1];
 }
 
 VectorAnimationRendererX::~VectorAnimationRendererX()
@@ -72,23 +68,31 @@ VectorAnimationRendererX::~VectorAnimationRendererX()
 
 bool VectorAnimationRendererX::Render(uint32_t frameNumber)
 {
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
   {
     Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
-    mCurrentRenderingData = mRenderingDataImpl[mCurrentDataIndex];
-    if(IsRenderingDataUpdated())
+    if(mPreparedRenderingData)
     {
+      mPreviousRenderingData.push_back(mCurrentRenderingData);
+      mCurrentRenderingData = mPreparedRenderingData;
+      mPreparedRenderingData.reset();
       mResourceReady = false;
-      mIsDataActivated = true;
     }
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mCurrentRenderingData);
+  }
+
+  if(!renderingDataImpl)
+  {
+    return false;
   }
 
   Dali::Mutex::ScopedLock lock(mMutex);
-  if(!mVectorRenderer || !mCurrentRenderingData->mPixelBuffer)
+  if(!mVectorRenderer || !renderingDataImpl->mPixelBuffer)
   {
     return false;
   }
 
-  mVectorRenderer->renderSync(frameNumber, mCurrentRenderingData->mLottieSurface);
+  mVectorRenderer->renderSync(frameNumber, renderingDataImpl->mLottieSurface);
   mRenderCallback->Trigger();
 
   if(!mResourceReady)
@@ -106,55 +110,57 @@ void VectorAnimationRendererX::RenderStopped()
 {
 }
 
+// This Method is called inside mMutex
 void VectorAnimationRendererX::ResetBuffers()
 {
-  for(auto&& renderingData : mRenderingDataImpl)
-  {
-    if(renderingData->mPixelBuffer)
-    {
-      uint32_t bufferSize = renderingData->mPixelBuffer.GetWidth() * renderingData->mPixelBuffer.GetHeight() * Dali::Pixel::GetBytesPerPixel(renderingData->mPixelBuffer.GetPixelFormat());
-      memset(renderingData->mPixelBuffer.GetBuffer(), 0, bufferSize);
-    }
-  }
 }
 
+// This Method is called inside mRenderingDataMutex
 void VectorAnimationRendererX::OnFinalize()
 {
 }
 
 void VectorAnimationRendererX::OnLottieRendered()
 {
-  Dali::Mutex::ScopedLock lock(mMutex);
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mCurrentRenderingData);
+  }
 
-  if(mCurrentRenderingData->mPixelBuffer && mCurrentRenderingData->mTexture)
+  Dali::Mutex::ScopedLock lock(mMutex);
+  if(renderingDataImpl && renderingDataImpl->mPixelBuffer && renderingDataImpl->mTexture)
   {
-    PixelData pixelData = mCurrentRenderingData->mPixelBuffer.CreatePixelData();
-    mCurrentRenderingData->mTexture.Upload(pixelData);
+    PixelData pixelData = renderingDataImpl->mPixelBuffer.CreatePixelData();
+    renderingDataImpl->mTexture.Upload(pixelData);
   }
 }
 
+// This Method is called inside mMutex
 void VectorAnimationRendererX::OnNotify()
 {
-  // If RenderingData is updated, then clear previous renderingData
-  if(IsRenderingDataUpdated())
-  {
-    std::shared_ptr<RenderingDataImpl> oldRenderingData = mRenderingDataImpl[1u - mCurrentDataIndex];
-    SetRenderingDataUpdated(false);
-  }
 }
 
-void VectorAnimationRendererX::PrepareTarget(uint32_t updatedDataIndex)
+// This Method is called inside mRenderingDataMutex
+void VectorAnimationRendererX::PrepareTarget(std::shared_ptr<RenderingData> renderingData)
 {
-  mRenderingDataImpl[updatedDataIndex]->mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, Dali::Pixel::BGRA8888, mRenderingDataImpl[updatedDataIndex]->mWidth, mRenderingDataImpl[updatedDataIndex]->mHeight);
-
-  mRenderingDataImpl[updatedDataIndex]->mPixelBuffer   = Dali::Devel::PixelBuffer::New(mRenderingDataImpl[updatedDataIndex]->mWidth, mRenderingDataImpl[updatedDataIndex]->mHeight, Dali::Pixel::BGRA8888);
-  mRenderingDataImpl[updatedDataIndex]->mLottieSurface = rlottie::Surface(reinterpret_cast<uint32_t*>(mRenderingDataImpl[updatedDataIndex]->mPixelBuffer.GetBuffer()), mRenderingDataImpl[updatedDataIndex]->mWidth, mRenderingDataImpl[updatedDataIndex]->mHeight, static_cast<size_t>(mRenderingDataImpl[updatedDataIndex]->mPixelBuffer.GetStride() * 4));
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(renderingData);
+  renderingDataImpl->mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, Dali::Pixel::BGRA8888, renderingDataImpl->mWidth, renderingDataImpl->mHeight);
+  renderingDataImpl->mPixelBuffer   = Dali::Devel::PixelBuffer::New(renderingDataImpl->mWidth, renderingDataImpl->mHeight, Dali::Pixel::BGRA8888);
+  renderingDataImpl->mLottieSurface = rlottie::Surface(reinterpret_cast<uint32_t*>(renderingDataImpl->mPixelBuffer.GetBuffer()), renderingDataImpl->mWidth, renderingDataImpl->mHeight, static_cast<size_t>(renderingDataImpl->mPixelBuffer.GetStride() * 4));
 }
 
-void VectorAnimationRendererX::SetShader(uint32_t updatedDataIndex)
+// This Method is called inside mRenderingDataMutex
+void VectorAnimationRendererX::SetShader(std::shared_ptr<RenderingData> renderingData)
 {
-  std::shared_ptr<RenderingDataImpl> renderingData = mRenderingDataImpl[updatedDataIndex];
-  if(mShaderChanged || !renderingData->mTexture)
+  if(!renderingData)
+  {
+    DALI_LOG_ERROR("Target Surface is not yet prepared.\n");
+    return;
+  }
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(renderingData);
+
+  if(mShaderChanged || !renderingDataImpl->mTexture)
   {
     return;
   }
@@ -166,17 +172,40 @@ void VectorAnimationRendererX::SetShader(uint32_t updatedDataIndex)
 
 bool VectorAnimationRendererX::IsTargetPrepared()
 {
-  return (mCurrentRenderingData) ? !!mCurrentRenderingData->mPixelBuffer : false;
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mPreparedRenderingData ? mPreparedRenderingData : mCurrentRenderingData);
+  }
+  return (renderingDataImpl) ? !!renderingDataImpl->mPixelBuffer : false;
 }
 
+// This Method is called inside mMutex
 bool VectorAnimationRendererX::IsRenderReady()
 {
-  return mResourceReady && ((mCurrentRenderingData) ? !!mCurrentRenderingData->mTexture : false);
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mCurrentRenderingData);
+  }
+  return mResourceReady && ((renderingDataImpl) ? !!renderingDataImpl->mTexture : false);
 }
 
+// This Method is called inside mMutex
 Dali::Texture VectorAnimationRendererX::GetTargetTexture()
 {
-  return (mCurrentRenderingData) ? mCurrentRenderingData->mTexture : Texture();
+  std::shared_ptr<RenderingDataImpl> renderingDataImpl;
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    renderingDataImpl = std::static_pointer_cast<RenderingDataImpl>(mCurrentRenderingData);
+  }
+  return (renderingDataImpl) ? renderingDataImpl->mTexture : Texture();
+}
+
+// This Method is called inside mRenderingDataMutex
+std::shared_ptr<VectorAnimationRenderer::RenderingData> VectorAnimationRendererX::CreateRenderingData()
+{
+  return std::make_shared<RenderingDataImpl>();
 }
 
 } // namespace Plugin
index 91cc74d9aa77bec64b0b00e3ed3b672ada5d2135..e0cc49e84bd34dcf6146df316546b174d2238e10 100644 (file)
@@ -82,17 +82,18 @@ private:
   /**
    * @copydoc VectorAnimationRenderer::PrepareTarget()
    */
-  void PrepareTarget(uint32_t updatedDataIndex) override;
+  void PrepareTarget(std::shared_ptr<RenderingData> renderingData) override;
 
   /**
    * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
    */
-  void SetShader(uint32_t updatedDataIndex) override;
+  void SetShader(std::shared_ptr<RenderingData> renderingData) override;
 
   /**
    * @copydoc VectorAnimationRenderer::OnSetSize()
+   * @note This Method is called inside mRenderingDataMutex
    */
-  void OnSetSize(uint32_t updatedDataIndex) override
+  void OnSetSize(std::shared_ptr<RenderingData> renderingData) override
   {}
 
   /**
@@ -110,9 +111,12 @@ private:
    */
   Dali::Texture GetTargetTexture() override;
 
+  /**
+   * @copydoc VectorAnimationRenderer::CreateRenderingData()
+   */
+  std::shared_ptr<RenderingData> CreateRenderingData() override;
+
 private:
-  std::shared_ptr<RenderingDataImpl>   mRenderingDataImpl[2];
-  std::shared_ptr<RenderingDataImpl>   mCurrentRenderingData;
   std::unique_ptr<EventThreadCallback> mRenderCallback; ///
 };
 
index 0c2677a5e3f16cb28277be11ee101f1283a424fc..48fd7a73f0b50b19b2e5b4bf0fc1f6fb197533af 100644 (file)
@@ -68,24 +68,28 @@ VectorAnimationRenderer::~VectorAnimationRenderer()
 {
 }
 
+// This Method is called inside mRenderingDataMutex
+void VectorAnimationRenderer::ClearPreviousRenderingData()
+{
+  mPreviousRenderingData.clear();
+}
+
 void VectorAnimationRenderer::Finalize()
 {
-  VectorAnimationPluginManager::Get().RemoveEventHandler(*this);
+  Dali::Mutex::ScopedLock lock(mMutex);
 
-  {
-    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
-    mRenderingData[0]->mTexture.Reset();
-    mRenderingData[1]->mTexture.Reset();
+  VectorAnimationPluginManager::Get().RemoveEventHandler(*this);
 
-    OnFinalize();
-  }
+  mVectorRenderer.reset();
+  mPropertyCallbacks.clear();
 
   mRenderer.Reset();
 
-  Dali::Mutex::ScopedLock lock(mMutex);
+  mPreparedRenderingData.reset();
+  mCurrentRenderingData.reset();
+  ClearPreviousRenderingData();
 
-  mVectorRenderer.reset();
-  mPropertyCallbacks.clear();
+  OnFinalize();
 
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "[%p]\n", this);
 }
@@ -154,18 +158,23 @@ void VectorAnimationRenderer::SetRenderer(Renderer renderer)
 
   if(IsTargetPrepared())
   {
-    Dali::Mutex::ScopedLock lock(mMutex);
-
-    if(IsRenderReady())
     {
-      TextureSet textureSet = renderer.GetTextures();
+      Dali::Mutex::ScopedLock lock(mMutex);
+
+      if(IsRenderReady())
+      {
+        TextureSet textureSet = renderer.GetTextures();
 
-      textureSet.SetTexture(0, GetTargetTexture());
+        textureSet.SetTexture(0, GetTargetTexture());
 
-      mUploadCompletedSignal.Emit();
+        mUploadCompletedSignal.Emit();
+      }
     }
 
-    SetShader(mCurrentDataIndex);
+    {
+      Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+      SetShader(mPreparedRenderingData ? mPreparedRenderingData : mCurrentRenderingData);
+    }
   }
 }
 
@@ -177,38 +186,48 @@ void VectorAnimationRenderer::SetSize(uint32_t width, uint32_t height)
     return;
   }
 
+  if(mLoadFailed)
+  {
+    DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Load is failed. Do not make texture [%p]\n", this);
+    return;
+  }
+
   {
     Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
 
-    if(mRenderingData[mCurrentDataIndex]->mWidth == width && mRenderingData[mCurrentDataIndex]->mHeight == height)
+    if(!mPreparedRenderingData && mCurrentRenderingData && (mCurrentRenderingData->mWidth == width && mCurrentRenderingData->mHeight == height))
     {
       return;
     }
 
-    // If updated data is not used yet, do not change current data index.
-    if(mIsDataActivated)
+    if(mPreparedRenderingData && (mPreparedRenderingData->mWidth == width && mPreparedRenderingData->mHeight == height))
     {
-      mCurrentDataIndex = 1u - mCurrentDataIndex;
+      return;
     }
-    std::shared_ptr<RenderingData> updatedData = mRenderingData[mCurrentDataIndex];
+    mPreparedRenderingData.reset();
+  }
 
-    updatedData->mWidth  = width;
-    updatedData->mHeight = height;
+  std::shared_ptr<RenderingData> preparedRenderingData = CreateRenderingData();
 
-    PrepareTarget(mCurrentDataIndex);
+  // If updated data is not used yet, do not change current data index.
+  preparedRenderingData->mWidth  = width;
+  preparedRenderingData->mHeight = height;
 
-    if(mRenderer)
-    {
-      SetShader(mCurrentDataIndex);
-    }
+  PrepareTarget(preparedRenderingData);
 
-    OnSetSize(mCurrentDataIndex);
+  if(mRenderer)
+  {
+    SetShader(preparedRenderingData);
+  }
 
-    mIsDataActivated = false;
-    SetRenderingDataUpdated(true);
+  OnSetSize(preparedRenderingData);
 
-    DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "width = %d, height = %d [%p]\n", updatedData->mWidth, updatedData->mHeight, this);
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    mPreparedRenderingData = preparedRenderingData;
   }
+
+  DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "width = %d, height = %d [%p]\n", preparedRenderingData->mWidth, preparedRenderingData->mHeight, this);
 }
 
 uint32_t VectorAnimationRenderer::GetTotalFrameNumber() const
@@ -294,41 +313,13 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
 
   mPropertyCallbacks.push_back(std::unique_ptr<CallbackBase>(callback));
 
-  switch(property)
+  if(mVectorRenderer)
   {
-    case VectorProperty::FILL_COLOR:
-    {
-      mVectorRenderer->setValue<rlottie::Property::FillColor>(keyPath,
-                                                              [property, callback, id](const rlottie::FrameInfo& info)
-                                                              {
-                                                                Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                                Vector3         color;
-                                                                if(value.Get(color))
-                                                                {
-                                                                  return rlottie::Color(color.r, color.g, color.b);
-                                                                }
-                                                                return rlottie::Color(1.0f, 1.0f, 1.0f);
-                                                              });
-      break;
-    }
-    case VectorProperty::FILL_OPACITY:
-    {
-      mVectorRenderer->setValue<rlottie::Property::FillOpacity>(keyPath,
-                                                                [property, callback, id](const rlottie::FrameInfo& info)
-                                                                {
-                                                                  Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                                  float           opacity;
-                                                                  if(value.Get(opacity))
-                                                                  {
-                                                                    return opacity * 100;
-                                                                  }
-                                                                  return 100.0f;
-                                                                });
-      break;
-    }
-    case VectorProperty::STROKE_COLOR:
+    switch(property)
     {
-      mVectorRenderer->setValue<rlottie::Property::StrokeColor>(keyPath,
+      case VectorProperty::FILL_COLOR:
+      {
+        mVectorRenderer->setValue<rlottie::Property::FillColor>(keyPath,
                                                                 [property, callback, id](const rlottie::FrameInfo& info)
                                                                 {
                                                                   Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
@@ -339,11 +330,11 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
                                                                   }
                                                                   return rlottie::Color(1.0f, 1.0f, 1.0f);
                                                                 });
-      break;
-    }
-    case VectorProperty::STROKE_OPACITY:
-    {
-      mVectorRenderer->setValue<rlottie::Property::StrokeOpacity>(keyPath,
+        break;
+      }
+      case VectorProperty::FILL_OPACITY:
+      {
+        mVectorRenderer->setValue<rlottie::Property::FillOpacity>(keyPath,
                                                                   [property, callback, id](const rlottie::FrameInfo& info)
                                                                   {
                                                                     Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
@@ -354,97 +345,128 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
                                                                     }
                                                                     return 100.0f;
                                                                   });
-      break;
-    }
-    case VectorProperty::STROKE_WIDTH:
-    {
-      mVectorRenderer->setValue<rlottie::Property::StrokeWidth>(keyPath,
-                                                                [property, callback, id](const rlottie::FrameInfo& info)
-                                                                {
-                                                                  Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                                  float           width;
-                                                                  if(value.Get(width))
+        break;
+      }
+      case VectorProperty::STROKE_COLOR:
+      {
+        mVectorRenderer->setValue<rlottie::Property::StrokeColor>(keyPath,
+                                                                  [property, callback, id](const rlottie::FrameInfo& info)
                                                                   {
-                                                                    return width;
-                                                                  }
-                                                                  return 1.0f;
-                                                                });
-      break;
-    }
-    case VectorProperty::TRANSFORM_ANCHOR:
-    {
-      mVectorRenderer->setValue<rlottie::Property::TrAnchor>(keyPath,
-                                                             [property, callback, id](const rlottie::FrameInfo& info)
-                                                             {
-                                                               Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                               Vector2         point;
-                                                               if(value.Get(point))
-                                                               {
-                                                                 return rlottie::Point(point.x, point.y);
-                                                               }
-                                                               return rlottie::Point(0.0f, 0.0f);
-                                                             });
-      break;
-    }
-    case VectorProperty::TRANSFORM_POSITION:
-    {
-      mVectorRenderer->setValue<rlottie::Property::TrPosition>(keyPath,
+                                                                    Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+                                                                    Vector3         color;
+                                                                    if(value.Get(color))
+                                                                    {
+                                                                      return rlottie::Color(color.r, color.g, color.b);
+                                                                    }
+                                                                    return rlottie::Color(1.0f, 1.0f, 1.0f);
+                                                                  });
+        break;
+      }
+      case VectorProperty::STROKE_OPACITY:
+      {
+        mVectorRenderer->setValue<rlottie::Property::StrokeOpacity>(keyPath,
+                                                                    [property, callback, id](const rlottie::FrameInfo& info)
+                                                                    {
+                                                                      Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+                                                                      float           opacity;
+                                                                      if(value.Get(opacity))
+                                                                      {
+                                                                        return opacity * 100;
+                                                                      }
+                                                                      return 100.0f;
+                                                                    });
+        break;
+      }
+      case VectorProperty::STROKE_WIDTH:
+      {
+        mVectorRenderer->setValue<rlottie::Property::StrokeWidth>(keyPath,
+                                                                  [property, callback, id](const rlottie::FrameInfo& info)
+                                                                  {
+                                                                    Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+                                                                    float           width;
+                                                                    if(value.Get(width))
+                                                                    {
+                                                                      return width;
+                                                                    }
+                                                                    return 1.0f;
+                                                                  });
+        break;
+      }
+      case VectorProperty::TRANSFORM_ANCHOR:
+      {
+        mVectorRenderer->setValue<rlottie::Property::TrAnchor>(keyPath,
                                                                [property, callback, id](const rlottie::FrameInfo& info)
                                                                {
                                                                  Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                                 Vector2         position;
-                                                                 if(value.Get(position))
+                                                                 Vector2         point;
+                                                                 if(value.Get(point))
                                                                  {
-                                                                   return rlottie::Point(position.x, position.y);
+                                                                   return rlottie::Point(point.x, point.y);
                                                                  }
                                                                  return rlottie::Point(0.0f, 0.0f);
                                                                });
-      break;
-    }
-    case VectorProperty::TRANSFORM_SCALE:
-    {
-      mVectorRenderer->setValue<rlottie::Property::TrScale>(keyPath,
-                                                            [property, callback, id](const rlottie::FrameInfo& info)
-                                                            {
-                                                              Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                              Vector2         scale;
-                                                              if(value.Get(scale))
-                                                              {
-                                                                return rlottie::Size(scale.x, scale.y);
-                                                              }
-                                                              return rlottie::Size(100.0f, 100.0f);
-                                                            });
-      break;
-    }
-    case VectorProperty::TRANSFORM_ROTATION:
-    {
-      mVectorRenderer->setValue<rlottie::Property::TrRotation>(keyPath,
-                                                               [property, callback, id](const rlottie::FrameInfo& info)
-                                                               {
-                                                                 Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                                 float           rotation;
-                                                                 if(value.Get(rotation))
+        break;
+      }
+      case VectorProperty::TRANSFORM_POSITION:
+      {
+        mVectorRenderer->setValue<rlottie::Property::TrPosition>(keyPath,
+                                                                 [property, callback, id](const rlottie::FrameInfo& info)
                                                                  {
-                                                                   return rotation;
-                                                                 }
-                                                                 return 0.0f;
-                                                               });
-      break;
-    }
-    case VectorProperty::TRANSFORM_OPACITY:
-    {
-      mVectorRenderer->setValue<rlottie::Property::TrOpacity>(keyPath,
+                                                                   Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+                                                                   Vector2         position;
+                                                                   if(value.Get(position))
+                                                                   {
+                                                                     return rlottie::Point(position.x, position.y);
+                                                                   }
+                                                                   return rlottie::Point(0.0f, 0.0f);
+                                                                 });
+        break;
+      }
+      case VectorProperty::TRANSFORM_SCALE:
+      {
+        mVectorRenderer->setValue<rlottie::Property::TrScale>(keyPath,
                                                               [property, callback, id](const rlottie::FrameInfo& info)
                                                               {
                                                                 Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
-                                                                float           opacity;
-                                                                if(value.Get(opacity))
+                                                                Vector2         scale;
+                                                                if(value.Get(scale))
                                                                 {
-                                                                  return opacity * 100;
+                                                                  return rlottie::Size(scale.x, scale.y);
                                                                 }
-                                                                return 100.0f;
+                                                                return rlottie::Size(100.0f, 100.0f);
                                                               });
-      break;
+        break;
+      }
+      case VectorProperty::TRANSFORM_ROTATION:
+      {
+        mVectorRenderer->setValue<rlottie::Property::TrRotation>(keyPath,
+                                                                 [property, callback, id](const rlottie::FrameInfo& info)
+                                                                 {
+                                                                   Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+                                                                   float           rotation;
+                                                                   if(value.Get(rotation))
+                                                                   {
+                                                                     return rotation;
+                                                                   }
+                                                                   return 0.0f;
+                                                                 });
+        break;
+      }
+      case VectorProperty::TRANSFORM_OPACITY:
+      {
+        mVectorRenderer->setValue<rlottie::Property::TrOpacity>(keyPath,
+                                                                [property, callback, id](const rlottie::FrameInfo& info)
+                                                                {
+                                                                  Property::Value value = CallbackBase::ExecuteReturn<Property::Value>(*callback, id, property, info.curFrame());
+                                                                  float           opacity;
+                                                                  if(value.Get(opacity))
+                                                                  {
+                                                                    return opacity * 100;
+                                                                  }
+                                                                  return 100.0f;
+                                                                });
+        break;
+      }
     }
   }
 }
@@ -483,22 +505,16 @@ void VectorAnimationRenderer::NotifyEvent()
     }
 
     OnNotify();
-    mRenderingData[1u - mCurrentDataIndex]->mTexture.Reset();
   }
-  if(emitSignal)
+
   {
-    mUploadCompletedSignal.Emit();
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    ClearPreviousRenderingData();
   }
-}
-
-void VectorAnimationRenderer::SetRenderingDataUpdated(bool renderingDataUpdated)
-{
-  if(!Stage::IsCoreThread())
+  if(emitSignal)
   {
-    DALI_LOG_ERROR("SetRenderingDataUpdated should be called by Core Thread.\n");
-    return;
+    mUploadCompletedSignal.Emit();
   }
-  mIsRenderingDataUpdated = renderingDataUpdated;
 }
 
 } // namespace Plugin
index cf2811079393714ce1a59678bec849c7240cb5ca..78a46ee2df5e01c8edf3421842dbdddb50fd0149 100644 (file)
@@ -128,6 +128,15 @@ protected: // Implementation of VectorAnimationEventHandler
   void NotifyEvent() override;
 
 protected:
+
+  class RenderingData
+  {
+  public:
+    Dali::Texture mTexture;   ///< Texture
+    uint32_t      mWidth{0};  ///< The width of the surface
+    uint32_t      mHeight{0}; ///< The height of the surface
+  };
+
   /**
    * @brief Reset buffer list.
    */
@@ -151,17 +160,17 @@ protected:
   /**
    * @brief Prepare target
    */
-  virtual void PrepareTarget(uint32_t updatedDataIndex) = 0;
+  virtual void PrepareTarget(std::shared_ptr<RenderingData> renderingData) = 0;
 
   /**
    * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
    */
-  virtual void SetShader(uint32_t updatedDataIndex) = 0;
+  virtual void SetShader(std::shared_ptr<RenderingData> renderingData) = 0;
 
   /**
    * @brief Apply the changes of Size
    */
-  virtual void OnSetSize(uint32_t updatedDataIndex) = 0;
+  virtual void OnSetSize(std::shared_ptr<RenderingData> renderingData) = 0;
 
   /**
    * @brief Retrieve whether the target is prepared or not.
@@ -178,30 +187,25 @@ protected:
    */
   virtual Dali::Texture GetTargetTexture() = 0;
 
-  void SetRenderingDataUpdated(bool renderingDataUpdated);
-
-  bool IsRenderingDataUpdated() const
-  {
-    return mIsRenderingDataUpdated;
-  }
+  /**
+   * @brief Clear Previous RenderingData
+   */
+  void ClearPreviousRenderingData();
 
-  class RenderingData
-  {
-  public:
-    Dali::Texture mTexture;   ///< Texture
-    uint32_t      mWidth{0};  ///< The width of the surface
-    uint32_t      mHeight{0}; ///< The height of the surface
-  };
+  /**
+   * @brief Create RenderingData
+   */
+  virtual std::shared_ptr<RenderingData> CreateRenderingData() = 0;
 
 protected:
   std::string                                        mUrl;               ///< The content file path
   std::vector<std::unique_ptr<CallbackBase>>         mPropertyCallbacks; ///< Property callback list
   std::vector<std::pair<std::vector<uint8_t>, bool>> mDecodedBuffers;
 
-  bool                                mIsRenderingDataUpdated{false};
-  bool                                mIsDataActivated{false};
-  uint32_t                            mCurrentDataIndex{0};
-  std::shared_ptr<RenderingData>      mRenderingData[2];
+  std::shared_ptr<RenderingData>              mPreparedRenderingData;
+  std::shared_ptr<RenderingData>              mCurrentRenderingData;
+  std::vector<std::shared_ptr<RenderingData>> mPreviousRenderingData;
+
   mutable Dali::Mutex                 mMutex;                  ///< Mutex
   mutable Dali::Mutex                 mRenderingDataMutex;     ///< Mutex
   Dali::Renderer                      mRenderer;               ///< Renderer