Make VectorAnimationTask get less thread dependancy 96/305896/6
authorseungho baek <sbsh.baek@samsung.com>
Wed, 7 Feb 2024 10:05:32 +0000 (19:05 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Mon, 26 Feb 2024 10:18:17 +0000 (19:18 +0900)
Change-Id: Icf19d54abb7a8b9bb6b169726ca61470b825b918
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 9be538c..f242fce 100644 (file)
@@ -49,13 +49,22 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging,
 #endif
 } // unnamed namespace
 
+class VectorAnimationRendererTizen::RenderingDataImpl : public VectorAnimationRenderer::RenderingData
+{
+public:
+  NativeImageSourceQueuePtr mTargetSurface;
+  tbm_surface_queue_h       mTbmQueue;
+};
+
 VectorAnimationRendererTizen::VectorAnimationRendererTizen()
 : mBuffers(),
   mRenderedTexture(),
-  mPreviousTextures(),
-  mTargetSurface(),
-  mTbmQueue(NULL)
+  mPreviousTextures()
 {
+  mRenderingDataImpl[0] = std::make_shared<RenderingDataImpl>();
+  mRenderingDataImpl[1] = std::make_shared<RenderingDataImpl>();
+  mRenderingData[0]     = mRenderingDataImpl[0];
+  mRenderingData[1]     = mRenderingDataImpl[1];
 }
 
 VectorAnimationRendererTizen::~VectorAnimationRendererTizen()
@@ -66,10 +75,20 @@ VectorAnimationRendererTizen::~VectorAnimationRendererTizen()
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "this = %p\n", this);
 }
 
+// Called by VectorAnimationTaskThread
 bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 {
-  Dali::Mutex::ScopedLock lock(mMutex);
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    mCurrentRenderingData = mRenderingDataImpl[mCurrentDataIndex];
+    if(IsRenderingDataUpdated())
+    {
+      mResourceReady = false;
+      mIsDataActivated = true;
+    }
+  }
 
+  Dali::Mutex::ScopedLock lock(mMutex);
   if(mEnableFixedCache)
   {
     if(mDecodedBuffers.size() < mTotalFrameNumber)
@@ -79,19 +98,19 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
     }
   }
 
-  if(!mTbmQueue || !mVectorRenderer || !mTargetSurface)
+  if(!mCurrentRenderingData->mTbmQueue || !mVectorRenderer || !mCurrentRenderingData->mTargetSurface)
   {
     return false;
   }
 
