From c20463e1d4a77117810c67adfec49bcdfab5efde Mon Sep 17 00:00:00 2001 From: Umar Date: Thu, 9 Nov 2017 20:48:49 +0000 Subject: [PATCH] Removed Texture Atlas for the GIF image. Added new RollingGifImageCache for animated images. Change-Id: Idda4fecb7f4c5303f459a9e6b18222fdb3c83a41 --- .../src/dali-toolkit/utc-Dali-VisualFactory.cpp | 46 ++--- dali-toolkit/internal/file.list | 1 + .../animated-image/animated-image-visual.cpp | 187 ++++++++++++--------- .../visuals/animated-image/animated-image-visual.h | 18 +- .../visuals/animated-image/fixed-image-cache.cpp | 30 +++- .../visuals/animated-image/fixed-image-cache.h | 5 +- .../visuals/animated-image/image-cache.cpp | 2 - .../internal/visuals/animated-image/image-cache.h | 4 +- .../animated-image/rolling-gif-image-cache.cpp | 182 ++++++++++++++++++++ .../animated-image/rolling-gif-image-cache.h | 123 ++++++++++++++ .../visuals/animated-image/rolling-image-cache.cpp | 24 ++- .../visuals/animated-image/rolling-image-cache.h | 3 +- .../internal/visuals/texture-manager-impl.cpp | 44 ++++- .../internal/visuals/texture-manager-impl.h | 9 +- dali-toolkit/internal/visuals/visual-base-impl.cpp | 0 dali-toolkit/internal/visuals/visual-url.cpp | 2 +- dali-toolkit/internal/visuals/visual-url.h | 2 +- 17 files changed, 535 insertions(+), 147 deletions(-) mode change 100644 => 100755 dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp create mode 100644 dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.cpp create mode 100644 dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.h mode change 100644 => 100755 dali-toolkit/internal/visuals/visual-base-impl.cpp diff --git a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp index 54a45a3..9556968 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp @@ -1905,14 +1905,14 @@ int UtcDaliVisualFactoryGetAnimatedImageVisual1(void) ToolkitTestApplication application; tet_infoline( "UtcDaliVisualFactoryGetAnimatedImageVisual1: Request animated image visual with a gif url" ); - VisualFactory factory = VisualFactory::Get(); - Visual::Base visual = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); - DALI_TEST_CHECK( visual ); - TestGlAbstraction& gl = application.GetGlAbstraction(); TraceCallStack& textureTrace = gl.GetTextureTrace(); textureTrace.Enable(true); + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); + DALI_TEST_CHECK( visual ); + DummyControl actor = DummyControl::New(true); DummyControlImpl& dummyImpl = static_cast(actor.GetImplementation()); dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); @@ -1924,54 +1924,34 @@ int UtcDaliVisualFactoryGetAnimatedImageVisual1(void) // renderer is added to actor DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); - - // test the uniforms which used to handle the atlas rect - // the four frames should be located inside atlas as follows: atlas size 100*100 - // ------------- - // | | | - // | 0 | 1 | - // ------------- - // | | | - // | 2 | 3 | - // ------------- - Renderer renderer = actor.GetRendererAt( 0u ); DALI_TEST_CHECK( renderer ); - Property::Value atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); - // take into consideration the half pixel correction - DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(0.5f, 0.5f, 49.5f, 49.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); - - // waiting for the resource uploading - application.SendNotification(); - application.Render(); - - DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); // Force the timer used by the animatedImageVisual to tick, Dali::Timer timer = Timer::New( 0 ); timer.MockEmitSignal(); application.SendNotification(); application.Render(); - atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); - // take into consideration the half pixel correction - DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(50.5f, 0.5f, 99.5f, 49.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); + // Force the timer used by the animatedImageVisual to tick, timer.MockEmitSignal(); application.SendNotification(); application.Render(); - atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); - // take into consideration the half pixel correction - DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(0.5f, 50.5f, 49.5f, 99.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); // Force the timer used by the animatedImageVisual to tick, timer.MockEmitSignal(); application.SendNotification(); application.Render(); - atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); - // take into consideration the half pixel correction - DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(50.5f, 50.5f, 99.5f, 99.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); // Test SetOffStage(). actor.Unparent(); diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index b5c1aaf..a83612d 100755 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -15,6 +15,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/visuals/animated-image/image-cache.cpp \ $(toolkit_src_dir)/visuals/animated-image/fixed-image-cache.cpp \ $(toolkit_src_dir)/visuals/animated-image/rolling-image-cache.cpp \ + $(toolkit_src_dir)/visuals/animated-image/rolling-gif-image-cache.cpp \ $(toolkit_src_dir)/visuals/border/border-visual.cpp \ $(toolkit_src_dir)/visuals/color/color-visual.cpp \ $(toolkit_src_dir)/visuals/gradient/gradient-visual.cpp \ diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp old mode 100644 new mode 100755 index 9ac0b90..84ae1c9 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -19,9 +19,9 @@ #include "animated-image-visual.h" // EXTERNAL INCLUDES -#include #include #include +#include // INTERNAL INCLUDES #include @@ -32,8 +32,10 @@ #include #include #include +#include #include #include +#include namespace Dali { @@ -65,12 +67,17 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " /** * Multi-image Flow of execution * - * | DoSetProperties() + * | New + * | DoSetProperties() * | LoadFirstBatch() - * | cache->LoadBatch() + * | new cache + * | cache->LoadBatch() * | * | DoSetOnStage() + * | PrepareTextureSet() + * | cache->FirstFrame() * | CreateRenderer() (Doesn't become ready until first frame loads) + * | StartFirstFrame() * | * | FrameReady(textureSet) * | start first frame: @@ -94,16 +101,21 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl, const Property::Map& properties ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); - visual->mImageUrl = imageUrl; + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) ); + visual->InitializeGif( imageUrl ); visual->SetProperties( properties ); + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } + return visual; } AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const Property::Array& imageUrls, const Property::Map& properties ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) ); visual->mImageUrls = new ImageCache::UrlList(); visual->mImageUrls->reserve( imageUrls.Count() ); @@ -114,26 +126,45 @@ AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCach urlStore.mUrl = imageUrls[i].Get(); visual->mImageUrls->push_back( urlStore ); } - + visual->mFrameCount = imageUrls.Count(); visual->SetProperties( properties ); - // starts loading immediately + + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } + return visual; } AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const VisualUrl& imageUrl ) { - AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); - visual->mImageUrl = imageUrl; + AnimatedImageVisualPtr visual( new AnimatedImageVisual( factoryCache ) ); + visual->InitializeGif( imageUrl ); + + if( visual->mFrameCount > 0 ) + { + visual->LoadFirstBatch(); + } return visual; } +void AnimatedImageVisual::InitializeGif( const VisualUrl& imageUrl ) +{ + mImageUrl = imageUrl; + mGifLoading = GifLoading::New( imageUrl.GetUrl() ); + mFrameCount = mGifLoading->GetImageCount(); + mGifLoading->LoadFrameDelays( mFrameDelayContainer ); +} + AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mFrameDelayTimer(), mPlacementActor(), mPixelArea( FULL_TEXTURE_RECT ), mImageUrl(), + mGifLoading( nullptr ), mCurrentFrameIndex( 0 ), mImageUrls( NULL ), mImageCache( NULL ), @@ -141,6 +172,7 @@ AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache ) mBatchSize( 1 ), mFrameDelay( 100 ), mUrlIndex( 0 ), + mFrameCount( 0 ), mImageSize(), mWrapModeU( WrapMode::DEFAULT ), mWrapModeV( WrapMode::DEFAULT ), @@ -159,7 +191,7 @@ void AnimatedImageVisual::GetNaturalSize( Vector2& naturalSize ) { if( mImageUrl.IsValid() ) { - mImageSize = Dali::GetGifImageSize( mImageUrl.GetUrl() ); + mImageSize = mGifLoading->GetImageSize(); } else if( mImageUrls && mImageUrls->size() > 0 ) { @@ -245,11 +277,6 @@ void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) } } } - - if( mImageUrls && mImageUrls->size() > 0 ) - { - LoadFirstBatch(); - } } void AnimatedImageVisual::DoSetProperty( Property::Index index, @@ -347,9 +374,6 @@ void AnimatedImageVisual::DoSetOffStage( Actor& actor ) mFrameDelayTimer.Reset(); } - mTextureRectContainer.Clear(); - mFrameDelayContainer.Clear(); - actor.RemoveRenderer( mImpl->mRenderer ); mImpl->mRenderer.Reset(); mPlacementActor.Reset(); @@ -366,7 +390,7 @@ void AnimatedImageVisual::OnSetTransform() void AnimatedImageVisual::CreateRenderer() { bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; - bool atlasing = (mTextureRectContainer.Count() > 0) ; + bool atlasing = false; Shader shader = ImageVisual::GetImageShader( mFactoryCache, atlasing, defaultWrapMode ); Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); @@ -389,27 +413,38 @@ void AnimatedImageVisual::CreateRenderer() } mCurrentFrameIndex = 0; - - if( mTextureRectContainer.Count() > 0 ) - { - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); - } } void AnimatedImageVisual::LoadFirstBatch() { - DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::LoadFirstBatch()\n"); - // Ensure the batch size and cache size are no bigger than the number of URLs, // and that the cache is at least as big as the batch size. - uint16_t numUrls = mImageUrls->size(); - uint16_t batchSize = std::min( mBatchSize, numUrls ); - uint16_t cacheSize = std::min( std::max( batchSize, mCacheSize ), numUrls ); + uint16_t numUrls = 0; + uint16_t batchSize = 1; + uint16_t cacheSize = 1; + + if( mImageUrls ) + { + numUrls = mImageUrls->size(); + } + else + { + numUrls = mFrameCount; + } + + batchSize = std::min( mBatchSize, numUrls ); + cacheSize = std::min( std::max( batchSize, mCacheSize ), numUrls ); + + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::LoadFirstBatch() batchSize:%d cacheSize:%d\n", batchSize, cacheSize); mUrlIndex = 0; TextureManager& textureManager = mFactoryCache.GetTextureManager(); - if( batchSize > 0 && cacheSize > 0 ) + if( mGifLoading != nullptr ) + { + mImageCache = new RollingGifImageCache( textureManager, *mGifLoading, mFrameCount, *this, cacheSize, batchSize ); + } + else if( batchSize > 0 && cacheSize > 0 ) { if( cacheSize < numUrls ) { @@ -424,6 +459,10 @@ void AnimatedImageVisual::LoadFirstBatch() { mImageCache = new RollingImageCache( textureManager, *mImageUrls, *this, 1, 1 ); } + if (!mImageCache) + { + DALI_LOG_ERROR("mImageCache is null"); + } } void AnimatedImageVisual::StartFirstFrame( TextureSet& textureSet ) @@ -439,55 +478,37 @@ void AnimatedImageVisual::StartFirstFrame( TextureSet& textureSet ) mPlacementActor.Reset(); } - int frameDelay = mFrameDelay; - if( mFrameDelayContainer.Count() > 1 ) + mCurrentFrameIndex = 0; + + if( mFrameCount > 1 ) { - frameDelay = mFrameDelayContainer[0]; - } - mFrameDelayTimer = Timer::New( frameDelay ); - mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); - mFrameDelayTimer.Start(); + int frameDelay = mFrameDelay; // from URL array + if( mFrameDelayContainer.Count() > 0 ) // from GIF + { + frameDelay = mFrameDelayContainer[0]; + } - DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady()\n"); + mFrameDelayTimer = Timer::New( frameDelay ); + mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); + mFrameDelayTimer.Start(); + } + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady(ResourceStatus::READY)\n"); ResourceReady( Toolkit::Visual::ResourceStatus::READY ); } TextureSet AnimatedImageVisual::PrepareTextureSet() { TextureSet textureSet; - if( mImageUrl.IsValid() ) + if (mImageCache) + textureSet = mImageCache->FirstFrame(); + if( textureSet ) { - textureSet = PrepareAnimatedGifImage(); + SetImageSize( textureSet ); } else { - textureSet = mImageCache->FirstFrame(); - if( textureSet ) - { - SetImageSize( textureSet ); - } - } - return textureSet; -} - -TextureSet AnimatedImageVisual::PrepareAnimatedGifImage() -{ - TextureSet textureSet; - - // load from image file - std::vector pixelDataList; - - if( mImageUrl.IsLocalResource() ) - { - if( Dali::LoadAnimatedGifFromFile( mImageUrl.GetUrl().c_str() , pixelDataList, mFrameDelayContainer ) ) - { - mImageSize.SetWidth( pixelDataList[0].GetWidth() ); - mImageSize.SetHeight( pixelDataList[0].GetHeight() ); - - Texture texture = Toolkit::ImageAtlas::PackToAtlas( pixelDataList, mTextureRectContainer ); - textureSet = TextureSet::New(); - textureSet.SetTexture( 0, texture ); - } + DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"ResourceReady(ResourceStatus::FAILED)\n"); + ResourceReady( Toolkit::Visual::ResourceStatus::FAILED ); } return textureSet; @@ -522,29 +543,31 @@ void AnimatedImageVisual::FrameReady( TextureSet textureSet ) bool AnimatedImageVisual::DisplayNextFrame() { - DALI_LOG_INFO(gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame() start\n"); - - if( mFrameDelayContainer.Count() > 0 ) + if( mFrameCount > 1 ) { // Wrap the frame index ++mCurrentFrameIndex; - mCurrentFrameIndex %= mFrameDelayContainer.Count(); + mCurrentFrameIndex %= mFrameCount; + } + DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) FrameCount:%d\n", this, mCurrentFrameIndex); - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); + if( mFrameDelayContainer.Count() > 0 ) + { + unsigned int delay = mFrameDelayContainer[mCurrentFrameIndex]; - if( mFrameDelayTimer.GetInterval() != mFrameDelayContainer[mCurrentFrameIndex] ) + if( mFrameDelayTimer.GetInterval() != delay ) { - mFrameDelayTimer.SetInterval( mFrameDelayContainer[mCurrentFrameIndex] ); + mFrameDelayTimer.SetInterval( delay ); } } - else if( mImageCache ) + + TextureSet textureSet; + if (mImageCache) + textureSet = mImageCache->NextFrame(); + if( textureSet ) { - TextureSet textureSet = mImageCache->NextFrame(); - if( textureSet ) - { - SetImageSize( textureSet ); - mImpl->mRenderer.SetTextures( textureSet ); - } + SetImageSize( textureSet ); + mImpl->mRenderer.SetTextures( textureSet ); } // Keep timer ticking diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h index 1e71ba1..5c9b31c 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h @@ -24,6 +24,7 @@ #include #include #include +#include // INTERNAL INCLUDES #include @@ -184,6 +185,7 @@ private: /** * Adds the texture set to the renderer, and the renderer to the * placement actor, and starts the frame timer + * @param[in] textureSet The texture set to apply */ void StartFirstFrame( TextureSet& textureSet ); @@ -193,18 +195,14 @@ private: TextureSet PrepareTextureSet(); /** - * Load the gif image and pack the frames into atlas. - * @return The atlas texture. - */ - TextureSet PrepareAnimatedGifImage(); - - /** * Set the image size from the texture set + * @param[in] textureSet The texture set to get the size from */ void SetImageSize( TextureSet& textureSet ); /** * Called when the next frame is ready. + * @param[in] textureSet the texture set to apply */ void FrameReady( TextureSet textureSet ); @@ -214,6 +212,11 @@ private: */ bool DisplayNextFrame(); + /** + * Initialize the gif variables. + * @param[in] imageUrl The url of the animated gif + */ + void InitializeGif( const VisualUrl& imageUrl ); // Undefined AnimatedImageVisual( const AnimatedImageVisual& animatedImageVisual ); @@ -227,10 +230,10 @@ private: WeakHandle mPlacementActor; // Variables for GIF player - Dali::Vector mTextureRectContainer; Dali::Vector mFrameDelayContainer; Vector4 mPixelArea; VisualUrl mImageUrl; + std::unique_ptr mGifLoading; // Only needed for animated gifs uint32_t mCurrentFrameIndex; // Frame index into textureRects // Variables for Multi-Image player @@ -242,6 +245,7 @@ private: uint16_t mUrlIndex; // Shared variables + uint32_t mFrameCount; // Number of frames ImageDimensions mImageSize; Dali::WrapMode::Type mWrapModeU:3; diff --git a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp index 03dbcbc..3764500 100644 --- a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp @@ -17,6 +17,9 @@ // CLASS HEADER #include +// INTERNAL HEADERS +#include // For ImageAtlasManagerPtr + namespace Dali { namespace Toolkit @@ -32,7 +35,8 @@ const bool ENABLE_ORIENTATION_CORRECTION( true ); FixedImageCache::FixedImageCache( TextureManager& textureManager, UrlList& urlList, ImageCache::FrameReadyObserver& observer, unsigned int batchSize ) -: ImageCache( textureManager, urlList, observer, batchSize ), +: ImageCache( textureManager, observer, batchSize ), + mImageUrls( urlList ), mFront(0u) { mReadyFlags.reserve( mImageUrls.size() ); @@ -102,10 +106,26 @@ void FixedImageCache::LoadBatch() // need to account for this inside the UploadComplete method using mRequestingLoad. mRequestingLoad = true; - mImageUrls[ mUrlIndex ].mTextureId = - mTextureManager.RequestLoad( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, - SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - this, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); + bool synchronousLoading = false; + bool atlasingStatus = false; + bool loadingStatus = false; + TextureManager::MaskingDataPointer maskInfo = nullptr; + AtlasUploadObserver* atlasObserver = nullptr; + ImageAtlasManagerPtr imageAtlasManager = nullptr; + Vector4 textureRect; + + mTextureManager.LoadTexture( + url, ImageDimensions(), FittingMode::SCALE_TO_FILL, + SamplingMode::BOX_THEN_LINEAR, maskInfo, + synchronousLoading, mImageUrls[ mUrlIndex ].mTextureId, textureRect, + atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, + Dali::WrapMode::Type::DEFAULT, this, + atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); + + if( loadingStatus == false ) // not loading, means it's already ready. + { + SetImageFrameReady( mImageUrls[ mUrlIndex ].mTextureId ); + } mRequestingLoad = false; ++mUrlIndex; } diff --git a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h index 4c59447..b9b2ddb 100644 --- a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h @@ -28,7 +28,7 @@ namespace Toolkit namespace Internal { -class FixedImageCache : public ImageCache +class FixedImageCache : public ImageCache, public TextureUploadObserver { public: /** @@ -97,7 +97,8 @@ protected: bool useAtlasing, const Vector4& atlasRect ); -protected: +private: + std::vector& mImageUrls; std::vector mReadyFlags; unsigned int mFront; }; diff --git a/dali-toolkit/internal/visuals/animated-image/image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/image-cache.cpp index 1d0db6f..84e5f66 100644 --- a/dali-toolkit/internal/visuals/animated-image/image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/image-cache.cpp @@ -24,12 +24,10 @@ namespace Internal { ImageCache::ImageCache( TextureManager& textureManager, - UrlList& urlList, ImageCache::FrameReadyObserver& observer, unsigned int batchSize ) : mTextureManager( textureManager ), mObserver( observer ), - mImageUrls( urlList ), mBatchSize( batchSize ), mUrlIndex(0u), mWaitingForReadyFrame(false), diff --git a/dali-toolkit/internal/visuals/animated-image/image-cache.h b/dali-toolkit/internal/visuals/animated-image/image-cache.h index 12e89e9..1a7ae75 100644 --- a/dali-toolkit/internal/visuals/animated-image/image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/image-cache.h @@ -28,7 +28,7 @@ namespace Toolkit namespace Internal { -class ImageCache : public TextureUploadObserver +class ImageCache { public: /** @@ -67,7 +67,6 @@ public: * batch and cache sizes. The cache is as large as the number of urls. */ ImageCache( TextureManager& textureManager, - UrlList& urlList, ImageCache::FrameReadyObserver& observer, unsigned int batchSize ); @@ -89,7 +88,6 @@ public: protected: TextureManager& mTextureManager; FrameReadyObserver& mObserver; - std::vector& mImageUrls; unsigned int mBatchSize; unsigned int mUrlIndex; bool mWaitingForReadyFrame:1; diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.cpp new file mode 100644 index 0000000..5922f74 --- /dev/null +++ b/dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// CLASS HEADER +#include "rolling-gif-image-cache.h" + +// EXTERNAL HEADERS + +// INTERNAL HEADERS +#include +#include // For ImageAtlasManagerPtr +#include + +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE"); + +#define LOG_CACHE \ + { \ + std::ostringstream oss; \ + oss<<"Size:"< pixelDataList; + + // Get the smallest number of frames we need to load + 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) ) + { + unsigned int pixelDataListCount = pixelDataList.size(); + + for( unsigned int i = 0; i < pixelDataListCount && !mQueue.IsFull(); ++i ) + { + ImageFrame imageFrame; + + // create the texture for uploading the pixel data + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, + pixelDataList[i].GetPixelFormat(), + pixelDataList[i].GetWidth(), + pixelDataList[i].GetHeight() ); + + texture.Upload( pixelDataList[i] ); + + mImageUrls[ mUrlIndex ].mUrl = Dali::Toolkit::TextureManager::AddTexture(texture); + imageFrame.mFrameNumber = mUrlIndex; + + ++mUrlIndex; + mUrlIndex %= mImageUrls.size(); + + mQueue.PushBack( imageFrame ); + + bool synchronousLoading = false; + bool atlasingStatus = false; + bool loadingStatus = false; + TextureManager::MaskingDataPointer maskInfo = nullptr; + AtlasUploadObserver* atlasObserver = nullptr; + ImageAtlasManagerPtr imageAtlasManager = nullptr; + Vector4 textureRect; + + mTextureManager.LoadTexture( + mImageUrls[ imageFrame.mFrameNumber ].mUrl, ImageDimensions(), FittingMode::SCALE_TO_FILL, + SamplingMode::BOX_THEN_LINEAR, maskInfo, + synchronousLoading, mImageUrls[ imageFrame.mFrameNumber ].mTextureId, textureRect, + atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, + Dali::WrapMode::Type::DEFAULT, NULL, + atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); + } + + mFrameIndex += batchSize; + mFrameIndex %= mFrameCount; + } + + LOG_CACHE; +} + +TextureSet RollingGifImageCache::GetFrontTextureSet() const +{ + DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "RollingGifImageCache::GetFrontTextureSet() FrameNumber:%d\n", mQueue[ 0 ].mFrameNumber ); + + TextureManager::TextureId textureId = GetCachedTextureId( 0 ); + return mTextureManager.GetTextureSet( textureId ); +} + +TextureManager::TextureId RollingGifImageCache::GetCachedTextureId( int index ) const +{ + return mImageUrls[ mQueue[ index ].mFrameNumber ].mTextureId; +} + +} //namespace Internal +} //namespace Toolkit +} //namespace Dali diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.h b/dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.h new file mode 100644 index 0000000..778eeda --- /dev/null +++ b/dali-toolkit/internal/visuals/animated-image/rolling-gif-image-cache.h @@ -0,0 +1,123 @@ +#ifndef DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H +#define DALI_TOOLKIT_INTERNAL_ROLLING_GIF_IMAGE_CACHE_H + +/* + * Copyright (c) 2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ + +/** + * Class to manage a rolling cache of GIF images, where the cache size + * is smaller than the total number of images. + * + * Frames are always ready, so the observer.FrameReady callback is never triggered; + * the FirstFrame and NextFrame APIs will always return a texture. + */ +class RollingGifImageCache : public ImageCache +{ +public: + /** + * Constructor. + * @param[in] textureManager The texture manager + * @param[in] gifLoader The loaded gif image + * @param[in] frameCount The number of frames in the gif + * @param[in] observer FrameReady observer + * @param[in] cacheSize The size of the cache + * @param[in] batchSize The size of a batch to load + * + * This will start loading textures immediately, according to the + * batch and cache sizes. + */ + RollingGifImageCache( TextureManager& textureManager, + GifLoading& gifLoader, + uint32_t frameCount, + ImageCache::FrameReadyObserver& observer, + uint16_t cacheSize, + uint16_t batchSize ); + + /** + * Destructor + */ + virtual ~RollingGifImageCache(); + + /** + * Get the first frame. If it's not ready, this will trigger the + * sending of FrameReady() when the image becomes ready. + */ + virtual TextureSet FirstFrame(); + + /** + * Get the next frame. If it's not ready, this will trigger the + * sending of FrameReady() when the image becomes ready. + * This will trigger the loading of the next batch. + */ + virtual TextureSet NextFrame(); + +private: + /** + * @return true if the front frame is ready + */ + bool IsFrontReady() const; + + /** + * Load the next batch of images + */ + void LoadBatch(); + + /** + * Get the texture set of the front frame. + * @return the texture set + */ + TextureSet GetFrontTextureSet() const; + + /** + * Get the texture id of the given index + */ + TextureManager::TextureId GetCachedTextureId( int index ) const; + +private: + /** + * Secondary class to hold readiness and index into url + */ + struct ImageFrame + { + unsigned int mFrameNumber; + }; + + GifLoading& mGifLoading; + uint32_t mFrameCount; + int mFrameIndex; + std::vector mImageUrls; + uint16_t mCacheSize; + CircularQueue mQueue; +}; + +} // namespace Internal +} // namespace Toolkit +} // namespace Dali + +#endif diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp index 9c3f82f..62599e5 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp @@ -18,6 +18,7 @@ #include // INTERNAL HEADERS +#include // For ImageAtlasManagerPtr #include // EXTERNAL HEADERS @@ -60,7 +61,8 @@ namespace Internal RollingImageCache::RollingImageCache( TextureManager& textureManager, UrlList& urlList, ImageCache::FrameReadyObserver& observer, uint16_t cacheSize, uint16_t batchSize ) -: ImageCache( textureManager, urlList, observer, batchSize ), +: ImageCache( textureManager, observer, batchSize ), + mImageUrls( urlList ), mQueue( cacheSize ) { LoadBatch(); @@ -139,10 +141,22 @@ void RollingImageCache::LoadBatch() // need to account for this inside the UploadComplete method using mRequestingLoad. mRequestingLoad = true; - mImageUrls[ imageFrame.mUrlIndex ].mTextureId = - mTextureManager.RequestLoad( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, - SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - this, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); + bool synchronousLoading = false; + bool atlasingStatus = false; + bool loadingStatus = false; + TextureManager::MaskingDataPointer maskInfo = nullptr; + AtlasUploadObserver* atlasObserver = nullptr; + ImageAtlasManagerPtr imageAtlasManager = nullptr; + Vector4 textureRect; + + mTextureManager.LoadTexture( + url, ImageDimensions(), FittingMode::SCALE_TO_FILL, + SamplingMode::BOX_THEN_LINEAR, maskInfo, + synchronousLoading, mImageUrls[ imageFrame.mUrlIndex ].mTextureId, textureRect, + atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, + Dali::WrapMode::Type::DEFAULT, this, + atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); + mRequestingLoad = false; } diff --git a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h index 1aed961..06240c6 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h +++ b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h @@ -34,7 +34,7 @@ namespace Internal * Class to manage a rolling cache of images, where the cache size * is smaller than the total number of images. */ -class RollingImageCache : public ImageCache +class RollingImageCache : public ImageCache, public TextureUploadObserver { public: /** @@ -123,6 +123,7 @@ private: bool mReady; }; + std::vector& mImageUrls; CircularQueue mQueue; }; diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index 11d3b0f..6b31322 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -105,7 +105,7 @@ TextureManager::TextureManager() } TextureSet TextureManager::LoadTexture( - VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, + const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, const MaskingDataPointer& maskInfo, bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect, bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU, @@ -128,6 +128,7 @@ TextureSet TextureManager::LoadTexture( { if( elem.textureId == id ) { + textureId = elem.textureId; return elem.textureSet; } } @@ -206,7 +207,7 @@ TextureSet TextureManager::LoadTexture( reloadPolicy ); } - TextureManager::LoadState loadState = GetTextureState( textureId ); + TextureManager::LoadState loadState = GetTextureStateInternal( textureId ); loadingStatus = ( loadState == TextureManager::LOADING ); if( loadState == TextureManager::UPLOADED ) @@ -456,6 +457,31 @@ TextureManager::LoadState TextureManager::GetTextureState( TextureId textureId ) TextureInfo& cachedTextureInfo( mTextureInfoContainer[ cacheIndex ] ); loadState = cachedTextureInfo.loadState; } + else + { + for( auto&& elem : mExternalTextures ) + { + if( elem.textureId == textureId ) + { + loadState = LoadState::UPLOADED; + break; + } + } + } + return loadState; +} + +TextureManager::LoadState TextureManager::GetTextureStateInternal( TextureId textureId ) +{ + LoadState loadState = TextureManager::NOT_STARTED; + + int cacheIndex = GetCacheIndexFromId( textureId ); + if( cacheIndex != INVALID_CACHE_INDEX ) + { + TextureInfo& cachedTextureInfo( mTextureInfoContainer[ cacheIndex ] ); + loadState = cachedTextureInfo.loadState; + } + return loadState; } @@ -469,6 +495,17 @@ TextureSet TextureManager::GetTextureSet( TextureId textureId ) TextureInfo& cachedTextureInfo( mTextureInfoContainer[ cacheIndex ] ); textureSet = cachedTextureInfo.textureSet; } + else + { + for( auto&& elem : mExternalTextures ) + { + if( elem.textureId == textureId ) + { + textureSet = elem.textureSet; + break; + } + } + } return textureSet; } @@ -590,7 +627,7 @@ void TextureManager::PostLoad( TextureInfo& textureInfo, Devel::PixelBuffer& pix // wait for the mask to finish loading. if( textureInfo.maskTextureId != INVALID_TEXTURE_ID ) { - LoadState maskLoadState = GetTextureState( textureInfo.maskTextureId ); + LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId ); if( maskLoadState == LOADING ) { textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily @@ -764,7 +801,6 @@ int TextureManager::GetCacheIndexFromId( const TextureId textureId ) } } - DALI_LOG_WARNING( "Cannot locate TextureId: %d\n", textureId ); return INVALID_CACHE_INDEX; } diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.h b/dali-toolkit/internal/visuals/texture-manager-impl.h index d27b87f..8d46f04 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.h +++ b/dali-toolkit/internal/visuals/texture-manager-impl.h @@ -140,7 +140,7 @@ public: // TextureManager Main API: - TextureSet LoadTexture(VisualUrl& url, Dali::ImageDimensions desiredSize, + TextureSet LoadTexture(const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, const MaskingDataPointer& maskInfo, bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect, @@ -318,6 +318,13 @@ private: bool orientationCorrection, TextureManager::ReloadPolicy reloadPolicy ); + /** + * @brief Get the current state of a texture + * @param[in] textureId The texture id to query + * @return The loading state if the texture is valid, or NOT_STARTED if the textureId + * is not valid. + */ + LoadState GetTextureStateInternal( TextureId textureId ); typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching. diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp old mode 100644 new mode 100755 diff --git a/dali-toolkit/internal/visuals/visual-url.cpp b/dali-toolkit/internal/visuals/visual-url.cpp index 907b428..b1f5f3e 100644 --- a/dali-toolkit/internal/visuals/visual-url.cpp +++ b/dali-toolkit/internal/visuals/visual-url.cpp @@ -234,7 +234,7 @@ bool VisualUrl::IsLocalResource() const return mLocation == VisualUrl::LOCAL; } -std::string VisualUrl::GetLocation() +std::string VisualUrl::GetLocation() const { const auto location = mUrl.find( "://" ); if( std::string::npos != location ) diff --git a/dali-toolkit/internal/visuals/visual-url.h b/dali-toolkit/internal/visuals/visual-url.h index b261813..aac605c 100644 --- a/dali-toolkit/internal/visuals/visual-url.h +++ b/dali-toolkit/internal/visuals/visual-url.h @@ -107,7 +107,7 @@ public: /** * @return the location part of the url */ - std::string GetLocation(); + std::string GetLocation() const; /** * Helper to create a URL of type TEXTURE -- 2.7.4