/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
#include <dali/devel-api/adaptor-framework/environment-variable.h>
#include <dali/devel-api/adaptor-framework/image-loading.h>
#include <dali/devel-api/common/hash.h>
-#include <dali/devel-api/images/texture-set-image.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/integration-api/debug.h>
}
}
+Devel::PixelBuffer TextureManager::LoadPixelBuffer(
+ const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, bool synchronousLoading, TextureUploadObserver* textureObserver, bool orientationCorrection, TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
+{
+ Devel::PixelBuffer pixelBuffer;
+ if( synchronousLoading )
+ {
+ if( url.IsValid() )
+ {
+ pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode,
+ orientationCorrection );
+ if( pixelBuffer && preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD )
+ {
+ PreMultiply( pixelBuffer, preMultiplyOnLoad );
+ }
+ }
+ }
+ else
+ {
+ RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS,
+ false, RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED,
+ preMultiplyOnLoad );
+ }
+
+ return pixelBuffer;
+}
+
TextureSet TextureManager::LoadTexture(
const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode,
- Dali::SamplingMode::Type samplingMode, const MaskingDataPointer& maskInfo,
+ Dali::SamplingMode::Type samplingMode, MaskingDataPointer& maskInfo,
bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect,
Dali::ImageDimensions& textureRectSize, bool& atlasingStatus, bool& loadingStatus,
Dali::WrapMode::Type wrapModeU, Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver,
{
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 );
if( !data )
{
// use broken image
- textureSet = TextureSet::New();
Devel::PixelBuffer pixelBuffer = LoadImageFromFile( mBrokenImageUrl );
if( pixelBuffer )
{
}
else
{
+ maskInfo->mAlphaMaskId = RequestMaskLoad( maskInfo->mAlphaMaskUrl );
textureId = RequestLoad( url,
maskInfo->mAlphaMaskId,
maskInfo->mContentScaleFactor,
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad )
{
// First check if the requested Texture is cached.
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, preMultiplyOnLoad );
+ maskTextureId, preMultiplyOnLoad, storageType );
// Check if the requested Texture exists in the cache.
if( cacheIndex != INVALID_CACHE_INDEX )
{
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;
}
break;
}
case TextureManager::LOAD_FINISHED:
- // Loading has already completed. Do nothing.
+ {
+ // Loading has already completed.
+ if( observer && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER )
+ {
+ LoadOrQueueTexture( textureInfo, observer );
+ }
break;
+ }
}
// Return the TextureId for which this Texture can now be referenced by externally.
return textureId;
}
-void TextureManager::Remove( const TextureManager::TextureId textureId )
+void TextureManager::Remove( const TextureManager::TextureId textureId, TextureUploadObserver* observer )
{
int textureInfoIndex = GetCacheIndexFromId( textureId );
if( textureInfoIndex != INVALID_INDEX )
TextureInfo& textureInfo( mTextureInfoContainer[ textureInfoIndex ] );
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise,
- "TextureManager::Remove(%d) url:%s\n cacheIdx:%d loadState:%s\n",
+ "TextureManager::Remove(%d) url:%s\n cacheIdx:%d loadState:%s reference count = %d\n",
textureId, textureInfo.url.GetUrl().c_str(),
- textureInfoIndex, GET_LOAD_STATE_STRING( textureInfo.loadState ) );
+ textureInfoIndex, GET_LOAD_STATE_STRING( textureInfo.loadState ), textureInfo.referenceCount );
// Decrement the reference count and check if this is the last user of this Texture.
if( --textureInfo.referenceCount <= 0 )
mTextureInfoContainer.erase( mTextureInfoContainer.begin() + textureInfoIndex );
}
}
+
+ if( observer )
+ {
+ // Remove element from the LoadQueue
+ for( auto&& element : mLoadQueue )
+ {
+ if( element.mObserver == observer )
+ {
+ mLoadQueue.Erase( &element );
+ break;
+ }
+ }
+ }
}
}
textureInfo.useAtlas, textureInfo.atlasRect,
textureInfo.preMultiplied );
}
+ else if ( textureInfo.loadState == LOAD_FINISHED && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER )
+ {
+ element.mObserver->LoadComplete( true, textureInfo.pixelBuffer, textureInfo.url, textureInfo.preMultiplied );
+ }
else
{
LoadTexture( textureInfo, element.mObserver );
}
else
{
- Remove( textureInfo.textureId );
+ Remove( textureInfo.textureId, nullptr );
}
}
}
{
// No atlas support for now
textureInfo.useAtlas = NO_ATLAS;
+ textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
if( textureInfo.storageType == UPLOAD_TO_TEXTURE )
{
textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
textureInfo.loadState = LOAD_FINISHED;
- // Check if there was another texture waiting for this load to complete
- // (e.g. if this was an image mask, and its load is on a different thread)
- CheckForWaitingTexture( textureInfo );
+ if( textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER )
+ {
+ NotifyObservers( textureInfo, true );
+ }
+ else
+ {
+ // Check if there was another texture waiting for this load to complete
+ // (e.g. if this was an image mask, and its load is on a different thread)
+ CheckForWaitingTexture( textureInfo );
+ }
}
}
else
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "NotifyObservers() url:%s loadState:%s\n",
textureInfo.url.GetUrl().c_str(), GET_LOAD_STATE_STRING(textureInfo.loadState ) );
- observer->UploadComplete( success, info->textureId, info->textureSet, info->useAtlas, info->atlasRect,
- info->preMultiplied );
+ // It is possible for the observer to be deleted.
+ // Disconnect and remove the observer first.
observer->DestructionSignal().Disconnect( this, &TextureManager::ObserverDestroyed );
+ info->observerList.Erase( info->observerList.begin() );
+
+ if( info->storageType == StorageType::RETURN_PIXEL_BUFFER )
+ {
+ observer->LoadComplete( success, info->pixelBuffer, info->url, info->preMultiplied );
+ }
+ else
+ {
+ observer->UploadComplete( success, info->textureId, info->textureSet, info->useAtlas, info->atlasRect,
+ info->preMultiplied );
+ }
+
// Get the textureInfo from the container again as it may have been invalidated.
int textureInfoIndex = GetCacheIndexFromId( textureId );
if( textureInfoIndex == INVALID_CACHE_INDEX)
break; // texture has been removed - can stop.
}
info = &mTextureInfoContainer[ textureInfoIndex ];
-
- // remove the observer that was just triggered if it's still in the list
- for( TextureInfo::ObserverListType::Iterator j = info->observerList.Begin(); j != info->observerList.End(); ++j )
- {
- if( *j == observer )
- {
- info->observerList.Erase( j );
- break;
- }
- }
}
mQueueLoadFlag = false;
ProcessQueuedTextures();
+
+ if( info->storageType == StorageType::RETURN_PIXEL_BUFFER && info->observerList.Count() == 0 )
+ {
+ Remove( info->textureId, nullptr );
+ }
}
TextureManager::TextureId TextureManager::GenerateUniqueTextureId()
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
TextureId maskTextureId,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad )
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad,
+ StorageType storageType )
{
// Default to an invalid ID, in case we do not find a match.
int cacheIndex = INVALID_CACHE_INDEX;
( size == textureInfo.desiredSize ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
- samplingMode == textureInfo.samplingMode ) ) )
+ samplingMode == textureInfo.samplingMode ) ) &&
+ ( storageType == textureInfo.storageType ) )
{
// 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.