From 5e351965bad7e1de2e94027548b022bac692603c Mon Sep 17 00:00:00 2001 From: Agnelo Vaz Date: Mon, 20 Nov 2017 13:23:41 +0000 Subject: [PATCH] ImageVisual Action::Reload added Reload forces reloading causing the texture to be reloaded even if cached. It updates all uses of this texture (same id) across all image visuals. The texture is replaced hence the renderer gets updated as already references the TextureSet. Change-Id: Idb484d18373d54083727c80f563b7a5f7fb2be8c --- .../dali-toolkit-test-utils/dummy-visual.cpp | 2 +- .../dali-toolkit-test-utils/dummy-visual.h | 2 +- .../utc-Dali-TextureManager.cpp | 3 +- .../src/dali-toolkit/utc-Dali-Control.cpp | 96 +++++++++++++++ dali-toolkit/devel-api/file.list | 1 + .../devel-api/visuals/image-visual-actions-devel.h | 51 ++++++++ .../controls/control/control-data-impl.cpp | 3 - .../visuals/animated-image/fixed-image-cache.cpp | 2 +- .../visuals/animated-image/rolling-image-cache.cpp | 2 +- .../internal/visuals/image/image-visual.cpp | 65 +++++++--- dali-toolkit/internal/visuals/image/image-visual.h | 18 ++- .../internal/visuals/texture-manager-impl.cpp | 132 +++++++++++++-------- .../internal/visuals/texture-manager-impl.h | 112 ++++++++++------- dali-toolkit/internal/visuals/visual-base-impl.cpp | 2 +- dali-toolkit/internal/visuals/visual-base-impl.h | 2 +- 15 files changed, 370 insertions(+), 123 deletions(-) create mode 100644 dali-toolkit/devel-api/visuals/image-visual-actions-devel.h diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.cpp index f5c5aeb..d792609 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.cpp @@ -70,7 +70,7 @@ void DummyVisual::DoSetOnStage( Actor& actor ) // Implement if required } -void DummyVisual::OnDoAction( const Property::Index actionName, const Property::Value attributes ) +void DummyVisual::OnDoAction( const Property::Index actionName, const Property::Value& attributes ) { if ( DummyVisual::TEST_ACTION == actionName ) { diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.h b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.h index 73e8185..23334ba 100644 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.h +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dummy-visual.h @@ -80,7 +80,7 @@ protected: virtual void DoSetProperties( const Property::Map& propertyMap ) override; virtual void OnSetTransform() override; virtual void DoSetOnStage( Actor& actor ) override; - virtual void OnDoAction( const Property::Index actionName, const Property::Value attributes ); + virtual void OnDoAction( const Property::Index actionName, const Property::Value& attributes ) override; private: unsigned int mActionCounter; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp index c2161d1..e09dd06 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp @@ -61,7 +61,8 @@ int UtcTextureManagerRequestLoad(void) SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, &observer, - true ); + true, + TextureManager::ReloadPolicy::CACHED ); const VisualUrl& url = textureManager.GetVisualUrl( textureId ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 9869f21..d695e92 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -27,6 +27,9 @@ #include #include #include +#include + + #include #include "dummy-control.h" @@ -952,3 +955,96 @@ int UtcDaliControlPaddingProperty(void) END_TEST; } + +int UtcDaliControlDoAction(void) +{ + ToolkitTestApplication application; + tet_infoline( "DoAction on a visual registered with a control" ); + + // Set up trace debug + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable( true ); + + //Created AnimatedImageVisual + VisualFactory factory = VisualFactory::Get(); + Visual::Base imageVisual = factory.CreateVisual( TEST_IMAGE_FILE_NAME, ImageDimensions() ); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + dummyControl.SetSize(200.f, 200.f); + Stage::GetCurrent().Add( dummyControl ); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); + + Property::Map attributes; + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, DevelImageVisual::Action::RELOAD, attributes ); + + tet_infoline( "Perform RELOAD action. should reload Image and generate a texture" ); + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliControlDoActionWhenNotStage(void) +{ + ToolkitTestApplication application; + tet_infoline( "DoAction on a visual registered with a control but not staged" ); + + // Set up trace debug + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable( true ); + + //Created AnimatedImageVisual + VisualFactory factory = VisualFactory::Get(); + Visual::Base imageVisual = factory.CreateVisual( TEST_IMAGE_FILE_NAME, ImageDimensions() ); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + dummyControl.SetSize(200.f, 200.f); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), false, TEST_LOCATION ); + textureTrace.Reset(); + + Property::Map attributes; + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, DevelImageVisual::Action::RELOAD, attributes ); + + tet_infoline( "Perform RELOAD action. should reload Image and generate a texture" ); + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); + + tet_infoline( "Adding control to stage will in turn add the visual to the stage" ); + + Stage::GetCurrent().Add( dummyControl ); + application.SendNotification(); + application.Render(); + tet_infoline( "No change in textures could occurs as already loaded and cached texture will be used" ); + + DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), false, TEST_LOCATION ); + textureTrace.Reset(); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index 275e14d..d515119 100644 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -92,6 +92,7 @@ devel_api_visual_factory_header_files = \ devel_api_visuals_header_files = \ $(devel_api_src_dir)/visuals/image-visual-properties-devel.h \ + $(devel_api_src_dir)/visuals/image-visual-actions-devel.h \ $(devel_api_src_dir)/visuals/animated-gradient-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/visual-properties-devel.h diff --git a/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h new file mode 100644 index 0000000..f76e772 --- /dev/null +++ b/dali-toolkit/devel-api/visuals/image-visual-actions-devel.h @@ -0,0 +1,51 @@ +#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_H +#define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_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. + * + */ + +namespace Dali +{ + +namespace Toolkit +{ + +namespace DevelImageVisual +{ + +/** + * @brief Actions that the image visual can perform. These actions are called through the Visual::Base::DoAction API. + */ +namespace Action +{ +/** + * @brief The available actions for this visual + */ +enum Type +{ + RELOAD = 0, ///< Force reloading of the image, all visuals using this image will get the latest one. +}; + +} // namespace Actions + +} // namespace DevelImageVisual + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_H diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index 187e62f..b061268 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -486,9 +486,6 @@ void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base if( !visualReplaced ) // New registration entry { - // monitor when the visual resources are ready - StartObservingVisual( visual ); - // If we've not set the depth-index value, we have more than one visual and the visual does not have a depth index, then set it to be the highest if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) && ( mVisuals.Size() > 0 ) && 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 32f2bc0..03dbcbc 100644 --- a/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp @@ -105,7 +105,7 @@ void FixedImageCache::LoadBatch() mImageUrls[ mUrlIndex ].mTextureId = mTextureManager.RequestLoad( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - this, ENABLE_ORIENTATION_CORRECTION ); + this, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); mRequestingLoad = false; ++mUrlIndex; } 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 847e681..9c3f82f 100644 --- a/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp +++ b/dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp @@ -142,7 +142,7 @@ void RollingImageCache::LoadBatch() mImageUrls[ imageFrame.mUrlIndex ].mTextureId = mTextureManager.RequestLoad( url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, - this, ENABLE_ORIENTATION_CORRECTION ); + this, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED ); mRequestingLoad = false; } diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 9afcb29..8845541 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -33,6 +33,7 @@ // INTERNAL HEADERS #include #include +#include #include #include #include @@ -411,12 +412,12 @@ void ImageVisual::DoSetProperties( const Property::Map& propertyMap ) } } } - // Load image immediately if LOAD_POLICY requires it if ( mLoadPolicy == DevelImageVisual::LoadPolicy::IMMEDIATE ) { - auto attemptAtlasing = mAttemptAtlasing; - LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection ); + auto attemptAtlasing = AttemptAtlasing(); + LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, + TextureManager::ReloadPolicy::CACHED ); } } @@ -759,7 +760,8 @@ bool ImageVisual::IsSynchronousResourceLoading() const return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } -void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection ) +void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection, + TextureManager::ReloadPolicy forceReload ) { TextureManager& textureManager = mFactoryCache.GetTextureManager(); @@ -776,28 +778,35 @@ void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& t textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, IsSynchronousResourceLoading(), mTextureId, atlasRect, atlasing, mLoading, mWrapModeU, - mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection ); + mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, + mOrientationCorrection, + forceReload ); + + if( atlasing ) // Flag needs to be set before creating renderer + { + mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; + } + else + { + mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + } } -void ImageVisual::InitializeRenderer() +bool ImageVisual::AttemptAtlasing() { - auto attemptAtlasing = ( ! mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL && mAttemptAtlasing ); + return ( ! mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL && mAttemptAtlasing ); +} +void ImageVisual::InitializeRenderer() +{ + auto attemptAtlasing = AttemptAtlasing(); // texture set has to be created first as we need to know if atlasing succeeded or not // when selecting the shader if( mTextureId == TextureManager::INVALID_TEXTURE_ID && ! mTextures ) // Only load the texture once { - LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection ); - } - - if( attemptAtlasing ) // Flag needs to be set before creating renderer - { - mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; - } - else - { - mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, + TextureManager::ReloadPolicy::CACHED ); } CreateRenderer( mTextures ); @@ -960,6 +969,22 @@ void ImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const } } +void ImageVisual::OnDoAction( const Dali::Property::Index actionName, const Dali::Property::Value& attributes ) +{ + // Check if action is valid for this visual type and perform action if possible + + switch ( actionName ) + { + case DevelImageVisual::Action::RELOAD: + { + auto attemptAtlasing = AttemptAtlasing(); + LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, + TextureManager::ReloadPolicy::FORCED ); + break; + } + } +} + void ImageVisual::OnSetTransform() { if( mImpl->mRenderer ) @@ -1031,7 +1056,8 @@ void ImageVisual::ApplyImageToSampler( const Image& image ) // From existing atlas manager void ImageVisual::UploadCompleted() { - // Texture has been uploaded. If weak handle is holding a placement actor, it is the time to add the renderer to actor. + // Texture has been uploaded. If weak handle is holding a placement actor, + // it is the time to add the renderer to actor. Actor actor = mPlacementActor.GetHandle(); if( actor ) { @@ -1046,7 +1072,8 @@ void ImageVisual::UploadCompleted() } // From Texture Manager -void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, TextureSet textureSet, bool usingAtlas, const Vector4& atlasRectangle ) +void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, TextureSet textureSet, bool usingAtlas, + const Vector4& atlasRectangle ) { Toolkit::Visual::ResourceStatus resourceStatus; Actor actor = mPlacementActor.GetHandle(); diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index 729185a..3108b55 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -177,6 +177,11 @@ public: // from Visual */ virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::OnDoAction + */ + virtual void OnDoAction( const Dali::Property::Index actionName, const Dali::Property::Value& attributes ) override; + protected: /** @@ -222,12 +227,12 @@ protected: /** * @copydoc Visual::Base::DoSetOffStage */ - virtual void DoSetOffStage( Actor& actor ); + virtual void DoSetOffStage( Actor& actor ) ; /** * @copydoc Visual::Base::OnSetTransform */ - virtual void OnSetTransform(); + virtual void OnSetTransform() ; /** * @copydoc Visual::Base::IsResourceReady @@ -280,8 +285,15 @@ private: * @param[out] atlasRect if atlasing is used this the texture area of the image in the atlas. * @param[out] textures resulting texture set from the image loading. * @param[in] orientationCorrection flag determines if orientation correction should be performed + * @param[in] forceReload flag determines if the texture should be reloaded from its source or use the cached texture. + */ + void LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection, TextureManager::ReloadPolicy forceReload ); + + /** + * @brief Checks if atlasing should be attempted + * @return bool returns true if atlasing can be attempted. */ - void LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection ); + bool AttemptAtlasing(); /** * @brief Initializes the Dali::Renderer from the image url diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index 308b1ee..b2e0d03 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -108,7 +108,8 @@ TextureSet TextureManager::LoadTexture( bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect, bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU, Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver, - AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection ) + AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ) { TextureSet textureSet; @@ -135,7 +136,8 @@ TextureSet TextureManager::LoadTexture( PixelData data; if( url.IsValid() ) { - Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection ); + Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode, + orientationCorrection ); if( pixelBuffer ) { data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer @@ -185,7 +187,8 @@ TextureSet TextureManager::LoadTexture( atlasingStatus = false; if( !maskInfo ) { - textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver, orientationCorrection ); + textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, + textureObserver, orientationCorrection, reloadPolicy ); } else { @@ -197,7 +200,8 @@ TextureSet TextureManager::LoadTexture( TextureManager::NO_ATLAS, maskInfo->mCropToMask, textureObserver, - orientationCorrection); + orientationCorrection, + reloadPolicy ); } TextureManager::LoadState loadState = GetTextureState( textureId ); @@ -222,67 +226,80 @@ TextureSet TextureManager::LoadTexture( } TextureManager::TextureId TextureManager::RequestLoad( - const VisualUrl& url, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - const UseAtlas useAtlas, - TextureUploadObserver* observer, - bool orientationCorrection ) + const VisualUrl& url, + const ImageDimensions desiredSize, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode, + const UseAtlas useAtlas, + TextureUploadObserver* observer, + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ) { - return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, UPLOAD_TO_TEXTURE, observer, orientationCorrection ); + return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, + false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy ); } TextureManager::TextureId TextureManager::RequestLoad( - const VisualUrl& url, - TextureId maskTextureId, - float contentScale, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - const UseAtlas useAtlas, - bool cropToMask, - TextureUploadObserver* observer, - bool orientationCorrection ) -{ - return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection ); + const VisualUrl& url, + TextureId maskTextureId, + float contentScale, + const ImageDimensions desiredSize, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode, + const UseAtlas useAtlas, + bool cropToMask, + TextureUploadObserver* observer, + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ) +{ + return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, + cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy ); } TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl ) { // Use the normal load procedure to get the alpha mask. - return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL, true ); + return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, + SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL, true, + TextureManager::ReloadPolicy::CACHED ); } TextureManager::TextureId TextureManager::RequestLoadInternal( - const VisualUrl& url, - TextureId maskTextureId, - float contentScale, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - UseAtlas useAtlas, - bool cropToMask, - StorageType storageType, - TextureUploadObserver* observer, - bool orientationCorrection ) + const VisualUrl& url, + TextureId maskTextureId, + float contentScale, + const ImageDimensions desiredSize, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode, + UseAtlas useAtlas, + bool cropToMask, + StorageType storageType, + TextureUploadObserver* observer, + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ) { // First check if the requested Texture is cached. - const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId ); + const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, + maskTextureId ); TextureManager::TextureId textureId = INVALID_TEXTURE_ID; // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision. - int cacheIndex = FindCachedTexture( textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId ); + int cacheIndex = FindCachedTexture( textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, + maskTextureId ); // Check if the requested Texture exists in the cache. if( cacheIndex != INVALID_CACHE_INDEX ) { - // Mark this texture being used by another client resource. - ++( mTextureInfoContainer[ cacheIndex ].referenceCount ); + if ( TextureManager::ReloadPolicy::CACHED == reloadPolicy ) + { + // Mark this texture being used by another client resource. Forced reload would replace the current texture + // without the need for incrementing the reference count. + ++( mTextureInfoContainer[ cacheIndex ].referenceCount ); + } textureId = mTextureInfoContainer[ cacheIndex ].textureId; - - DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture @%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId ); + DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d\n", + url.GetUrl().c_str(), observer, cacheIndex, textureId ); } if( textureId == INVALID_TEXTURE_ID ) // There was no caching, or caching not required @@ -294,7 +311,8 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( false, cropToMask, useAtlas, textureHash, orientationCorrection ) ); cacheIndex = mTextureInfoContainer.size() - 1u; - DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId ); + DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", + url.GetUrl().c_str(), observer, cacheIndex, textureId ); } // The below code path is common whether we are using the cache or not. @@ -311,9 +329,20 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( textureInfo.loadState == TextureManager::UPLOADED ? "UPLOADED" : textureInfo.loadState == TextureManager::CANCELLED ? "CANCELLED" : "Unknown" ); - // Check if we should add the observer. Only do this if we have not loaded yet and it will not have loaded by the end of this method. + // Force reloading of texture by setting loadState unless already loading or cancelled. + if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy && TextureManager::LOADING != textureInfo.loadState && + TextureManager::CANCELLED != textureInfo.loadState ) + { + DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n", + url.GetUrl().c_str(), observer, cacheIndex, textureId ); + textureInfo.loadState = TextureManager::NOT_STARTED; + } + + // Check if we should add the observer. + // Only do this if we have not loaded yet and it will not have loaded by the end of this method. switch( textureInfo.loadState ) { + case TextureManager::LOAD_FAILED: // Failed notifies observer which then stops observing. case TextureManager::NOT_STARTED: { LoadTexture( textureInfo ); @@ -346,7 +375,6 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( } case TextureManager::LOAD_FINISHED: case TextureManager::WAITING_FOR_MASK: - case TextureManager::LOAD_FAILED: // Loading has already completed. Do nothing. break; } @@ -511,7 +539,8 @@ void TextureManager::ObserveTexture( TextureInfo& textureInfo, } } -void TextureManager::AsyncLoadComplete( AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, Devel::PixelBuffer pixelBuffer ) +void TextureManager::AsyncLoadComplete( AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, + Devel::PixelBuffer pixelBuffer ) { DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( id:%d )\n", id ); @@ -644,10 +673,14 @@ void TextureManager::UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo { DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, " TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId ); - Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() ); + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), + pixelBuffer.GetWidth(), pixelBuffer.GetHeight() ); PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer ); texture.Upload( pixelData ); - textureInfo.textureSet = TextureSet::New(); + if ( ! textureInfo.textureSet ) + { + textureInfo.textureSet = TextureSet::New(); + } textureInfo.textureSet.SetTexture( 0u, texture ); } @@ -833,7 +866,8 @@ void TextureManager::ObserverDestroyed( TextureUploadObserver* observer ) for( unsigned int i = 0; i < count; ++i ) { TextureInfo& textureInfo( mTextureInfoContainer[i] ); - for( TextureInfo::ObserverListType::Iterator j = textureInfo.observerList.Begin(); j != textureInfo.observerList.End(); ) + for( TextureInfo::ObserverListType::Iterator j = textureInfo.observerList.Begin(); + j != textureInfo.observerList.End(); ) { if( *j == observer ) { diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.h b/dali-toolkit/internal/visuals/texture-manager-impl.h index b385344..d27b87f 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.h +++ b/dali-toolkit/internal/visuals/texture-manager-impl.h @@ -104,6 +104,15 @@ public: LOAD_FAILED ///< Async loading failed, e.g. connection problem }; + /** + * @breif Types of reloading policies + */ + enum class ReloadPolicy + { + CACHED = 0, ///< Loads cached texture if it exists. + FORCED ///< Forces reloading of texture. + }; + public: struct MaskingData @@ -139,7 +148,8 @@ public: Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver, AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, - bool orientationCorrection ); + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ); /** * @brief Requests an image load of the given URL. @@ -158,15 +168,17 @@ public: * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. * This is called when an image load completes (or fails). * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data + * @param[in] reloadPolicy Forces a reload of the texture even if already cached * @return A TextureId to use as a handle to reference this Texture */ - TextureId RequestLoad( const VisualUrl& url, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - const UseAtlas useAtlasing, - TextureUploadObserver* observer, - bool orientationCorrection ); + TextureId RequestLoad( const VisualUrl& url, + const ImageDimensions desiredSize, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode, + const UseAtlas useAtlasing, + TextureUploadObserver* observer, + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ); /** * @brief Requests an image load of the given URL, when the texture has @@ -179,29 +191,36 @@ public: * When the client has finished with the Texture, Remove() should be called. * * @param[in] url The URL of the image to load - * @param[in] maskTextureId The texture id of an image to mask this with (can be INVALID if no masking required) + * @param[in] maskTextureId The texture id of an image to mask this with + * (can be INVALID if no masking required) * @param[in] contentScale The scale factor to apply to the image before masking * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic * @param[in] fittingMode The FittingMode to use * @param[in] samplingMode The SamplingMode to use - * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, - * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. - * @param[in] cropToMask Only used with masking, this will crop the scaled image to the mask size. If false, then the mask will be scaled to fit the image before being applied. - * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. + * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still + * be loaded, and marked successful, + * but "useAtlasing" will be set to false in the "UploadCompleted" callback from + * the TextureManagerUploadObserver. + * @param[in] cropToMask Only used with masking, this will crop the scaled image to the mask size. + * If false, then the mask will be scaled to fit the image before being applied. + * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" + * virtual. * This is called when an image load completes (or fails). * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data + * @param[in] reloadPolicy Forces a reload of the texture even if already cached * @return A TextureId to use as a handle to reference this Texture */ - TextureId RequestLoad( const VisualUrl& url, - TextureId maskTextureId, - float contentScale, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - const UseAtlas useAtlasing, - bool cropToMask, - TextureUploadObserver* observer, - bool orientationCorrection ); + TextureId RequestLoad( const VisualUrl& url, + TextureId maskTextureId, + float contentScale, + const ImageDimensions desiredSize, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode, + const UseAtlas useAtlasing, + bool cropToMask, + TextureUploadObserver* observer, + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ); /** * Requests a masking image to be loaded. This mask is not uploaded to GL, @@ -266,32 +285,38 @@ private: * When the client has finished with the Texture, Remove() should be called. * * @param[in] url The URL of the image to load - * @param[in] maskTextureId The texture id of an image to use as a mask. If no mask is required, then set to INVALID_TEXTURE_ID + * @param[in] maskTextureId The texture id of an image to use as a mask. If no mask is required, then set + * to INVALID_TEXTURE_ID * @param[in] contentScale The scaling factor to apply to the content when masking * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic * @param[in] fittingMode The FittingMode to use * @param[in] samplingMode The SamplingMode to use - * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful, - * but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver. - * @param[in] cropToMask Whether to crop the target after masking, or scale the mask to the image before masking. + * @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be + * loaded, and marked successful, but "useAtlasing" will be set to false in the + * "UploadCompleted" callback from the TextureManagerUploadObserver. + * @param[in] cropToMask Whether to crop the target after masking, or scale the mask to the image before + * masking. * @param[in] storageType, Whether the pixel data is stored in the cache or uploaded to the GPU - * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual. + * @param[in] observer The client object should inherit from this and provide the "UploadCompleted" + * virtual. * This is called when an image load completes (or fails). * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data + * @param[in] reloadPolicy Forces a reload of the texture even if already cached * @return A TextureId to use as a handle to reference this Texture */ TextureId RequestLoadInternal( - const VisualUrl& url, - TextureId maskTextureId, - float contentScale, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - UseAtlas useAtlas, - bool cropToMask, - StorageType storageType, - TextureUploadObserver* observer, - bool orientationCorrection ); + const VisualUrl& url, + TextureId maskTextureId, + float contentScale, + const ImageDimensions desiredSize, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode, + UseAtlas useAtlas, + bool cropToMask, + StorageType storageType, + TextureUploadObserver* observer, + bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ); typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching. @@ -356,7 +381,8 @@ private: Dali::SamplingMode::Type samplingMode:3; ///< The requested SamplingMode StorageType storageType:1; ///< CPU storage / GPU upload; bool loadSynchronously:1; ///< True if synchronous loading was requested - UseAtlas useAtlas:1; ///< USE_ATLAS if an atlas was requested. This is updated to false if atlas is not used + UseAtlas useAtlas:1; ///< USE_ATLAS if an atlas was requested. + ///< This is updated to false if atlas is not used bool cropToMask:1; ///< true if the image should be cropped to the mask size. bool orientationCorrection:1; ///< true if the image should be rotated to match exif orientation data }; @@ -537,10 +563,12 @@ private: * @brief Load a new texture. * @param[in] textureId TextureId to reference the texture that will be loaded * @param[in] url The URL of the image to load - * @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic + * @param[in] desiredSize The size the image is likely to appear at. + * This can be set to 0,0 for automatic * @param[in] fittingMode The FittingMode to use * @param[in] samplingMode The SamplingMode to use - * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image, e.g., from portrait to landscape + * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image, + * e.g., from portrait to landscape */ void Load(TextureId textureId, const VisualUrl& url, diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 3473509..e4f12c8 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -342,7 +342,7 @@ bool Visual::Base::IsOnStage() const return mImpl->mFlags & Impl::IS_ON_STAGE; } -void Visual::Base::OnDoAction( const Property::Index actionId, const Property::Value attributes ) +void Visual::Base::OnDoAction( const Property::Index actionId, const Property::Value& attributes ) { // May be overriden by derived class } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index 996fa3c..6fc777d 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -315,7 +315,7 @@ protected: * @param[in] actionId The action to perform * @param[in] attributes The list of attributes for the action. ( optional for this data structure to have content ) */ - virtual void OnDoAction( const Property::Index actionId, const Property::Value attributes ); + virtual void OnDoAction( const Property::Index actionId, const Property::Value& attributes ); protected: -- 2.7.4