[Tizen] Support YUV decoding for JPEG 35/270335/6 accepted/tizen/6.5/unified/20220218.152712 submit/tizen_6.5/20220217.044919
authorHeeyong Song <heeyong.song@samsung.com>
Fri, 28 Jan 2022 04:46:20 +0000 (13:46 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Tue, 15 Feb 2022 01:43:42 +0000 (10:43 +0900)
Change-Id: Iea9312b49bc9e4d4d395dd53afde947c4e577d41

17 files changed:
dali-toolkit/devel-api/image-loader/async-image-loader-devel.cpp
dali-toolkit/devel-api/image-loader/async-image-loader-devel.h
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/image-loader/async-image-loader-impl.cpp
dali-toolkit/internal/image-loader/async-image-loader-impl.h
dali-toolkit/internal/image-loader/image-atlas-impl.cpp
dali-toolkit/internal/image-loader/image-load-thread.cpp
dali-toolkit/internal/image-loader/image-load-thread.h
dali-toolkit/internal/visuals/image-visual-shader-factory.cpp
dali-toolkit/internal/visuals/image-visual-shader-factory.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/internal/visuals/texture-manager-impl.h
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/public-api/controls/control.h
dali-toolkit/public-api/image-loader/async-image-loader.cpp

index df9499e..92757e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -38,7 +38,7 @@ uint32_t Load(AsyncImageLoader                         asyncImageLoader,
               bool                                     orientationCorrection,
               DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
-  return GetImplementation(asyncImageLoader).Load(Toolkit::Internal::VisualUrl(url), dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
+  return GetImplementation(asyncImageLoader).Load(Toolkit::Internal::VisualUrl(url), dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, false);
 }
 
 uint32_t ApplyMask(AsyncImageLoader                         asyncImageLoader,
index 9cf1589..ce91e09 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_IMAGE_LOADER_ASYNC_IMAGE_LOADER_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -31,7 +31,7 @@ namespace Toolkit
 {
 namespace DevelAsyncImageLoader
 {
-typedef Signal<void(uint32_t, Devel::PixelBuffer)> PixelBufferLoadedSignalType;
+typedef Signal<void(uint32_t, std::vector<Devel::PixelBuffer>&)> PixelBufferLoadedSignalType;
 
 /**
  * @brief Whether to multiply alpha into color channels on load
index c2324e7..edbdba9 100644 (file)
@@ -13,6 +13,9 @@
 #ifndef ATLAS_CUSTOM_WARP
 #define ATLAS_CUSTOM_WARP 0
 #endif
+#ifndef IS_REQUIRED_YUV_TO_RGB
+#define IS_REQUIRED_YUV_TO_RGB 0
+#endif
 
 INPUT mediump vec2 vTexCoord;
 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
@@ -25,6 +28,10 @@ INPUT mediump vec4 vCornerRadius;
 #endif
 
 uniform sampler2D sTexture;
+#if IS_REQUIRED_YUV_TO_RGB
+uniform sampler2D sTextureU;
+uniform sampler2D sTextureV;
+#endif
 
 #if IS_REQUIRED_ALPHA_MASKING
 uniform sampler2D sMaskTexture;
@@ -224,6 +231,20 @@ mediump float calculateCornerOpacity()
 }
 #endif
 
+#if IS_REQUIRED_YUV_TO_RGB
+lowp vec3 ConvertYuvToRgb(mediump vec2 texCoord)
+{
+  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;
+}
+#endif
+
 void main()
 {
 #if ATLAS_DEFAULT_WARP
@@ -235,7 +256,11 @@ void main()
   mediump vec2 texCoord = vTexCoord;
 #endif
 
+#if IS_REQUIRED_YUV_TO_RGB
+  lowp vec4 textureColor = vec4(ConvertYuvToRgb(texCoord), 1.0) * vec4( mixColor, 1.0 ) * uColor;
+#else
   lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
+#endif
 
 #if IS_REQUIRED_ALPHA_MASKING
   mediump float maskAlpha = TEXTURE(sMaskTexture, vMaskTexCoord).a;
index 64639b5..b084fa8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -64,14 +64,15 @@ uint32_t AsyncImageLoader::Load(const VisualUrl&                         url,
                                 FittingMode::Type                        fittingMode,
                                 SamplingMode::Type                       samplingMode,
                                 bool                                     orientationCorrection,
-                                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+                                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+                                bool                                     loadYuvPlanes)
 {
   if(!mIsLoadThreadStarted)
   {
     mLoadThread.Start();
     mIsLoadThreadStarted = true;
   }
-  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad));
+  mLoadThread.AddTask(new LoadingTask(++mLoadTaskId, url, dimensions, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadYuvPlanes));
 
   return mLoadTaskId;
 }
@@ -135,7 +136,7 @@ void AsyncImageLoader::ProcessLoadedImage()
   {
     if(mPixelBufferLoadedSignal.GetConnectionCount() > 0)
     {
-      mPixelBufferLoadedSignal.Emit(next->id, next->pixelBuffer);
+      mPixelBufferLoadedSignal.Emit(next->id, next->pixelBuffers);
     }
     else if(mLoadedSignal.GetConnectionCount() > 0)
     {
index 39e4690..1b45bf1 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -59,7 +59,8 @@ public:
                 FittingMode::Type                        fittingMode,
                 SamplingMode::Type                       samplingMode,
                 bool                                     orientationCorrection,
-                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+                bool                                     loadYuvPlanes);
 
   /**
    * @brief Starts an image loading task by encoded image buffer.
index 31c3351..5a04a0f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -162,7 +162,7 @@ bool ImageAtlas::Upload(Vector4&             textureRect,
   unsigned int packPositionY = 0;
   if(mPacker.Pack(dimensions.GetWidth(), dimensions.GetHeight(), packPositionX, packPositionY))
   {
-    unsigned short loadId = GetImplementation(mAsyncLoader).Load(url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+    unsigned short loadId = GetImplementation(mAsyncLoader).Load(url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, false);
     mLoadingTaskInfoContainer.PushBack(new LoadingTaskInfo(loadId, packPositionX, packPositionY, dimensions.GetWidth(), dimensions.GetHeight(), atlasUploadObserver));
     // apply the half pixel correction
     textureRect.x = (static_cast<float>(packPositionX) + 0.5f) / mWidth;                      // left
index 3c4ee19..6d795a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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 "image-load-thread.h"
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <dali/devel-api/adaptor-framework/thread-settings.h>
 #include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 
 namespace Dali
 {
@@ -50,7 +50,7 @@ LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLo
 {
 }
 
-LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadYuvPlanes)
 : pixelBuffer(),
   url(url),
   encodedImageBuffer(),
@@ -65,7 +65,8 @@ LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dime
   contentScale(1.0f),
   cropToMask(false),
   animatedImageLoading(),
-  frameIndex(0u)
+  frameIndex(0u),
+  loadYuvPlanes(loadYuvPlanes)
 {
 }
 
@@ -119,7 +120,18 @@ void LoadingTask::Load()
   }
   else if(url.IsValid() && url.IsLocalResource())
   {
-    pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
+    if(!loadYuvPlanes)
+    {
+      pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
+    }
+    else
+    {
+      Dali::LoadImagePlanesFromFile(url.GetUrl(), pixelBuffers, dimensions, fittingMode, samplingMode, orientationCorrection);
+      if(!pixelBuffers.empty())
+      {
+        pixelBuffer = pixelBuffers.front();
+      }
+    }
   }
   else if(url.IsValid())
   {
@@ -284,6 +296,11 @@ void ImageLoadThread::AddCompletedTask(LoadingTask* task)
   Mutex::ScopedLock lock(mMutex);
   mCompleteQueue.PushBack(task);
 
+  if(task->pixelBuffers.empty() && task->pixelBuffer)
+  {
+    task->pixelBuffers.push_back(task->pixelBuffer);
+  }
+
   // wake up the main thread
   mTrigger->Trigger();
 }
index 95ec260..b575539 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_IMAGE_LOAD_THREAD_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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/threading/mutex.h>
 #include <dali/devel-api/threading/thread.h>
 #include <dali/integration-api/adaptor-framework/log-factory-interface.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/images/image-operations.h>
 #include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
 
 namespace Dali
 {
@@ -68,7 +68,8 @@ struct LoadingTask
               FittingMode::Type                        fittingMode,
               SamplingMode::Type                       samplingMode,
               bool                                     orientationCorrection,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+              bool                                     loadYuvPlanes);
 
   /**
    * Constructor.
@@ -144,6 +145,9 @@ public:
   bool                       cropToMask;      ///< Whether to crop the content to the mask size
   Dali::AnimatedImageLoading animatedImageLoading;
   uint32_t                   frameIndex;
+  bool                       loadYuvPlanes{false};
+
+  std::vector<Devel::PixelBuffer> pixelBuffers{};
 };
 
 /**
index 8e7e304..fcbd744 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -46,24 +46,23 @@ const int NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMA
 // enum of required list when we select shader
 enum class ImageVisualRequireFlag : uint32_t
 {
-  DEFAULT         = 0,
-  ROUNDED_CORNER  = 1 << 0,
-  BORDERLINE      = 1 << 1,
-  ALPHA_MASKING = 1 << 2,
+  DEFAULT        = 0,
+  ROUNDED_CORNER = 1 << 0,
+  BORDERLINE     = 1 << 1,
+  ALPHA_MASKING  = 1 << 2,
 };
 
-static constexpr auto SHADER_TYPE_COUNT = 8u;
+static constexpr auto          SHADER_TYPE_COUNT = 8u;
 VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
-{
-  VisualFactoryCache::IMAGE_SHADER,
-  VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
-  VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
-  VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
-  VisualFactoryCache::IMAGE_SHADER_MASKING,
-  VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
-  VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
-  VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING
-};
+  {
+    VisualFactoryCache::IMAGE_SHADER,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+    VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
+    VisualFactoryCache::IMAGE_SHADER_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING};
 
 } // unnamed namespace
 
@@ -74,31 +73,42 @@ FeatureBuilder& FeatureBuilder::EnableTextureAtlas(bool enableAtlas)
   mTextureAtlas = (enableAtlas ? TextureAtlas::ENABLED : TextureAtlas::DISABLED);
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode)
 {
   mDefaultTextureWrapMode = (applyDefaultTextureWrapMode ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY);
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::EnableRoundedCorner(bool enableRoundedCorner)
 {
   mRoundedCorner = (enableRoundedCorner ? RoundedCorner::ENABLED : RoundedCorner::DISABLED);
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::EnableBorderline(bool enableBorderline)
 {
   mBorderline = (enableBorderline ? Borderline::ENABLED : Borderline::DISABLED);
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
 {
   mTexture = texture;
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::EnableAlphaMasking(bool enableAlphaMasking)
 {
   mAlphaMasking = (enableAlphaMasking ? AlphaMasking::ENABLED : AlphaMasking::DISABLED);
   return *this;
 }
+
+FeatureBuilder& FeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb)
+{
+  mColorConversion = (enableYuvToRgb ? ColorConversion::YUV_TO_RGB : ColorConversion::DONT_NEED);
+  return *this;
+}
 } // namespace ImageVisualShaderFeature
 
 ImageVisualShaderFactory::ImageVisualShaderFactory()
@@ -112,7 +122,7 @@ ImageVisualShaderFactory::~ImageVisualShaderFactory()
 
 Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const ImageVisualShaderFeature::FeatureBuilder& featureBuilder)
 {
-  Shader shader;
+  Shader                         shader;
   VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER;
 
   const auto& atlasing               = featureBuilder.mTextureAtlas;
@@ -120,6 +130,7 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
   const auto& roundedCorner          = featureBuilder.mRoundedCorner;
   const auto& borderline             = featureBuilder.mBorderline;
   const auto& alphaMasking           = featureBuilder.mAlphaMasking;
+  const auto& colorConversion        = featureBuilder.mColorConversion;
   const auto& changeFragmentShader   = (featureBuilder.mTexture && DevelTexture::IsNative(featureBuilder.mTexture))
                                          ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
                                          : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
@@ -160,42 +171,56 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
     shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) + NATIVE_SHADER_TYPE_OFFSET);
   }
 
+  if(colorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB)
+  {
+    shaderType = VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB;
+  }
+
   shader = factoryCache.GetShader(shaderType);
   if(!shader)
   {
     std::string vertexShaderPrefixList;
     std::string fragmentShaderPrefixList;
-    if(atlasing == ImageVisualShaderFeature::TextureAtlas::ENABLED)
+
+    // We don't support other properties in case of yuv format for now.
+    if(colorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB)
     {
-      if(defaultTextureWrapping == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
-      {
-        fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP 1\n";
-      }
-      else
-      {
-        fragmentShaderPrefixList += "#define ATLAS_CUSTOM_WARP 1\n";
-      }
+      fragmentShaderPrefixList += "#define IS_REQUIRED_YUV_TO_RGB 1\n";
     }
     else
     {
-      if(roundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
-      {
-        vertexShaderPrefixList   += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
-        fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
-      }
-      if(borderline == ImageVisualShaderFeature::Borderline::ENABLED)
+      if(atlasing == ImageVisualShaderFeature::TextureAtlas::ENABLED)
       {
-        vertexShaderPrefixList   += "#define IS_REQUIRED_BORDERLINE 1\n";
-        fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+        if(defaultTextureWrapping == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
+        {
+          fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP 1\n";
+        }
+        else
+        {
+          fragmentShaderPrefixList += "#define ATLAS_CUSTOM_WARP 1\n";
+        }
       }
-      if(alphaMasking == ImageVisualShaderFeature::AlphaMasking::ENABLED)
+      else
       {
-        vertexShaderPrefixList   += "#define IS_REQUIRED_ALPHA_MASKING 1\n";
-        fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING 1\n";
+        if(roundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+        {
+          vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+          fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+        }
+        if(borderline == ImageVisualShaderFeature::Borderline::ENABLED)
+        {
+          vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+          fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+        }
+        if(alphaMasking == ImageVisualShaderFeature::AlphaMasking::ENABLED)
+        {
+          vertexShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING 1\n";
+          fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING 1\n";
+        }
       }
     }
 
-    std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix()   + vertexShaderPrefixList   + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
+    std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
     std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
 
     if(changeFragmentShader == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
index 1e1974d..20ae85e 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -107,6 +107,18 @@ enum Type
 };
 } // namespace AlphaMasking
 
+namespace ColorConversion
+{
+/**
+ * @brief Whether the color format conversion is needed or not
+ */
+enum Type
+{
+  DONT_NEED = 0, ///< Not need to convert
+  YUV_TO_RGB     ///< Need yuv to rgb conversion
+};
+} // namespace ColorConversion
+
 /**
  * @brief Collection of current image visual feature. Only use for ImageVisualShaderFactory::GetShader()
  */
@@ -118,6 +130,7 @@ struct FeatureBuilder
     mRoundedCorner(RoundedCorner::DISABLED),
     mBorderline(Borderline::DISABLED),
     mAlphaMasking(AlphaMasking::DISABLED),
+    mColorConversion(ColorConversion::DONT_NEED),
     mTexture()
   {
   }
@@ -128,12 +141,14 @@ struct FeatureBuilder
   FeatureBuilder& EnableBorderline(bool enableBorderline);
   FeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
   FeatureBuilder& EnableAlphaMasking(bool enableAlphaMasking);
+  FeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb);
 
   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
   RoundedCorner::Type          mRoundedCorner : 2;          ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
   Borderline::Type             mBorderline : 2;             ///< Whether use borderline, or not. default as Borderline::DISABLED
   AlphaMasking::Type           mAlphaMasking : 2;           ///< Whether use runtime alpha masking, or not. default as AlphaMasking::DISABLED
+  ColorConversion::Type        mColorConversion : 2;        ///< Whether the color format conversion is needed or not
   Dali::Texture                mTexture;                    ///< Texture to check whether we need to change fragment shader or not
 };
 
index 650c508..406b85d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -477,7 +477,7 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
     }
 
     auto textureSet = mImpl->mRenderer.GetTextures();
-    if(textureSet)
+    if(textureSet && textureSet.GetTextureCount())
     {
       auto texture = textureSet.GetTexture(0);
       if(texture)
@@ -513,7 +513,7 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
       }
       else
       {
-        Actor actor = mPlacementActor.GetHandle();
+        Actor   actor     = mPlacementActor.GetHandle();
         Vector2 imageSize = Vector2::ZERO;
         if(actor)
         {
@@ -521,8 +521,8 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
         }
         mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
         Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
-        naturalSize.x = brokenImage.GetWidth();
-        naturalSize.y = brokenImage.GetWidth();
+        naturalSize.x       = brokenImage.GetWidth();
+        naturalSize.y       = brokenImage.GetWidth();
       }
       return;
     }