-  int canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
+  int canDequeue = tbm_surface_queue_can_dequeue(mCurrentRenderingData->mTbmQueue, 0);
   if(!canDequeue)
   {
     // Ignore the previous image which is inserted to the queue.
-    mTargetSurface->IgnoreSourceImage();
+    mCurrentRenderingData->mTargetSurface->IgnoreSourceImage();
 
     // Check again
-    canDequeue = tbm_surface_queue_can_dequeue(mTbmQueue, 0);
+    canDequeue = tbm_surface_queue_can_dequeue(mCurrentRenderingData->mTbmQueue, 0);
     if(!canDequeue)
     {
       return false;
@@ -100,7 +119,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
   tbm_surface_h tbmSurface;
 
-  if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
+  if(tbm_surface_queue_dequeue(mCurrentRenderingData->mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
   {
     DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", this);
     return false;
@@ -120,16 +139,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(mTbmQueue, tbmSurface);
+    tbm_surface_queue_cancel_dequeue(mCurrentRenderingData->mTbmQueue, tbmSurface);
     return false;
   }
 
   unsigned char* buffer = info.planes[0].ptr;
-  if(info.width != mWidth || info.height != mHeight || !buffer)
+  if(info.width != mCurrentRenderingData->mWidth || info.height != mCurrentRenderingData->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(mTbmQueue, tbmSurface);
+    tbm_surface_queue_cancel_dequeue(mCurrentRenderingData->mTbmQueue, tbmSurface);
     return false;
   }
 
@@ -157,7 +176,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
   if(mEnableFixedCache && (frameNumber < mDecodedBuffers.size()) && mDecodedBuffers[frameNumber].second)
   {
-    const int bufferSize = mWidth * mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
+    const int bufferSize = mCurrentRenderingData->mWidth * mCurrentRenderingData->mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
     memcpy(buffer, &mDecodedBuffers[frameNumber].first[0], bufferSize);
   }
   else
@@ -167,7 +186,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
       tbm_surface_internal_ref(tbmSurface);
 
       // Create Surface object
-      surface = rlottie::Surface(reinterpret_cast<uint32_t*>(buffer), mWidth, mHeight, static_cast<size_t>(info.planes[0].stride));
+      surface = rlottie::Surface(reinterpret_cast<uint32_t*>(buffer), mCurrentRenderingData->mWidth, mCurrentRenderingData->mHeight, static_cast<size_t>(info.planes[0].stride));
 
       // Push the buffer
       mBuffers.push_back(SurfacePair(tbmSurface, surface));
@@ -178,7 +197,7 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
     if(mEnableFixedCache && (frameNumber < mDecodedBuffers.size()))
     {
-      const uint32_t       bufferSize = mWidth * mHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
+      const uint32_t       bufferSize = mCurrentRenderingData->mWidth * mCurrentRenderingData->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;
@@ -187,13 +206,13 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
   tbm_surface_unmap(tbmSurface);
 
-  tbm_surface_queue_enqueue(mTbmQueue, tbmSurface);
+  tbm_surface_queue_enqueue(mCurrentRenderingData->mTbmQueue, tbmSurface);
 
   if(!mResourceReady)
   {
     mPreviousTextures.push_back(mRenderedTexture); // It is used to destroy the object in the main thread.
 
-    mRenderedTexture        = mTexture;
+    mRenderedTexture        = mCurrentRenderingData->mTexture;
     mResourceReady          = true;
     mResourceReadyTriggered = true;
 
@@ -207,10 +226,10 @@ bool VectorAnimationRendererTizen::Render(uint32_t frameNumber)
 
 void VectorAnimationRendererTizen::RenderStopped()
 {
-  if(mTargetSurface)
+  if(mCurrentRenderingData->mTargetSurface)
   {
     // Animation is stopped. Free empty buffers
-    mTargetSurface->FreeReleasedBuffers();
+    mCurrentRenderingData->mTargetSurface->FreeReleasedBuffers();
 
     {
       Dali::Mutex::ScopedLock lock(mMutex);
@@ -219,7 +238,49 @@ void VectorAnimationRendererTizen::RenderStopped()
   }
 }
 
-void VectorAnimationRendererTizen::SetShader()
+void VectorAnimationRendererTizen::ResetBuffers()
+{
+  for(auto&& iter : mBuffers)
+  {
+    tbm_surface_internal_unref(iter.first);
+  }
+  mBuffers.clear();
+}
+
+void VectorAnimationRendererTizen::OnFinalize()
+{
+  mRenderedTexture.Reset();
+  mPreviousTextures.clear();
+
+  for(auto&& renderingData : mRenderingDataImpl)
+  {
+    renderingData->mTargetSurface = nullptr;
+    renderingData->mTbmQueue      = nullptr;
+  }
+}
+
+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)
+{
+  mRenderingDataImpl[updatedDataIndex]->mTargetSurface = NativeImageSourceQueue::New(mRenderingDataImpl[updatedDataIndex]->mWidth, mRenderingDataImpl[updatedDataIndex]->mHeight, NativeImageSourceQueue::ColorFormat::RGBA8888);
+  mRenderingDataImpl[updatedDataIndex]->mTexture       = Texture::New(*mRenderingDataImpl[updatedDataIndex]->mTargetSurface);
+}
+
+void VectorAnimationRendererTizen::SetShader(uint32_t updatedDataIndex)
 {
   if(mShaderChanged)
   {
@@ -250,7 +311,7 @@ void VectorAnimationRendererTizen::SetShader()
   }
 
   // Get custom fragment shader prefix
-  mTargetSurface->ApplyNativeFragmentShader(fragmentShader);
+  mRenderingDataImpl[updatedDataIndex]->mTargetSurface->ApplyNativeFragmentShader(fragmentShader);
 
   // Set the modified shader again
   Shader newShader = Shader::New(vertexShader, fragmentShader);
@@ -261,48 +322,15 @@ void VectorAnimationRendererTizen::SetShader()
   mShaderChanged = true;
 }
 
-void VectorAnimationRendererTizen::ResetBuffers()
+void VectorAnimationRendererTizen::OnSetSize(uint32_t updatedDataIndex)
 {
-  for(auto&& iter : mBuffers)
-  {
-    tbm_surface_internal_unref(iter.first);
-  }
-  mBuffers.clear();
-}
-
-void VectorAnimationRendererTizen::OnFinalize()
-{
-  mRenderedTexture.Reset();
-  mPreviousTextures.clear();
-
-  mTargetSurface = nullptr;
-  mTbmQueue      = NULL;
-}
-
-void VectorAnimationRendererTizen::OnSetSize()
-{
-  mTbmQueue = AnyCast<tbm_surface_queue_h>(mTargetSurface->GetNativeImageSourceQueue());
-
-  // Reset the previous texture to destroy it in the main thread
-  mPreviousTextures.clear();
-}
-
-void VectorAnimationRendererTizen::OnNotify()
-{
-  // Reset the previous texture to destroy it in the main thread
-  mPreviousTextures.clear();
-}
-
-void VectorAnimationRendererTizen::PrepareTarget()
-{
-  mTargetSurface = NativeImageSourceQueue::New(mWidth, mHeight, NativeImageSourceQueue::ColorFormat::RGBA8888);
-
-  mTexture = Texture::New(*mTargetSurface);
+  std::shared_ptr<RenderingDataImpl> renderingData = mRenderingDataImpl[updatedDataIndex];
+  renderingData->mTbmQueue                         = AnyCast<tbm_surface_queue_h>(renderingData->mTargetSurface->GetNativeImageSourceQueue());
 }
 
 bool VectorAnimationRendererTizen::IsTargetPrepared()
 {
-  return !!mTargetSurface;
+  return (mCurrentRenderingData) ? !!mCurrentRenderingData->mTargetSurface : false;
 }
 
 bool VectorAnimationRendererTizen::IsRenderReady()
index 97bd1a7..6c0e97c 100644 (file)
@@ -35,6 +35,8 @@ namespace Plugin
  */
 class VectorAnimationRendererTizen : public VectorAnimationRenderer
 {
+  class RenderingDataImpl;
+
 public:
   /**
    * @brief Constructor.
@@ -58,11 +60,6 @@ public:
 
 private:
   /**
-   * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
-   */
-  void SetShader() override;
-
-  /**
    * @brief Reset buffer list.
    */
   void ResetBuffers() override;
@@ -73,15 +70,11 @@ private:
   void OnFinalize() override;
 
   /**
-   * @copydoc VectorAnimationRenderer::OnSetSize()
-   */
-  void OnSetSize() override;
-
-  /**
    * @brief Event callback to process events.
    */
   void OnLottieRendered() override
-  {}
+  {
+  }
 
   /**
    * @copydoc VectorAnimationRenderer::OnNotify()
@@ -91,7 +84,17 @@ private:
   /**
    * @copydoc VectorAnimationRenderer::PrepareTarget()
    */
-  void PrepareTarget() override;
+  void PrepareTarget(uint32_t updatedDataIndex) override;
+
+  /**
+   * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
+   */
+  void SetShader(uint32_t updatedDataIndex) override;
+
+  /**
+   * @copydoc VectorAnimationRenderer::OnSetSize()
+   */
+  void OnSetSize(uint32_t updatedDataIndex) override;
 
   /**
    * @copydoc VectorAnimationRenderer::IsTargetPrepared()
@@ -113,10 +116,10 @@ private:
 
   std::vector<SurfacePair> mBuffers; ///< EGL Image vector
 
-  Dali::Texture              mRenderedTexture;  ///< Rendered Texture
-  std::vector<Dali::Texture> mPreviousTextures; ///< Previous rendered texture
-  NativeImageSourceQueuePtr  mTargetSurface;    ///< The target surface
-  tbm_surface_queue_h        mTbmQueue;         ///< Tbm surface queue handle
+  std::shared_ptr<RenderingDataImpl> mRenderingDataImpl[2];
+  std::shared_ptr<RenderingDataImpl> mCurrentRenderingData;
+  Dali::Texture                      mRenderedTexture;  ///< Rendered Texture
+  std::vector<Dali::Texture>         mPreviousTextures; ///< Previous rendered texture
 };
 
 } // namespace Plugin
index c9dfc56..50070fd 100644 (file)
@@ -46,10 +46,20 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging,
 #endif
 } // unnamed namespace
 
+class VectorAnimationRendererX::RenderingDataImpl : public VectorAnimationRenderer::RenderingData
+{
+public:
+  rlottie::Surface         mLottieSurface;
+  Dali::Devel::PixelBuffer mPixelBuffer;
+};
+
 VectorAnimationRendererX::VectorAnimationRendererX()
-: mLottieSurface(),
-  mRenderCallback(std::unique_ptr<EventThreadCallback>(new EventThreadCallback(MakeCallback(this, &VectorAnimationRendererX::OnLottieRendered))))
+: 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()
@@ -62,14 +72,23 @@ VectorAnimationRendererX::~VectorAnimationRendererX()
 
 bool VectorAnimationRendererX::Render(uint32_t frameNumber)
 {
-  Dali::Mutex::ScopedLock lock(mMutex);
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    mCurrentRenderingData = mRenderingDataImpl[mCurrentDataIndex];
+    if(IsRenderingDataUpdated())
+    {
+      mResourceReady = false;
+      mIsDataActivated = true;
+    }
+  }
 
-  if(!mVectorRenderer || !mPixelBuffer)
+  Dali::Mutex::ScopedLock lock(mMutex);
+  if(!mVectorRenderer || !mCurrentRenderingData->mPixelBuffer)
   {
     return false;
   }
 
-  mVectorRenderer->renderSync(frameNumber, mLottieSurface);
+  mVectorRenderer->renderSync(frameNumber, mCurrentRenderingData->mLottieSurface);
   mRenderCallback->Trigger();
 
   if(!mResourceReady)
@@ -87,25 +106,15 @@ void VectorAnimationRendererX::RenderStopped()
 {
 }
 
-
-void VectorAnimationRendererX::SetShader()
-{
-  if(mShaderChanged || !mTexture)
-  {
-    return;
-  }
-
-  // Not implemented
-
-  mShaderChanged = true;
-}
-
 void VectorAnimationRendererX::ResetBuffers()
 {
-  if(mPixelBuffer)
+  for(auto&& renderingData : mRenderingDataImpl)
   {
-    uint32_t bufferSize = mPixelBuffer.GetWidth() * mPixelBuffer.GetHeight() * Dali::Pixel::GetBytesPerPixel(mPixelBuffer.GetPixelFormat());
-    memset(mPixelBuffer.GetBuffer(), 0, bufferSize);
+    if(renderingData->mPixelBuffer)
+    {
+      uint32_t bufferSize = renderingData->mPixelBuffer.GetWidth() * renderingData->mPixelBuffer.GetHeight() * Dali::Pixel::GetBytesPerPixel(renderingData->mPixelBuffer.GetPixelFormat());
+      memset(renderingData->mPixelBuffer.GetBuffer(), 0, bufferSize);
+    }
   }
 }
 
@@ -117,34 +126,57 @@ void VectorAnimationRendererX::OnLottieRendered()
 {
   Dali::Mutex::ScopedLock lock(mMutex);
 
-  if(mPixelBuffer && mTexture)
+  if(mCurrentRenderingData->mPixelBuffer && mCurrentRenderingData->mTexture)
+  {
+    PixelData pixelData = mCurrentRenderingData->mPixelBuffer.CreatePixelData();
+    mCurrentRenderingData->mTexture.Upload(pixelData);
+  }
+}
+
+void VectorAnimationRendererX::OnNotify()
+{
+  // If RenderingData is updated, then clear previous renderingData
+  if(IsRenderingDataUpdated())
   {
-    PixelData pixelData = mPixelBuffer.CreatePixelData();
-    mTexture.Upload(pixelData);
+    std::shared_ptr<RenderingDataImpl> oldRenderingData = mRenderingDataImpl[1u - mCurrentDataIndex];
+    SetRenderingDataUpdated(false);
   }
 }
 
-void VectorAnimationRendererX::PrepareTarget()
+void VectorAnimationRendererX::PrepareTarget(uint32_t updatedDataIndex)
+{
+  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));
+}
+
+void VectorAnimationRendererX::SetShader(uint32_t updatedDataIndex)
 {
-  mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, Dali::Pixel::BGRA8888, mWidth, mHeight);
+  std::shared_ptr<RenderingDataImpl> renderingData = mRenderingDataImpl[updatedDataIndex];
+  if(mShaderChanged || !renderingData->mTexture)
+  {
+    return;
+  }
+
+  // Not implemented
 
-  mPixelBuffer   = Dali::Devel::PixelBuffer::New(mWidth, mHeight, Dali::Pixel::BGRA8888);
-  mLottieSurface = rlottie::Surface(reinterpret_cast<uint32_t*>(mPixelBuffer.GetBuffer()), mWidth, mHeight, static_cast<size_t>(mPixelBuffer.GetStride() * 4));
+  mShaderChanged = true;
 }
 
 bool VectorAnimationRendererX::IsTargetPrepared()
 {
-  return !!mPixelBuffer;
+  return (mCurrentRenderingData) ? !!mCurrentRenderingData->mPixelBuffer : false;
 }
 
 bool VectorAnimationRendererX::IsRenderReady()
 {
-  return mResourceReady && mTexture;
+  return mResourceReady && ((mCurrentRenderingData) ? !!mCurrentRenderingData->mTexture : false);
 }
 
 Dali::Texture VectorAnimationRendererX::GetTargetTexture()
 {
-  return mTexture;
+  return (mCurrentRenderingData) ? mCurrentRenderingData->mTexture : Texture();
 }
 
 } // namespace Plugin
index 842162e..91cc74d 100644 (file)
@@ -35,6 +35,8 @@ namespace Plugin
  */
 class VectorAnimationRendererX : public VectorAnimationRenderer
 {
+  class RenderingDataImpl;
+
 public:
   /**
    * @brief Constructor.
@@ -58,11 +60,6 @@ public:
 
 private:
   /**
-   * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
-   */
-  void SetShader() override;
-
-  /**
    * @brief Reset buffer list.
    */
   void ResetBuffers() override;
@@ -73,12 +70,6 @@ private:
   void OnFinalize() override;
 
   /**
-   * @copydoc VectorAnimationRenderer::OnSetSize()
-   */
-  void OnSetSize() override
-  {}
-
-  /**
    * @brief Event callback to process events.
    */
   void OnLottieRendered() override;
@@ -86,13 +77,23 @@ private:
   /**
    * @copydoc VectorAnimationRenderer::OnNotify()
    */
-  void OnNotify() override
-  {}
+  void OnNotify() override;
 
   /**
    * @copydoc VectorAnimationRenderer::PrepareTarget()
    */
-  void PrepareTarget() override;
+  void PrepareTarget(uint32_t updatedDataIndex) override;
+
+  /**
+   * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
+   */
+  void SetShader(uint32_t updatedDataIndex) override;
+
+  /**
+   * @copydoc VectorAnimationRenderer::OnSetSize()
+   */
+  void OnSetSize(uint32_t updatedDataIndex) override
+  {}
 
   /**
    * @copydoc VectorAnimationRenderer::IsTargetPrepared()
@@ -110,8 +111,8 @@ private:
   Dali::Texture GetTargetTexture() override;
 
 private:
-  rlottie::Surface                     mLottieSurface;  ///
-  Dali::Devel::PixelBuffer             mPixelBuffer;    ///
+  std::shared_ptr<RenderingDataImpl>   mRenderingDataImpl[2];
+  std::shared_ptr<RenderingDataImpl>   mCurrentRenderingData;
   std::unique_ptr<EventThreadCallback> mRenderCallback; ///
 };
 
index 2fc1c49..0c2677a 100644 (file)
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/common/hash.h>
+#include <dali/devel-api/common/stage.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/texture-integ.h>
 #include <dali/public-api/object/property-array.h>
@@ -46,13 +47,11 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging,
 VectorAnimationRenderer::VectorAnimationRenderer()
 : mUrl(),
   mMutex(),
+  mRenderingDataMutex(),
   mRenderer(),
-  mTexture(),
   mVectorRenderer(),
   mUploadCompletedSignal(),
   mTotalFrameNumber(0),
-  mWidth(0),
-  mHeight(0),
   mDefaultWidth(0),
   mDefaultHeight(0),
   mFrameRate(60.0f),
@@ -71,20 +70,27 @@ VectorAnimationRenderer::~VectorAnimationRenderer()
 
 void VectorAnimationRenderer::Finalize()
 {
-  Dali::Mutex::ScopedLock lock(mMutex);
-
   VectorAnimationPluginManager::Get().RemoveEventHandler(*this);
 
+  {
+    Dali::Mutex::ScopedLock lock(mRenderingDataMutex);
+    mRenderingData[0]->mTexture.Reset();
+    mRenderingData[1]->mTexture.Reset();
+
+    OnFinalize();
+  }
+
   mRenderer.Reset();
-  mTexture.Reset();
+
+  Dali::Mutex::ScopedLock lock(mMutex);
+
   mVectorRenderer.reset();
   mPropertyCallbacks.clear();
 
-  OnFinalize();
-
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "[%p]\n", this);
 }
 
+// Called by VectorAnimationTaskThread
 bool VectorAnimationRenderer::Load(const std::string& url)
 {
   Dali::Mutex::ScopedLock lock(mMutex);
@@ -112,6 +118,7 @@ bool VectorAnimationRenderer::Load(const std::string& url)
   return true;
 }
 
+// Called by VectorAnimationTaskThread
 bool VectorAnimationRenderer::Load(const Dali::Vector<uint8_t>& data)
 {
   Dali::Mutex::ScopedLock lock(mMutex);
@@ -158,41 +165,50 @@ void VectorAnimationRenderer::SetRenderer(Renderer renderer)
       mUploadCompletedSignal.Emit();
     }
 
-    SetShader();
+    SetShader(mCurrentDataIndex);
   }
 }
 
 void VectorAnimationRenderer::SetSize(uint32_t width, uint32_t height)
 {
-  Dali::Mutex::ScopedLock lock(mMutex);
-
-  if(mWidth == width && mHeight == height)
+  if(!Stage::IsCoreThread())
   {
-    DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "Same size (%d, %d) [%p]\n", mWidth, mHeight, this);
+    DALI_LOG_ERROR("SetSize should be called by Core Thread.\n");
     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);
 
-  mWidth  = width;
-  mHeight = height;
+    if(mRenderingData[mCurrentDataIndex]->mWidth == width && mRenderingData[mCurrentDataIndex]->mHeight == height)
+    {
+      return;
+    }
 
-  PrepareTarget();
+    // If updated data is not used yet, do not change current data index.
+    if(mIsDataActivated)
+    {
+      mCurrentDataIndex = 1u - mCurrentDataIndex;
+    }
+    std::shared_ptr<RenderingData> updatedData = mRenderingData[mCurrentDataIndex];
 
-  if(mRenderer)
-  {
-    SetShader();
-  }
+    updatedData->mWidth  = width;
+    updatedData->mHeight = height;
 
-  mResourceReady = false;
+    PrepareTarget(mCurrentDataIndex);
+
+    if(mRenderer)
+    {
+      SetShader(mCurrentDataIndex);
+    }
+
+    OnSetSize(mCurrentDataIndex);
 
-  OnSetSize();
+    mIsDataActivated = false;
+    SetRenderingDataUpdated(true);
 
-  DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "width = %d, height = %d [%p]\n", mWidth, mHeight, this);
+    DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "width = %d, height = %d [%p]\n", updatedData->mWidth, updatedData->mHeight, this);
+  }
 }
 
 uint32_t VectorAnimationRenderer::GetTotalFrameNumber() const
@@ -283,7 +299,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::FILL_COLOR:
     {
       mVectorRenderer->setValue<rlottie::Property::FillColor>(keyPath,
-                                                              [property, callback, id](const rlottie::FrameInfo& info) {
+                                                              [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))
@@ -297,7 +314,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::FILL_OPACITY:
     {
       mVectorRenderer->setValue<rlottie::Property::FillOpacity>(keyPath,
-                                                                [property, callback, id](const rlottie::FrameInfo& info) {
+                                                                [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))
@@ -311,7 +329,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::STROKE_COLOR:
     {
       mVectorRenderer->setValue<rlottie::Property::StrokeColor>(keyPath,
-                                                                [property, callback, id](const rlottie::FrameInfo& info) {
+                                                                [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))
@@ -325,7 +344,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::STROKE_OPACITY:
     {
       mVectorRenderer->setValue<rlottie::Property::StrokeOpacity>(keyPath,
-                                                                  [property, callback, id](const rlottie::FrameInfo& info) {
+                                                                  [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))
@@ -339,7 +359,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::STROKE_WIDTH:
     {
       mVectorRenderer->setValue<rlottie::Property::StrokeWidth>(keyPath,
-                                                                [property, callback, id](const rlottie::FrameInfo& info) {
+                                                                [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))
@@ -353,7 +374,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::TRANSFORM_ANCHOR:
     {
       mVectorRenderer->setValue<rlottie::Property::TrAnchor>(keyPath,
-                                                             [property, callback, id](const rlottie::FrameInfo& info) {
+                                                             [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))
@@ -367,7 +389,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::TRANSFORM_POSITION:
     {
       mVectorRenderer->setValue<rlottie::Property::TrPosition>(keyPath,
-                                                               [property, callback, id](const rlottie::FrameInfo& info) {
+                                                               [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))
@@ -381,7 +404,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::TRANSFORM_SCALE:
     {
       mVectorRenderer->setValue<rlottie::Property::TrScale>(keyPath,
-                                                            [property, callback, id](const rlottie::FrameInfo& info) {
+                                                            [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))
@@ -395,7 +419,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::TRANSFORM_ROTATION:
     {
       mVectorRenderer->setValue<rlottie::Property::TrRotation>(keyPath,
-                                                               [property, callback, id](const rlottie::FrameInfo& info) {
+                                                               [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))
@@ -409,7 +434,8 @@ void VectorAnimationRenderer::AddPropertyValueCallback(const std::string& keyPat
     case VectorProperty::TRANSFORM_OPACITY:
     {
       mVectorRenderer->setValue<rlottie::Property::TrOpacity>(keyPath,
-                                                              [property, callback, id](const rlottie::FrameInfo& info) {
+                                                              [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))
@@ -457,6 +483,7 @@ void VectorAnimationRenderer::NotifyEvent()
     }
 
     OnNotify();
+    mRenderingData[1u - mCurrentDataIndex]->mTexture.Reset();
   }
   if(emitSignal)
   {
@@ -464,6 +491,16 @@ void VectorAnimationRenderer::NotifyEvent()
   }
 }
 
+void VectorAnimationRenderer::SetRenderingDataUpdated(bool renderingDataUpdated)
+{
+  if(!Stage::IsCoreThread())
+  {
+    DALI_LOG_ERROR("SetRenderingDataUpdated should be called by Core Thread.\n");
+    return;
+  }
+  mIsRenderingDataUpdated = renderingDataUpdated;
+}
+
 } // namespace Plugin
 
 } // namespace Dali
index 959f8c3..cf28110 100644 (file)
@@ -129,11 +129,6 @@ protected: // Implementation of VectorAnimationEventHandler
 
 protected:
   /**
-   * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
-   */
-  virtual void SetShader() = 0;
-
-  /**
    * @brief Reset buffer list.
    */
   virtual void ResetBuffers() = 0;
@@ -144,11 +139,6 @@ protected:
   virtual void OnFinalize() = 0;
 
   /**
-   * @brief Apply the changes of Size
-   */
-  virtual void OnSetSize() = 0;
-
-  /**
    * @brief Event callback to process events.
    */
   virtual void OnLottieRendered() = 0;
@@ -161,7 +151,17 @@ protected:
   /**
    * @brief Prepare target
    */
-  virtual void PrepareTarget() = 0;
+  virtual void PrepareTarget(uint32_t updatedDataIndex) = 0;
+
+  /**
+   * @brief Set shader for NativeImageSourceQueue with custom sampler type and prefix.
+   */
+  virtual void SetShader(uint32_t updatedDataIndex) = 0;
+
+  /**
+   * @brief Apply the changes of Size
+   */
+  virtual void OnSetSize(uint32_t updatedDataIndex) = 0;
 
   /**
    * @brief Retrieve whether the target is prepared or not.
@@ -178,19 +178,36 @@ protected:
    */
   virtual Dali::Texture GetTargetTexture() = 0;
 
+  void SetRenderingDataUpdated(bool renderingDataUpdated);
+
+  bool IsRenderingDataUpdated() const
+  {
+    return mIsRenderingDataUpdated;
+  }
+
+  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
+  };
+
 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];
   mutable Dali::Mutex                 mMutex;                  ///< Mutex
+  mutable Dali::Mutex                 mRenderingDataMutex;     ///< Mutex
   Dali::Renderer                      mRenderer;               ///< Renderer
-  Dali::Texture                       mTexture;                ///< Texture
   std::unique_ptr<rlottie::Animation> mVectorRenderer;         ///< The vector animation renderer
   UploadCompletedSignalType           mUploadCompletedSignal;  ///< Upload completed signal
   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