/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
+int UtcDaliAnimatedImageVisualJumpToAction(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( ImageVisual::Property::BATCH_SIZE, 4);
+ propertyMap.Insert( ImageVisual::Property::CACHE_SIZE, 12);
+ propertyMap.Insert( ImageVisual::Property::FRAME_DELAY, 20);
+
+ VisualFactory factory = VisualFactory::Get();
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+
+ 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 );
+ Stage::GetCurrent().Add( dummyControl );
+ application.SendNotification();
+ application.Render(20);
+
+ tet_infoline( "Ready the visual after the visual is on stage" );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 4 ), true, TEST_LOCATION );
+
+ tet_infoline( "Test that a timer has been started" );
+ DALI_TEST_EQUALS( Test::GetTimerCount(), 1, TEST_LOCATION );
+
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetLastGenTextureId(), 4, TEST_LOCATION );
+
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::STOP, Property::Map() );
+
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 4, TEST_LOCATION );
+
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::JUMP_TO, 20 );
+
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 4, TEST_LOCATION );
+
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::JUMP_TO, 6 );
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 6 ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 4, 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 UtcDaliAnimatedImageVisualStopBehavior(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::FIRST_FRAME);
+ propertyMap.Insert( ImageVisual::Property::BATCH_SIZE, 4);
+ propertyMap.Insert( ImageVisual::Property::CACHE_SIZE, 8);
+ 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 );
+ Stage::GetCurrent().Add( dummyControl );
+ application.SendNotification();
+ application.Render(20);
+
+ tet_infoline( "Ready the visual after the visual is on stage" );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 4 ), true, TEST_LOCATION );
+
+ tet_infoline( "Test that a timer has been started" );
+ DALI_TEST_EQUALS( Test::GetTimerCount(), 1, TEST_LOCATION );
+
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetLastGenTextureId(), 4, TEST_LOCATION );
+
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::STOP, Property::Map() );
+
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 4, TEST_LOCATION );
+
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::JUMP_TO, 1 );
+
+ // Expect the second batch has been requested
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 4 ), true, TEST_LOCATION );
+
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 4, 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 UtcDaliAnimatedImageVisualGif01(void)
+{
+ ToolkitTestApplication application;
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ {
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::ANIMATED_IMAGE );
+ propertyMap.Insert( ImageVisual::Property::URL, TEST_GIF_FILE_NAME );
+ propertyMap.Insert( ImageVisual::Property::BATCH_SIZE, 2);
+ propertyMap.Insert( ImageVisual::Property::CACHE_SIZE, 4);
+ 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 );
+ Stage::GetCurrent().Add( dummyControl );
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetLastGenTextureId(), 2, TEST_LOCATION );
+
+ tet_infoline( "Test that a timer has been started" );
+
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ Test::EmitGlobalTimerSignal();
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetLastGenTextureId(), 4, TEST_LOCATION );
+
+ dummyControl.Unparent();
+ }
+ tet_infoline("Test that removing the visual from stage deletes all textures");
+ application.SendNotification();
+ application.Render(20);
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 0, TEST_LOCATION );
+
+ END_TEST;
+}
int UtcDaliAnimatedImageVisualMultiImage01(void)
{
for ( uint16_t j = 0; j < frameCount; j++ )
{
+ if( i == 0 && j == 0 )
+ {
+ continue; // Because first frame is already showed and we call 2nd frame at the first time of timer animation.
+ }
tet_printf( "Test that after %u ticks, and we have %u frame \n", j + 1u, j + 1u );
Test::EmitGlobalTimerSignal();
application.SendNotification();
#define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_IMAGE_VISUAL_ACTIONS_DEVEL_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
PLAY, ///< Play the animated GIF. This is also Default playback mode.
PAUSE, ///< Pause the animated GIF.
- STOP ///< Stop the animated GIF.
+ STOP, ///< Stop the animated GIF.
+ JUMP_TO ///< Jump to the specified frame. Property::INTEGER value should be passed.
};
} // namespace Action
#define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_PROPERTIES_DEVEL_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
TOTAL_FRAME_NUMBER = ORIENTATION_CORRECTION + 7,
/**
- * @brief The stop behavior the AnimatedVectorImageVisual will use.
+ * @brief The stop behavior the AnimatedImageVisual and AnimatedVectorImageVisual will use.
* @details Name "stopBehavior", Type StopBehavior::Type (Property::INTEGER)
* @note Default value is StopBehavior::CURRENT_FRAME.
*/
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
namespace
{
+// stop behavior
+DALI_ENUM_TO_STRING_TABLE_BEGIN( STOP_BEHAVIOR )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, FIRST_FRAME )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::Toolkit::DevelImageVisual::StopBehavior, LAST_FRAME )
+DALI_ENUM_TO_STRING_TABLE_END( STOP_BEHAVIOR )
+
// wrap modes
DALI_ENUM_TO_STRING_TABLE_BEGIN( WRAP_MODE )
DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, DEFAULT )
mWrapModeU( WrapMode::DEFAULT ),
mWrapModeV( WrapMode::DEFAULT ),
mActionStatus( DevelAnimatedImageVisual::Action::PLAY ),
- mStartFirstFrame(false)
+ mStopBehavior( DevelImageVisual::StopBehavior::CURRENT_FRAME ),
+ mStartFirstFrame(false),
+ mIsJumpTo( false )
{}
AnimatedImageVisual::~AnimatedImageVisual()
map.Insert( Toolkit::ImageVisual::Property::CACHE_SIZE, static_cast<int>(mCacheSize) );
map.Insert( Toolkit::ImageVisual::Property::FRAME_DELAY, static_cast<int>(mFrameDelay) );
map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast<int>(mLoopCount) );
+
+ map.Insert( Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mStopBehavior );
}
void AnimatedImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
{
// STOP reset functionality will actually be done in a future change
// Stop will be executed on next timer tick
- mCurrentFrameIndex = 0;
mActionStatus = DevelAnimatedImageVisual::Action::STOP;
+ if( IsOnStage() )
+ {
+ DisplayNextFrame();
+ }
+ break;
+ }
+ case DevelAnimatedImageVisual::Action::JUMP_TO:
+ {
+ int32_t frameNumber;
+ if( attributes.Get( frameNumber ) )
+ {
+ if( frameNumber < 0 || frameNumber >= static_cast<int32_t>( mFrameCount ) )
+ {
+ DALI_LOG_ERROR( "Invalid frame index used.\n" );
+ }
+ else
+ {
+ mIsJumpTo = true;
+ mCurrentFrameIndex = frameNumber;
+ if( IsOnStage() )
+ {
+ DisplayNextFrame();
+ }
+ }
+ }
break;
}
}
{
DoSetProperty( Toolkit::DevelImageVisual::Property::LOOP_COUNT, keyValue.second );
}
+ else if( keyValue.first == STOP_BEHAVIOR_NAME )
+ {
+ DoSetProperty( Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, keyValue.second );
+ }
}
}
}
}
break;
}
+
+ case Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR:
+ {
+ int32_t stopBehavior = mStopBehavior;
+ if( Scripting::GetEnumerationProperty( value, STOP_BEHAVIOR_TABLE, STOP_BEHAVIOR_TABLE_COUNT, stopBehavior ) )
+ {
+ mStopBehavior = DevelImageVisual::StopBehavior::Type( stopBehavior );
+ }
+ break;
+ }
}
}
if (!mImageCache)
{
- DALI_LOG_ERROR("mImageCache is null");
+ DALI_LOG_ERROR("mImageCache is null\n");
}
}
bool AnimatedImageVisual::DisplayNextFrame()
{
- if( mActionStatus == DevelAnimatedImageVisual::Action::STOP || mActionStatus == DevelAnimatedImageVisual::Action::PAUSE )
+ if( mIsJumpTo )
+ {
+ mIsJumpTo = false;
+ }
+ else if( mActionStatus == DevelAnimatedImageVisual::Action::PAUSE )
{
return false;
}
- if( mFrameCount > 1 )
+ else if( mActionStatus == DevelAnimatedImageVisual::Action::STOP )
{
- // Wrap the frame index
- ++mCurrentFrameIndex;
-
- if( mLoopCount < 0 || mCurrentLoopIndex < mLoopCount)
+ mCurrentLoopIndex = 0;
+ if( mStopBehavior == DevelImageVisual::StopBehavior::FIRST_FRAME )
{
- mCurrentFrameIndex %= mFrameCount;
- if( mCurrentFrameIndex == 0 )
- {
- ++mCurrentLoopIndex;
- }
+ mCurrentFrameIndex = 0;
+ }
+ else if( mStopBehavior == DevelImageVisual::StopBehavior::LAST_FRAME )
+ {
+ mCurrentFrameIndex = mFrameCount - 1;
}
else
{
- // This will stop timer
- return false;
+ return false; // Do not draw already rendered scene twice.
}
}
- DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) FrameCount:%d\n", this, mCurrentFrameIndex);
-
- if( mFrameDelayContainer.Count() > 0 )
+ else
{
- unsigned int delay = mFrameDelayContainer[mCurrentFrameIndex];
+ if( mFrameCount > 1 )
+ {
+ // Wrap the frame index
+ bool finished = false;
+ ++mCurrentFrameIndex;
+ if( mCurrentFrameIndex >= mFrameCount )
+ {
+ ++mCurrentLoopIndex;
+ finished = true;
+ }
- if( mFrameDelayTimer.GetInterval() != delay )
+ if( mLoopCount < 0 || mCurrentLoopIndex < mLoopCount)
+ {
+ if( finished )
+ {
+ mCurrentFrameIndex = 0; // Back to the first frame
+ }
+ }
+ else
+ {
+ // This will stop timer
+ mActionStatus = DevelAnimatedImageVisual::Action::STOP;
+ return DisplayNextFrame();
+ }
+ }
+
+ if( mFrameDelayContainer.Count() > 0 )
{
- mFrameDelayTimer.SetInterval( delay );
+ unsigned int delay = mFrameDelayContainer[mCurrentFrameIndex];
+
+ if( mFrameDelayTimer.GetInterval() != delay )
+ {
+ mFrameDelayTimer.SetInterval( delay );
+ }
}
}
+ DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, mCurrentFrameIndex);
+
TextureSet textureSet;
if( mImageCache )
{
- textureSet = mImageCache->NextFrame();
+ textureSet = mImageCache->Frame( mCurrentFrameIndex );
if( textureSet )
{
SetImageSize( textureSet );
}
}
- // Keep timer ticking
- return true;
+ return ( mActionStatus == DevelAnimatedImageVisual::Action::PLAY ) ? true : false;
}
#define DALI_TOOLKIT_INTERNAL_ANIMATED_IMAGE_VISUAL_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Dali::WrapMode::Type mWrapModeU:3;
Dali::WrapMode::Type mWrapModeV:3;
DevelAnimatedImageVisual::Action::Type mActionStatus:3;
+ DevelImageVisual::StopBehavior::Type mStopBehavior:2;
bool mStartFirstFrame:1;
+ bool mIsJumpTo:1;
};
} // namespace Internal
}
}
+TextureSet FixedImageCache::Frame( uint32_t frameIndex )
+{
+ while( frameIndex > mFront )
+ {
+ NextFrame();
+ }
+ mFront = frameIndex;
+
+ TextureSet textureSet;
+ if( IsFrontReady() == true )
+ {
+ textureSet = GetFrontTextureSet();
+ }
+ else
+ {
+ mWaitingForReadyFrame = true;
+ }
+
+ return textureSet;
+}
+
TextureSet FixedImageCache::FirstFrame()
{
TextureSet textureSet = GetFrontTextureSet();
{
mWaitingForReadyFrame = true;
}
-
LoadBatch();
return textureSet;
// Try and load up to mBatchSize images, until the cache is filled.
// Once the cache is filled, mUrlIndex exceeds mImageUrls size and
// no more images are loaded.
- bool frontFrameReady = IsFrontReady();;
+ bool frontFrameReady = IsFrontReady();
for( unsigned int i=0; i< mBatchSize && mUrlIndex < mImageUrls.size(); ++i )
{
virtual ~FixedImageCache();
/**
+ * Get the Nth frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet Frame( uint32_t frameIndex ) override;
+
+ /**
* Get the first frame. If it's not ready, this will trigger the
* sending of FrameReady() when the image becomes ready.
*/
#define DALI_TOOLKIT_INTERNAL_IMAGE_CACHE_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
struct UrlStore
{
- TextureManager::TextureId mTextureId;
+ TextureManager::TextureId mTextureId = TextureManager::INVALID_TEXTURE_ID;
std::string mUrl;
};
*/
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.
+ */
+ virtual TextureSet Frame( uint32_t frameIndex ) = 0;
+
private:
/**
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
}
+TextureSet RollingGifImageCache::Frame( uint32_t frameIndex )
+{
+ // If a frame of frameIndex is not loaded, clear the queue and remove all loaded textures.
+ if( mImageUrls[ frameIndex ].mTextureId == TextureManager::INVALID_TEXTURE_ID )
+ {
+ mFrameIndex = frameIndex;
+ while( !mQueue.IsEmpty() )
+ {
+ ImageFrame imageFrame = mQueue.PopFront();
+ Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
+ mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ }
+ LoadBatch();
+ }
+ // If the frame is already loaded, remove previous frames of the frame in the queue
+ // and load new frames amount of removed frames.
+ else
+ {
+ bool popExist = false;
+ while( !mQueue.IsEmpty() && mQueue.Front().mFrameNumber != frameIndex )
+ {
+ ImageFrame imageFrame = mQueue.PopFront();
+ Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
+ mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ popExist = true;
+ }
+ if( popExist )
+ {
+ mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
+ LoadBatch();
+ }
+ }
+
+ return GetFrontTextureSet();
+}
TextureSet RollingGifImageCache::FirstFrame()
{
- return GetFrontTextureSet();
+ return Frame( 0u );
}
TextureSet RollingGifImageCache::NextFrame()
{
- TextureSet textureSet;
-
ImageFrame imageFrame = mQueue.PopFront();
Dali::Toolkit::TextureManager::RemoveTexture( mImageUrls[ imageFrame.mFrameNumber ].mUrl );
mImageUrls[ imageFrame.mFrameNumber ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
int batchSize = std::min( std::size_t(mBatchSize), mCacheSize - mQueue.Count() );
DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingGifImageCache::LoadBatch() mFrameIndex:%d batchSize:%d\n", mFrameIndex, batchSize );
- if( mGifLoading.LoadNextNFrames( mFrameIndex, batchSize, pixelDataList) )
+ if( mGifLoading.LoadNextNFrames( mFrameIndex, batchSize, pixelDataList) )
{
unsigned int pixelDataListCount = pixelDataList.size();
#define DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H
/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
virtual ~RollingGifImageCache();
/**
+ * Get the Nth frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet Frame( uint32_t frameIndex ) override;
+
+ /**
* Get the first frame. If it's not ready, this will trigger the
* sending of FrameReady() when the image becomes ready.
*/
}
}
-TextureSet RollingImageCache::FirstFrame()
+TextureSet RollingImageCache::Frame( uint32_t frameIndex )
{
- TextureSet textureSet = GetFrontTextureSet();
+ // If a frame of frameIndex is not loaded, clear the queue and remove all loaded textures.
+ if( mImageUrls[ frameIndex ].mTextureId == TextureManager::INVALID_TEXTURE_ID )
+ {
+ mUrlIndex = frameIndex;
+ while( !mQueue.IsEmpty() )
+ {
+ ImageFrame imageFrame = mQueue.PopFront();
+ mTextureManager.Remove( mImageUrls[ imageFrame.mUrlIndex ].mTextureId, this );
+ mImageUrls[ imageFrame.mUrlIndex ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ }
+ LoadBatch();
+ }
+ // If the frame is already loaded, remove previous frames of the frame in the queue
+ // and load new frames amount of removed frames.
+ else
+ {
+ bool popExist = false;
+ while( !mQueue.IsEmpty() && mQueue.Front().mUrlIndex != frameIndex )
+ {
+ ImageFrame imageFrame = mQueue.PopFront();
+ mTextureManager.Remove( mImageUrls[ imageFrame.mUrlIndex ].mTextureId, this );
+ mImageUrls[ imageFrame.mUrlIndex ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ popExist = true;
+ }
+ if( popExist )
+ {
+ mUrlIndex = ( mQueue.Back().mUrlIndex + 1 ) % mImageUrls.size();
+ LoadBatch();
+ }
+ }
- if( ! textureSet )
+ TextureSet textureSet;
+ if( IsFrontReady() == true )
+ {
+ textureSet = GetFrontTextureSet();
+ }
+ else
{
mWaitingForReadyFrame = true;
}
return textureSet;
}
+TextureSet RollingImageCache::FirstFrame()
+{
+ return Frame( 0u );
+}
+
TextureSet RollingImageCache::NextFrame()
{
TextureSet textureSet;
mTextureManager.Remove( mImageUrls[ imageFrame.mUrlIndex ].mTextureId, this );
mImageUrls[ imageFrame.mUrlIndex ].mTextureId = TextureManager::INVALID_TEXTURE_ID;
+ LoadBatch();
+
if( IsFrontReady() == true )
{
textureSet = GetFrontTextureSet();
mWaitingForReadyFrame = true;
}
- LoadBatch();
-
return textureSet;
}
// Try and load up to mBatchSize images, until the cache is filled.
// Once the cache is filled, as frames progress, the old frame is
// cleared, but not erased, and another image is loaded
- bool frontFrameReady = IsFrontReady();;
+ bool frontFrameReady = IsFrontReady();
for( unsigned int i=0; i< mBatchSize && !mQueue.IsFull(); ++i )
{
virtual ~RollingImageCache();
/**
+ * Get the Nth frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet Frame( uint32_t frameIndex ) override;
+
+ /**
* Get the first frame. If it's not ready, this will trigger the
* sending of FrameReady() when the image becomes ready.
*/