@@ -658,10 +658,19 @@ void ImageVisual::InitializeRenderer()
   if(mTextures)
   {
     mImpl->mRenderer.SetTextures(mTextures);
-    if(DevelTexture::IsNative(mTextures.GetTexture(0)))
+
+    bool needToUpdateShader = DevelTexture::IsNative(mTextures.GetTexture(0));
+    if(mTextures.GetTextureCount() > 1)
+    {
+      mNeedYuvToRgb      = true;
+      needToUpdateShader = true;
+    }
+
+    if(needToUpdateShader)
     {
       UpdateShader();
     }
+
     mTextures.Reset(); // Visual should not keep a handle to the texture after this point.
   }
 
@@ -882,6 +891,13 @@ void ImageVisual::UploadComplete(bool loadingSuccess, int32_t textureId, Texture
       sampler.SetWrapMode(mWrapModeU, mWrapModeV);
       textureSet.SetSampler(0u, sampler);
       mImpl->mRenderer.SetTextures(textureSet);
+
+      if(textureSet.GetTextureCount() > 1)
+      {
+        mNeedYuvToRgb = true;
+
+        UpdateShader();
+      }
     }
 
     if(actor)
@@ -974,9 +990,9 @@ Shader ImageVisual::GenerateShader() const
 {
   Shader shader;
 
-  bool             usesWholeTexture  = true;
-  const bool       useStandardShader = !mImpl->mCustomShader;
-  const bool       useNativeImage    = (mTextures && DevelTexture::IsNative(mTextures.GetTexture(0)));
+  bool       usesWholeTexture  = true;
+  const bool useStandardShader = !mImpl->mCustomShader;
+  const bool useNativeImage    = (mTextures && DevelTexture::IsNative(mTextures.GetTexture(0)));
 
   if(useStandardShader)
   {
@@ -984,12 +1000,12 @@ Shader ImageVisual::GenerateShader() const
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
       ImageVisualShaderFeature::FeatureBuilder()
-      .EnableTextureAtlas(mImpl->mFlags & Impl::IS_ATLASING_APPLIED && !useNativeImage)
-      .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE)
-      .EnableRoundedCorner(IsRoundedCornerRequired())
-      .EnableBorderline(IsBorderlineRequired())
-      .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture())
-    );
+        .EnableTextureAtlas(mImpl->mFlags & Impl::IS_ATLASING_APPLIED && !useNativeImage)
+        .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE)
+        .EnableRoundedCorner(IsRoundedCornerRequired())
+        .EnableBorderline(IsBorderlineRequired())
+        .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture())
+        .EnableYuvToRgb(mNeedYuvToRgb));
   }
   else
   {
index c0a3f75..1c61a3a 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_IMAGE_VISUAL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -343,6 +343,7 @@ private:
   TextureManager::LoadState                       mLoadState;             ///< The texture loading state
   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.
 };
 
 } // namespace Internal
