Fix 2 animatedImageVisual issues 19/249119/4
authorSeungho Baek <sbsh.baek@samsung.com>
Mon, 7 Dec 2020 08:10:34 +0000 (17:10 +0900)
committerSeungho Baek <sbsh.baek@samsung.com>
Mon, 14 Dec 2020 07:02:28 +0000 (16:02 +0900)
 - 1. Make animate image visual do not caching in texture-manager
  - If 2 visual those have same image url and play without sync, it makes caching error.
 - 2. Make NextFrame methods.
  - Currently, the visual requests to load specific frame with index.
    But, if the system getting slow(like so many agif/webp in playing), the request and the loading can not be synchronized.
  - The visual will request next frame index with identical timing, but because the loading is slow, the loading frame will be throwed away and start next frame of the index.
  - This make bottle neck and also make stop to play.
  - This patch adds NextFrame that returns prepared next frame. If the next frame is in loading, this method is not to increase index and returns current rendered frame again.

Change-Id: Ia301ae654bcf8ee88167585bc4f4b1259a1e4e46
Signed-off-by: Seungho Baek <sbsh.baek@samsung.com>
12 files changed:
automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h
dali-toolkit/internal/visuals/animated-image/image-cache.h
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/internal/visuals/texture-manager-impl.h

index a6d827e..90ee00e 100644 (file)
@@ -392,6 +392,77 @@ int UtcDaliAnimatedImageVisualStopBehavior(void)
 }
 
 
 }
 
 
+int UtcDaliAnimatedImageVisualStopBehavior02(void)
+{
+  ToolkitTestApplication application;
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  Property::Array urls;
+  CopyUrlsIntoArray( urls );
+
+  {
+    Property::Map propertyMap;
+    propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE );
+    propertyMap.Insert( ImageVisual::Property::URL, Property::Value(urls) );
+    propertyMap.Insert( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME);
+    propertyMap.Insert( ImageVisual::Property::BATCH_SIZE, 2);
+    propertyMap.Insert( ImageVisual::Property::CACHE_SIZE, 2);
+    propertyMap.Insert( ImageVisual::Property::FRAME_DELAY, 20);
+
+    VisualFactory factory = VisualFactory::Get();
+    Visual::Base visual = factory.CreateVisual( propertyMap );
+
+    // Expect that a batch of 4 textures has been requested. These will be serially loaded
+    // below.
+
+    DummyControl dummyControl = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+    dummyControl.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+    application.GetScene().Add( dummyControl );
+
+    tet_infoline( "Ready the visual after the visual is on stage" );
+    DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+
+    TraceCallStack& textureTrace = gl.GetTextureTrace();
+    textureTrace.Enable(true);
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS( gl.GetLastGenTextureId(), 2, TEST_LOCATION );
+
+    Test::EmitGlobalTimerSignal();
+
+    DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 2, TEST_LOCATION );
+
+    DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::STOP, Property::Map() );
+
+    tet_infoline( "Ready the visual after the visual is on stage" );
+    DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 2, TEST_LOCATION );
+
+    dummyControl.Unparent();
+  }
+  tet_infoline("Test that removing the visual from stage deletes all textures");
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 0, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
 int UtcDaliAnimatedImageVisualAnimatedImage01(void)
 {
   ToolkitTestApplication application;
 int UtcDaliAnimatedImageVisualAnimatedImage01(void)
 {
   ToolkitTestApplication application;
index 456b89e..745c45c 100755 (executable)
@@ -174,7 +174,7 @@ AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache, Imag
   mPixelArea( FULL_TEXTURE_RECT ),
   mImageUrl(),
   mAnimatedImageLoading(),
   mPixelArea( FULL_TEXTURE_RECT ),
   mImageUrl(),
   mAnimatedImageLoading(),
-  mCurrentFrameIndex( 0 ),
+  mFrameIndexForJumpTo( 0 ),
   mImageUrls( NULL ),
   mImageCache( NULL ),
   mCacheSize( 2 ),
   mImageUrls( NULL ),
   mImageCache( NULL ),
   mCacheSize( 2 ),
@@ -302,7 +302,7 @@ void AnimatedImageVisual::OnDoAction( const Dali::Property::Index actionId, cons
         else
         {
           mIsJumpTo = true;
         else
         {
           mIsJumpTo = true;
-          mCurrentFrameIndex = frameNumber;
+          mFrameIndexForJumpTo = frameNumber;
           if( IsOnScene() )
           {
             DisplayNextFrame();
           if( IsOnScene() )
           {
             DisplayNextFrame();
@@ -544,8 +544,6 @@ void AnimatedImageVisual::CreateRenderer()
   {
     mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea );
   }
   {
     mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea );
   }
-
-  mCurrentFrameIndex = 0;
 }
 
 void AnimatedImageVisual::LoadFirstBatch()
 }
 
 void AnimatedImageVisual::LoadFirstBatch()
@@ -618,14 +616,12 @@ void AnimatedImageVisual::StartFirstFrame( TextureSet& textureSet )
     mPlacementActor.Reset();
   }
 
     mPlacementActor.Reset();
   }
 
-  mCurrentFrameIndex = 0;
-
   if( mFrameCount > 1 )
   {
   if( mFrameCount > 1 )
   {
-    int frameDelay = mFrameDelay; // from URL array
-    if( mAnimatedImageLoading && mImageCache )
+    int frameDelay = mImageCache->GetFrameInterval( 0 );
+    if( frameDelay == 0u )
     {
     {
-      frameDelay = mImageCache->GetFrameInterval( 0 );
+      frameDelay = mFrameDelay; // from URL array
     }
     mFrameDelayTimer = Timer::New( frameDelay );
     mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame );
     }
     mFrameDelayTimer = Timer::New( frameDelay );
     mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame );
@@ -642,15 +638,11 @@ TextureSet AnimatedImageVisual::PrepareTextureSet()
   {
     textureSet = mImageCache->FirstFrame();
   }
   {
     textureSet = mImageCache->FirstFrame();
   }
+
   if( textureSet )
   {
     SetImageSize( textureSet );
   }
   if( textureSet )
   {
     SetImageSize( textureSet );
   }
-  else
-  {
-    DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n" );
-    ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
-  }
 
   return textureSet;
 }
 
   return textureSet;
 }
