int UtcDaliImageVisualLoadFastTrackImagePlanes01(void)
{
-#if 0 //< Do not open this UTC yet.
EnvironmentVariable::SetTestEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV, "1");
EnvironmentVariable::SetTestEnvironmentVariable(ENABLE_DECODE_JPEG_TO_YUV_420_ENV, "1");
DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 3, TEST_LOCATION);
- // Event thread don't know the result yet.
- DALI_TEST_EQUALS(actor.IsResourceReady(), false, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
- DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliImageVisualLoadFastTrackImagePlanes02(void)
+{
+ EnvironmentVariable::SetTestEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV, "1");
+ EnvironmentVariable::SetTestEnvironmentVariable(ENABLE_DECODE_JPEG_TO_YUV_420_ENV, "1");
+
+ ToolkitTestApplication application;
+
+ Test::TextureUploadManager::InitalizeGraphicsController(application.GetGraphicsController());
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+ propertyMap.Insert(DevelImageVisual::Property::FAST_TRACK_UPLOADING, true);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.GetScene().Add(actor);
- // Check resource ready comes after
application.SendNotification();
+ application.Render();
- DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
- DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+ // EventThread without callback
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1, 30, false), true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 0, TEST_LOCATION);
+
+ {
+ // TODO : There is no way to flush TextureUploadManager in test-application's Render() now.
+ // How can we make it? Should it be integration-api?
+ auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
+ textureUploadManager.ResourceUpload();
+ application.Render();
+ }
+ // Render only without SendNotification(). And check whether glTexImage2D called or not.
+ application.Render();
+
+ DALI_TEST_GREATER(textureTrace.CountMethod("GenTextures"), 0, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
-#else
- DALI_TEST_CHECK(true);
-#endif
END_TEST;
}
\ No newline at end of file
#endif
uniform sampler2D sTexture;
-#ifdef IS_REQUIRED_YUV_TO_RGB
+#if defined(IS_REQUIRED_YUV_TO_RGB) || defined(IS_REQUIRED_UNIFIED_YUV_AND_RGB)
uniform sampler2D sTextureU;
uniform sampler2D sTextureV;
#endif
}
#endif
-#ifdef IS_REQUIRED_YUV_TO_RGB
-lowp vec3 ConvertYuvToRgb(mediump vec2 texCoord)
+#if defined(IS_REQUIRED_YUV_TO_RGB) || defined(IS_REQUIRED_UNIFIED_YUV_AND_RGB)
+lowp vec4 ConvertYuvToRgba(mediump vec2 texCoord)
{
+#ifdef IS_REQUIRED_UNIFIED_YUV_AND_RGB
+ // Special case when shader use YUV but actual textures are not YUV format.
+ // In this case, just resturn sTexture.
+ if(textureSize(sTextureU, 0) != textureSize(sTextureV, 0))
+ {
+ return texture(sTexture, texCoord);
+ }
+#endif
+
lowp float y = texture(sTexture, texCoord).r;
lowp float u = texture(sTextureU, texCoord).r - 0.5;
lowp float v = texture(sTextureV, texCoord).r - 0.5;
- lowp vec3 rgb;
- rgb.r = y + (1.403 * v);
- rgb.g = y - (0.344 * u) - (0.714 * v);
- rgb.b = y + (1.770 * u);
- return rgb;
+ lowp vec4 rgba;
+ rgba.r = y + (1.403 * v);
+ rgba.g = y - (0.344 * u) - (0.714 * v);
+ rgba.b = y + (1.770 * u);
+ rgba.a = 1.0;
+ return rgba;
}
#endif
mediump vec2 texCoord = vTexCoord;
#endif
-#ifdef IS_REQUIRED_YUV_TO_RGB
- lowp vec4 textureColor = vec4(ConvertYuvToRgb(texCoord), 1.0) * vec4( mixColor, 1.0 ) * uColor;
+#if defined(IS_REQUIRED_YUV_TO_RGB) || defined(IS_REQUIRED_UNIFIED_YUV_AND_RGB)
+ lowp vec4 textureColor = ConvertYuvToRgba(texCoord) * vec4( mixColor, 1.0 ) * uColor;
#else
lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
#endif
#include <dali/integration-api/debug.h>
#include <dali/integration-api/texture-integ.h>
#include <dali/integration-api/trace.h>
+#include <dali/public-api/common/vector-wrapper.h>
#ifdef TRACE_ENABLED
#include <sstream>
namespace
{
DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
+
+constexpr uint32_t CHROMINANCE_U_INDEX = 1u;
+constexpr uint32_t CHROMINANCE_V_INDEX = 2u;
+
+Dali::PixelData GetDummyChrominanceUPixelData()
+{
+ static Dali::PixelData pixelDataU = PixelData::New(new uint8_t[2]{0x00, 0x00}, 2, 1, 2, Pixel::L8, PixelData::DELETE_ARRAY);
+ return pixelDataU;
+}
+
+Dali::PixelData GetDummyChrominanceVPixelData()
+{
+ static Dali::PixelData pixelDataV = PixelData::New(new uint8_t[2]{0x00, 0x00}, 2, 2, 1, Pixel::L8, PixelData::DELETE_ARRAY);
+ return pixelDataV;
}
-FastTrackLoadingTask::FastTrackLoadingTask(const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, CallbackBase* callback)
+} // namespace
+
+FastTrackLoadingTask::FastTrackLoadingTask(const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadPlanes, CallbackBase* callback)
: AsyncTask(MakeCallback(this, &FastTrackLoadingTask::OnComplete), url.GetProtocolType() == VisualUrl::ProtocolType::REMOTE ? AsyncTask::PriorityType::LOW : AsyncTask::PriorityType::HIGH),
mUrl(url),
- mTexture(),
+ mTextures(),
mDimensions(dimensions),
mFittingMode(fittingMode),
mSamplingMode(samplingMode),
mPreMultiplyOnLoad(preMultiplyOnLoad),
mCallback(),
mTextureUploadManager(Dali::Devel::TextureUploadManager::Get()),
- mImageWidth(0u),
- mImageHeight(0u),
- mImageFormat(Pixel::INVALID),
+ mImageInformations(),
mPixelData(),
- mResourceId(0u),
mOrientationCorrection(orientationCorrection),
mLoadSuccess(false),
- mPremultiplied(false)
+ mLoadPlanesAvaliable(loadPlanes),
+ mPremultiplied(false),
+ mPlanesLoaded(false)
{
mCallback = std::unique_ptr<CallbackBase>(callback);
PrepareTexture();
void FastTrackLoadingTask::PrepareTexture()
{
- mTexture = mTextureUploadManager.GenerateTexture2D();
- mResourceId = Integration::GetTextureResourceId(mTexture);
+ const uint32_t requiredTexturesCount = mLoadPlanesAvaliable ? 3u : 1u;
+
+ mTextures.resize(requiredTexturesCount);
+ mImageInformations.resize(requiredTexturesCount);
+ for(uint32_t index = 0u; index < requiredTexturesCount; ++index)
+ {
+ mTextures[index] = mTextureUploadManager.GenerateTexture2D();
+
+ mImageInformations[index].resourceId = Integration::GetTextureResourceId(mTextures[index]);
+ }
+
+ if(mLoadPlanesAvaliable)
+ {
+ // Create static dummy chrominance pixel data now, for thread safety.
+ [[maybe_unused]] auto pixelDataU = GetDummyChrominanceUPixelData();
+ [[maybe_unused]] auto pixelDataV = GetDummyChrominanceVPixelData();
+ }
}
void FastTrackLoadingTask::OnComplete(AsyncTaskPtr task)
{
if(mLoadSuccess)
{
- Dali::Integration::SetTextureSize(mTexture, Dali::ImageDimensions(mImageWidth, mImageHeight));
- Dali::Integration::SetTexturePixelFormat(mTexture, mImageFormat);
+ for(uint32_t index = 0u; index < mImageInformations.size(); ++index)
+ {
+ Dali::Integration::SetTextureSize(mTextures[index], Dali::ImageDimensions(mImageInformations[index].width, mImageInformations[index].height));
+ Dali::Integration::SetTexturePixelFormat(mTextures[index], mImageInformations[index].format);
+ }
+ if(mLoadPlanesAvaliable && !mPlanesLoaded)
+ {
+ // We will not use ChrominanceU and ChrominanceV texture anymore.
+ mTextures.resize(1u);
+ }
+ }
+ else
+ {
+ mTextures.clear();
}
+
if(mCallback)
{
CallbackBase::Execute(*mCallback, FastTrackLoadingTaskPtr(reinterpret_cast<FastTrackLoadingTask*>(task.Get())));
if(mUrl.IsValid() && mUrl.IsLocalResource())
{
- // TODO : We need to consider YUV case in future.
- //Dali::LoadImagePlanesFromFile(mUrl.GetUrl(), pixelBuffers, mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
-
- pixelBuffer = Dali::LoadImageFromFile(mUrl.GetUrl(), mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
+ if(mLoadPlanesAvaliable)
+ {
+ Dali::LoadImagePlanesFromFile(mUrl.GetUrl(), pixelBuffers, mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
+ }
+ else
+ {
+ pixelBuffer = Dali::LoadImageFromFile(mUrl.GetUrl(), mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
+ }
}
else if(mUrl.IsValid())
{
if(pixelBuffer)
{
- pixelBuffers.push_back(pixelBuffer);
+ pixelBuffers.emplace_back(std::move(pixelBuffer));
}
if(pixelBuffers.empty())
{
- DALI_LOG_ERROR("FastTrackLoadingTask::Load: Loading is failed: ResourceId : %d, url : [%s]\n", mResourceId, mUrl.GetUrl().c_str());
+ mLoadSuccess = false;
+ DALI_LOG_ERROR("FastTrackLoadingTask::Load: Loading is failed: ResourceId : %d url : [%s]\n", mImageInformations[0u].resourceId, mUrl.GetUrl().c_str());
}
else
{
- if(pixelBuffers.size() == 1u)
+ mPixelData.resize(pixelBuffers.size());
+
+ mLoadSuccess = true;
+ MultiplyAlpha(pixelBuffers[0]);
+ uint32_t index = 0u;
+ for(auto&& pixelBuffer : pixelBuffers)
{
- mLoadSuccess = true;
- MultiplyAlpha(pixelBuffers[0]);
- mPixelData = Dali::Devel::PixelBuffer::Convert(pixelBuffers[0]);
+ mPixelData[index++] = Dali::Devel::PixelBuffer::Convert(pixelBuffer);
}
- else
+
+ if(pixelBuffers.size() > 1u)
{
- DALI_LOG_ERROR("FastTrackLoadingTask::Load: ??? Undefined case. PixelBuffers.size() : %zu : ResourceId : %d, url : [%s]\n", pixelBuffers.size(), mResourceId, mUrl.GetUrl().c_str());
+ mPlanesLoaded = true;
+ }
+ else if(mLoadPlanesAvaliable && pixelBuffers.size() == 1u && mTextures.size() == 3u) ///< Case when we prepare three textures to render YUV, but loaded image is not YUV.
+ {
+ // Dummy pixel data for fake shader that we don't use actual YUV format.
+ // To fake shader, let we use indivisual sizes of texture for U and V.
+ mPixelData.resize(3u);
+ mPixelData[CHROMINANCE_U_INDEX] = GetDummyChrominanceUPixelData();
+ mPixelData[CHROMINANCE_V_INDEX] = GetDummyChrominanceVPixelData();
+ }
+
+ if(DALI_UNLIKELY(mPixelData.size() != mImageInformations.size()))
+ {
+ DALI_LOG_ERROR("FastTrackLoadingTask::Load: Undefined case. pixelBuffers.size() : %zu, image size : %zu, ResourceId : %d, url : [%s]\n", pixelBuffers.size(), mImageInformations.size(), mImageInformations[0u].resourceId, mUrl.GetUrl().c_str());
+ mLoadSuccess = false;
}
}
{
if(mLoadSuccess)
{
- mImageWidth = mPixelData.GetWidth();
- mImageHeight = mPixelData.GetHeight();
- mImageFormat = mPixelData.GetPixelFormat();
+ DALI_ASSERT_DEBUG(mPixelData.size() == mImageInformations.size());
- mTextureUploadManager.RequestUpload(mResourceId, mPixelData);
+ uint32_t index = 0u;
+ for(auto&& pixelData : mPixelData)
+ {
+ mImageInformations[index].width = pixelData.GetWidth();
+ mImageInformations[index].height = pixelData.GetHeight();
+ mImageInformations[index].format = pixelData.GetPixelFormat();
+
+ mTextureUploadManager.RequestUpload(mImageInformations[index].resourceId, pixelData);
+
+ pixelData.Reset();
+
+ ++index;
+ }
}
- mPixelData.Reset();
+ mPixelData.clear();
}
} // namespace Internal
*/
// EXTERNAL INCLUDES
-#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
-#include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
-#include <dali-toolkit/internal/visuals/visual-url.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
#include <dali/public-api/adaptor-framework/async-task-manager.h>
+#include <dali/public-api/common/vector-wrapper.h>
#include <dali/public-api/rendering/texture.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-type.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
namespace Dali
{
namespace Toolkit
SamplingMode::Type samplingMode,
bool orientationCorrection,
DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+ bool loadPlanes,
CallbackBase* callback);
/**
void OnComplete(AsyncTaskPtr task);
public:
- VisualUrl mUrl; ///< url of the image to load.
- Dali::Texture mTexture; ///< texture for regular image.
+ VisualUrl mUrl; ///< url of the image to load.
+ std::vector<Dali::Texture> mTextures; ///< textures for regular image.
private:
ImageDimensions mDimensions; ///< dimensions to load
Dali::Devel::TextureUploadManager mTextureUploadManager;
// Note : mPixelData is invalid after upload requested. We should keep image size informations.
- uint32_t mImageWidth;
- uint32_t mImageHeight;
- Pixel::Format mImageFormat;
+ struct ImageInformation
+ {
+ uint32_t resourceId;
- Dali::PixelData mPixelData;
+ uint32_t width;
+ uint32_t height;
+ Pixel::Format format;
+ };
+ std::vector<ImageInformation> mImageInformations;
- uint32_t mResourceId;
+ std::vector<Dali::PixelData> mPixelData;
bool mOrientationCorrection : 1; ///< If orientation correction is needed
public:
- bool mLoadSuccess : 1; ///< Whether image load successed or not.
- bool mPremultiplied : 1; ///< True if the image's color was multiplied by it's alpha
+ bool mLoadSuccess : 1; ///< Whether image load successed or not.
+ bool mLoadPlanesAvaliable : 1; ///< If image valid to load as planes or not.
+ bool mPremultiplied : 1; ///< True if the image's color was multiplied by it's alpha
+ bool mPlanesLoaded : 1; ///< True if the image load as planes.
};
} // namespace Internal
#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
// EXTERNAL HEADERS
-#include <dali/devel-api/adaptor-framework/environment-variable.h>
#include <dali/devel-api/adaptor-framework/image-loading.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/integration-api/adaptor-framework/adaptor.h>
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";
-constexpr auto LOAD_IMAGE_YUV_PLANES_ENV = "DALI_LOAD_IMAGE_YUV_PLANES";
-
-bool NeedToLoadYuvPlanes()
-{
- auto loadYuvPlanesString = Dali::EnvironmentVariable::GetEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV);
- bool loadYuvPlanes = loadYuvPlanesString ? std::atoi(loadYuvPlanesString) : false;
- return loadYuvPlanes;
-}
} // namespace
namespace Dali
{
}
-TextureManager::TextureManager()
+TextureManager::TextureManager(bool loadYuvPlanes)
: mTextureCacheManager(),
mAsyncLoader(std::unique_ptr<TextureAsyncLoadingHelper>(new TextureAsyncLoadingHelper(*this))),
mLifecycleObservers(),
mLoadQueue(),
mLoadingQueueTextureId(INVALID_TEXTURE_ID),
mRemoveQueue(),
- mLoadYuvPlanes(NeedToLoadYuvPlanes()),
+ mLoadYuvPlanes(loadYuvPlanes),
mRemoveProcessorRegistered(false)
{
// Initialize the AddOn
/**
* Constructor.
+ *
+ * @param[in] loadYuvPlanes Whether we allow to load YuvPlanes or not. Default is false.
*/
- TextureManager();
+ TextureManager(bool loadYuvPlanes = false);
/**
* Destructor.
Dali::Vector<TextureManager::TextureId> mRemoveQueue; ///< Queue of textures to remove at PostProcess. It will be cleared after PostProcess.
- bool mLoadYuvPlanes; ///< A global flag to specify if the image should be loaded as yuv planes
- bool mRemoveProcessorRegistered; ///< Flag if remove processor registered or not.
+ const bool mLoadYuvPlanes; ///< A global flag to specify if the image should be loaded as yuv planes
+ bool mRemoveProcessorRegistered; ///< Flag if remove processor registered or not.
};
} // namespace Internal
/*
- * 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.
BORDERLINE = 1 << 1,
ALPHA_MASKING = 1 << 2,
COLOR_CONVERSION = 1 << 3,
+
+ UNIFIED_YUV_AND_RGB = 1 << 2, // Special enum to trick unified YUV and RGB.
};
-static constexpr auto SHADER_TYPE_COUNT = 12u;
+static constexpr auto SHADER_TYPE_COUNT = 16u;
VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
{
VisualFactoryCache::IMAGE_SHADER,
VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
- VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB};
+ VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB,
+ VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+ VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+ VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
+ VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB};
} // unnamed namespace
namespace ImageVisualShaderFeature
return *this;
}
-FeatureBuilder& FeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb)
+FeatureBuilder& FeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb)
{
- mColorConversion = (enableYuvToRgb ? ColorConversion::YUV_TO_RGB : ColorConversion::DONT_NEED);
+ mColorConversion = (enableUnifiedYuvAndRgb ? ColorConversion::UNIFIED_YUV_AND_RGB : (enableYuvToRgb ? ColorConversion::YUV_TO_RGB : ColorConversion::DONT_NEED));
return *this;
}
} // namespace ImageVisualShaderFeature
{
shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
}
+ else if(colorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
+ {
+ shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
+ shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::UNIFIED_YUV_AND_RGB);
+ }
shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
}
{
fragmentShaderPrefixList += "#define IS_REQUIRED_YUV_TO_RGB\n";
}
+ else if(colorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
+ {
+ fragmentShaderPrefixList += "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n";
+ }
}
std::string vertexShader = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
/*
- * 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.
*/
enum Type
{
- DONT_NEED = 0, ///< Not need to convert
- YUV_TO_RGB ///< Need yuv to rgb conversion
+ DONT_NEED = 0, ///< Not need to convert
+ YUV_TO_RGB, ///< Need yuv to rgb conversion
+ UNIFIED_YUV_AND_RGB ///< Need to support both yuv conversion case and normal case.
};
} // namespace ColorConversion
FeatureBuilder& EnableBorderline(bool enableBorderline);
FeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
FeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
- FeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb);
+ FeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb = false);
TextureAtlas::Type mTextureAtlas : 2; ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED
DefaultTextureWrapMode::Type mDefaultTextureWrapMode : 2; ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY
EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
// Set new TextureSet with fast track loading task
- mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, MakeCallback(this, &ImageVisual::FastLoadComplete));
+ mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, mFactoryCache.GetLoadYuvPlanes(), MakeCallback(this, &ImageVisual::FastLoadComplete));
TextureSet textureSet = TextureSet::New();
- textureSet.SetTexture(0u, mFastTrackLoadingTask->mTexture);
+ if(!mFastTrackLoadingTask->mLoadPlanesAvaliable)
+ {
+ DALI_ASSERT_ALWAYS(mFastTrackLoadingTask->mTextures.size() >= 1u);
+ textureSet.SetTexture(0u, mFastTrackLoadingTask->mTextures[0]);
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS(mFastTrackLoadingTask->mTextures.size() >= 3u);
+ textureSet.SetTexture(0u, mFastTrackLoadingTask->mTextures[0]);
+ textureSet.SetTexture(1u, mFastTrackLoadingTask->mTextures[1]);
+ textureSet.SetTexture(2u, mFastTrackLoadingTask->mTextures[2]);
+
+ // We cannot determine what kind of shader will be used.
+ // Just use unified shader, and then change shader after load completed.
+ mNeedUnifiedYuvAndRgb = true;
+ UpdateShader();
+ }
mImpl->mRenderer.SetTextures(textureSet);
Dali::AsyncTaskManager::Get().AddTask(mFastTrackLoadingTask);
// Change premultiplied alpha flag after change renderer.
EnablePreMultipliedAlpha(mFastTrackLoadingTask->mPremultiplied);
+
+ if(mFastTrackLoadingTask->mLoadPlanesAvaliable)
+ {
+ if(mFastTrackLoadingTask->mPlanesLoaded)
+ {
+ // Let we use regular yuv cases.
+ mNeedYuvToRgb = true;
+ }
+ else
+ {
+ // Let we use regular image cases.
+ mNeedYuvToRgb = false;
+
+ auto textureSet = mImpl->mRenderer.GetTextures();
+ DALI_ASSERT_ALWAYS(textureSet && textureSet.GetTextureCount() > 0u && "Previous texture set must exist!");
+
+ Dali::TextureSet newTextureSet = TextureSet::New();
+ newTextureSet.SetTexture(0u, textureSet.GetTexture(0u));
+ mImpl->mRenderer.SetTextures(newTextureSet);
+ }
+
+ // We can specify what kind of shader we need to use now. Update shader.
+ mNeedUnifiedYuvAndRgb = false;
+ UpdateShader();
+ }
}
else
{
.EnableBorderline(IsBorderlineRequired())
.SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture())
.EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering)
- .EnableYuvToRgb(mNeedYuvToRgb));
+ .EnableYuvToRgb(mNeedYuvToRgb, mNeedUnifiedYuvAndRgb));
}
else
{
bool mAttemptAtlasing; ///< If true will attempt atlasing, otherwise create unique texture
bool mOrientationCorrection; ///< true if the image will have it's orientation corrected.
bool mNeedYuvToRgb{false}; ///< true if we need to convert yuv to rgb.
+ bool mNeedUnifiedYuvAndRgb{false}; ///< true if we need to support both yuv and rgb.
bool mEnableBrokenImage{true}; ///< true if enable broken image.
bool mUseFastTrackUploading{false}; ///< True if we use fast tack feature.
bool mRendererAdded{false}; ///< True if renderer added into actor.
/*
- * 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.
#include "visual-factory-cache.h"
// EXTERNAL INCLUDES
+#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/integration-api/debug.h>
namespace
{
const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+
+constexpr auto LOAD_IMAGE_YUV_PLANES_ENV = "DALI_LOAD_IMAGE_YUV_PLANES";
+
+bool NeedToLoadYuvPlanes()
+{
+ auto loadYuvPlanesString = Dali::EnvironmentVariable::GetEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV);
+ bool loadYuvPlanes = loadYuvPlanesString ? std::atoi(loadYuvPlanesString) : false;
+ return loadYuvPlanes;
}
+} // namespace
VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
-: mVectorAnimationManager(nullptr),
+: mLoadYuvPlanes(NeedToLoadYuvPlanes()),
+ mTextureManager(mLoadYuvPlanes),
+ mVectorAnimationManager(nullptr),
mPreMultiplyOnLoad(preMultiplyOnLoad),
mBrokenImageInfoContainer(),
mDefaultBrokenImageUrl(""),
mPreMultiplyOnLoad = preMultiply;
}
-bool VisualFactoryCache::GetPreMultiplyOnLoad()
+bool VisualFactoryCache::GetPreMultiplyOnLoad() const
{
return mPreMultiplyOnLoad;
}
+bool VisualFactoryCache::GetLoadYuvPlanes() const
+{
+ return mLoadYuvPlanes;
+}
+
void VisualFactoryCache::SetBrokenImageUrl(std::string& defaultBrokenUrl, const std::vector<std::string>& brokenImageUrlList)
{
mUseDefaultBrokenImageOnly = false;
#define DALI_TOOLKIT_VISUAL_FACTORY_CACHE_H
/*
- * 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.
IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB,
+ IMAGE_SHADER_YUV_AND_RGB,
+ IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+ IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
+ IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB,
NATIVE_IMAGE_SHADER,
NATIVE_IMAGE_SHADER_ROUNDED_CORNER,
NATIVE_IMAGE_SHADER_BORDERLINE,
/**
* @copydoc Toolkit::VisualFactory::GetPreMultiplyOnLoad()
*/
- bool GetPreMultiplyOnLoad();
+ bool GetPreMultiplyOnLoad() const;
/**
* @brief Set an image to be used when a visual has failed to correctly render
*/
void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size, const bool& rendererIsImage = true);
+ /**
+ * @brief Get whether we support YUV Planes load or not.
+ *
+ * @return True if we support to load YUV Planes. False otherwise.
+ */
+ bool GetLoadYuvPlanes() const;
+
public:
/**
* Get the image atlas manager.
Geometry mGeometry[GEOMETRY_TYPE_MAX + 1];
Shader mShader[SHADER_TYPE_MAX + 1];
+ bool mLoadYuvPlanes; ///< A global flag to specify if the image should be loaded as yuv planes
+
ImageAtlasManagerPtr mAtlasManager;
TextureManager mTextureManager;
NPatchLoader mNPatchLoader;