const int INVALID_INDEX( -1 ); ///< Invalid index used to represent a non-existant TextureInfo struct
const int INVALID_CACHE_INDEX( -1 ); ///< Invalid Cache index
+
+void PreMultiply( Devel::PixelBuffer pixelBuffer, TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
+{
+ if( Pixel::HasAlpha( pixelBuffer.GetPixelFormat() ) )
+ {
+ if( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD )
+ {
+ pixelBuffer.MultiplyColorByAlpha();
+ }
+ }
+ else
+ {
+ preMultiplyOnLoad = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+ }
+}
+
} // Anonymous namespace
TextureManager::MaskingData::MaskingData()
bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU,
Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver,
AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy, TextureManager::MultiplyOnLoad preMultiplyOnLoad )
+ TextureManager::ReloadPolicy reloadPolicy, TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
{
TextureSet textureSet;
orientationCorrection );
if( pixelBuffer )
{
- if( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD )
- {
- pixelBuffer.MultiplyColorByAlpha();
- }
-
+ PreMultiply( pixelBuffer, preMultiplyOnLoad );
data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
}
}
Devel::PixelBuffer pixelBuffer = LoadImageFromFile( BROKEN_IMAGE_URL );
if( pixelBuffer )
{
- if( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
- {
- pixelBuffer.MultiplyColorByAlpha();
- }
+ PreMultiply( pixelBuffer, preMultiplyOnLoad );
data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
}
Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(),
}
TextureManager::TextureId TextureManager::RequestLoad(
- const VisualUrl& url,
- const ImageDimensions desiredSize,
- FittingMode::Type fittingMode,
- Dali::SamplingMode::Type samplingMode,
- const UseAtlas useAtlas,
- TextureUploadObserver* observer,
- bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad )
+ const VisualUrl& url,
+ const ImageDimensions desiredSize,
+ FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ const UseAtlas useAtlas,
+ TextureUploadObserver* observer,
+ bool orientationCorrection,
+ TextureManager::ReloadPolicy reloadPolicy,
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
{
return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas,
- false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad );
+ false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy,
+ preMultiplyOnLoad );
}
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,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad )
+ 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,
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
{
return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas,
- cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad );
+ cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy,
+ preMultiplyOnLoad );
}
TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl )
{
// Use the normal load procedure to get the alpha mask.
+ auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
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::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY);
+ TextureManager::ReloadPolicy::CACHED, preMultiply );
}
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,
- TextureManager::ReloadPolicy reloadPolicy,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad)
+ 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,
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
{
// First check if the requested Texture is cached.
const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
{
// We need a new Texture.
textureId = GenerateUniqueTextureId();
+ bool preMultiply = ( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD );
mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(),
desiredSize, contentScale, fittingMode, samplingMode,
- false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiplyOnLoad ) );
+ false, cropToMask, useAtlas, textureHash, orientationCorrection,
+ preMultiply ) );
cacheIndex = mTextureInfoContainer.size() - 1u;
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n",
// The Texture has already loaded. The other observers have already been notified.
// We need to send a "late" loaded notification for this observer.
observer->UploadComplete( true, textureInfo.textureId, textureInfo.textureSet,
- textureInfo.useAtlas, textureInfo.atlasRect );
+ textureInfo.useAtlas, textureInfo.atlasRect,
+ textureInfo.preMultiplied );
}
break;
}
pixelBuffer.ApplyMask( maskPixelBuffer, contentScale, cropToMask );
}
+
void TextureManager::UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo )
{
if( textureInfo.useAtlas != USE_ATLAS )
{
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, " 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 );
+
Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(),
pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
- if( textureInfo.preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD )
- {
- pixelBuffer.MultiplyColorByAlpha();
- }
PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
texture.Upload( pixelData );
// because new load requests can modify the mTextureInfoContainer list
// (e.g. if more requests are pushed back it can cause the list to be
// resized invalidating the reference to the TextureInfo ).
- observer->UploadComplete( success, info->textureId, info->textureSet, info->useAtlas, info->atlasRect );
+ observer->UploadComplete( success, info->textureId, info->textureSet, info->useAtlas, info->atlasRect,
+ info->preMultiplied );
observer->DestructionSignal().Disconnect( this, &TextureManager::ObserverDestroyed );
// Get the textureInfo from the container again as it may have been
auto premultipliedIndex = hashTarget.length();
hashTarget.resize( premultipliedIndex + 1 );
- char* preMultPtr = &( hashTarget[ premultipliedIndex ] );
- *preMultPtr = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? 't':'f';
+ 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 == textureInfo.preMultiplyOnLoad ) &&
+ ( preMultiplyOnLoad == multiplyOnLoad ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
samplingMode == textureInfo.samplingMode ) ) )