From ad5dac31f7b579b499825acb44ad84e8629add6f Mon Sep 17 00:00:00 2001 From: Agnelo Vaz Date: Wed, 18 Oct 2017 09:12:00 +0100 Subject: [PATCH] [4.0] ImageVisual Load policy ImageVisual can be created with a PropertyMap that inserts a load policy. Depending on the load policy the image(texture) will load immediately when the visual is created or when the visual is attached to the stage. Can be used to preload special images so can be displayed immediately on request. Registered Visuals with LoadPolicy::IMMEDIATE will signal ResourceReadySignal when attached to stage. Limitations: Atlasing not supported with IMMEDIATE mode currently. Change-Id: I3e1b3fd19f3027edb62858549890972f6a166cd0 Signed-off-by: Adeel Kazmi --- .../src/dali-toolkit/utc-Dali-ImageVisual.cpp | 258 +++++++++++++----- .../visuals/image-visual-properties-devel.h | 24 ++ .../internal/visuals/image/image-visual.cpp | 126 +++++---- .../internal/visuals/image/image-visual.h | 15 + .../internal/visuals/texture-manager-impl.cpp | 1 - .../visuals/visual-string-constants.cpp | 1 + .../visuals/visual-string-constants.h | 1 + 7 files changed, 303 insertions(+), 123 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp index d0e1561bd8..1bd6203a5f 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp @@ -49,6 +49,13 @@ const char* TEST_REMOTE_IMAGE_FILE_NAME = "https://www.tizen.org/sites/all/theme const char* TEST_INVALID_FILE_NAME = TEST_RESOURCE_DIR "/invalid.jpg"; const char* TEST_REMOTE_INVALID_FILE_NAME = "https://www.tizen.org/invalid.png"; const char* TEST_MASK_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/mask.png"; + + +bool gResourceReadySignalFired = false; + +void ResourceReadySignal( Control control ) +{ + gResourceReadySignalFired = true; } @@ -65,6 +72,23 @@ Actor CreateActorWithImageVisual(const Property::Map& map) return actor; } + +Visual::Base CreateVisualWithPolicy( const char* url, Property::Index key, const Property::Value& value ) +{ + VisualFactory factory = VisualFactory::Get(); + + Property::Map propertyMap; + propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); + propertyMap.Insert( ImageVisual::Property::URL, url ); + propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); + propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); + propertyMap.Insert( key , value ); + + return factory.CreateVisual( propertyMap ); +} + +} // namespace + void TestVisualRender( ToolkitTestApplication& application, DummyControl& actor, Visual::Base& visual, @@ -223,6 +247,7 @@ int UtcDaliImageVisualTextureReuse1(void) Property::Map propertyMap; propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::IMAGE ); propertyMap.Insert( ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME ); + propertyMap.Insert( DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DETACHED ); TestGlAbstraction& gl = application.GetGlAbstraction(); TraceCallStack& textureTrace = gl.GetTextureTrace(); @@ -274,7 +299,7 @@ int UtcDaliImageVisualTextureReuse1(void) tet_infoline("Test that removing last actor does delete the texture\n"); - Stage::GetCurrent().Remove( actor2 ); + Stage::GetCurrent().Remove( actor2 ); // Detaches remaining ImageVisual application.SendNotification(); application.Render(); @@ -1188,16 +1213,7 @@ int UtcDaliImageVisualReleasePolicy01(void) ToolkitTestApplication application; tet_infoline( "UtcDaliImageVisualReleasePolicy01 Detached Policy, disabling visual with this policy deletes texture" ); - VisualFactory factory = VisualFactory::Get(); - - Property::Map propertyMap; - propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMap.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMap.Insert( DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DETACHED ); - - Visual::Base imageVisual = factory.CreateVisual(propertyMap); + Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DETACHED ); DALI_TEST_CHECK( imageVisual ); // Set up debug trace @@ -1247,18 +1263,7 @@ int UtcDaliImageVisualReleasePolicy02(void) ToolkitTestApplication application; tet_infoline( "UtcDaliImageVisualReleasePolicy02 Destroyed Policy, Texture should be deleted when visual destroyed" ); - VisualFactory factory = VisualFactory::Get(); - const std::string MASK_IMAGE = TEST_REMOTE_IMAGE_FILE_NAME; - - Property::Map propertyMap; - propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMap.Insert( Visual::Property::MIX_COLOR, Color::MAGENTA ); - propertyMap.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMap.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::DESTROYED ); - - Visual::Base imageVisual = factory.CreateVisual(propertyMap); + Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DESTROYED ); DALI_TEST_CHECK( imageVisual ); // Setup debug trace @@ -1310,16 +1315,7 @@ int UtcDaliImageVisualReleasePolicy03(void) ToolkitTestApplication application; tet_infoline( "UtcDaliImageVisualReleasePolicy03 Never Policy, texture should not be deleted after visual destroyed" ); - VisualFactory factory = VisualFactory::Get(); - - Property::Map propertyMap; - propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMap.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMap.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::NEVER ); - - Visual::Base imageVisual = factory.CreateVisual(propertyMap); + Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::NEVER ); DALI_TEST_CHECK( imageVisual ); TestGlAbstraction& gl = application.GetGlAbstraction(); @@ -1368,25 +1364,11 @@ int UtcDaliImageVisualReleasePolicy04(void) ToolkitTestApplication application; tet_infoline( "UtcDaliImageVisualReleasePolicy04 Two visuals with different policies sharing a texture" ); - VisualFactory factory = VisualFactory::Get(); - tet_infoline( "Create first visual with Never release policy" ); - Property::Map propertyMapNeverReleasePolicy; - propertyMapNeverReleasePolicy.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMapNeverReleasePolicy.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMapNeverReleasePolicy.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMapNeverReleasePolicy.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMapNeverReleasePolicy.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::NEVER ); - Visual::Base imageVisualNever = factory.CreateVisual( propertyMapNeverReleasePolicy ); + Visual::Base imageVisualNever = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::NEVER ); tet_infoline( "Create second visual with Destroyed release policy"); - Property::Map propertyMapDestroyedReleasePolicy; - propertyMapDestroyedReleasePolicy.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMapDestroyedReleasePolicy.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMapDestroyedReleasePolicy.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMapDestroyedReleasePolicy.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMapDestroyedReleasePolicy.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::DESTROYED ); - Visual::Base imageVisualDestroyed = factory.CreateVisual( propertyMapDestroyedReleasePolicy ); + Visual::Base imageVisualDestroyed = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DESTROYED ); // Set up trace debug TestGlAbstraction& gl = application.GetGlAbstraction(); @@ -1472,16 +1454,7 @@ int UtcDaliImageVisualReleasePolicy06(void) ToolkitTestApplication application; tet_infoline( "UtcDaliImageVisualReleasePolicy06 Never Policy, texture should not be affected by Disabling and Enabling visual" ); - VisualFactory factory = VisualFactory::Get(); - - Property::Map propertyMap; - propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMap.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMap.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::NEVER ); - - Visual::Base imageVisual = factory.CreateVisual(propertyMap); + Visual::Base imageVisual= CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::NEVER ); DALI_TEST_CHECK( imageVisual ); TestGlAbstraction& gl = application.GetGlAbstraction(); @@ -1540,25 +1513,12 @@ int UtcDaliImageVisualReleasePolicy07(void) ToolkitTestApplication application; tet_infoline( "UtcDaliImageVisualReleasePolicy07 Two visuals with different policies sharing a texture DETACHED and DESTROYED" ); - VisualFactory factory = VisualFactory::Get(); - tet_infoline( "Create first visual with DESTROYED release policy" ); - Property::Map propertyMapNeverReleasePolicy; - propertyMapNeverReleasePolicy.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMapNeverReleasePolicy.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMapNeverReleasePolicy.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMapNeverReleasePolicy.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMapNeverReleasePolicy.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::DESTROYED ); - Visual::Base imageVisualDestroyed = factory.CreateVisual( propertyMapNeverReleasePolicy ); + Visual::Base imageVisualDestroyed = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DESTROYED ); + tet_infoline( "Create second visual with DETACHED release policy"); - Property::Map propertyMapDestroyedReleasePolicy; - propertyMapDestroyedReleasePolicy.Insert( Visual::Property::TYPE, Visual::IMAGE ); - propertyMapDestroyedReleasePolicy.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME ); - propertyMapDestroyedReleasePolicy.Insert( ImageVisual::Property::DESIRED_WIDTH, 20 ); - propertyMapDestroyedReleasePolicy.Insert( ImageVisual::Property::DESIRED_HEIGHT, 30 ); - propertyMapDestroyedReleasePolicy.Insert( DevelImageVisual::Property::RELEASE_POLICY , DevelImageVisual::ReleasePolicy::DETACHED ); - Visual::Base imageVisualDetached = factory.CreateVisual( propertyMapDestroyedReleasePolicy ); + Visual::Base imageVisualDetached = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::RELEASE_POLICY, DevelImageVisual::ReleasePolicy::DETACHED ); // Set up trace debug TestGlAbstraction& gl = application.GetGlAbstraction(); @@ -1612,3 +1572,151 @@ int UtcDaliImageVisualReleasePolicy07(void) END_TEST; } + +int UtcDaliImageVisualLoadPolicy01(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliImageVisualLoadPolicy01 Load a visual image before attaching to stage" ); + + // Set up trace debug + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + tet_infoline( "Create visual with IMMEDIATE load policy" ); + Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::IMMEDIATE ); + + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + // Ensure texture has been uploaded + application.SendNotification(); + application.Render(); + + tet_infoline( "Ensure texture loading starts after visual created" ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); + + tet_infoline( "Register visuals with control and ensure it has the only handles" ); + DummyControl actor = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + imageVisual.Reset(); // reduce ref count so only the control keeps the visual alive. + + actor.SetSize(200.f, 200.f); + Stage::GetCurrent().Add( actor ); + tet_infoline( "Ensure nothing triggers another load as texure already loaded" ); + const unsigned int TIME_OUT_3_SECONDS = 3; + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1, TIME_OUT_3_SECONDS ), false, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), false, TEST_LOCATION ); + + // Ensure texture is deleted when no longer needed (ref count was correct ) + dummyImpl.UnregisterVisual( DummyControl::Property::TEST_VISUAL ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliImageVisualLoadPolicy02(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliImageVisualLoadPolicy01 Load a visual image only after attached to stage" ); + + // Set up trace debug + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + tet_infoline( "Create visual with IMMEDIATE load policy" ); + Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::ATTACHED ); + + const unsigned int TIME_OUT_3_SECONDS = 3; + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1, TIME_OUT_3_SECONDS ), false, TEST_LOCATION ); + + // Act on meeage queue even although nothing expected to load + application.SendNotification(); + application.Render(); + + tet_infoline( "Ensure texture is not generated yet" ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), false, TEST_LOCATION ); + textureTrace.Reset(); + + tet_infoline( "Register visuals with control and ensure it has the only handles" ); + DummyControl actor = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + imageVisual.Reset(); // reduce ref count so only the control keeps the visual alive. + + actor.SetSize(200.f, 200.f); + Stage::GetCurrent().Add( actor ); + tet_infoline( "Allow image time to load" ); + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + tet_infoline( "Ensure texture generated and renderer created" ); + DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + + // Ensure texture is delete when no longer needed + dummyImpl.UnregisterVisual( DummyControl::Property::TEST_VISUAL ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliImageVisualLoadPolicy03(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliImageVisualLoadPolicy03 Load a visual image before attaching to stage and receive ResourceReady signal" ); + + // Set up trace debug + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + tet_infoline( "Create visual with IMMEDIATE load policy" ); + Visual::Base imageVisual = CreateVisualWithPolicy( TEST_IMAGE_FILE_NAME, DevelImageVisual::Property::LOAD_POLICY, DevelImageVisual::LoadPolicy::IMMEDIATE ); + + // Wait for image to load, ResourceReady signal will not be emitted until Visual is registered with a control and on stage. + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + + // Ensure texture has been uploaded + application.SendNotification(); + application.Render(); + + tet_infoline( "Ensure texture loading starts after visual created" ); + DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); + textureTrace.Reset(); + + tet_infoline( "Register visuals with control and ensure it has the only handles" ); + DummyControl actor = DummyControl::New(true); + actor.ResourceReadySignal().Connect( &ResourceReadySignal); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + + tet_infoline( "Registering visual attaches it to stage and trigger the loading signal if Image loaded" ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, imageVisual ); + imageVisual.Reset(); // reduce ref count so only the control keeps the visual alive. + actor.SetSize(200.f, 200.f); + // Adding the Control hence Visual to stage will cause the Visual to trigger ResourceReadySignal if the image is already loaded. + Stage::GetCurrent().Add( actor ); // If LoadPolicy was not IMMEDIATE then as this point (after attached to stage) the test would need to wait for Loading + + DALI_TEST_EQUALS( gResourceReadySignalFired, true, TEST_LOCATION ); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h index d0c93797cf..e37d712b8e 100644 --- a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h @@ -30,6 +30,22 @@ namespace Toolkit namespace DevelImageVisual { +/** + * @brief The policy determining if the image is loaded when the visual is staged or created. + */ +namespace LoadPolicy +{ + +/** + * @brief The available named elements that define the LoadPolicy. + */ +enum Type +{ + IMMEDIATE = 0, ///< The image is loaded when the ImageVisual is created. + ATTACHED ///< The image is loaded when the ImageVisual is attached to the stage. +}; + +} // namespace LoadPolicy /** * @brief The policy determining when a image is deleted from the cache in relation to the ImageVisual lifetime. @@ -74,6 +90,14 @@ enum Type MASK_CONTENT_SCALE = Dali::Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, CROP_TO_MASK = Dali::Toolkit::ImageVisual::Property::CROP_TO_MASK, + /** + * @brief The policy to determine when an image should be loaded. + * @details Name "loadPolicy", Type LoadPolicy::Type (Property::INTEGER)or Property::STRING. + * @note Default LoadPolicy::ATTACHED + * @see LoadPolicy::Type + */ + LOAD_POLICY = CROP_TO_MASK + 1, + /** * @brief The policy to determine when an image should no longer be cached. * @details Name "releasePolicy", Type ReleasePolicy::Type (Property::INTEGER) or Property::STRING diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 82f7fd14cb..9522618406 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -91,6 +91,12 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, REPEAT ) DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT ) DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE ) +// load policies +DALI_ENUM_TO_STRING_TABLE_BEGIN( LOAD_POLICY ) +DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::LoadPolicy, IMMEDIATE ) +DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::LoadPolicy, ATTACHED ) +DALI_ENUM_TO_STRING_TABLE_END( LOAD_POLICY ) + // release policies DALI_ENUM_TO_STRING_TABLE_BEGIN( RELEASE_POLICY ) DALI_ENUM_TO_STRING_WITH_SCOPE( DevelImageVisual::ReleasePolicy, DETACHED ) @@ -274,6 +280,7 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, mSamplingMode( samplingMode ), mWrapModeU( WrapMode::DEFAULT ), mWrapModeV( WrapMode::DEFAULT ), + mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ), mReleasePolicy( DevelImageVisual::ReleasePolicy::DETACHED ), mAttemptAtlasing( false ), mLoading( false ) @@ -293,6 +300,7 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image ) mSamplingMode( SamplingMode::DEFAULT ), mWrapModeU( WrapMode::DEFAULT ), mWrapModeV( WrapMode::DEFAULT ), + mLoadPolicy( DevelImageVisual::LoadPolicy::ATTACHED ), mReleasePolicy( DevelImageVisual::ReleasePolicy::DESTROYED ), mAttemptAtlasing( false ), mLoading( false ) @@ -383,12 +391,23 @@ void ImageVisual::DoSetProperties( const Property::Map& propertyMap ) { DoSetProperty( Toolkit::ImageVisual::Property::CROP_TO_MASK, keyValue.second ); } + else if ( keyValue.first == LOAD_POLICY_NAME ) + { + DoSetProperty( Toolkit::DevelImageVisual::Property::LOAD_POLICY, keyValue.second ); + } else if( keyValue.first == RELEASE_POLICY_NAME ) { DoSetProperty( Toolkit::DevelImageVisual::Property::RELEASE_POLICY, keyValue.second ); } } } + + // Load image immediately if LOAD_POLICY requires it + if ( mLoadPolicy == DevelImageVisual::LoadPolicy::IMMEDIATE ) + { + auto attemptAtlasing = mAttemptAtlasing; + LoadTexture( attemptAtlasing, mAtlasRect, mTextures ); + } } void ImageVisual::DoSetProperty( Property::Index index, const Property::Value& value ) @@ -532,6 +551,13 @@ void ImageVisual::DoSetProperty( Property::Index index, const Property::Value& v mReleasePolicy = DevelImageVisual::ReleasePolicy::Type( releasePolicy ); break; } + + case Toolkit::DevelImageVisual::Property::LOAD_POLICY: + { + int loadPolicy; + Scripting::GetEnumerationProperty( value, LOAD_POLICY_TABLE, LOAD_POLICY_TABLE_COUNT, loadPolicy ); + mLoadPolicy = DevelImageVisual::LoadPolicy::Type( loadPolicy ); + } } } @@ -714,61 +740,62 @@ bool ImageVisual::IsSynchronousResourceLoading() const return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } -/* -( VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, - ImageVisual::MaskingData* maskInfo, bool synchronousLoading, - TextureManager::TextureId textureId, Vector4& textureRect, bool& atlasingStatus, bool& loadingStatus - */ -void ImageVisual::InitializeRenderer() +void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures ) { - mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; - TextureManager& textureManager = mFactoryCache.GetTextureManager(); - if( ! mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL ) + ImageAtlasManagerPtr atlasManager = nullptr; + AtlasUploadObserver* atlasUploadObserver = nullptr; + auto textureObserver = this; + + if( atlasing ) { - bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; + atlasManager = mFactoryCache.GetAtlasManager(); + atlasUploadObserver = this; + } - Vector4 atlasRect; + textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, + mMaskingData, IsSynchronousResourceLoading(), mTextureId, + atlasRect, atlasing, mLoading, mWrapModeU, + mWrapModeV, textureObserver, atlasUploadObserver, atlasManager ); +} - auto attemptAtlasing = mAttemptAtlasing; +void ImageVisual::InitializeRenderer() +{ + auto attemptAtlasing = ( ! mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL && mAttemptAtlasing ); - // texture set has to be created first as we need to know if atlasing succeeded or not - // when selecting the shader - TextureSet textures = - textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, - mMaskingData, IsSynchronousResourceLoading(), mTextureId, - atlasRect, attemptAtlasing, mLoading, mWrapModeU, - mWrapModeV, this, this, mFactoryCache.GetAtlasManager()); - if(attemptAtlasing) - { - mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; - } - CreateRenderer( textures ); + // texture set has to be created first as we need to know if atlasing succeeded or not + // when selecting the shader - if( mImpl->mFlags & Impl::IS_ATLASING_APPLIED ) // the texture is packed inside atlas - { - mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect ); - if( !defaultWrapMode ) // custom wrap mode - { - Vector2 wrapMode(mWrapModeU-WrapMode::CLAMP_TO_EDGE, mWrapModeV-WrapMode::CLAMP_TO_EDGE); - wrapMode.Clamp( Vector2::ZERO, Vector2( 2.f, 2.f ) ); - mImpl->mRenderer.RegisterProperty( WRAP_MODE_UNIFORM_NAME, wrapMode ); - } - } + if( mTextureId == TextureManager::INVALID_TEXTURE_ID && ! mTextures ) // Only load the texture once + { + LoadTexture( attemptAtlasing, mAtlasRect, mTextures ); + } + + if( attemptAtlasing ) // Flag needs to be set before creating renderer + { + mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; } else { - auto attemptAtlasing = false; - // for custom shader or remote image, atlas is not applied - Vector4 atlasRect; // ignored in this case - TextureSet textures = - textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, - mMaskingData, IsSynchronousResourceLoading(), mTextureId, - atlasRect, attemptAtlasing, mLoading, mWrapModeU, mWrapModeV, this, - nullptr, nullptr); // no atlasing - DALI_ASSERT_DEBUG(attemptAtlasing == false); - CreateRenderer( textures ); + mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; + } + + CreateRenderer( mTextures ); + mTextures.Reset(); // Visual should not keep a handle to the texture after this point. + + if( attemptAtlasing ) // the texture is packed inside atlas + { + mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect ); + + bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; + + if( !defaultWrapMode ) // custom wrap mode + { + Vector2 wrapMode(mWrapModeU-WrapMode::CLAMP_TO_EDGE, mWrapModeV-WrapMode::CLAMP_TO_EDGE); + wrapMode.Clamp( Vector2::ZERO, Vector2( 2.f, 2.f ) ); + mImpl->mRenderer.RegisterProperty( WRAP_MODE_UNIFORM_NAME, wrapMode ); + } } } @@ -786,7 +813,7 @@ void ImageVisual::InitializeRenderer( const Image& image ) else { // reuse existing code for regular images - CreateRenderer( textures ); + CreateRenderer( textures ); // Textures will be retreived from Image } ApplyImageToSampler( image ); } @@ -892,6 +919,7 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::CROP_TO_MASK, mMaskingData->mCropToMask ); } + map.Insert( Toolkit::DevelImageVisual::Property::LOAD_POLICY, mLoadPolicy ); map.Insert( Toolkit::DevelImageVisual::Property::RELEASE_POLICY, mReleasePolicy ); } @@ -981,8 +1009,8 @@ void ImageVisual::UploadCompleted() Actor actor = mPlacementActor.GetHandle(); if( actor ) { + mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect ); actor.AddRenderer( mImpl->mRenderer ); - // reset the weak handle so that the renderer only get added to actor once mPlacementActor.Reset(); } @@ -997,10 +1025,14 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur { if( mImpl->mRenderer ) { + if( usingAtlas ) + { + mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect ); + } + actor.AddRenderer( mImpl->mRenderer ); // reset the weak handle so that the renderer only get added to actor once mPlacementActor.Reset(); - if( loadingSuccess ) { Sampler sampler = Sampler::New(); diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index 0e4009bd09..87111b7415 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -65,6 +65,7 @@ typedef IntrusivePtr< ImageVisual > ImageVisualPtr; * | pixelArea | VECTOR4 | * | wrapModeU | INTEGER OR STRING | * | wrapModeV | INTEGER OR STRING | + * | loadPolicy | INTEGER OR STRING | * | releasePolicy | INTEGER OR STRING | * * where pixelArea is a rectangular area. @@ -96,6 +97,9 @@ typedef IntrusivePtr< ImageVisual > ImageVisualPtr; * "DONT_CARE" * "DEFAULT" * + * where loadPolicy should be one of the following image loading modes + * "IMMEDIATE" // Loads image even if visual not attached to stage yet + * "ATTACHED" // Only loads image once visual is attached to stage * * where releasePolicy should be one of the following policies for when to cache the image * "DETACHED" // Release image from cache when visual detached from stage @@ -264,6 +268,14 @@ private: */ void ApplyImageToSampler( const Image& image ); + /** + * @brief Load the texture, will try to atlas unless unable or param set to false. + * @param[in, out] atlasing flag if the image has been put in a atlas (true), passing false will not atlas even if possible. + * @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. + */ + void LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures ); + /** * @brief Initializes the Dali::Renderer from the image url */ @@ -332,12 +344,15 @@ private: Dali::ImageDimensions mDesiredSize; TextureManager::TextureId mTextureId; + TextureSet mTextures; Dali::FittingMode::Type mFittingMode:3; Dali::SamplingMode::Type mSamplingMode:4; Dali::WrapMode::Type mWrapModeU:3; Dali::WrapMode::Type mWrapModeV:3; + DevelImageVisual::LoadPolicy::Type mLoadPolicy; DevelImageVisual::ReleasePolicy::Type mReleasePolicy; + Vector4 mAtlasRect; bool mAttemptAtlasing; ///< If true will attempt atlasing, otherwise create unique texture bool mLoading; ///< True if the texture is still loading. }; diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index 66f6a813ae..e79586351b 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -135,7 +135,6 @@ TextureSet TextureManager::LoadTexture( PixelData data; if( url.IsValid() ) { - // if sync loading is required, the loading should immediately when actor is on stage Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode ); if( pixelBuffer ) { diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 0670dd8609..6282559cb5 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -85,6 +85,7 @@ const char * const CACHE_SIZE_NAME("cacheSize"); const char * const FRAME_DELAY_NAME("frameDelay"); const char * const MASK_CONTENT_SCALE_NAME("maskContentScale"); const char * const CROP_TO_MASK_NAME("cropToMask"); +const char * const LOAD_POLICY_NAME("loadPolicy"); const char * const RELEASE_POLICY_NAME("releasePolicy"); // Text visual diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 9aa14a12c9..27030df3d2 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -73,6 +73,7 @@ extern const char * const CACHE_SIZE_NAME; extern const char * const FRAME_DELAY_NAME; extern const char * const MASK_CONTENT_SCALE_NAME; extern const char * const CROP_TO_MASK_NAME; +extern const char * const LOAD_POLICY_NAME; extern const char * const RELEASE_POLICY_NAME; // Text visual -- 2.34.1