index 5286717..7334cf7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -38,9 +38,9 @@
 
 namespace
 {
-constexpr auto INITIAL_CACHE_NUMBER                     = size_t{0u};
-constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS   = size_t{4u};
-constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS  = size_t{8u};
+constexpr auto INITIAL_CACHE_NUMBER                    = size_t{0u};
+constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS  = size_t{4u};
+constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u};
 
 constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV  = "DALI_TEXTURE_LOCAL_THREADS";
 constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS";
@@ -234,7 +234,8 @@ TextureSet TextureManager::LoadAnimatedImageTexture(Dali::AnimatedImageLoading a
                                     preMultiply,
                                     animatedImageLoading,
                                     frameIndex,
-                                    useCache);
+                                    useCache,
+                                    false);
 
     TextureManager::LoadState loadState = GetTextureStateInternal(textureId);
     if(loadState == TextureManager::LoadState::UPLOADED)
@@ -291,7 +292,7 @@ Devel::PixelBuffer TextureManager::LoadPixelBuffer(
   }
   else
   {
-    RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, false, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, StorageType::RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, false);
+    RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, false, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, StorageType::RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, false, false);
   }
 
   return pixelBuffer;
@@ -470,7 +471,7 @@ TextureManager::TextureId TextureManager::RequestLoad(
   TextureManager::ReloadPolicy    reloadPolicy,
   TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
 {
-  return RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, false, desiredSize, fittingMode, samplingMode, useAtlas, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, true);
+  return RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, false, desiredSize, fittingMode, samplingMode, useAtlas, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, true, true);
 }
 
 TextureManager::TextureId TextureManager::RequestLoad(
@@ -487,14 +488,15 @@ TextureManager::TextureId TextureManager::RequestLoad(
   TextureManager::ReloadPolicy    reloadPolicy,
   TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
 {
-  return RequestLoadInternal(url, maskTextureId, contentScale, cropToMask, desiredSize, fittingMode, samplingMode, useAtlas, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, true);
+  bool loadYuvPlanes = (maskTextureId == INVALID_TEXTURE_ID) ? true : false;
+  return RequestLoadInternal(url, maskTextureId, contentScale, cropToMask, desiredSize, fittingMode, samplingMode, useAtlas, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, true, loadYuvPlanes);
 }
 
 TextureManager::TextureId TextureManager::RequestMaskLoad(const VisualUrl& maskUrl, StorageType storageType)
 {
   // 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, false, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, storageType, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, true);
+  return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, false, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, storageType, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, true, false);
 }
 
 TextureManager::TextureId TextureManager::RequestLoadInternal(
@@ -513,7 +515,8 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
   TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
   Dali::AnimatedImageLoading      animatedImageLoading,
   uint32_t                        frameIndex,
-  bool                            useCache)
+  bool                            useCache,
+  bool                            loadYuvPlanes)
 {
   // First check if the requested Texture is cached.
   TextureHash textureHash = INITIAL_CACHE_NUMBER;
@@ -523,8 +526,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     textureHash = GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId);
 
     // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
-    cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
-                                   storageType, maskTextureId, preMultiplyOnLoad, (animatedImageLoading) ? true : false);
+    cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, storageType, maskTextureId, preMultiplyOnLoad, (animatedImageLoading) ? true : false);
   }
 
   TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
@@ -564,7 +566,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
         // Insert this buffer at mTextureInfoContainer.
         // This buffer will decode at ImageLoaderThread.
         bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
-        mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+        mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex, false));
         cacheIndex = mTextureInfoContainer.size() - 1u;
 
         DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New buffered texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
@@ -577,7 +579,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     // We need a new Texture.
     textureId        = GenerateUniqueTextureId();
     bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
-    mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+    mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex, loadYuvPlanes));
     cacheIndex = mTextureInfoContainer.size() - 1u;
 
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
@@ -846,7 +848,8 @@ std::string TextureManager::AddExternalEncodedImageBuffer(const EncodedImageBuff
     {
       // If same buffer added, increase reference count and return.
       elem.referenceCount++;
-      return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));;
+      return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));
+      ;
     }
   }
   TextureManager::EncodedBufferTextureInfo info(GenerateUniqueTextureId(), encodedImageBuffer);
@@ -894,7 +897,7 @@ EncodedImageBuffer TextureManager::RemoveExternalEncodedImageBuffer(const std::s
       std::string location = VisualUrl::GetLocation(url);
       if(location.size() > 0u)
       {
-        TextureId id = std::stoi(location);
+        TextureId  id  = std::stoi(location);
         const auto end = mEncodedBufferTextures.end();
         for(auto iter = mEncodedBufferTextures.begin(); iter != end; ++iter)
         {
@@ -1048,7 +1051,7 @@ void TextureManager::LoadTexture(TextureInfo& textureInfo, TextureUploadObserver
     }
     else
     {
-      loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad);
+      loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad, textureInfo.loadYuvPlanes);
     }
   }
   ObserveTexture(textureInfo, observer);