@@ -670,26 +662,38 @@ void AnimatedImageVisual::SetImageSize( TextureSet& textureSet )
 
 void AnimatedImageVisual::FrameReady( TextureSet textureSet )
 {
 
 void AnimatedImageVisual::FrameReady( TextureSet textureSet )
 {
-  SetImageSize( textureSet );
-
-  if( mStartFirstFrame )
+  if(textureSet)
   {
   {
-    StartFirstFrame( textureSet );
+    SetImageSize(textureSet);
+
+    if(mStartFirstFrame)
+    {
+      StartFirstFrame(textureSet);
+    }
+    else
+    {
+      if(mImpl->mRenderer)
+      {
+        mImpl->mRenderer.SetTextures(textureSet);
+      }
+    }
   }
   else
   {
   }
   else
   {
-    if( mImpl->mRenderer )
-    {
-      mImpl->mRenderer.SetTextures( textureSet );
-    }
+    DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n" );
+    ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
   }
 }
 
 bool AnimatedImageVisual::DisplayNextFrame()
 {
   }
 }
 
 bool AnimatedImageVisual::DisplayNextFrame()
 {
+  bool nextFrame = false;
+  uint32_t frameIndex = mImageCache->GetCurrentFrameIndex();
+
   if( mIsJumpTo )
   {
     mIsJumpTo = false;
   if( mIsJumpTo )
   {
     mIsJumpTo = false;
+    frameIndex = mFrameIndexForJumpTo;
   }
   else if( mActionStatus == DevelAnimatedImageVisual::Action::PAUSE )
   {
   }
   else if( mActionStatus == DevelAnimatedImageVisual::Action::PAUSE )
   {
@@ -697,14 +701,14 @@ bool AnimatedImageVisual::DisplayNextFrame()
   }
   else if( mActionStatus == DevelAnimatedImageVisual::Action::STOP )
   {
   }
   else if( mActionStatus == DevelAnimatedImageVisual::Action::STOP )
   {
-    mCurrentLoopIndex = 0;
+    frameIndex = 0;
     if( mStopBehavior == DevelImageVisual::StopBehavior::FIRST_FRAME )
     {
     if( mStopBehavior == DevelImageVisual::StopBehavior::FIRST_FRAME )
     {
-      mCurrentFrameIndex = 0;
+      frameIndex = 0;
     }
     else if( mStopBehavior == DevelImageVisual::StopBehavior::LAST_FRAME )
     {
     }
     else if( mStopBehavior == DevelImageVisual::StopBehavior::LAST_FRAME )
     {
-      mCurrentFrameIndex = mFrameCount - 1;
+      frameIndex = mFrameCount - 1;
     }
     else
     {
     }
     else
     {
@@ -715,33 +719,25 @@ bool AnimatedImageVisual::DisplayNextFrame()
   {
     if( mFrameCount > 1 )
     {
   {
     if( mFrameCount > 1 )
     {
-      // Wrap the frame index
-      bool finished = false;
-      ++mCurrentFrameIndex;
-      if( mCurrentFrameIndex >= mFrameCount )
+      nextFrame = true;
+      frameIndex++;
+      if( frameIndex >= mFrameCount )
       {
       {
+        frameIndex %= mFrameCount;
         ++mCurrentLoopIndex;
         ++mCurrentLoopIndex;
-        finished = true;
       }
 
       }
 
-      if( mLoopCount < 0 || mCurrentLoopIndex < mLoopCount)
-      {
-        if( finished )
-        {
-          mCurrentFrameIndex = 0; // Back to the first frame
-        }
-      }
-      else
+      if(mLoopCount >= 0 && mCurrentLoopIndex >= mLoopCount)
       {
         // This will stop timer
         mActionStatus = DevelAnimatedImageVisual::Action::STOP;
         return DisplayNextFrame();
       }
     }
       {
         // This will stop timer
         mActionStatus = DevelAnimatedImageVisual::Action::STOP;
         return DisplayNextFrame();
       }
     }
-    // TODO : newly added one.
-    if( mAnimatedImageLoading && mImageCache )
+
+    unsigned int delay = mImageCache->GetFrameInterval( frameIndex );
+    if( delay > 0u )
     {
     {
-      unsigned int delay = mImageCache->GetFrameInterval( mCurrentFrameIndex );
       if( mFrameDelayTimer.GetInterval() != delay )
       {
         mFrameDelayTimer.SetInterval( delay );
       if( mFrameDelayTimer.GetInterval() != delay )
       {
         mFrameDelayTimer.SetInterval( delay );
@@ -749,12 +745,20 @@ bool AnimatedImageVisual::DisplayNextFrame()
     }
   }
 
     }
   }
 
-  DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, mCurrentFrameIndex);
+  DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, frameIndex);
 
   TextureSet textureSet;
   if( mImageCache )
   {
 
   TextureSet textureSet;
   if( mImageCache )
   {
-    textureSet = mImageCache->Frame( mCurrentFrameIndex );
+    if(nextFrame)
+    {
+      textureSet = mImageCache->NextFrame();
+    }
+    else
+    {
+      textureSet = mImageCache->Frame( frameIndex );
+    }
+
     if( textureSet )
     {
       SetImageSize( textureSet );
     if( textureSet )
     {
       SetImageSize( textureSet );
index 8e91623..862dbb8 100644 (file)
@@ -246,7 +246,7 @@ private:
   Vector4 mPixelArea;
   VisualUrl mImageUrl;
   Dali::AnimatedImageLoading mAnimatedImageLoading; // Only needed for animated image
   Vector4 mPixelArea;
   VisualUrl mImageUrl;
   Dali::AnimatedImageLoading mAnimatedImageLoading; // Only needed for animated image
-  uint32_t mCurrentFrameIndex; // Frame index into textureRects
+  uint32_t mFrameIndexForJumpTo; // Frame index into textureRects
 
   // Variables for Multi-Image player
   ImageCache::UrlList* mImageUrls;
 
   // Variables for Multi-Image player
   ImageCache::UrlList* mImageUrls;
index 726cd39..a90b31e 100644 (file)
@@ -93,11 +93,23 @@ TextureSet FixedImageCache::FirstFrame()
   return textureSet;
 }
 
   return textureSet;
 }
 
-uint32_t FixedImageCache::GetFrameInterval( uint32_t frameIndex )
+TextureSet FixedImageCache::NextFrame()
+{
+  TextureSet textureSet = Frame((mFront + 1) % mImageUrls.size());
+
+  return textureSet;
+}
+
+uint32_t FixedImageCache::GetFrameInterval( uint32_t frameIndex ) const
 {
   return 0u;
 }
 
 {
   return 0u;
 }
 
+int32_t FixedImageCache::GetCurrentFrameIndex() const
+{
+  return static_cast<int32_t>(mFront);
+}
+
 bool FixedImageCache::IsFrontReady() const
 {
   return ( mReadyFlags.size() > 0 && mReadyFlags[mFront] == true );
 bool FixedImageCache::IsFrontReady() const
 {
   return ( mReadyFlags.size() > 0 && mReadyFlags[mFront] == true );
index ec7f419..bd232b4 100644 (file)
@@ -61,9 +61,21 @@ public:
   TextureSet FirstFrame() override;
 
   /**
   TextureSet FirstFrame() override;
 
   /**
+   * Get the next frame. If it's not ready, this will trigger the
+   * sending of FrameReady() when the image becomes ready.
+   */
+  TextureSet NextFrame() override;
+
+  /**
    * Get the interval of Nth frame.
    */
    * Get the interval of Nth frame.
    */
-  uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+  uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+  /**
+   * Get the current rendered frame index.
+   * If there isn't any loaded frame, returns -1.
+   */
+  int32_t GetCurrentFrameIndex() const override;
 
 private:
   /**
 
 private:
   /**
index 1d385c8..b16b94e 100644 (file)
@@ -79,6 +79,12 @@ public:
   virtual TextureSet FirstFrame() = 0;
 
   /**
   virtual TextureSet FirstFrame() = 0;
 
   /**
+   * Get the next frame. If it's not ready, this will trigger the
+   * sending of FrameReady() when the image becomes ready.
+   */
+  virtual TextureSet NextFrame() = 0;
+
+  /**
    * Get the Nth frame. If it's not ready, this will trigger the
    * sending of FrameReady() when the image becomes ready.
    */
    * Get the Nth frame. If it's not ready, this will trigger the
    * sending of FrameReady() when the image becomes ready.
    */
@@ -87,7 +93,13 @@ public:
   /**
    * Get the interval of Nth frame.
    */
   /**
    * Get the interval of Nth frame.
    */
-  virtual uint32_t GetFrameInterval( uint32_t frameIndex ) = 0;
+  virtual uint32_t GetFrameInterval( uint32_t frameIndex ) const = 0;
+
+  /**
+   * Get the current rendered frame index.
+   * If there isn't any loaded frame, returns -1.
+   */
+  virtual int32_t GetCurrentFrameIndex() const = 0;
 
 private:
 
 
 private:
 
index 3992b08..2733d7a 100644 (file)
@@ -65,6 +65,7 @@ RollingAnimatedImageCache::RollingAnimatedImageCache(
   mAnimatedImageLoading( animatedImageLoading ),
   mFrameCount( frameCount ),
   mFrameIndex( 0 ),
   mAnimatedImageLoading( animatedImageLoading ),
   mFrameCount( frameCount ),
   mFrameIndex( 0 ),
+  mCacheSize( cacheSize ),
   mQueue( cacheSize ),
   mIsSynchronousLoading( isSynchronousLoading ),
   mOnLoading( false )
   mQueue( cacheSize ),
   mIsSynchronousLoading( isSynchronousLoading ),
   mOnLoading( false )
@@ -114,10 +115,18 @@ TextureSet RollingAnimatedImageCache::Frame( uint32_t frameIndex )
     // If the frame of frameIndex was already loaded, load batch from the last frame of queue
     if( !mQueue.IsEmpty() )
     {
     // If the frame of frameIndex was already loaded, load batch from the last frame of queue
     if( !mQueue.IsEmpty() )
     {
-      mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
+      if(!mLoadWaitingQueue.empty())
+      {
+        mFrameIndex = ( mLoadWaitingQueue.back() + 1 ) % mFrameCount;
+      }
+      else
+      {
+        mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
+      }
     }
     else
     {
     }
     else
     {
+      mOnLoading = false;
       // If the request is for the first frame or a jumped frame(JUMP_TO) remove current waiting queue.
       mLoadWaitingQueue.clear();
       // If the queue is empty, and the frame of frameIndex is not loaded synchronously. load batch from the frame of frameIndex
       // If the request is for the first frame or a jumped frame(JUMP_TO) remove current waiting queue.
       mLoadWaitingQueue.clear();
       // If the queue is empty, and the frame of frameIndex is not loaded synchronously. load batch from the frame of frameIndex
@@ -149,11 +158,40 @@ TextureSet RollingAnimatedImageCache::FirstFrame()
   return Frame( 0u );
 }
 
   return Frame( 0u );
 }
 
-uint32_t RollingAnimatedImageCache::GetFrameInterval( uint32_t frameIndex )
+TextureSet RollingAnimatedImageCache::NextFrame()
+{
+  TextureSet textureSet;
+  if(!mQueue.IsEmpty())
+  {
+    uint32_t frameIndex = mQueue.Front().mFrameNumber;
+    if(IsFrontReady())
+    {
+      frameIndex = (frameIndex + 1) % mFrameCount;
+    }
+    textureSet = Frame(frameIndex);
+  }
+  else
+  {
+    DALI_LOG_ERROR("Cache is empty.");
+  }
+
+  return textureSet;
+}
+
+uint32_t RollingAnimatedImageCache::GetFrameInterval( uint32_t frameIndex ) const
 {
   return mAnimatedImageLoading.GetFrameInterval( frameIndex );
 }
 
 {
   return mAnimatedImageLoading.GetFrameInterval( frameIndex );
 }
 
+int32_t RollingAnimatedImageCache::GetCurrentFrameIndex() const
+{
+  if(mQueue.IsEmpty())
+  {
+    return -1;
+  }
+  return mQueue.Front().mFrameNumber;
+}
+
 bool RollingAnimatedImageCache::IsFrontReady() const
 {
   return ( !mQueue.IsEmpty() && mQueue.Front().mReady );
 bool RollingAnimatedImageCache::IsFrontReady() const
 {
   return ( !mQueue.IsEmpty() && mQueue.Front().mReady );
@@ -161,6 +199,12 @@ bool RollingAnimatedImageCache::IsFrontReady() const
 
 void RollingAnimatedImageCache::RequestFrameLoading( uint32_t frameIndex )
 {
 
 void RollingAnimatedImageCache::RequestFrameLoading( uint32_t frameIndex )
 {
+  ImageFrame imageFrame;
+  imageFrame.mFrameNumber = frameIndex;
+  imageFrame.mReady       = false;
+
+  mQueue.PushBack(imageFrame);
+
   mRequestingLoad = true;
 
   bool synchronousLoading = false;
   mRequestingLoad = true;
 
   bool synchronousLoading = false;
@@ -178,14 +222,8 @@ void RollingAnimatedImageCache::LoadBatch()
   // removed, and another frame is loaded
 
   bool frontFrameReady = IsFrontReady();
   // removed, and another frame is loaded
 
   bool frontFrameReady = IsFrontReady();
-  for( unsigned int i=0; i< mBatchSize && !mQueue.IsFull(); ++i )
+  for( unsigned int i=0; i< mBatchSize && mQueue.Count() + mLoadWaitingQueue.size() < static_cast<uint32_t>(mCacheSize) && !mQueue.IsFull(); ++i )
   {
   {
-    ImageFrame imageFrame;
-    imageFrame.mFrameNumber = mFrameIndex;
-    imageFrame.mReady = false;
-
-    mQueue.PushBack( imageFrame );
-
     if( !mOnLoading )
     {
       mOnLoading = true;
     if( !mOnLoading )
     {
       mOnLoading = true;
index 3a24eb6..db35741 100644 (file)
@@ -79,9 +79,21 @@ public:
   TextureSet FirstFrame() override;
 
   /**
   TextureSet FirstFrame() override;
 
   /**
+   * Get the next frame. If it's not ready, this will trigger the
+   * sending of FrameReady() when the image becomes ready.
+   */
+  TextureSet NextFrame() override;
+
+  /**
    * Get the interval of Nth frame.
    */
    * Get the interval of Nth frame.
    */
-  uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+  uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+  /**
+   * Get the current rendered frame index.
+   * If there isn't any loaded frame, returns -1.
+   */
+  int32_t GetCurrentFrameIndex() const override;
 
 private:
   /**
 
 private:
   /**
@@ -149,6 +161,7 @@ private:
   Dali::AnimatedImageLoading  mAnimatedImageLoading;
   uint32_t                    mFrameCount;
   int                         mFrameIndex;
   Dali::AnimatedImageLoading  mAnimatedImageLoading;
   uint32_t                    mFrameCount;
   int                         mFrameIndex;
+  int                         mCacheSize;
   std::vector<UrlStore>       mImageUrls;
   std::vector<int32_t>        mIntervals;
   std::vector<uint32_t>       mLoadWaitingQueue;
   std::vector<UrlStore>       mImageUrls;
   std::vector<int32_t>        mIntervals;
   std::vector<uint32_t>       mLoadWaitingQueue;
index 2284778..e838060 100644 (file)
@@ -131,11 +131,40 @@ TextureSet RollingImageCache::FirstFrame()
   return Frame( 0u );
 }
 
   return Frame( 0u );
 }
 
-uint32_t RollingImageCache::GetFrameInterval( uint32_t frameIndex )
+TextureSet RollingImageCache::NextFrame()
+{
+  TextureSet textureSet;
+  if(!mQueue.IsEmpty())
+  {
+    uint32_t frameIndex = mQueue.Front().mUrlIndex;
+    if(IsFrontReady())
+    {
+      frameIndex = (frameIndex + 1) % mImageUrls.size();
+    }
+    textureSet = Frame(frameIndex);
+  }
+  else
+  {
+    DALI_LOG_ERROR("Cache is empty.");
+  }
+
+  return textureSet;
+}
+
+uint32_t RollingImageCache::GetFrameInterval( uint32_t frameIndex ) const
 {
   return 0u;
 }
 
 {
   return 0u;
 }
 
+int32_t RollingImageCache::GetCurrentFrameIndex() const
+{
+  if(mQueue.IsEmpty())
+  {
+    return -1;
+  }
+  return mQueue.Front().mUrlIndex;
+}
+
 bool RollingImageCache::IsFrontReady() const
 {
   return ( !mQueue.IsEmpty() && mQueue.Front().mReady );
 bool RollingImageCache::IsFrontReady() const
 {
   return ( !mQueue.IsEmpty() && mQueue.Front().mReady );
index 5f4aa46..c20586f 100644 (file)
@@ -72,9 +72,21 @@ public:
   TextureSet FirstFrame() override;
 
   /**
   TextureSet FirstFrame() override;
 
   /**
+   * Get the next frame. If it's not ready, this will trigger the
+   * sending of FrameReady() when the image becomes ready.
+   */
+  TextureSet NextFrame() override;
+
+  /**
    * Get the interval of Nth frame.
    */
    * Get the interval of Nth frame.
    */
-  uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+  uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+  /**
+   * Get the current rendered frame index.
+   * If there isn't any loaded frame, returns -1.
+   */
+  int32_t GetCurrentFrameIndex() const override;
 
 private:
   /**
 
 private:
   /**
index 2d82b41..ea0abc1 100644 (file)
@@ -458,16 +458,15 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 
   TextureHash textureHash = INITIAL_CACHE_NUMBER;
   int cacheIndex = INVALID_CACHE_INDEX;
 
   TextureHash textureHash = INITIAL_CACHE_NUMBER;
   int cacheIndex = INVALID_CACHE_INDEX;
-  if(storageType != StorageType::RETURN_PIXEL_BUFFER)
+  if(storageType != StorageType::RETURN_PIXEL_BUFFER && !isAnimatedImage)
   {
   {
-    textureHash = GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, isAnimatedImage, frameIndex);
+    textureHash = GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId);
 
     // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
 
     // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
-    cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, preMultiplyOnLoad, isAnimatedImage, frameIndex);
+    cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, preMultiplyOnLoad);
   }
 
   TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
   }
 
   TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
-
   // Check if the requested Texture exists in the cache.
   if( cacheIndex != INVALID_CACHE_INDEX )
   {
   // Check if the requested Texture exists in the cache.
   if( cacheIndex != INVALID_CACHE_INDEX )
   {
@@ -1175,9 +1174,7 @@ TextureManager::TextureHash TextureManager::GenerateHash(
   const FittingMode::Type        fittingMode,
   const Dali::SamplingMode::Type samplingMode,
   const UseAtlas                 useAtlas,
   const FittingMode::Type        fittingMode,
   const Dali::SamplingMode::Type samplingMode,
   const UseAtlas                 useAtlas,
-  TextureId                      maskTextureId,
-  bool                           isAnimationImage,
-  uint32_t                       frameIndex )
+  TextureId                      maskTextureId)
 {
   std::string hashTarget( url );
   const size_t urlLength = hashTarget.length();
 {
   std::string hashTarget( url );
   const size_t urlLength = hashTarget.length();
@@ -1222,19 +1219,6 @@ TextureManager::TextureHash TextureManager::GenerateHash(
     }
   }
 
     }
   }
 
-  if( isAnimationImage )
-  {
-    auto textureIdIndex = hashTarget.length();
-    hashTarget.resize( hashTarget.length() + sizeof( uint32_t ) );
-    char* hashTargetPtr = &( hashTarget[ textureIdIndex ] );
-
-    for( size_t byteIter = 0; byteIter < sizeof( uint32_t ); ++byteIter )
-    {
-      *hashTargetPtr++ = frameIndex & 0xff;
-      frameIndex >>= 8u;
-    }
-  }
-
   if( maskTextureId != INVALID_TEXTURE_ID )
   {
     auto textureIdIndex = hashTarget.length();
   if( maskTextureId != INVALID_TEXTURE_ID )
   {
     auto textureIdIndex = hashTarget.length();
@@ -1261,9 +1245,7 @@ int TextureManager::FindCachedTexture(
   const Dali::SamplingMode::Type    samplingMode,
   const bool                        useAtlas,
   TextureId                         maskTextureId,
   const Dali::SamplingMode::Type    samplingMode,
   const bool                        useAtlas,
   TextureId                         maskTextureId,
-  TextureManager::MultiplyOnLoad    preMultiplyOnLoad,
-  bool                              isAnimatedImage,
-  uint32_t                          frameIndex )
+  TextureManager::MultiplyOnLoad    preMultiplyOnLoad)
 {
   // Default to an invalid ID, in case we do not find a match.
   int cacheIndex = INVALID_CACHE_INDEX;
 {
   // Default to an invalid ID, in case we do not find a match.
   int cacheIndex = INVALID_CACHE_INDEX;
@@ -1283,9 +1265,7 @@ int TextureManager::FindCachedTexture(
           ( size == textureInfo.desiredSize ) &&
           ( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
             ( fittingMode == textureInfo.fittingMode &&
           ( size == textureInfo.desiredSize ) &&
           ( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
             ( fittingMode == textureInfo.fittingMode &&
-              samplingMode == textureInfo.samplingMode ) ) &&
-          ( isAnimatedImage == ( ( textureInfo.animatedImageLoading ) ? true : false ) ) &&
-          ( frameIndex == textureInfo.frameIndex ) )
+              samplingMode == textureInfo.samplingMode ) ) )
       {
         // 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
         // 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
       {
         // 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
         // 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
index a3da3fc..28e0869 100644 (file)
@@ -752,14 +752,12 @@ private:
    * @param[in] samplingMode     The SamplingMode to use
    * @param[in] useAtlas         True if atlased
    * @param[in] maskTextureId    The masking texture id (or INVALID_TEXTURE_ID)
    * @param[in] samplingMode     The SamplingMode to use
    * @param[in] useAtlas         True if atlased
    * @param[in] maskTextureId    The masking texture id (or INVALID_TEXTURE_ID)
-   * @param[in] isAnimatedImage  The boolean value to know whether the request is for animated image or not
-   * @param[in] frameIndex       The frame index of a frame to be loaded frame
    * @return                     A hash of the provided data for caching.
    */
   TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
                             const FittingMode::Type fittingMode,
                             const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
    * @return                     A hash of the provided data for caching.
    */
   TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
                             const FittingMode::Type fittingMode,
                             const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
-                            TextureId maskTextureId, bool isAnimatedImage, uint32_t frameIndex );
+                            TextureId maskTextureId );
 
   /**
    * @brief Looks up a cached texture by its hash.
 
   /**
    * @brief Looks up a cached texture by its hash.
@@ -772,8 +770,6 @@ private:
    * @param[in] useAtlas          True if atlased
    * @param[in] maskTextureId     Optional texture ID to use to mask this image
    * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
    * @param[in] useAtlas          True if atlased
    * @param[in] maskTextureId     Optional texture ID to use to mask this image
    * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
-   * @param[in] isAnimatedImage   The boolean value to know whether the request is for animated image or not
-   * @param[in] frameIndex        The frame index of a frame to be loaded frame
    * @return                      A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
    */
   TextureManager::TextureId FindCachedTexture(
    * @return                      A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
    */
   TextureManager::TextureId FindCachedTexture(
@@ -784,9 +780,7 @@ private:
     const Dali::SamplingMode::Type samplingMode,
     const bool useAtlas,
     TextureId maskTextureId,
     const Dali::SamplingMode::Type samplingMode,
     const bool useAtlas,
     TextureId maskTextureId,
-    MultiplyOnLoad preMultiplyOnLoad,
-    bool isAnimatedImage,
-    uint32_t frameIndex );
+    MultiplyOnLoad preMultiplyOnLoad);
 
 private:
 
 
 private: