/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
*/
// CLASS HEADER
-#include "texture-cache-manager.h"
+#include <dali-toolkit/internal/texture-manager/texture-cache-manager.h>
// EXTERNAL HEADERS
#include <dali/devel-api/common/hash.h>
#include <dali/integration-api/debug.h>
+#include <string_view>
+#include <unordered_map>
// INTERNAL HEADERS
{
namespace Internal
{
+namespace
+{
+const std::string_view& GetEncodedImageBufferExtensions(Dali::EncodedImageBuffer::ImageType imageType)
+{
+ static const std::unordered_map<Dali::EncodedImageBuffer::ImageType, const std::string_view> gEncodedImageBufferExtensionMap =
+ {
+ {Dali::EncodedImageBuffer::ImageType::REGULAR_IMAGE, ""},
+ {Dali::EncodedImageBuffer::ImageType::VECTOR_IMAGE, ".svg"},
+ {Dali::EncodedImageBuffer::ImageType::ANIMATED_VECTOR_IMAGE, ".json"},
+ };
+
+ const auto iter = gEncodedImageBufferExtensionMap.find(imageType);
+
+ DALI_ASSERT_DEBUG(iter != gEncodedImageBufferExtensionMap.end());
+
+ return iter->second;
+}
+} // namespace
#ifdef DEBUG_ENABLED
extern Debug::Filter* gTextureManagerLogFilter; ///< Define at texture-manager-impl.cpp
loadState == TextureManagerType::LoadState::MASK_APPLIED ? "MASK_APPLIED" : \
loadState == TextureManagerType::LoadState::UPLOADED ? "UPLOADED" : \
loadState == TextureManagerType::LoadState::CANCELLED ? "CANCELLED" : \
+ loadState == TextureManagerType::LoadState::MASK_CANCELLED ? "MASK_CANCELLED" : \
loadState == TextureManagerType::LoadState::LOAD_FAILED ? "LOAD_FAILED" : \
"Unknown"
// clang-format on
if(static_cast<std::size_t>(removeContainerIndex.GetIndex() + 1) < cacheContainer.size())
{
// First, change the cache index infomations inside of converter
- mTextureIdConverter[cacheContainer.back().bufferId] = static_cast<std::uint32_t>(removeContainerIndex);
+ mTextureIdConverter[cacheContainer.back().bufferId] = static_cast<uint32_t>(removeContainerIndex);
// After change converter, swap the value between current data and last data.
std::swap(cacheContainer[removeContainerIndex.GetIndex()], cacheContainer.back());
if(static_cast<std::size_t>(removeContainerIndex.GetIndex() + 1) < cacheContainer.size())
{
// First, change the cache index infomations inside of converter
- mTextureIdConverter[cacheContainer.back().textureId] = static_cast<std::uint32_t>(removeContainerIndex);
+ mTextureIdConverter[cacheContainer.back().textureId] = static_cast<uint32_t>(removeContainerIndex);
// After change converter, swap the value between current data and last data.
std::swap(cacheContainer[removeContainerIndex.GetIndex()], cacheContainer.back());
{
}
-VisualUrl TextureCacheManager::GetVisualUrl(const TextureCacheManager::TextureId& textureId)
+VisualUrl TextureCacheManager::GetVisualUrl(const TextureCacheManager::TextureId textureId)
{
VisualUrl visualUrl("");
- TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(textureId)]);
+ TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<uint32_t>(textureId)]);
switch(static_cast<TextureCacheIndexType>(cacheIndex.detailValue.type))
{
case TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_BUFFER:
{
DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::GetVisualUrl. Using cached buffer index=%d, bufferId=%d\n", cacheIndex.GetIndex(), textureId);
- visualUrl = VisualUrl::CreateBufferUrl(std::to_string(textureId));
+
+ EncodedImageBufferInfo& cachedEncodedImageBufferInfo(mEncodedImageBuffers[cacheIndex.GetIndex()]);
+ const auto& encodedImageBuffer = cachedEncodedImageBufferInfo.encodedImageBuffer;
+ visualUrl = VisualUrl::CreateBufferUrl(std::to_string(textureId), GetEncodedImageBufferExtensions(encodedImageBuffer.GetImageType()));
break;
}
default:
return visualUrl;
}
-TextureCacheManager::LoadState TextureCacheManager::GetTextureState(const TextureCacheManager::TextureId& textureId)
+TextureCacheManager::LoadState TextureCacheManager::GetTextureState(const TextureCacheManager::TextureId textureId)
{
LoadState loadState = TextureCacheManager::LoadState::NOT_STARTED;
- TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(textureId)]);
+ TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<uint32_t>(textureId)]);
switch(static_cast<TextureCacheIndexType>(cacheIndex.detailValue.type))
{
return loadState;
}
-TextureCacheManager::LoadState TextureCacheManager::GetTextureStateInternal(const TextureCacheManager::TextureId& textureId)
+TextureCacheManager::LoadState TextureCacheManager::GetTextureStateInternal(const TextureCacheManager::TextureId textureId)
{
LoadState loadState = TextureCacheManager::LoadState::NOT_STARTED;
TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
return loadState;
}
-TextureSet TextureCacheManager::GetTextureSet(const TextureCacheManager::TextureId& textureId)
+Texture TextureCacheManager::GetTexture(const TextureCacheManager::TextureId textureId, const uint32_t textureIndex)
{
- TextureSet textureSet; // empty handle
- TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(textureId)]);
+ Texture texture; // empty handle
+ TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
switch(static_cast<TextureCacheIndexType>(cacheIndex.detailValue.type))
{
case TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_LOCAL:
{
TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex.GetIndex()]);
- textureSet = cachedTextureInfo.textureSet;
- break;
- }
- case TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_TEXTURE:
- {
- textureSet = mExternalTextures[cacheIndex.GetIndex()].textureSet;
+ if(textureIndex < static_cast<uint32_t>(cachedTextureInfo.textures.size()))
+ {
+ texture = cachedTextureInfo.textures[textureIndex];
+ }
break;
}
default:
}
}
- return textureSet;
+ return texture;
}
-TextureSet TextureCacheManager::GetExternalTextureSet(const TextureCacheManager::TextureId& textureId)
+TextureCacheManager::ExternalTextureInfo& TextureCacheManager::GetExternalTextureInfo(const TextureCacheManager::TextureId textureId)
{
- TextureSet textureSet; // empty handle
TextureCacheIndex cacheIndex = GetCacheIndexFromExternalTextureId(textureId);
- if(cacheIndex != INVALID_CACHE_INDEX)
- {
- textureSet = mExternalTextures[cacheIndex.GetIndex()].textureSet;
- }
- return textureSet;
+ DALI_ASSERT_ALWAYS(cacheIndex != INVALID_CACHE_INDEX);
+
+ return mExternalTextures[cacheIndex.GetIndex()];
}
-EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const TextureCacheManager::TextureId& bufferId)
+EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const TextureCacheManager::TextureId bufferId)
{
EncodedImageBuffer encodedImageBuffer; // empty handle
TextureCacheIndex cacheIndex = GetCacheIndexFromEncodedImageBufferId(bufferId);
EncodedImageBuffer encodedImageBuffer; // empty handle
if(url.IsValid() && VisualUrl::BUFFER == url.GetProtocolType())
{
- std::string location = url.GetLocation();
+ std::string location = url.GetLocationWithoutExtension();
if(location.size() > 0u)
{
TextureId bufferId = std::stoi(location);
return encodedImageBuffer;
}
-std::string TextureCacheManager::AddExternalTexture(const TextureSet& textureSet)
+std::string TextureCacheManager::AddExternalTexture(const TextureSet& textureSet, const bool preMultiplied)
{
TextureId textureId = GenerateTextureId(TextureCacheIndex(TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_TEXTURE, mExternalTextures.size()));
- TextureCacheManager::ExternalTextureInfo textureInfo(textureId, textureSet);
+ TextureCacheManager::ExternalTextureInfo textureInfo(textureId, textureSet, preMultiplied);
mExternalTextures.emplace_back(textureInfo);
- DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::AddExternalTexture() : New texture registered. textureId:%d\n", textureInfo.textureId);
+ DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::AddExternalTexture() : New texture registered. textureId:%d, preMultiplied:%d\n", textureInfo.textureId, preMultiplied);
return VisualUrl::CreateTextureUrl(std::to_string(textureInfo.textureId));
}
// If same buffer added, increase reference count and return.
bufferInfo.referenceCount++;
- return VisualUrl::CreateBufferUrl(std::to_string(bufferInfo.bufferId));
+ return VisualUrl::CreateBufferUrl(std::to_string(bufferInfo.bufferId), GetEncodedImageBufferExtensions(encodedImageBuffer.GetImageType()));
}
TextureId bufferId = GenerateTextureId(TextureCacheIndex(TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_BUFFER, mEncodedImageBuffers.size()));
DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::AddExternalEncodedImageBuffer() : New buffer regested. bufferId:%d\n", info.bufferId);
- return VisualUrl::CreateBufferUrl(std::to_string(info.bufferId));
+ return VisualUrl::CreateBufferUrl(std::to_string(info.bufferId), GetEncodedImageBufferExtensions(encodedImageBuffer.GetImageType()));
}
TextureSet TextureCacheManager::RemoveExternalTexture(const VisualUrl& url)
if(VisualUrl::BUFFER == url.GetProtocolType())
{
// get the location from the Url
- std::string location = url.GetLocation();
+ std::string location = url.GetLocationWithoutExtension();
if(location.size() > 0u)
{
TextureId bufferId = std::stoi(location);
}
else if(VisualUrl::BUFFER == url.GetProtocolType())
{
- std::string location = url.GetLocation();
+ std::string location = url.GetLocationWithoutExtension();
if(location.size() > 0u)
{
TextureId id = std::stoi(location);
TextureCacheManager::TextureId TextureCacheManager::GenerateTextureId(const TextureCacheIndex& textureCacheIndex)
{
- return mTextureIdConverter.Add(static_cast<std::uint32_t>(textureCacheIndex.indexValue));
+ return mTextureIdConverter.Add(static_cast<uint32_t>(textureCacheIndex.indexValue));
}
-TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromId(const TextureCacheManager::TextureId& textureId)
+TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromId(const TextureCacheManager::TextureId textureId)
{
if(textureId == INVALID_TEXTURE_ID) return INVALID_CACHE_INDEX;
- TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(textureId)]);
+ TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<uint32_t>(textureId)]);
if(DALI_UNLIKELY(cacheIndex.detailValue.type != TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_LOCAL))
{
return INVALID_CACHE_INDEX;
return cacheIndex;
}
-TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromExternalTextureId(const TextureCacheManager::TextureId& textureId)
+TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromExternalTextureId(const TextureCacheManager::TextureId textureId)
{
if(textureId == INVALID_TEXTURE_ID) return INVALID_CACHE_INDEX;
- TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(textureId)]);
+ TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<uint32_t>(textureId)]);
if(DALI_UNLIKELY(cacheIndex.detailValue.type != TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_TEXTURE))
{
return INVALID_CACHE_INDEX;
return cacheIndex;
}
-TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromEncodedImageBufferId(const TextureCacheManager::TextureId& bufferId)
+TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromEncodedImageBufferId(const TextureCacheManager::TextureId bufferId)
{
if(bufferId == INVALID_TEXTURE_ID) return INVALID_CACHE_INDEX;
- TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(bufferId)]);
+ TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<uint32_t>(bufferId)]);
if(DALI_UNLIKELY(cacheIndex.detailValue.type != TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_BUFFER))
{
return INVALID_CACHE_INDEX;
return cacheIndex;
}
-TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedEncodedImageBuffer(const TextureCacheManager::TextureHash& hash, const EncodedImageBuffer& encodedImageBuffer)
+TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedEncodedImageBuffer(const TextureCacheManager::TextureHash hash, const EncodedImageBuffer& encodedImageBuffer)
{
// Iterate through our hashes to find a match.
const auto& hashIterator = mTextureHashContainer.find(hash);
}
TextureCacheManager::TextureHash TextureCacheManager::GenerateHash(
- const VisualUrl& url,
- const Dali::ImageDimensions& size,
- const Dali::FittingMode::Type& fittingMode,
- const Dali::SamplingMode::Type& samplingMode,
- const TextureCacheManager::UseAtlas& useAtlas,
- const TextureCacheManager::TextureId& maskTextureId,
- const bool& cropToMask,
- const std::uint32_t& frameIndex)
+ const VisualUrl& url,
+ const Dali::ImageDimensions& size,
+ const Dali::FittingMode::Type fittingMode,
+ const Dali::SamplingMode::Type samplingMode,
+ const TextureCacheManager::TextureId maskTextureId,
+ const bool cropToMask,
+ const uint32_t frameIndex)
{
std::vector<std::uint8_t> hashTarget;
const uint16_t width = size.GetWidth();
*hashTargetPtr++ = size.GetHeight() & 0xff;
*hashTargetPtr++ = (size.GetHeight() >> 8u) & 0xff;
- // Bit-pack the FittingMode, SamplingMode and atlasing.
- // FittingMode=2bits, SamplingMode=3bits, useAtlas=1bit
- *hashTargetPtr = (fittingMode << 4u) | (samplingMode << 1) | (useAtlas == UseAtlas::USE_ATLAS ? 1 : 0);
- }
- else
- {
- // We are not including sizing information, but we still need an extra byte for atlasing.
- hashTarget.resize(1u);
-
- // Add the atlasing to the hash input.
- switch(useAtlas)
- {
- case UseAtlas::NO_ATLAS:
- {
- hashTarget[0u] = 'f';
- break;
- }
- case UseAtlas::USE_ATLAS:
- {
- hashTarget[0u] = 't';
- break;
- }
- }
+ // Bit-pack the FittingMode, SamplingMode.
+ // FittingMode=2bits, SamplingMode=3bits
+ *hashTargetPtr = (fittingMode << 3u) | (samplingMode);
}
if(maskTextureId != INVALID_TEXTURE_ID)
if(frameIndex > 0u)
{
auto textureIdIndex = hashTarget.size();
- hashTarget.resize(hashTarget.size() + sizeof(std::uint32_t));
+ hashTarget.resize(hashTarget.size() + sizeof(uint32_t));
std::uint8_t* hashTargetPtr = reinterpret_cast<std::uint8_t*>(&(hashTarget[textureIdIndex]));
// Append the frame index to the end of the URL byte by byte:
- std::uint32_t saltedFrameIndex = frameIndex;
- for(size_t byteIter = 0; byteIter < sizeof(std::uint8_t); ++byteIter)
+ // (to avoid SIGBUS / alignment issues)
+ uint32_t saltedFrameIndex = frameIndex;
+ for(size_t byteIter = 0; byteIter < sizeof(uint32_t); ++byteIter)
{
*hashTargetPtr++ = saltedFrameIndex & 0xff;
saltedFrameIndex >>= 8u;
}
TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedTexture(
- const TextureCacheManager::TextureHash& hash,
- const VisualUrl& url,
- const Dali::ImageDimensions& size,
- const Dali::FittingMode::Type& fittingMode,
- const Dali::SamplingMode::Type& samplingMode,
- const TextureCacheManager::UseAtlas& useAtlas,
- const StorageType& storageType,
- const TextureCacheManager::TextureId& maskTextureId,
- const bool& cropToMask,
- const TextureCacheManager::MultiplyOnLoad& preMultiplyOnLoad,
- const bool& isAnimatedImage,
- const std::uint32_t& frameIndex)
+ const TextureCacheManager::TextureHash hash,
+ const VisualUrl& url,
+ const Dali::ImageDimensions& size,
+ const Dali::FittingMode::Type fittingMode,
+ const Dali::SamplingMode::Type samplingMode,
+ const TextureCacheManager::StorageType storageType,
+ const TextureCacheManager::TextureId maskTextureId,
+ const bool cropToMask,
+ const TextureCacheManager::MultiplyOnLoad preMultiplyOnLoad,
+ const bool isAnimatedImage,
+ const uint32_t frameIndex)
{
// Iterate through our hashes to find a match.
const auto& hashIterator = mTextureHashContainer.find(hash);
TextureInfo& textureInfo(mTextureInfoContainer[cacheIndex.GetIndex()]);
if((url.GetUrl() == textureInfo.url.GetUrl()) &&
- (useAtlas == textureInfo.useAtlas) &&
(maskTextureId == textureInfo.maskTextureId) &&
(cropToMask == textureInfo.cropToMask) &&
(size == textureInfo.desiredSize) &&
void TextureCacheManager::RemoveCache(TextureCacheManager::TextureInfo& textureInfo)
{
- TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureInfo.textureId);
- bool removeTextureInfo = false;
+ TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureInfo.textureId);
+ bool removeTextureInfo = false;
DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::Remove(textureId:%d) url:%s\n cacheIdx:%d loadState:%s reference count = %d\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), textureInfoIndex.GetIndex(), GET_LOAD_STATE_STRING(textureInfo.loadState), textureInfo.referenceCount);
// This is the last remove for this Texture.
textureInfo.referenceCount = 0;
- // If loaded, we can remove the TextureInfo and the Atlas (if atlased).
+ // If loaded, we can remove the TextureInfo
if(textureInfo.loadState == LoadState::UPLOADED)
{
- if(textureInfo.atlas)
- {
- textureInfo.atlas.Remove(textureInfo.atlasRect);
- }
removeTextureInfo = true;
}
- else if(textureInfo.loadState == LoadState::LOADING || textureInfo.loadState == LoadState::MASK_APPLYING)
+ else if(textureInfo.loadState == LoadState::LOADING)
{
// We mark the textureInfo for removal.
// Once the load has completed, this method will be called again.
textureInfo.loadState = LoadState::CANCELLED;
}
+ else if(textureInfo.loadState == LoadState::MASK_APPLYING)
+ {
+ // We mark the textureInfo for removal.
+ // Once the load has completed, this method will be called again.
+ textureInfo.loadState = LoadState::MASK_CANCELLED;
+ }
else
{
// In other states, we are not waiting for a load so we are safe to remove the TextureInfo data.
}
}
-void TextureCacheManager::RemoveHashId(const TextureCacheManager::TextureHash& textureHash, const TextureCacheManager::TextureId& textureId)
+void TextureCacheManager::RemoveHashId(const TextureCacheManager::TextureHash textureHash, const TextureCacheManager::TextureId textureId)
{
auto hashIterator = mTextureHashContainer.find(textureHash);
if(hashIterator != mTextureHashContainer.end())