@@ -1103,7 +1106,7 @@ void TextureManager::ObserveTexture(TextureInfo&           textureInfo,
   }
 }
 
-void TextureManager::AsyncLoadComplete(AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, Devel::PixelBuffer pixelBuffer)
+void TextureManager::AsyncLoadComplete(AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( id:%d )\n", id);
 
@@ -1123,7 +1126,7 @@ void TextureManager::AsyncLoadComplete(AsyncLoadingInfoContainerType& loadingCon
         if(textureInfo.loadState != LoadState::CANCELLED)
         {
           // textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified)
-          PostLoad(textureInfo, pixelBuffer);
+          PostLoad(textureInfo, pixelBuffers);
         }
         else
         {
@@ -1136,92 +1139,111 @@ void TextureManager::AsyncLoadComplete(AsyncLoadingInfoContainerType& loadingCon
   }
 }
 
-void TextureManager::PostLoad(TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer)
+void TextureManager::PostLoad(TextureInfo& textureInfo, std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
   // Was the load successful?
-  if(pixelBuffer && (pixelBuffer.GetWidth() != 0) && (pixelBuffer.GetHeight() != 0))
+  //  if(pixelBuffer && (pixelBuffer.GetWidth() != 0) && (pixelBuffer.GetHeight() != 0))
+  if(!pixelBuffers.empty())
   {
-    // No atlas support for now
-    textureInfo.useAtlas      = NO_ATLAS;
-    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
-
-    if(textureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE)
+    if(pixelBuffers.size() == 1)
     {
-      // If there is a mask texture ID associated with this texture, then apply the mask
-      // if it's already loaded. If it hasn't, and the mask is still loading,
-      // wait for the mask to finish loading.
-      if(textureInfo.maskTextureId != INVALID_TEXTURE_ID)
+      Devel::PixelBuffer pixelBuffer = pixelBuffers[0];
+
+      // No atlas support for now
+      textureInfo.useAtlas      = NO_ATLAS;
+      textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
+
+      if(textureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE)
       {
-        if(textureInfo.loadState == LoadState::MASK_APPLYING)
+        // If there is a mask texture ID associated with this texture, then apply the mask
+        // if it's already loaded. If it hasn't, and the mask is still loading,
+        // wait for the mask to finish loading.
+        if(textureInfo.maskTextureId != INVALID_TEXTURE_ID)
         {
-          textureInfo.loadState = LoadState::MASK_APPLIED;
-          UploadTexture(pixelBuffer, textureInfo);
-          NotifyObservers(textureInfo, true);
-        }
-        else
-        {
-          LoadState maskLoadState = GetTextureStateInternal(textureInfo.maskTextureId);
-          textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
-          if(maskLoadState == LoadState::LOADING)
+          if(textureInfo.loadState == LoadState::MASK_APPLYING)
           {
-            textureInfo.loadState = LoadState::WAITING_FOR_MASK;
+            textureInfo.loadState = LoadState::MASK_APPLIED;
+            UploadTexture(pixelBuffer, textureInfo);
+            NotifyObservers(textureInfo, true);
           }
-          else if(maskLoadState == LoadState::LOAD_FINISHED)
+          else
           {
-            int32_t maskCacheIndex = GetCacheIndexFromId(textureInfo.maskTextureId);
-            if(maskCacheIndex != INVALID_CACHE_INDEX)
+            LoadState maskLoadState = GetTextureStateInternal(textureInfo.maskTextureId);
+            textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
+            if(maskLoadState == LoadState::LOADING)
             {
-              TextureInfo& maskTextureInfo(mTextureInfoContainer[maskCacheIndex]);
-              if(maskTextureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER)
+              textureInfo.loadState = LoadState::WAITING_FOR_MASK;
+            }
+            else if(maskLoadState == LoadState::LOAD_FINISHED)
+            {
+              int32_t maskCacheIndex = GetCacheIndexFromId(textureInfo.maskTextureId);
+              if(maskCacheIndex != INVALID_CACHE_INDEX)
               {
-                // Send New Task to Thread
-                ApplyMask(textureInfo, textureInfo.maskTextureId);
+                TextureInfo& maskTextureInfo(mTextureInfoContainer[maskCacheIndex]);
+                if(maskTextureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER)
+                {
+                  // Send New Task to Thread
+                  ApplyMask(textureInfo, textureInfo.maskTextureId);
+                }
               }
             }
-          }
-          else if(maskLoadState == LoadState::UPLOADED)
-          {
-            int32_t maskCacheIndex = GetCacheIndexFromId(textureInfo.maskTextureId);
-            if(maskCacheIndex != INVALID_CACHE_INDEX)
+            else if(maskLoadState == LoadState::UPLOADED)
             {
-              TextureInfo& maskTextureInfo(mTextureInfoContainer[maskCacheIndex]);
-              if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
+              int32_t maskCacheIndex = GetCacheIndexFromId(textureInfo.maskTextureId);
+              if(maskCacheIndex != INVALID_CACHE_INDEX)
               {
-                // Upload image texture. textureInfo.loadState will be UPLOADED.
-                UploadTexture(textureInfo.pixelBuffer, textureInfo);
-                if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
+                TextureInfo& maskTextureInfo(mTextureInfoContainer[maskCacheIndex]);
+                if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
                 {
-                  Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
-                  textureInfo.textureSet.SetTexture(1u, maskTexture);
+                  // Upload image texture. textureInfo.loadState will be UPLOADED.
+                  UploadTexture(textureInfo.pixelBuffer, textureInfo);
+                  if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
+                  {
+                    Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
+                    textureInfo.textureSet.SetTexture(1u, maskTexture);
+                  }
+                  // notify mask texture set.
+                  NotifyObservers(textureInfo, true);
                 }
-                // notify mask texture set.
-                NotifyObservers(textureInfo, true);
               }
             }
           }
         }
+        else
+        {
+          UploadTexture(pixelBuffer, textureInfo);
+          NotifyObservers(textureInfo, true);
+        }
       }
       else
       {
-        UploadTexture(pixelBuffer, textureInfo);
-        NotifyObservers(textureInfo, true);
+        textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
+        textureInfo.loadState   = LoadState::LOAD_FINISHED;
+
+        if(textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+        {
+          NotifyObservers(textureInfo, true);
+        }
+        else // for the StorageType::KEEP_PIXEL_BUFFER and StorageType::KEEP_TEXTURE
+        {
+          // 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
     {
-      textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
-      textureInfo.loadState   = LoadState::LOAD_FINISHED;
+      // YUV case
+      // No atlas support for now
+      textureInfo.useAtlas      = NO_ATLAS;
+      textureInfo.preMultiplied = false;
 
-      if(textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+      if(textureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE)
       {
+        UploadTextures(pixelBuffers, textureInfo);
         NotifyObservers(textureInfo, true);
       }
-      else  // for the StorageType::KEEP_PIXEL_BUFFER and StorageType::KEEP_TEXTURE
-      {
-        // 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
@@ -1259,7 +1281,7 @@ void TextureManager::CheckForWaitingTexture(TextureInfo& maskTextureInfo)
           ApplyMask(textureInfo, maskTextureInfo.textureId);
         }
       }
-      else if (maskTextureInfo.loadState == LoadState::UPLOADED)
+      else if(maskTextureInfo.loadState == LoadState::UPLOADED)
       {
         if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
         {
@@ -1338,6 +1360,46 @@ void TextureManager::UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo&
   textureInfo.loadState = LoadState::UPLOADED;
 }
 
+void TextureManager::UploadTextures(std::vector<Devel::PixelBuffer>& pixelBuffers, TextureInfo& textureInfo)
+{
+  if(textureInfo.loadState != LoadState::UPLOADED && textureInfo.useAtlas != USE_ATLAS)
+  {
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::UploadTextures() New Texture for textureId:%d\n", textureInfo.textureId);
+
+    // Not premultiplied
+    textureInfo.preMultiplied = false;
+
+    auto& renderingAddOn = RenderingAddOn::Get();
+    if(renderingAddOn.IsValid())
+    {
+      renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffers[0]);
+    }
+
+    if(!textureInfo.textureSet)
+    {
+      textureInfo.textureSet = TextureSet::New();
+    }
+
+    uint32_t index = 0;
+    for(auto&& iter : pixelBuffers)
+    {
+      Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, iter.GetPixelFormat(), iter.GetWidth(), iter.GetHeight());
+
+      PixelData pixelData = Devel::PixelBuffer::Convert(iter);
+      texture.Upload(pixelData);
+      textureInfo.textureSet.SetTexture(index++, texture);
+    }
+
+    pixelBuffers.clear();
+  }
+
+  // Update the load state.
+  // Note: This is regardless of success as we care about whether a
+  // load attempt is in progress or not.  If unsuccessful, a broken
+  // image is still loaded.
+  textureInfo.loadState = LoadState::UPLOADED;
+}
+
 void TextureManager::NotifyObservers(TextureInfo& textureInfo, bool success)
 {
   TextureId textureId = textureInfo.textureId;
@@ -1348,7 +1410,7 @@ void TextureManager::NotifyObservers(TextureInfo& textureInfo, bool success)
 
   if(info->animatedImageLoading)
   {
-    info->frameCount = info->animatedImageLoading.GetImageCount();
+    info->frameCount    = info->animatedImageLoading.GetImageCount();
     info->frameInterval = info->animatedImageLoading.GetFrameInterval(info->frameIndex);
     info->animatedImageLoading.Reset();
   }
@@ -1594,7 +1656,8 @@ void TextureManager::AsyncLoadingHelper::Load(TextureId
                                               FittingMode::Type                        fittingMode,
                                               SamplingMode::Type                       samplingMode,
                                               bool                                     orientationCorrection,
-                                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+                                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+                                              bool                                     loadYuvPlanes)
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
   if(DALI_UNLIKELY(url.IsBufferResource()))
@@ -1604,7 +1667,7 @@ void TextureManager::AsyncLoadingHelper::Load(TextureId
   }
   else
   {
-    auto id                             = GetImplementation(mLoader).Load(url, desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
+    auto id                             = GetImplementation(mLoader).Load(url, desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad, loadYuvPlanes);
     mLoadingInfoContainer.back().loadId = id;
   }
 }
@@ -1638,10 +1701,10 @@ TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(
     this, &AsyncLoadingHelper::AsyncLoadComplete);
 }
 
-void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t           id,
-                                                           Devel::PixelBuffer pixelBuffer)
+void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t                         id,
+                                                           std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
-  mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer);
+  mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffers);
 }
 
 Geometry TextureManager::GetRenderGeometry(TextureId textureId, uint32_t& frontElements, uint32_t& backElements)
index 4098dd8..40e4bbd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -58,7 +58,7 @@ typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
 class TextureManager : public ConnectionTracker
 {
 public:
-  typedef int32_t  TextureId;               ///< The TextureId type. This is used as a handle to refer to a particular Texture.
+  typedef int32_t          TextureId;               ///< The TextureId type. This is used as a handle to refer to a particular Texture.
   static constexpr int32_t INVALID_TEXTURE_ID = -1; ///< Used to represent a null TextureId or error
 
   /**
@@ -520,7 +520,8 @@ private:
     MultiplyOnLoad&              preMultiplyOnLoad,
     Dali::AnimatedImageLoading   animatedImageLoading,
     uint32_t                     frameIndex,
-    bool                         useCache);
+    bool                         useCache,
+    bool                         loadYuvPlanes);
 
   /**
    * @brief Get the current state of a texture
@@ -553,7 +554,8 @@ private:
                 bool                        orientationCorrection,
                 bool                        preMultiplyOnLoad,
                 Dali::AnimatedImageLoading  animatedImageLoading,
-                uint32_t                    frameIndex)
+                uint32_t                    frameIndex,
+                bool                        loadYuvPlanes)
     : url(url),
       desiredSize(desiredSize),
       useSize(desiredSize),
@@ -576,7 +578,8 @@ private:
       cropToMask(cropToMask),
       orientationCorrection(true),
       preMultiplyOnLoad(preMultiplyOnLoad),
-      preMultiplied(false)
+      preMultiplied(false),
+      loadYuvPlanes(loadYuvPlanes)
     {
       isAnimatedImageFormat = (animatedImageLoading) ? true : false;
     }
@@ -615,6 +618,7 @@ private:
     bool preMultiplyOnLoad : 1;                        ///< true if the image's color should be multiplied by it's alpha
     bool preMultiplied : 1;                            ///< true if the image's color was multiplied by it's alpha
     bool isAnimatedImageFormat : 1;                    ///< true if the image is requested from animated image visual.
+    bool loadYuvPlanes : 1;                            ///< true if the image should be loaded as yuv planes
   };
 
   /**
@@ -706,7 +710,7 @@ private:
    * @param[in] id        This is the async image loaders Id
    * @param[in] pixelBuffer The loaded image data
    */
-  void AsyncLoadComplete(AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer);
+  void AsyncLoadComplete(AsyncLoadingInfoContainerType& container, uint32_t id, std::vector<Devel::PixelBuffer>& pixelBuffer);
 
   /**
    * @brief Performs Post-Load steps including atlasing.
@@ -714,7 +718,7 @@ private:
    * @param[in] pixelBuffer The image pixelBuffer
    * @return    True if successful
    */
-  void PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer);
+  void PostLoad(TextureManager::TextureInfo& textureInfo, std::vector<Devel::PixelBuffer>& pixelBuffer);
 
   /**
    * Check if there is a texture waiting to be masked. If there
@@ -739,6 +743,14 @@ private:
   void UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo);
 
   /**
+   * Upload the texture specified in pixelBuffer to the appropriate location
+   * @param[in] pixelBuffer The image data to upload
+   * @param[in] textureInfo The texture info containing the location to
+   * store the data to.
+   */
+  void UploadTextures(std::vector<Devel::PixelBuffer>& pixelBuffers, TextureInfo& textureInfo);
+
+  /**
    * Creates tiled geometry of for the texture which separates fully-opaque
    * tiles from ones which use transparency.
    * @param pixelBuffer
@@ -856,7 +868,8 @@ private:
               FittingMode::Type                        fittingMode,
               SamplingMode::Type                       samplingMode,
               bool                                     orientationCorrection,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+              bool                                     loadYuvPlanes);
 
     /**
      * @brief Apply mask
@@ -894,7 +907,7 @@ private:
      * @param[in] id          Loader id
      * @param[in] pixelBuffer Image data
      */
-    void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
+    void AsyncLoadComplete(uint32_t id, std::vector<Devel::PixelBuffer>& pixelBuffers);
 
   private:
     Toolkit::AsyncImageLoader     mLoader;
index 3dbbb6f..ba008fd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_VISUAL_FACTORY_CACHE_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -90,6 +90,7 @@ public:
     IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
     IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
     IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
+    IMAGE_SHADER_YUV_TO_RGB,
     NATIVE_IMAGE_SHADER,
     NATIVE_IMAGE_SHADER_ROUNDED_CORNER,
     NATIVE_IMAGE_SHADER_BORDERLINE,
@@ -324,12 +325,12 @@ private:
   struct BrokenImageInfo
   {
     BrokenImageInfo()
-    :visualType(),
-     url(""),
-     npatchId(NPatchData::INVALID_NPATCH_DATA_ID),
-     texture(),
-     width(0),
-     height(0)
+    : visualType(),
+      url(""),
+      npatchId(NPatchData::INVALID_NPATCH_DATA_ID),
+      texture(),
+      width(0),
+      height(0)
     {
     }
 
@@ -338,20 +339,20 @@ private:
     }
 
     // Data
-    VisualUrl::Type                         visualType;
-    std::string                             url;
-    NPatchData::NPatchDataId                npatchId;
-    Texture                                 texture;
-    uint32_t                                width;
-    uint32_t                                height;
+    VisualUrl::Type          visualType;
+    std::string              url;
+    NPatchData::NPatchDataId npatchId;
+    Texture                  texture;
+    uint32_t                 width;
+    uint32_t                 height;
   };
 
   Geometry mGeometry[GEOMETRY_TYPE_MAX + 1];
   Shader   mShader[SHADER_TYPE_MAX + 1];
 
-  ImageAtlasManagerPtr                    mAtlasManager;
-  TextureManager                          mTextureManager;
-  NPatchLoader                            mNPatchLoader;
+  ImageAtlasManagerPtr mAtlasManager;
+  TextureManager       mTextureManager;
+  NPatchLoader         mNPatchLoader;
 
   SvgRasterizeThread*                     mSvgRasterizeThread;
   std::unique_ptr<VectorAnimationManager> mVectorAnimationManager;
index 7e6beff..360429c 100644 (file)
@@ -153,8 +153,8 @@ public:
       DOWN,      ///< Move keyboard focus towards the down direction @SINCE_1_0.0
       PAGE_UP,   ///< Move keyboard focus towards the previous page direction @SINCE_1_2.14
       PAGE_DOWN, ///< Move keyboard focus towards the next page direction @SINCE_1_2.14
-      FORWARD,   ///< Move keyboard focus towards the forward direction @SINCE_2_1.10
-      BACKWARD,  ///< Move keyboard focus towards the backward direction @SINCE_2_1.10
+      FORWARD,   ///< Move keyboard focus towards the forward direction
+      BACKWARD,  ///< Move keyboard focus towards the backward direction
     };
   };
 
index 3cbfc60..97ebf62 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -59,12 +59,12 @@ AsyncImageLoader AsyncImageLoader::New()
 
 uint32_t AsyncImageLoader::Load(const std::string& url)
 {
-  return GetImplementation(*this).Load(Toolkit::Internal::VisualUrl(url), ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+  return GetImplementation(*this).Load(Toolkit::Internal::VisualUrl(url), ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, false);
 }
 
 uint32_t AsyncImageLoader::Load(const std::string& url, ImageDimensions dimensions)
 {
-  return GetImplementation(*this).Load(Toolkit::Internal::VisualUrl(url), dimensions, FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+  return GetImplementation(*this).Load(Toolkit::Internal::VisualUrl(url), dimensions, FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, false);
 }
 
 uint32_t AsyncImageLoader::Load(const std::string& url,
@@ -73,7 +73,7 @@ uint32_t AsyncImageLoader::Load(const std::string& url,
                                 SamplingMode::Type samplingMode,
                                 bool               orientationCorrection)
 {
-  return GetImplementation(*this).Load(Toolkit::Internal::VisualUrl(url), dimensions, fittingMode, samplingMode, orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+  return GetImplementation(*this).Load(Toolkit::Internal::VisualUrl(url), dimensions, fittingMode, samplingMode, orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, false);
 }
 
 bool AsyncImageLoader::Cancel(uint32_t loadingTaskId)