X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Ftexture-manager-impl.cpp;h=6b31322d4221e1d0f02a66c2e152707175659d9c;hp=f0740874b39f7e7a3547b32f91449c6516fe525e;hb=c20463e1d4a77117810c67adfec49bcdfab5efde;hpb=4d305b893731daafafc293b92dc4fa25a896e929 diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp index f074087..6b31322 100644 --- a/dali-toolkit/internal/visuals/texture-manager-impl.cpp +++ b/dali-toolkit/internal/visuals/texture-manager-impl.cpp @@ -21,7 +21,9 @@ // EXTERNAL HEADERS #include #include +#include #include +#include #include #include #include @@ -30,6 +32,7 @@ // INTERNAL HEADERS #include #include +#include namespace { @@ -44,8 +47,10 @@ size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue) { using Dali::EnvironmentVariable::GetEnvironmentVariable; auto numberString = GetEnvironmentVariable(environmentVariable); - auto numberOfThreads = numberString ? std::strtol(numberString, nullptr, 10) : 0; - return (numberOfThreads > 0) ? numberOfThreads : defaultValue; + auto numberOfThreads = numberString ? std::strtoul(numberString, nullptr, 10) : 0; + constexpr auto MAX_NUMBER_OF_THREADS = 100u; + DALI_ASSERT_DEBUG( numberOfThreads < MAX_NUMBER_OF_THREADS ); + return ( numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS ) ? numberOfThreads : defaultValue; } size_t GetNumberOfLocalLoaderThreads() @@ -84,6 +89,13 @@ const int INVALID_CACHE_INDEX( -1 ); ///< Invalid Cache index } // Anonymous namespace +TextureManager::MaskingData::MaskingData() +: mAlphaMaskUrl(), + mAlphaMaskId( INVALID_TEXTURE_ID ), + mContentScaleFactor( 1.0f ), + mCropToMask( true ) +{ +} TextureManager::TextureManager() : mAsyncLocalLoaders( GetNumberOfLocalLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); } ), @@ -92,66 +104,205 @@ TextureManager::TextureManager() { } -TextureManager::TextureId TextureManager::RequestLoad( - const VisualUrl& url, - const ImageDimensions desiredSize, - FittingMode::Type fittingMode, - Dali::SamplingMode::Type samplingMode, - const UseAtlas useAtlas, - TextureUploadObserver* observer ) +TextureSet TextureManager::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, + bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU, + Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver, + AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection, + TextureManager::ReloadPolicy reloadPolicy ) { - return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, UPLOAD_TO_TEXTURE, observer ); + TextureSet textureSet; + + loadingStatus = false; + textureRect = FULL_ATLAS_RECT; + + if( VisualUrl::TEXTURE == url.GetProtocolType()) + { + std::string location = url.GetLocation(); + if( location.size() > 0u ) + { + TextureId id = std::stoi( location ); + for( auto&& elem : mExternalTextures ) + { + if( elem.textureId == id ) + { + textureId = elem.textureId; + return elem.textureSet; + } + } + } + } + else if( synchronousLoading ) + { + PixelData data; + if( url.IsValid() ) + { + Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode, + orientationCorrection ); + if( pixelBuffer ) + { + data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer + } + } + if( !data ) + { + // use broken image + textureSet = TextureSet::New(); + Devel::PixelBuffer pixelBuffer = LoadImageFromFile( BROKEN_IMAGE_URL ); + if( pixelBuffer ) + { + data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer + } + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), + data.GetWidth(), data.GetHeight() ); + texture.Upload( data ); + textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); + } + else + { + if( atlasingStatus ) // attempt atlasing + { + textureSet = imageAtlasManager->Add( textureRect, data ); + } + if( !textureSet ) // big image, no atlasing or atlasing failed + { + atlasingStatus = false; + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), + data.GetWidth(), data.GetHeight() ); + texture.Upload( data ); + textureSet = TextureSet::New(); + textureSet.SetTexture( 0u, texture ); + } + } + } + else + { + loadingStatus = true; + if( atlasingStatus ) + { + textureSet = imageAtlasManager->Add( textureRect, url.GetUrl(), desiredSize, fittingMode, true, atlasObserver ); + } + if( !textureSet ) // big image, no atlasing or atlasing failed + { + atlasingStatus = false; + if( !maskInfo ) + { + textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, + textureObserver, orientationCorrection, reloadPolicy ); + } + else + { + textureId = RequestLoad( url, + maskInfo->mAlphaMaskId, + maskInfo->mContentScaleFactor, + desiredSize, + fittingMode, samplingMode, + TextureManager::NO_ATLAS, + maskInfo->mCropToMask, + textureObserver, + orientationCorrection, + reloadPolicy ); + } + + TextureManager::LoadState loadState = GetTextureStateInternal( textureId ); + loadingStatus = ( loadState == TextureManager::LOADING ); + + if( loadState == TextureManager::UPLOADED ) + { + // UploadComplete has already been called - keep the same texture set + textureSet = GetTextureSet( textureId ); + } + } + } + + if( ! atlasingStatus && textureSet ) + { + Sampler sampler = Sampler::New(); + sampler.SetWrapMode( wrapModeU, wrapModeV ); + textureSet.SetSampler( 0u, sampler ); + } + + return textureSet; } 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 ) + 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, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, UPLOAD_TO_TEXTURE, observer ); + 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, + 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 ); + 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 ) + 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 @@ -160,10 +311,11 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( textureId = GenerateUniqueTextureId(); mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(), desiredSize, contentScale, fittingMode, samplingMode, - false, cropToMask, useAtlas, textureHash ) ); + 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. @@ -172,6 +324,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( TextureInfo& textureInfo( mTextureInfoContainer[ cacheIndex ] ); textureInfo.maskTextureId = maskTextureId; textureInfo.storageType = storageType; + textureInfo.orientationCorrection = orientationCorrection; DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureInfo loadState:%s\n", textureInfo.loadState == TextureManager::NOT_STARTED ? "NOT_STARTED" : @@ -179,9 +332,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 ); @@ -214,7 +378,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; } @@ -294,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; } @@ -307,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; } @@ -362,7 +561,7 @@ bool TextureManager::LoadTexture( TextureInfo& textureInfo ) DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End()); loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, - textureInfo.samplingMode, true); + textureInfo.samplingMode, textureInfo.orientationCorrection ); } } @@ -379,7 +578,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 ); @@ -427,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 @@ -512,10 +712,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 ); } @@ -597,7 +801,6 @@ int TextureManager::GetCacheIndexFromId( const TextureId textureId ) } } - DALI_LOG_WARNING( "Cannot locate TextureId: %d\n", textureId ); return INVALID_CACHE_INDEX; } @@ -701,7 +904,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 ) { @@ -715,10 +919,6 @@ void TextureManager::ObserverDestroyed( TextureUploadObserver* observer ) } } -TextureManager::~TextureManager() -{ -} - TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(TextureManager& textureManager) : AsyncLoadingHelper(Toolkit::AsyncImageLoader::New(), textureManager, AsyncLoadingInfoContainerType())