loadState == TextureManager::LOADING ? "LOADING" : \
loadState == TextureManager::LOAD_FINISHED ? "LOAD_FINISHED" : \
loadState == TextureManager::WAITING_FOR_MASK ? "WAITING_FOR_MASK" : \
+ loadState == TextureManager::MASK_APPLYING ? "MASK_APPLYING" : \
+ loadState == TextureManager::MASK_APPLIED ? "MASK_APPLIED" : \
loadState == TextureManager::UPLOADED ? "UPLOADED" : \
loadState == TextureManager::CANCELLED ? "CANCELLED" : \
loadState == TextureManager::LOAD_FAILED ? "LOAD_FAILED" : "Unknown"
{
Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode,
orientationCorrection );
+ if( maskInfo )
+ {
+ Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile( maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(),
+ FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true );
+ if( maskPixelBuffer )
+ {
+ pixelBuffer.ApplyMask( maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask );
+ }
+ }
if( pixelBuffer )
{
PreMultiply( pixelBuffer, preMultiplyOnLoad );
}
else
{
+ TextureId alphaMaskId = RequestMaskLoad( maskInfo->mAlphaMaskUrl );
textureId = RequestLoad( url,
- maskInfo->mAlphaMaskId,
+ alphaMaskId,
maskInfo->mContentScaleFactor,
desiredSize,
fittingMode, samplingMode,
// If we are loading the texture, or waiting for the ready signal handler to complete, inform
// caller that they need to wait.
loadingStatus = ( loadState == TextureManager::LOADING ||
+ loadState == TextureManager::WAITING_FOR_MASK ||
+ loadState == TextureManager::MASK_APPLYING ||
+ loadState == TextureManager::MASK_APPLIED ||
loadState == TextureManager::NOT_STARTED ||
mQueueLoadFlag );
{
// First check if the requested Texture is cached.
const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
- maskTextureId, preMultiplyOnLoad );
+ maskTextureId );
TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
GET_LOAD_STATE_STRING(textureInfo.loadState ) );
// Force reloading of texture by setting loadState unless already loading or cancelled.
- if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy && TextureManager::LOADING != textureInfo.loadState &&
+ if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy &&
+ TextureManager::LOADING != textureInfo.loadState &&
+ TextureManager::WAITING_FOR_MASK != textureInfo.loadState &&
+ TextureManager::MASK_APPLYING != textureInfo.loadState &&
+ TextureManager::MASK_APPLIED != textureInfo.loadState &&
TextureManager::CANCELLED != textureInfo.loadState )
{
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n",
break;
}
case TextureManager::LOADING:
+ case TextureManager::WAITING_FOR_MASK:
+ case TextureManager::MASK_APPLYING:
+ case TextureManager::MASK_APPLIED:
{
ObserveTexture( textureInfo, observer );
break;
break;
}
case TextureManager::LOAD_FINISHED:
- case TextureManager::WAITING_FOR_MASK:
// Loading has already completed. Do nothing.
break;
}
}
break;
}
- case LOADING:
case UPLOADED:
{
if( mQueueLoadFlag )
textureInfo.useAtlas, textureInfo.atlasRect,
textureInfo.preMultiplied );
}
+ break;
}
+ case LOADING:
case CANCELLED:
case LOAD_FINISHED:
case WAITING_FOR_MASK:
+ case MASK_APPLYING:
+ case MASK_APPLIED:
{
break;
}
{
auto& loadersContainer = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
auto loadingHelperIt = loadersContainer.GetNext();
+ auto premultiplyOnLoad = ( textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID ) ?
+ DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
loadingHelperIt->Load(textureInfo.textureId, textureInfo.url,
textureInfo.desiredSize, textureInfo.fittingMode,
- textureInfo.samplingMode, textureInfo.orientationCorrection );
+ textureInfo.samplingMode, textureInfo.orientationCorrection,
+ premultiplyOnLoad );
}
ObserveTexture( textureInfo, observer );
}
// wait for the mask to finish loading.
if( textureInfo.maskTextureId != INVALID_TEXTURE_ID )
{
- LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId );
- if( maskLoadState == LOADING )
- {
- textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
- textureInfo.loadState = WAITING_FOR_MASK;
- }
- else if( maskLoadState == LOAD_FINISHED )
+ if( textureInfo.loadState == MASK_APPLYING )
{
- ApplyMask( pixelBuffer, textureInfo.maskTextureId, textureInfo.scaleFactor, textureInfo.cropToMask );
+ textureInfo.loadState = MASK_APPLIED;
UploadTexture( pixelBuffer, textureInfo );
NotifyObservers( textureInfo, true );
}
+ else
+ {
+ LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId );
+ textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
+ if( maskLoadState == LOADING )
+ {
+ textureInfo.loadState = WAITING_FOR_MASK;
+ }
+ else if( maskLoadState == LOAD_FINISHED )
+ {
+ // Send New Task to Thread
+ ApplyMask( textureInfo, textureInfo.maskTextureId );
+ }
+ }
}
else
{
}
else
{
- DALI_LOG_ERROR( "TextureManager::AsyncImageLoad(%s) failed\n", textureInfo.url.GetUrl().c_str() );
// @todo If the load was unsuccessful, upload the broken image.
textureInfo.loadState = LOAD_FAILED;
CheckForWaitingTexture( textureInfo );
mTextureInfoContainer[cacheIndex].loadState == WAITING_FOR_MASK )
{
TextureInfo& textureInfo( mTextureInfoContainer[cacheIndex] );
- Devel::PixelBuffer pixelBuffer = textureInfo.pixelBuffer;
- textureInfo.pixelBuffer.Reset();
if( maskTextureInfo.loadState == LOAD_FINISHED )
{
- ApplyMask( pixelBuffer, maskTextureInfo.textureId, textureInfo.scaleFactor, textureInfo.cropToMask );
- UploadTexture( pixelBuffer, textureInfo );
- NotifyObservers( textureInfo, true );
+ // Send New Task to Thread
+ ApplyMask( textureInfo, maskTextureInfo.textureId );
}
else
{
- DALI_LOG_ERROR( "TextureManager::ApplyMask to %s failed\n", textureInfo.url.GetUrl().c_str() );
+ textureInfo.pixelBuffer.Reset();
textureInfo.loadState = LOAD_FAILED;
NotifyObservers( textureInfo, false );
}
}
}
-void TextureManager::ApplyMask(
- Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
- float contentScale, bool cropToMask )
+void TextureManager::ApplyMask( TextureInfo& textureInfo, TextureId maskTextureId )
{
int maskCacheIndex = GetCacheIndexFromId( maskTextureId );
if( maskCacheIndex != INVALID_CACHE_INDEX )
{
Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
- pixelBuffer.ApplyMask( maskPixelBuffer, contentScale, cropToMask );
+ Devel::PixelBuffer pixelBuffer = textureInfo.pixelBuffer;
+ textureInfo.pixelBuffer.Reset();
+
+ DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n",
+ textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously?"T":"F" );
+
+ textureInfo.loadState = MASK_APPLYING;
+ auto& loadersContainer = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+ auto loadingHelperIt = loadersContainer.GetNext();
+ auto premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
+ DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
+ loadingHelperIt->ApplyMask( textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad );
}
}
{
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::General, " TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId );
- // If the texture doesn't have an alpha channel, can't pre-multiply it.
- // Ensure that we don't change the load parameter (it's used for hashing), and instead set
- // the status for use in the observer.
- auto preMultiply = textureInfo.preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD :
- TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
- PreMultiply( pixelBuffer, preMultiply );
- textureInfo.preMultiplied = (preMultiply == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD );
+ // Check if this pixelBuffer is premultiplied
+ textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(),
pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode,
const UseAtlas useAtlas,
- TextureId maskTextureId,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad)
+ TextureId maskTextureId )
{
std::string hashTarget( url );
const size_t urlLength = hashTarget.length();
}
}
- auto premultipliedIndex = hashTarget.length();
- hashTarget.resize( premultipliedIndex + 1 );
- switch( preMultiplyOnLoad )
- {
- case TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD:
- {
- hashTarget[ premultipliedIndex ] = 't';
- break;
- }
- case TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY:
- {
- hashTarget[ premultipliedIndex ] = 'f';
- break;
- }
- }
-
return Dali::CalculateHash( hashTarget );
}
{
// We have a match, now we check all the original parameters in case of a hash collision.
TextureInfo& textureInfo( mTextureInfoContainer[i] );
- auto multiplyOnLoad = textureInfo.preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD :
- TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
if( ( url == textureInfo.url.GetUrl() ) &&
( useAtlas == textureInfo.useAtlas ) &&
( maskTextureId == textureInfo.maskTextureId ) &&
( size == textureInfo.desiredSize ) &&
- ( preMultiplyOnLoad == multiplyOnLoad ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
samplingMode == textureInfo.samplingMode ) ) )
{
- // The found Texture is a match.
- cacheIndex = i;
- break;
+ // 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
+ // 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
+ if( ( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD && textureInfo.preMultiplyOnLoad )
+ || ( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY && !textureInfo.preMultiplied ) )
+ {
+ // The found Texture is a match.
+ cacheIndex = i;
+ break;
+ }
}
}
}
ImageDimensions desiredSize,
FittingMode::Type fittingMode,
SamplingMode::Type samplingMode,
- bool orientationCorrection)
+ bool orientationCorrection,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+{
+ mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+ auto id = DevelAsyncImageLoader::Load( mLoader, url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad );
+ mLoadingInfoContainer.back().loadId = id;
+}
+
+void TextureManager::AsyncLoadingHelper::ApplyMask( TextureId textureId,
+ Devel::PixelBuffer pixelBuffer,
+ Devel::PixelBuffer maskPixelBuffer,
+ float contentScale,
+ bool cropToMask,
+ DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad )
{
mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
- auto id = mLoader.Load(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+ auto id = DevelAsyncImageLoader::ApplyMask( mLoader, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad );
mLoadingInfoContainer.back().loadId = id;
}
}
void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t id,
- Devel::PixelBuffer pixelBuffer)
+ Devel::PixelBuffer pixelBuffer )
{
- mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer);
+ mTextureManager.AsyncLoadComplete( mLoadingInfoContainer, id, pixelBuffer );
}
void TextureManager::SetBrokenImageUrl(const std::string& brokenImageUrl)