constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS = size_t{4u};
constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u};
-constexpr auto TEXTURE_INDEX = 0u; ///< The Index for texture
-constexpr auto MASK_TEXTURE_INDEX = 1u; ///< The Index for mask texture
+constexpr auto TEXTURE_INDEX = 0u; ///< The Index for texture
+constexpr auto MASK_TEXTURE_INDEX = 1u; ///< The Index for mask texture
constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV = "DALI_TEXTURE_LOCAL_THREADS";
constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS";
mLifecycleObservers(),
mLoadQueue(),
mRemoveQueue(),
- mQueueLoadFlag(false),
+ mLoadingQueueTextureId(INVALID_TEXTURE_ID),
mLoadYuvPlanes(NeedToLoadYuvPlanes())
{
// Initialize the AddOn
loadState == TextureManager::LoadState::MASK_APPLYING ||
loadState == TextureManager::LoadState::MASK_APPLIED ||
loadState == TextureManager::LoadState::NOT_STARTED ||
- mQueueLoadFlag);
+ mLoadingQueueTextureId != INVALID_TEXTURE_ID);
}
else
{
{
if(textureId != INVALID_TEXTURE_ID)
{
- if(mQueueLoadFlag)
- {
- // Remove textureId after NotifyObserver finished
- mRemoveQueue.PushBack(textureId);
- }
- else
+ TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
+ if(textureCacheIndex != INVALID_CACHE_INDEX)
{
- // Remove textureId in CacheManager.
- mTextureCacheManager.RemoveCache(textureId);
- }
+ TextureManager::TextureId maskTextureId = INVALID_TEXTURE_ID;
+ TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]);
+ // We only need to consider maskTextureId when texture's loadState is not CANCELLED. Because it is already deleted.
+ if(textureInfo.loadState != LoadState::CANCELLED)
+ {
+ if(textureInfo.maskTextureId != INVALID_TEXTURE_ID)
+ {
+ maskTextureId = textureInfo.maskTextureId;
+ }
+ }
- if(observer)
- {
- // Remove element from the LoadQueue
- for(auto&& element : mLoadQueue)
+ // the case that LoadingQueue is working.
+ if(mLoadingQueueTextureId != INVALID_TEXTURE_ID)
{
- if(element.mObserver == observer)
+ // If textureId is not same, this observer need to delete when ProcessRemoveQueue() is called.
+ // If textureId is same, we should not call RemoveTextureObserver.
+ // Because ObserverDestroyed signal already disconnected in NotifyObservers
+ TextureUploadObserver* queueObserver = observer;
+ if(mLoadingQueueTextureId == textureId)
+ {
+ queueObserver = nullptr;
+ }
+
+ // Remove element from the mLoadQueue
+ for(auto&& element : mLoadQueue)
{
- // Do not erase the item. We will clear it later in ProcessLoadQueue().
- element.mObserver = nullptr;
- break;
+ if(element.mTextureId == textureId && element.mObserver == observer)
+ {
+ // Do not erase the item. We will clear it later in ProcessLoadQueue().
+ element.mTextureId = INVALID_TEXTURE_ID;
+ element.mObserver = nullptr;
+ break;
+ }
+ }
+
+ mRemoveQueue.PushBack(QueueElement(textureId, queueObserver));
+ }
+ else
+ {
+ // Remove its observer
+ RemoveTextureObserver(textureInfo, observer);
+
+ // Remove textureId in CacheManager. Now, textureInfo is invalidate.
+ mTextureCacheManager.RemoveCache(textureInfo);
+
+ // Remove maskTextureId in CacheManager
+ if(maskTextureId != INVALID_TEXTURE_ID)
+ {
+ TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(maskTextureId);
+ if(maskCacheIndex != INVALID_CACHE_INDEX)
+ {
+ TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]);
+ mTextureCacheManager.RemoveCache(maskTextureInfo);
+ }
}
}
}
case LoadState::NOT_STARTED:
case LoadState::LOAD_FAILED:
{
- if(mQueueLoadFlag)
+ if(mLoadingQueueTextureId != INVALID_TEXTURE_ID)
{
QueueLoadTexture(textureInfo, observer);
}
}
case LoadState::UPLOADED:
{
- if(mQueueLoadFlag)
+ if(mLoadingQueueTextureId != INVALID_TEXTURE_ID)
{
QueueLoadTexture(textureInfo, observer);
}
void TextureManager::QueueLoadTexture(const TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
{
const auto& textureId = textureInfo.textureId;
- mLoadQueue.PushBack(LoadQueueElement(textureId, observer));
+ mLoadQueue.PushBack(QueueElement(textureId, observer));
- observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
+ if(observer)
+ {
+ observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
+ }
}
void TextureManager::LoadTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
{
for(auto&& element : mLoadQueue)
{
- if(!element.mObserver)
+ if(element.mTextureId == INVALID_TEXTURE_ID)
{
continue;
}
TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
if((textureInfo.loadState == LoadState::UPLOADED) || (textureInfo.loadState == LoadState::LOAD_FINISHED && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER))
{
- EmitLoadComplete(element.mObserver, textureInfo, true);
+ if(element.mObserver)
+ {
+ EmitLoadComplete(element.mObserver, textureInfo, true);
+ }
}
else if(textureInfo.loadState == LoadState::LOADING)
{
void TextureManager::ProcessRemoveQueue()
{
- for(const auto& textureId : mRemoveQueue)
+ for(auto&& element : mRemoveQueue)
{
- mTextureCacheManager.RemoveCache(textureId);
+ if(element.mTextureId != INVALID_TEXTURE_ID)
+ {
+ Remove(element.mTextureId, element.mObserver);
+ }
}
mRemoveQueue.Clear();
}
UploadTextures(pixelBuffers, maskTextureInfo);
}
- // Search the cache, checking if any texture has this texture id as a
- // maskTextureId:
+ // Search the cache, checking if any texture has this texture id as a maskTextureId
const std::size_t size = mTextureCacheManager.size();
+ // Keep notify observer required textureIds.
+ // Note : NotifyObservers can change mTextureCacheManager cache struct. We should check id's validation before notify.
+ std::vector<TextureId> notifyRequiredTextureIds;
+
// TODO : Refactorize here to not iterate whole cached image.
for(TextureCacheIndex cacheIndex = TextureCacheIndex(TextureManagerType::TEXTURE_CACHE_INDEX_TYPE_LOCAL, 0u); cacheIndex.GetIndex() < size; ++cacheIndex.detailValue.index)
{
pixelBuffers.push_back(textureInfo.pixelBuffer);
UploadTextures(pixelBuffers, textureInfo);
- // notify mask texture set.
- NotifyObservers(textureInfo, true);
+ // Increase reference counts for notify required textureId.
+ // Now we can assume that we don't remove & re-assign this textureId
+ // during NotifyObserver signal emit.
+ maskTextureInfo.referenceCount++;
+ textureInfo.referenceCount++;
+
+ notifyRequiredTextureIds.push_back(textureInfo.textureId);
}
}
else
std::vector<Devel::PixelBuffer> pixelBuffers;
pixelBuffers.push_back(textureInfo.pixelBuffer);
UploadTextures(pixelBuffers, textureInfo);
- NotifyObservers(textureInfo, true);
+
+ // Increase reference counts for notify required textureId.
+ // Now we can assume that we don't remove & re-assign this textureId
+ // during NotifyObserver signal emit.
+ maskTextureInfo.referenceCount++;
+ textureInfo.referenceCount++;
+
+ notifyRequiredTextureIds.push_back(textureInfo.textureId);
}
}
}
+
+ // Notify textures are masked
+ for(const auto textureId : notifyRequiredTextureIds)
+ {
+ TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
+ if(textureCacheIndex != INVALID_CACHE_INDEX)
+ {
+ TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]);
+ NotifyObservers(textureInfo, true);
+ }
+ }
+
+ // Decrease reference count
+ for(const auto textureId : notifyRequiredTextureIds)
+ {
+ Remove(textureId, nullptr);
+ }
}
void TextureManager::ApplyMask(TextureManager::TextureInfo& textureInfo, const TextureManager::TextureId& maskTextureId)
for(auto&& pixelBuffer : pixelBuffers)
{
- 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.textures.push_back(texture);
info->animatedImageLoading.Reset();
}
- mQueueLoadFlag = true;
+ mLoadingQueueTextureId = textureId;
// Reverse observer list that we can pop_back the observer.
std::reverse(info->observerList.Begin(), info->observerList.End());
info = &mTextureCacheManager[textureInfoIndex];
}
- mQueueLoadFlag = false;
+ mLoadingQueueTextureId = INVALID_TEXTURE_ID;
ProcessLoadQueue();
ProcessRemoveQueue();
{
if(element.mObserver == observer)
{
- element.mObserver = nullptr;
+ element.mTextureId = INVALID_TEXTURE_ID;
+ element.mObserver = nullptr;
}
}
}
TextureSet TextureManager::GetTextureSet(const TextureManager::TextureId& textureId)
{
- TextureSet textureSet;
+ TextureSet textureSet;
TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
if(loadState == TextureManager::LoadState::UPLOADED)
{
return textureSet;
}
+void TextureManager::RemoveTextureObserver(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
+{
+ // Remove its observer
+ if(observer)
+ {
+ const auto iterEnd = textureInfo.observerList.End();
+ const auto iter = std::find(textureInfo.observerList.Begin(), iterEnd, observer);
+ if(iter != iterEnd)
+ {
+ // Disconnect and remove the observer.
+ observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
+ textureInfo.observerList.Erase(iter);
+ }
+ }
+}
+
} // namespace Internal
} // namespace Toolkit