Support YUV decoding for JPEG 04/276404/7
authorHeeyong Song <heeyong.song@samsung.com>
Thu, 16 Jun 2022 04:46:29 +0000 (13:46 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Mon, 27 Jun 2022 10:00:04 +0000 (19:00 +0900)
Change-Id: Ibf098d991e21813c0a388c66e7420a51f628706d

25 files changed:
automated-tests/resources/gallery-small-1-yuv420.jpg [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-environment-variable.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-environment-variable.h
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
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/texture-manager/texture-async-loading-helper.cpp
dali-toolkit/internal/texture-manager/texture-async-loading-helper.h
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp
dali-toolkit/internal/texture-manager/texture-manager-impl.h
dali-toolkit/internal/texture-manager/texture-manager-type.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/svg/svg-rasterize-thread.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/public-api/image-loader/async-image-loader.cpp

diff --git a/automated-tests/resources/gallery-small-1-yuv420.jpg b/automated-tests/resources/gallery-small-1-yuv420.jpg
new file mode 100644 (file)
index 0000000..c1362a6
Binary files /dev/null and b/automated-tests/resources/gallery-small-1-yuv420.jpg differ
index 4b917a0..1c8fea2 100644 (file)
@@ -760,8 +760,11 @@ int UtcTextureManagerUseInvalidMaskAndMaskLoadedLater(void)
       true, ///< orientationCorrection
       preMultiply);
 
       true, ///< orientationCorrection
       preMultiply);
 
-    textureManager.AsyncLoadComplete(textureId, pixelBuffer);
-    textureManager.AsyncLoadComplete(maskInfo->mAlphaMaskId, Dali::Devel::PixelBuffer());
+    std::vector<Devel::PixelBuffer> pixelBuffers;
+    pixelBuffers.push_back(pixelBuffer);
+    textureManager.AsyncLoadComplete(textureId, pixelBuffers);
+    std::vector<Devel::PixelBuffer> maskBuffers;
+    textureManager.AsyncLoadComplete(maskInfo->mAlphaMaskId, maskBuffers);
     textureManager.Remove(maskInfo->mAlphaMaskId, nullptr);
     textureManager.Remove(textureId, &observer);
   }
     textureManager.Remove(maskInfo->mAlphaMaskId, nullptr);
     textureManager.Remove(textureId, &observer);
   }
@@ -1216,7 +1219,8 @@ int UtcTextureManagerRemoveDuringApplyMasking(void)
   // ApplyMask event come back, and do nothing.
   // CAPTION : HARD-CODING.
   {
   // ApplyMask event come back, and do nothing.
   // CAPTION : HARD-CODING.
   {
-    textureManager.AsyncLoadComplete(textureId1, Dali::Devel::PixelBuffer());
+    std::vector<Devel::PixelBuffer> pixelBuffers;
+    textureManager.AsyncLoadComplete(textureId1, pixelBuffers);
     textureManager.Remove(maskInfo->mAlphaMaskId, nullptr);
   }
 
     textureManager.Remove(maskInfo->mAlphaMaskId, nullptr);
   }
 
@@ -1230,7 +1234,8 @@ int UtcTextureManagerRemoveDuringApplyMasking(void)
 
   // CAPTION : HARD-CODING.
   {
 
   // CAPTION : HARD-CODING.
   {
-    textureManager.AsyncLoadComplete(textureId2, Dali::Devel::PixelBuffer());
+    std::vector<Devel::PixelBuffer> pixelBuffers;
+    textureManager.AsyncLoadComplete(textureId2, pixelBuffers);
     textureManager.Remove(textureId2, &observer2);
   }
 
     textureManager.Remove(textureId2, &observer2);
   }
 
@@ -1239,4 +1244,4 @@ int UtcTextureManagerRemoveDuringApplyMasking(void)
   DALI_TEST_EQUALS(observer2.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION);
 
   END_TEST;
   DALI_TEST_EQUALS(observer2.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
index f02bfb4..5d8d143 100644 (file)
 
 // EXTERNAL INCLUDE
 #include <cstddef>
 
 // EXTERNAL INCLUDE
 #include <cstddef>
+#include <string>
 
 namespace Dali
 {
 
 namespace Dali
 {
-
 namespace EnvironmentVariable
 {
 namespace EnvironmentVariable
 {
-
 namespace
 {
 namespace
 {
-const char * gReturnValue = NULL;
-}
+const char* gReturnValue = NULL;
+std::string gEnvironmentVariableName;
+std::string gEnvironmentVariableValue;
+} // namespace
 
 
-const char * GetEnvironmentVariable( const char * variable )
+const char* GetEnvironmentVariable(const char* variable)
 {
 {
+  if(gEnvironmentVariableName == variable)
+  {
+    return gEnvironmentVariableValue.c_str();
+  }
   return gReturnValue;
 }
 
   return gReturnValue;
 }
 
-void SetTestingEnvironmentVariable( bool testing)
+void SetTestingEnvironmentVariable(bool testing)
 {
 {
-  if( testing )
+  if(testing)
   {
     gReturnValue = "1";
   }
   {
     gReturnValue = "1";
   }
@@ -48,6 +53,12 @@ void SetTestingEnvironmentVariable( bool testing)
   }
 }
 
   }
 }
 
+void SetTestEnvironmentVariable(const char* variable, const char* value)
+{
+  gEnvironmentVariableName  = variable;
+  gEnvironmentVariableValue = value;
+}
+
 } // namespace EnvironmentVariable
 
 } // namespace Dali
 } // namespace EnvironmentVariable
 
 } // namespace Dali
index b1ebae0..43b0758 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_ENVIRONMENT_VARIABLE_H
 
 /*
 #define DALI_TOOLKIT_ENVIRONMENT_VARIABLE_H
 
 /*
- * Copyright (c) 2019 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 namespace Dali
 {
 
 namespace Dali
 {
-
 namespace EnvironmentVariable
 {
 namespace EnvironmentVariable
 {
+const char* GetEnvironmentVariable(const char* variable);
 
 
-const char * GetEnvironmentVariable( const char * variable );
+void SetTestingEnvironmentVariable(bool);
 
 
-void SetTestingEnvironmentVariable( bool );
+void SetTestEnvironmentVariable(const char* variable, const char* value);
 
 } // namespace EnvironmentVariable
 
 } // namespace Dali
 
 
 } // namespace EnvironmentVariable
 
 } // namespace Dali
 
-
 #endif // DALI_TOOLKIT_ENVIRONMENT_VARIABLE_H
 #endif // DALI_TOOLKIT_ENVIRONMENT_VARIABLE_H
index 3f4fdba..c399993 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <dali-toolkit-test-suite-utils.h>
 
 
 #include <dali-toolkit-test-suite-utils.h>
 
+#include <toolkit-environment-variable.h>
 #include <toolkit-event-thread-callback.h>
 #include <toolkit-timer.h>
 
 #include <toolkit-event-thread-callback.h>
 #include <toolkit-timer.h>
 
@@ -60,6 +61,9 @@ const char* TEST_INVALID_FILE_NAME        = TEST_RESOURCE_DIR "/invalid.jpg";
 const char* TEST_REMOTE_INVALID_FILE_NAME = "https://www.tizen.org/invalid.png";
 const char* TEST_MASK_IMAGE_FILE_NAME     = TEST_RESOURCE_DIR "/mask.png";
 const char* TEST_ROTATED_IMAGE            = TEST_RESOURCE_DIR "/keyboard-Landscape.jpg";
 const char* TEST_REMOTE_INVALID_FILE_NAME = "https://www.tizen.org/invalid.png";
 const char* TEST_MASK_IMAGE_FILE_NAME     = TEST_RESOURCE_DIR "/mask.png";
 const char* TEST_ROTATED_IMAGE            = TEST_RESOURCE_DIR "/keyboard-Landscape.jpg";
+const char* TEST_YUV420_IMAGE_FILE_NAME   = TEST_RESOURCE_DIR "/gallery-small-1-yuv420.jpg";
+
+constexpr auto LOAD_IMAGE_YUV_PLANES_ENV = "DALI_LOAD_IMAGE_YUV_PLANES_ENV";
 
 bool             gResourceReadySignalFired = false;
 std::vector<int> gReadyIds                 = {};
 
 bool             gResourceReadySignalFired = false;
 std::vector<int> gReadyIds                 = {};
@@ -1694,7 +1698,7 @@ int UtcDaliImageVisualAlphaMask02(void)
   application.Render();
 
   DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
   application.Render();
 
   DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
-  Renderer renderer = actor.GetRendererAt(0u);
+  Renderer   renderer = actor.GetRendererAt(0u);
   TextureSet textures = renderer.GetTextures();
   DALI_TEST_CHECK(textures);
   DALI_TEST_EQUALS(textures.GetTextureCount(), 2u, TEST_LOCATION);
   TextureSet textures = renderer.GetTextures();
   DALI_TEST_CHECK(textures);
   DALI_TEST_EQUALS(textures.GetTextureCount(), 2u, TEST_LOCATION);
@@ -1753,7 +1757,7 @@ int UtcDaliImageVisualAlphaMask03(void)
   application.Render();
 
   DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
   application.Render();
 
   DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
-  Renderer renderer = actor.GetRendererAt(0u);
+  Renderer   renderer = actor.GetRendererAt(0u);
   TextureSet textures = renderer.GetTextures();
   DALI_TEST_CHECK(textures);
   DALI_TEST_EQUALS(textures.GetTextureCount(), 1u, TEST_LOCATION);
   TextureSet textures = renderer.GetTextures();
   DALI_TEST_CHECK(textures);
   DALI_TEST_EQUALS(textures.GetTextureCount(), 1u, TEST_LOCATION);
@@ -1865,7 +1869,7 @@ int UtcDaliImageVisualSynchronousLoadAlphaMask02(void)
   application.Render();
 
   DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
   application.Render();
 
   DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
-  Renderer renderer = actor.GetRendererAt(0u);
+  Renderer   renderer = actor.GetRendererAt(0u);
   TextureSet textures = renderer.GetTextures();
   DALI_TEST_CHECK(textures);
   DALI_TEST_EQUALS(textures.GetTextureCount(), 2u, TEST_LOCATION);
   TextureSet textures = renderer.GetTextures();
   DALI_TEST_CHECK(textures);
   DALI_TEST_EQUALS(textures.GetTextureCount(), 2u, TEST_LOCATION);
@@ -2921,3 +2925,128 @@ int UtcDaliImageVisualLoadReady01(void)
 
   END_TEST;
 }
 
   END_TEST;
 }
+
+int UtcDaliImageVisualLoadImagePlanes01(void)
+{
+  EnvironmentVariable::SetTestEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV, "1");
+
+  ToolkitTestApplication application;
+
+  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_YUV420_IMAGE_FILE_NAME);
+
+  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));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 3, TEST_LOCATION);
+
+  Renderer renderer           = actor.GetRendererAt(0);
+  auto     preMultipliedAlpha = renderer.GetProperty<bool>(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA);
+  DALI_TEST_EQUALS(preMultipliedAlpha, false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualLoadImagePlanes02(void)
+{
+  EnvironmentVariable::SetTestEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV, "1");
+
+  ToolkitTestApplication application;
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  // Alpha masking case - not support yuv planes
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_YUV420_IMAGE_FILE_NAME);
+  propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME);
+
+  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));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION);
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualLoadImagePlanes03(void)
+{
+  EnvironmentVariable::SetTestEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV, "1");
+
+  ToolkitTestApplication application;
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  Property::Map propertyMap;
+  propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap.Insert(ImageVisual::Property::URL, TEST_YUV420_IMAGE_FILE_NAME);
+  propertyMap.Insert(ImageVisual::Property::SYNCHRONOUS_LOADING, 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));
+  application.GetScene().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 3, TEST_LOCATION);
+
+  END_TEST;
+}
index e73a53c..cf47c70 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ uint32_t Load(AsyncImageLoader                         asyncImageLoader,
               bool                                     orientationCorrection,
               DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
               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,
 }
 
 uint32_t ApplyMask(AsyncImageLoader                         asyncImageLoader,
index 0e059a5..9073da7 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_IMAGE_LOADER_ASYNC_IMAGE_LOADER_DEVEL_H
 
 /*
 #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.
  *
  * 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
 {
 {
 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
 
 /**
  * @brief Whether to multiply alpha into color channels on load
index 3694280..c292b0e 100644 (file)
@@ -9,6 +9,10 @@ INPUT mediump vec4 vCornerRadius;
 #endif
 
 uniform sampler2D sTexture;
 #endif
 
 uniform sampler2D sTexture;
+#ifdef IS_REQUIRED_YUV_TO_RGB
+uniform sampler2D sTextureU;
+uniform sampler2D sTextureV;
+#endif
 
 #ifdef IS_REQUIRED_ALPHA_MASKING
 uniform sampler2D sMaskTexture;
 
 #ifdef IS_REQUIRED_ALPHA_MASKING
 uniform sampler2D sMaskTexture;
@@ -208,6 +212,20 @@ mediump float calculateCornerOpacity()
 }
 #endif
 
 }
 #endif
 
+#ifdef 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()
 {
 #ifdef ATLAS_DEFAULT_WARP
 void main()
 {
 #ifdef ATLAS_DEFAULT_WARP
@@ -219,7 +237,11 @@ void main()
   mediump vec2 texCoord = vTexCoord;
 #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;
+#else
   lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
   lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
+#endif
 
 #ifdef IS_REQUIRED_ALPHA_MASKING
   mediump float maskAlpha = TEXTURE(sMaskTexture, vMaskTexCoord).a;
 
 #ifdef IS_REQUIRED_ALPHA_MASKING
   mediump float maskAlpha = TEXTURE(sMaskTexture, vMaskTexCoord).a;
index cd3ac9f..880db04 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -65,14 +65,15 @@ uint32_t AsyncImageLoader::Load(const VisualUrl&                         url,
                                 FittingMode::Type                        fittingMode,
                                 SamplingMode::Type                       samplingMode,
                                 bool                                     orientationCorrection,
                                 FittingMode::Type                        fittingMode,
                                 SamplingMode::Type                       samplingMode,
                                 bool                                     orientationCorrection,
-                                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
+                                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+                                bool                                     loadPlanes)
 {
   if(!mIsLoadThreadStarted)
   {
     mLoadThread.Start();
     mIsLoadThreadStarted = true;
   }
 {
   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, loadPlanes));
 
   return mLoadTaskId;
 }
 
   return mLoadTaskId;
 }
@@ -136,14 +137,14 @@ void AsyncImageLoader::ProcessLoadedImage()
   {
     if(mPixelBufferLoadedSignal.GetConnectionCount() > 0)
     {
   {
     if(mPixelBufferLoadedSignal.GetConnectionCount() > 0)
     {
-      mPixelBufferLoadedSignal.Emit(next->id, next->pixelBuffer);
+      mPixelBufferLoadedSignal.Emit(next->id, next->pixelBuffers);
     }
     else if(mLoadedSignal.GetConnectionCount() > 0)
     {
       PixelData pixelData;
     }
     else if(mLoadedSignal.GetConnectionCount() > 0)
     {
       PixelData pixelData;
-      if(next->pixelBuffer)
+      if(!next->pixelBuffers.empty())
       {
       {
-        pixelData = Devel::PixelBuffer::Convert(next->pixelBuffer);
+        pixelData = Devel::PixelBuffer::Convert(next->pixelBuffers[0]);
       }
       mLoadedSignal.Emit(next->id, pixelData);
     }
       }
       mLoadedSignal.Emit(next->id, pixelData);
     }
index aa2efc9..34496b1 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H
 
 /*
 #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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -53,14 +53,23 @@ public:
                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
 
   /**
                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
 
   /**
-   * @copydoc Toolkit::AsyncImageLoader::Load( const std::string&, ImageDimensions, FittingMode::Type, SamplingMode::Type, bool , DevelAsyncImageLoader::PreMultiplyOnLoad )
+   * @brief Starts an image loading task.
+   * @param[in] url The URL of the image file to load
+   * @param[in] dimensions The width and height to fit the loaded image to
+   * @param[in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter
+   * @param[in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size
+   * @param[in] orientationCorrection Reorient the image to respect any orientation metadata in its header
+   * @param[in] preMultiplyOnLoad ON if the image color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+   * @param[in] loadPlanes true to load image planes or false to load bitmap image.
+   * @return The loading task id
    */
   uint32_t Load(const VisualUrl&                         url,
                 ImageDimensions                          dimensions,
                 FittingMode::Type                        fittingMode,
                 SamplingMode::Type                       samplingMode,
                 bool                                     orientationCorrection,
    */
   uint32_t Load(const VisualUrl&                         url,
                 ImageDimensions                          dimensions,
                 FittingMode::Type                        fittingMode,
                 SamplingMode::Type                       samplingMode,
                 bool                                     orientationCorrection,
-                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+                DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+                bool                                     loadPlanes);
 
   /**
    * @brief Starts an image loading task by encoded image buffer.
 
   /**
    * @brief Starts an image loading task by encoded image buffer.
index 08b4cd0..be946ab 100644 (file)
@@ -160,7 +160,7 @@ bool ImageAtlas::Upload(Vector4&             textureRect,
   uint32_t packPositionY = 0;
   if(mPacker.Pack(dimensions.GetWidth(), dimensions.GetHeight(), packPositionX, packPositionY))
   {
   uint32_t packPositionY = 0;
   if(mPacker.Pack(dimensions.GetWidth(), dimensions.GetHeight(), packPositionX, packPositionY))
   {
-    uint32_t loadId = GetImplementation(mAsyncLoader).Load(url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad::OFF);
+    uint32_t 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
     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 c0959f6..deb0178 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.
  *
  * 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 "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/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
 {
 
 namespace Dali
 {
@@ -32,83 +32,85 @@ namespace Toolkit
 namespace Internal
 {
 LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 namespace Internal
 {
 LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: pixelBuffer(),
-  url(),
+: url(),
   encodedImageBuffer(),
   id(id),
   dimensions(),
   fittingMode(),
   samplingMode(),
   encodedImageBuffer(),
   id(id),
   dimensions(),
   fittingMode(),
   samplingMode(),
-  orientationCorrection(),
   preMultiplyOnLoad(preMultiplyOnLoad),
   preMultiplyOnLoad(preMultiplyOnLoad),
-  isMaskTask(false),
   maskPixelBuffer(),
   contentScale(1.0f),
   maskPixelBuffer(),
   contentScale(1.0f),
-  cropToMask(false),
   animatedImageLoading(animatedImageLoading),
   animatedImageLoading(animatedImageLoading),
-  frameIndex(frameIndex)
+  frameIndex(frameIndex),
+  orientationCorrection(),
+  isMaskTask(false),
+  cropToMask(false),
+  loadPlanes(false)
 {
 }
 
 {
 }
 
-LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: pixelBuffer(),
-  url(url),
+LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadPlanes)
+: url(url),
   encodedImageBuffer(),
   id(id),
   dimensions(dimensions),
   fittingMode(fittingMode),
   samplingMode(samplingMode),
   encodedImageBuffer(),
   id(id),
   dimensions(dimensions),
   fittingMode(fittingMode),
   samplingMode(samplingMode),
-  orientationCorrection(orientationCorrection),
   preMultiplyOnLoad(preMultiplyOnLoad),
   preMultiplyOnLoad(preMultiplyOnLoad),
-  isMaskTask(false),
   maskPixelBuffer(),
   contentScale(1.0f),
   maskPixelBuffer(),
   contentScale(1.0f),
-  cropToMask(false),
   animatedImageLoading(),
   animatedImageLoading(),
-  frameIndex(0u)
+  frameIndex(0u),
+  orientationCorrection(orientationCorrection),
+  isMaskTask(false),
+  cropToMask(false),
+  loadPlanes(loadPlanes)
 {
 }
 
 LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuffer, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
 }
 
 LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuffer, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: pixelBuffer(),
-  url(),
+: url(),
   encodedImageBuffer(encodedImageBuffer),
   id(id),
   dimensions(dimensions),
   fittingMode(fittingMode),
   samplingMode(samplingMode),
   encodedImageBuffer(encodedImageBuffer),
   id(id),
   dimensions(dimensions),
   fittingMode(fittingMode),
   samplingMode(samplingMode),
-  orientationCorrection(orientationCorrection),
   preMultiplyOnLoad(preMultiplyOnLoad),
   preMultiplyOnLoad(preMultiplyOnLoad),
-  isMaskTask(false),
   maskPixelBuffer(),
   contentScale(1.0f),
   maskPixelBuffer(),
   contentScale(1.0f),
-  cropToMask(false),
   animatedImageLoading(),
   animatedImageLoading(),
-  frameIndex(0u)
+  frameIndex(0u),
+  orientationCorrection(orientationCorrection),
+  isMaskTask(false),
+  cropToMask(false),
+  loadPlanes(false)
 {
 }
 
 LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
 }
 
 LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-: pixelBuffer(pixelBuffer),
-  url(""),
+: url(""),
   encodedImageBuffer(),
   id(id),
   dimensions(),
   fittingMode(),
   samplingMode(),
   encodedImageBuffer(),
   id(id),
   dimensions(),
   fittingMode(),
   samplingMode(),
-  orientationCorrection(),
   preMultiplyOnLoad(preMultiplyOnLoad),
   preMultiplyOnLoad(preMultiplyOnLoad),
-  isMaskTask(true),
   maskPixelBuffer(maskPixelBuffer),
   contentScale(contentScale),
   maskPixelBuffer(maskPixelBuffer),
   contentScale(contentScale),
-  cropToMask(cropToMask),
   animatedImageLoading(),
   animatedImageLoading(),
-  frameIndex(0u)
+  frameIndex(0u),
+  orientationCorrection(),
+  isMaskTask(true),
+  cropToMask(cropToMask),
+  loadPlanes(false)
 {
 {
+  pixelBuffers.push_back(pixelBuffer);
 }
 
 void LoadingTask::Load()
 {
 }
 
 void LoadingTask::Load()
 {
+  Devel::PixelBuffer pixelBuffer;
   if(animatedImageLoading)
   {
     pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
   if(animatedImageLoading)
   {
     pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
@@ -119,14 +121,26 @@ void LoadingTask::Load()
   }
   else if(url.IsValid() && url.IsLocalResource())
   {
   }
   else if(url.IsValid() && url.IsLocalResource())
   {
-    pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
+    if(loadPlanes)
+    {
+      Dali::LoadImagePlanesFromFile(url.GetUrl(), pixelBuffers, dimensions, fittingMode, samplingMode, orientationCorrection);
+    }
+    else
+    {
+      pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
+    }
   }
   else if(url.IsValid())
   {
     pixelBuffer = Dali::DownloadImageSynchronously(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
   }
 
   }
   else if(url.IsValid())
   {
     pixelBuffer = Dali::DownloadImageSynchronously(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
   }
 
-  if(!pixelBuffer)
+  if(pixelBuffer)
+  {
+    pixelBuffers.push_back(pixelBuffer);
+  }
+
+  if(pixelBuffers.empty())
   {
     DALI_LOG_ERROR("LoadingTask::Load: Loading is failed: %s\n", url.GetUrl().c_str());
   }
   {
     DALI_LOG_ERROR("LoadingTask::Load: Loading is failed: %s\n", url.GetUrl().c_str());
   }
@@ -134,16 +148,19 @@ void LoadingTask::Load()
 
 void LoadingTask::ApplyMask()
 {
 
 void LoadingTask::ApplyMask()
 {
-  pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+  if(!pixelBuffers.empty())
+  {
+    pixelBuffers[0].ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+  }
 }
 
 void LoadingTask::MultiplyAlpha()
 {
 }
 
 void LoadingTask::MultiplyAlpha()
 {
-  if(pixelBuffer && Pixel::HasAlpha(pixelBuffer.GetPixelFormat()))
+  if(!pixelBuffers.empty() && Pixel::HasAlpha(pixelBuffers[0].GetPixelFormat()))
   {
     if(preMultiplyOnLoad == DevelAsyncImageLoader::PreMultiplyOnLoad::ON)
     {
   {
     if(preMultiplyOnLoad == DevelAsyncImageLoader::PreMultiplyOnLoad::ON)
     {
-      pixelBuffer.MultiplyColorByAlpha();
+      pixelBuffers[0].MultiplyColorByAlpha();
     }
   }
 }
     }
   }
 }
index 319f750..520d2b2 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_IMAGE_LOAD_THREAD_H
 
 /*
 #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.
  *
  * 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/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/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
 {
 
 namespace Dali
 {
@@ -63,6 +63,7 @@ struct LoadingTask
    * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
    * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
    * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
    * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
    * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
    * @param [in] preMultiplyOnLoad ON if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+   * @param [in] loadPlanes true to load image planes or false to load bitmap image.
    */
   LoadingTask(uint32_t                                 id,
               const VisualUrl&                         url,
    */
   LoadingTask(uint32_t                                 id,
               const VisualUrl&                         url,
@@ -70,7 +71,8 @@ struct LoadingTask
               FittingMode::Type                        fittingMode,
               SamplingMode::Type                       samplingMode,
               bool                                     orientationCorrection,
               FittingMode::Type                        fittingMode,
               SamplingMode::Type                       samplingMode,
               bool                                     orientationCorrection,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
+              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad,
+              bool                                     loadPlanes);
 
   /**
    * Constructor.
 
   /**
    * Constructor.
@@ -129,23 +131,25 @@ private:
   LoadingTask& operator=(const LoadingTask& queue);
 
 public:
   LoadingTask& operator=(const LoadingTask& queue);
 
 public:
-  Devel::PixelBuffer pixelBuffer;                                     ///< pixelBuffer handle after successful load
-                                                                      ///< or pixelBuffer to be masked image in the mask task
-  VisualUrl                                url;                       ///< url of the image to load
-  EncodedImageBuffer                       encodedImageBuffer;        ///< encoded buffer of the image to load
-  uint32_t                                 id;                        ///< The unique id associated with this task.
-  ImageDimensions                          dimensions;                ///< dimensions to load
-  FittingMode::Type                        fittingMode;               ///< fitting options
-  SamplingMode::Type                       samplingMode;              ///< sampling options
-  bool                                     orientationCorrection : 1; ///< if orientation correction is needed
-  DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad;         //< if the image's color should be multiplied by it's alpha
-
-  bool                       isMaskTask;      ///< whether this task is for mask or not
+  std::vector<Devel::PixelBuffer> pixelBuffers{};              ///< pixelBuffer handle after successful load
+                                                               ///< or pixelBuffer to be masked image in the mask task
+  VisualUrl                                url;                ///< url of the image to load
+  EncodedImageBuffer                       encodedImageBuffer; ///< encoded buffer of the image to load
+  uint32_t                                 id;                 ///< The unique id associated with this task.
+  ImageDimensions                          dimensions;         ///< dimensions to load
+  FittingMode::Type                        fittingMode;        ///< fitting options
+  SamplingMode::Type                       samplingMode;       ///< sampling options
+  DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad;  ///< if the image's color should be multiplied by it's alpha
+
   Devel::PixelBuffer         maskPixelBuffer; ///< pixelBuffer of mask image
   float                      contentScale;    ///< The factor to scale the content
   Devel::PixelBuffer         maskPixelBuffer; ///< pixelBuffer of mask image
   float                      contentScale;    ///< The factor to scale the content
-  bool                       cropToMask;      ///< Whether to crop the content to the mask size
   Dali::AnimatedImageLoading animatedImageLoading;
   uint32_t                   frameIndex;
   Dali::AnimatedImageLoading animatedImageLoading;
   uint32_t                   frameIndex;
+
+  bool orientationCorrection : 1; ///< if orientation correction is needed
+  bool isMaskTask : 1;            ///< whether this task is for mask or not
+  bool cropToMask : 1;            ///< Whether to crop the content to the mask size
+  bool loadPlanes : 1;            ///< Whether to load image planes
 };
 
 /**
 };
 
 /**
index f17c62a..8f0982e 100644 (file)
@@ -56,7 +56,8 @@ void TextureAsyncLoadingHelper::Load(const TextureManager::TextureId&
                                      const Dali::FittingMode::Type&                  fittingMode,
                                      const Dali::SamplingMode::Type&                 samplingMode,
                                      const bool&                                     orientationCorrection,
                                      const Dali::FittingMode::Type&                  fittingMode,
                                      const Dali::SamplingMode::Type&                 samplingMode,
                                      const bool&                                     orientationCorrection,
-                                     const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
+                                     const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad,
+                                     const bool&                                     loadYuvPlanes)
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
   if(DALI_UNLIKELY(url.IsBufferResource()))
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
   if(DALI_UNLIKELY(url.IsBufferResource()))
@@ -66,7 +67,7 @@ void TextureAsyncLoadingHelper::Load(const TextureManager::TextureId&
   }
   else
   {
   }
   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;
   }
 }
     mLoadingInfoContainer.back().loadId = id;
   }
 }
@@ -100,8 +101,8 @@ TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(
     this, &TextureAsyncLoadingHelper::AsyncLoadComplete);
 }
 
     this, &TextureAsyncLoadingHelper::AsyncLoadComplete);
 }
 
-void TextureAsyncLoadingHelper::AsyncLoadComplete(uint32_t           id,
-                                                  Devel::PixelBuffer pixelBuffer)
+void TextureAsyncLoadingHelper::AsyncLoadComplete(uint32_t                         id,
+                                                  std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureAsyncLoadingHelper::AsyncLoadComplete( loadId :%d )\n", id);
   if(mLoadingInfoContainer.size() >= 1u)
 {
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureAsyncLoadingHelper::AsyncLoadComplete( loadId :%d )\n", id);
   if(mLoadingInfoContainer.size() >= 1u)
@@ -112,7 +113,7 @@ void TextureAsyncLoadingHelper::AsyncLoadComplete(uint32_t           id,
     if(loadingInfo.loadId == id)
     {
       // Call TextureManager::AsyncLoadComplete
     if(loadingInfo.loadId == id)
     {
       // Call TextureManager::AsyncLoadComplete
-      mTextureManager.AsyncLoadComplete(loadingInfo.textureId, pixelBuffer);
+      mTextureManager.AsyncLoadComplete(loadingInfo.textureId, pixelBuffers);
     }
 
     mLoadingInfoContainer.pop_front();
     }
 
     mLoadingInfoContainer.pop_front();
index 482bfd3..d8830f7 100644 (file)
@@ -82,6 +82,7 @@ public:
    * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
    *                                  e.g., from portrait to landscape
    * @param[in] preMultiplyOnLoad     if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
    * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
    *                                  e.g., from portrait to landscape
    * @param[in] preMultiplyOnLoad     if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+   * @param[in] loadYuvPlanes         True if the image should be loaded as yuv planes
    */
   void Load(const TextureManager::TextureId&                textureId,
             const VisualUrl&                                url,
    */
   void Load(const TextureManager::TextureId&                textureId,
             const VisualUrl&                                url,
@@ -89,7 +90,8 @@ public:
             const Dali::FittingMode::Type&                  fittingMode,
             const Dali::SamplingMode::Type&                 samplingMode,
             const bool&                                     orientationCorrection,
             const Dali::FittingMode::Type&                  fittingMode,
             const Dali::SamplingMode::Type&                 samplingMode,
             const bool&                                     orientationCorrection,
-            const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad);
+            const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad,
+            const bool&                                     loadYuvPlanes);
 
   /**
    * @brief Apply mask
 
   /**
    * @brief Apply mask
@@ -126,11 +128,11 @@ private:
                             AsyncLoadingInfoContainerType&& loadingInfoContainer);
 
   /**
                             AsyncLoadingInfoContainerType&& loadingInfoContainer);
 
   /**
-   * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
-   * @param[in] id          Loader id
-   * @param[in] pixelBuffer Image data
+   * @brief Callback to be called when texture loading is complete, it passes the pixel buffer list on to texture manager.
+   * @param[in] id           Loader id
+   * @param[in] pixelBuffers Image data
    */
    */
-  void AsyncLoadComplete(std::uint32_t id, Devel::PixelBuffer pixelBuffer);
+  void AsyncLoadComplete(std::uint32_t id, std::vector<Devel::PixelBuffer>& pixelBuffers);
 
 private: // Member Variables:
   Toolkit::AsyncImageLoader     mLoader;
 
 private: // Member Variables:
   Toolkit::AsyncImageLoader     mLoader;
index 92031ae..223208a 100644 (file)
@@ -39,6 +39,7 @@ 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";
 
 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_ENV";
 
 size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
 {
 
 size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
 {
@@ -60,6 +61,12 @@ size_t GetNumberOfRemoteLoaderThreads()
   return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS);
 }
 
   return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS);
 }
 
+bool NeedToLoadYuvPlanes()
+{
+  auto loadYuvPlanesString = Dali::EnvironmentVariable::GetEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV);
+  bool loadYuvPlanes       = loadYuvPlanesString ? std::atoi(loadYuvPlanesString) : false;
+  return loadYuvPlanes;
+}
 } // namespace
 
 namespace Dali
 } // namespace
 
 namespace Dali
@@ -126,7 +133,8 @@ TextureManager::TextureManager()
   mLifecycleObservers(),
   mLoadQueue(),
   mRemoveQueue(),
   mLifecycleObservers(),
   mLoadQueue(),
   mRemoveQueue(),
-  mQueueLoadFlag(false)
+  mQueueLoadFlag(false),
+  mLoadYuvPlanes(NeedToLoadYuvPlanes())
 {
   // Initialize the AddOn
   RenderingAddOn::Get();
 {
   // Initialize the AddOn
   RenderingAddOn::Get();
@@ -337,22 +345,24 @@ TextureSet TextureManager::LoadTexture(
                                                                                                          : false;
       if(synchronousAtlasAvaliable)
       {
                                                                                                          : false;
       if(synchronousAtlasAvaliable)
       {
-        Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);
+        std::vector<Devel::PixelBuffer> pixelBuffers;
+        LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection, false, pixelBuffers);
 
 
-        if(pixelBuffer && maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
+        if(!pixelBuffers.empty() && maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
         {
         {
-          Devel::PixelBuffer maskPixelBuffer = LoadImageSynchronously(maskInfo->mAlphaMaskUrl, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
-          if(maskPixelBuffer)
+          std::vector<Devel::PixelBuffer> maskPixelBuffers;
+          LoadImageSynchronously(maskInfo->mAlphaMaskUrl, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true, false, maskPixelBuffers);
+          if(!maskPixelBuffers.empty())
           {
           {
-            pixelBuffer.ApplyMask(maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
+            pixelBuffers[0].ApplyMask(maskPixelBuffers[0], maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
           }
         }
 
         PixelData data;
           }
         }
 
         PixelData data;
-        if(pixelBuffer)
+        if(!pixelBuffers.empty())
         {
         {
-          PreMultiply(pixelBuffer, preMultiplyOnLoad);
-          data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+          PreMultiply(pixelBuffers[0], preMultiplyOnLoad);
+          data = Devel::PixelBuffer::Convert(pixelBuffers[0]); // takes ownership of buffer
 
           if(data)
           {
 
           if(data)
           {
@@ -529,8 +539,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
   const std::uint32_t&                frameIndex,
   const bool&                         synchronousLoading)
 {
   const std::uint32_t&                frameIndex,
   const bool&                         synchronousLoading)
 {
-  TextureHash       textureHash = INITIAL_HASH_NUMBER;
-  TextureCacheIndex cacheIndex  = INVALID_CACHE_INDEX;
+  TextureHash       textureHash   = INITIAL_HASH_NUMBER;
+  TextureCacheIndex cacheIndex    = INVALID_CACHE_INDEX;
+  bool              loadYuvPlanes = (mLoadYuvPlanes && maskTextureId == INVALID_TEXTURE_ID && storageType == StorageType::UPLOAD_TO_TEXTURE);
+
   if(storageType != StorageType::RETURN_PIXEL_BUFFER)
   {
     textureHash = mTextureCacheManager.GenerateHash(url, desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, cropToMask, frameIndex);
   if(storageType != StorageType::RETURN_PIXEL_BUFFER)
   {
     textureHash = mTextureCacheManager.GenerateHash(url, desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, cropToMask, frameIndex);
@@ -564,7 +576,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
 
     // Cache new texutre, and get cacheIndex.
     bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
 
     // Cache new texutre, and get cacheIndex.
-    cacheIndex = mTextureCacheManager.AppendCache(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+    cacheIndex = mTextureCacheManager.AppendCache(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex, loadYuvPlanes));
 
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, frameindex=%d premultiply=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, frameIndex, preMultiply);
   }
 
     DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, frameindex=%d premultiply=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, frameIndex, preMultiply);
   }
@@ -646,9 +658,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     if(!(textureInfo.loadState == TextureManager::LoadState::UPLOADED ||
          textureInfo.loadState == TextureManager::LoadState::LOAD_FINISHED))
     {
     if(!(textureInfo.loadState == TextureManager::LoadState::UPLOADED ||
          textureInfo.loadState == TextureManager::LoadState::LOAD_FINISHED))
     {
-      Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);
+      std::vector<Devel::PixelBuffer> pixelBuffers;
+      LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection, loadYuvPlanes, pixelBuffers);
 
 
-      if(!pixelBuffer)
+      if(pixelBuffers.empty())
       {
         // If pixelBuffer loading is failed in synchronously, call Remove() method.
         Remove(textureId, nullptr);
       {
         // If pixelBuffer loading is failed in synchronously, call Remove() method.
         Remove(textureId, nullptr);
@@ -657,7 +670,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 
       if(storageType == StorageType::KEEP_PIXEL_BUFFER) // For the mask image loading.
       {
 
       if(storageType == StorageType::KEEP_PIXEL_BUFFER) // For the mask image loading.
       {
-        textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
+        textureInfo.pixelBuffer = pixelBuffers[0]; // Store the pixel data
         textureInfo.loadState   = LoadState::LOAD_FINISHED;
       }
       else // For the image loading.
         textureInfo.loadState   = LoadState::LOAD_FINISHED;
       }
       else // For the image loading.
@@ -681,7 +694,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
               Devel::PixelBuffer maskPixelBuffer = mTextureCacheManager[maskCacheIndex].pixelBuffer;
               if(maskPixelBuffer)
               {
               Devel::PixelBuffer maskPixelBuffer = mTextureCacheManager[maskCacheIndex].pixelBuffer;
               if(maskPixelBuffer)
               {
-                pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+                pixelBuffers[0].ApplyMask(maskPixelBuffer, contentScale, cropToMask);
               }
               else
               {
               }
               else
               {
@@ -694,10 +707,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
             DALI_LOG_ERROR("Mask image is not stored in cache.\n");
           }
         }
             DALI_LOG_ERROR("Mask image is not stored in cache.\n");
           }
         }
-        PreMultiply(pixelBuffer, preMultiplyOnLoad);
+        PreMultiply(pixelBuffers[0], preMultiplyOnLoad);
 
         // Upload texture
 
         // Upload texture
-        UploadTexture(pixelBuffer, textureInfo);
+        UploadTextures(pixelBuffers, textureInfo);
         if(maskTexture && textureInfo.textureSet)
         {
           textureInfo.textureSet.SetTexture(1u, maskTexture);
         if(maskTexture && textureInfo.textureSet)
         {
           textureInfo.textureSet.SetTexture(1u, maskTexture);
@@ -739,12 +752,14 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU
   }
 }
 
   }
 }
 
-Devel::PixelBuffer TextureManager::LoadImageSynchronously(
-  const VisualUrl&                url,
-  const Dali::ImageDimensions&    desiredSize,
-  const Dali::FittingMode::Type&  fittingMode,
-  const Dali::SamplingMode::Type& samplingMode,
-  const bool&                     orientationCorrection)
+void TextureManager::LoadImageSynchronously(
+  const VisualUrl&                 url,
+  const Dali::ImageDimensions&     desiredSize,
+  const Dali::FittingMode::Type&   fittingMode,
+  const Dali::SamplingMode::Type&  samplingMode,
+  const bool&                      orientationCorrection,
+  const bool&                      loadYuvPlanes,
+  std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
   Devel::PixelBuffer pixelBuffer;
   if(url.IsBufferResource())
 {
   Devel::PixelBuffer pixelBuffer;
   if(url.IsBufferResource())
@@ -757,9 +772,20 @@ Devel::PixelBuffer TextureManager::LoadImageSynchronously(
   }
   else
   {
   }
   else
   {
-    pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+    if(loadYuvPlanes)
+    {
+      Dali::LoadImagePlanesFromFile(url.GetUrl(), pixelBuffers, desiredSize, fittingMode, samplingMode, orientationCorrection);
+    }
+    else
+    {
+      pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+    }
+  }
+
+  if(pixelBuffer)
+  {
+    pixelBuffers.push_back(pixelBuffer);
   }
   }
-  return pixelBuffer;
 }
 
 void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
 }
 
 void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
@@ -853,7 +879,7 @@ void TextureManager::LoadTexture(TextureManager::TextureInfo& textureInfo, Textu
     }
     else
     {
     }
     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);
     }
   }
   ObserveTexture(textureInfo, observer);
@@ -912,7 +938,7 @@ void TextureManager::ObserveTexture(TextureManager::TextureInfo& textureInfo,
   }
 }
 
   }
 }
 
-void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureId, Devel::PixelBuffer pixelBuffer)
+void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureId, std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
   TextureCacheIndex cacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( textureId:%d CacheIndex:%d )\n", textureId, cacheIndex.GetIndex());
 {
   TextureCacheIndex cacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( textureId:%d CacheIndex:%d )\n", textureId, cacheIndex.GetIndex());
@@ -925,7 +951,7 @@ void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureI
     if(textureInfo.loadState != LoadState::CANCELLED)
     {
       // textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified)
     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
     {
     }
     else
     {
@@ -934,95 +960,112 @@ void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureI
   }
 }
 
   }
 }
 
-void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer)
+void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, std::vector<Devel::PixelBuffer>& pixelBuffers)
 {
   // Was the load successful?
 {
   // Was the load successful?
-  if(pixelBuffer && (pixelBuffer.GetWidth() != 0) && (pixelBuffer.GetHeight() != 0))
+  if(!pixelBuffers.empty())
   {
   {
-    // No atlas support for now
-    textureInfo.useAtlas      = 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.
-      // note, If the texture is already uploaded synchronously during loading,
-      // we don't need to apply mask.
-      if(textureInfo.loadState != LoadState::UPLOADED &&
-         textureInfo.maskTextureId != INVALID_TEXTURE_ID)
+      Devel::PixelBuffer pixelBuffer = pixelBuffers[0];
+      if(pixelBuffer && (pixelBuffer.GetWidth() != 0) && (pixelBuffer.GetHeight() != 0))
       {
       {
-        if(textureInfo.loadState == LoadState::MASK_APPLYING)
-        {
-          textureInfo.loadState = LoadState::MASK_APPLIED;
-          UploadTexture(pixelBuffer, textureInfo);
-          NotifyObservers(textureInfo, true);
-        }
-        else
+        // No atlas support for now
+        textureInfo.useAtlas      = UseAtlas::NO_ATLAS;
+        textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
+
+        if(textureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE)
         {
         {
-          LoadState maskLoadState = mTextureCacheManager.GetTextureStateInternal(textureInfo.maskTextureId);
-          textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
-          if(maskLoadState == LoadState::LOADING)
+          // 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.
+          // note, If the texture is already uploaded synchronously during loading,
+          // we don't need to apply mask.
+          if(textureInfo.loadState != LoadState::UPLOADED &&
+             textureInfo.maskTextureId != INVALID_TEXTURE_ID)
           {
           {
-            textureInfo.loadState = LoadState::WAITING_FOR_MASK;
-          }
-          else if(maskLoadState == LoadState::LOAD_FINISHED || maskLoadState == LoadState::UPLOADED)
-          {
-            // Send New Task to Thread
-            TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureInfo.maskTextureId);
-            if(maskCacheIndex != INVALID_CACHE_INDEX)
+            if(textureInfo.loadState == LoadState::MASK_APPLYING)
+            {
+              textureInfo.loadState = LoadState::MASK_APPLIED;
+              UploadTextures(pixelBuffers, textureInfo);
+              NotifyObservers(textureInfo, true);
+            }
+            else
             {
             {
-              TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]);
-              if(maskTextureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER)
+              LoadState maskLoadState = mTextureCacheManager.GetTextureStateInternal(textureInfo.maskTextureId);
+              textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
+              if(maskLoadState == LoadState::LOADING)
               {
               {
-                // Send New Task to Thread
-                ApplyMask(textureInfo, textureInfo.maskTextureId);
+                textureInfo.loadState = LoadState::WAITING_FOR_MASK;
               }
               }
-              else if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
+              else if(maskLoadState == LoadState::LOAD_FINISHED || maskLoadState == LoadState::UPLOADED)
               {
               {
-                // Upload image texture. textureInfo.loadState will be UPLOADED.
-                UploadTexture(textureInfo.pixelBuffer, textureInfo);
-                if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
+                // Send New Task to Thread
+                TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureInfo.maskTextureId);
+                if(maskCacheIndex != INVALID_CACHE_INDEX)
                 {
                 {
-                  Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
-                  textureInfo.textureSet.SetTexture(1u, maskTexture);
+                  TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]);
+                  if(maskTextureInfo.storageType == StorageType::KEEP_PIXEL_BUFFER)
+                  {
+                    // Send New Task to Thread
+                    ApplyMask(textureInfo, textureInfo.maskTextureId);
+                  }
+                  else if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
+                  {
+                    // Upload image texture. textureInfo.loadState will be UPLOADED.
+                    UploadTextures(pixelBuffers, 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.
+              }
+              else // maskLoadState == LoadState::LOAD_FAILED
+              {
+                // Url texture load success, But alpha mask texture load failed. Run as normal image upload.
+                DALI_LOG_ERROR("Alpha mask image loading failed! Image will not be masked\n");
+                UploadTextures(pixelBuffers, textureInfo);
                 NotifyObservers(textureInfo, true);
               }
             }
           }
                 NotifyObservers(textureInfo, true);
               }
             }
           }
-          else // maskLoadState == LoadState::LOAD_FAILED
+          else
           {
           {
-            // Url texture load success, But alpha mask texture load failed. Run as normal image upload.
-            DALI_LOG_ERROR("Alpha mask image loading failed! Image will not be masked\n");
-            UploadTexture(pixelBuffer, textureInfo);
+            UploadTextures(pixelBuffers, textureInfo);
             NotifyObservers(textureInfo, true);
           }
         }
             NotifyObservers(textureInfo, true);
           }
         }
-      }
-      else
-      {
-        UploadTexture(pixelBuffer, textureInfo);
-        NotifyObservers(textureInfo, true);
+        else
+        {
+          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
     {
       }
     }
     else
     {
-      textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
-      textureInfo.loadState   = LoadState::LOAD_FINISHED;
+      // YUV case
+      // No atlas support for now
+      textureInfo.useAtlas      = UseAtlas::NO_ATLAS;
+      textureInfo.preMultiplied = false;
 
 
-      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);
-      }
+      UploadTextures(pixelBuffers, textureInfo);
+      NotifyObservers(textureInfo, true);
     }
   }
   else
     }
   }
   else
@@ -1047,7 +1090,9 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex
      maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
   {
     // Upload mask texture. textureInfo.loadState will be UPLOADED.
      maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
   {
     // Upload mask texture. textureInfo.loadState will be UPLOADED.
-    UploadTexture(maskTextureInfo.pixelBuffer, maskTextureInfo);
+    std::vector<Devel::PixelBuffer> pixelBuffers;
+    pixelBuffers.push_back(maskTextureInfo.pixelBuffer);
+    UploadTextures(pixelBuffers, maskTextureInfo);
   }
 
   // Search the cache, checking if any texture has this texture id as a
   }
 
   // Search the cache, checking if any texture has this texture id as a
@@ -1075,7 +1120,9 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex
         if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
         {
           // Upload image texture. textureInfo.loadState will be UPLOADED.
         if(maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
         {
           // Upload image texture. textureInfo.loadState will be UPLOADED.
-          UploadTexture(textureInfo.pixelBuffer, textureInfo);
+          std::vector<Devel::PixelBuffer> pixelBuffers;
+          pixelBuffers.push_back(textureInfo.pixelBuffer);
+          UploadTextures(pixelBuffers, textureInfo);
           if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
           {
             Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
           if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
           {
             Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
@@ -1089,7 +1136,9 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex
       {
         // Url texture load success, But alpha mask texture load failed. Run as normal image upload.
         DALI_LOG_ERROR("Alpha mask image loading failed! Image will not be masked\n");
       {
         // Url texture load success, But alpha mask texture load failed. Run as normal image upload.
         DALI_LOG_ERROR("Alpha mask image loading failed! Image will not be masked\n");
-        UploadTexture(textureInfo.pixelBuffer, textureInfo);
+        std::vector<Devel::PixelBuffer> pixelBuffers;
+        pixelBuffers.push_back(textureInfo.pixelBuffer);
+        UploadTextures(pixelBuffers, textureInfo);
         NotifyObservers(textureInfo, true);
       }
     }
         NotifyObservers(textureInfo, true);
       }
     }
@@ -1116,30 +1165,35 @@ void TextureManager::ApplyMask(TextureManager::TextureInfo& textureInfo, const T
   }
 }
 
   }
 }
 
-void TextureManager::UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureManager::TextureInfo& textureInfo)
+void TextureManager::UploadTextures(std::vector<Devel::PixelBuffer>& pixelBuffers, TextureManager::TextureInfo& textureInfo)
 {
 {
-  if(textureInfo.loadState != LoadState::UPLOADED && textureInfo.useAtlas != UseAtlas::USE_ATLAS)
+  if(!pixelBuffers.empty() && textureInfo.loadState != LoadState::UPLOADED && textureInfo.useAtlas != UseAtlas::USE_ATLAS)
   {
   {
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "  TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId);
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "  TextureManager::UploadTextures() New Texture for textureId:%d\n", textureInfo.textureId);
 
     // Check if this pixelBuffer is premultiplied
 
     // Check if this pixelBuffer is premultiplied
-    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
+    textureInfo.preMultiplied = pixelBuffers[0].IsAlphaPreMultiplied();
 
     auto& renderingAddOn = RenderingAddOn::Get();
     if(renderingAddOn.IsValid())
     {
 
     auto& renderingAddOn = RenderingAddOn::Get();
     if(renderingAddOn.IsValid())
     {
-      renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffer);
+      renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffers[0]);
     }
 
     }
 
-    Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
-
-    PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
-    texture.Upload(pixelData);
     if(!textureInfo.textureSet)
     {
       textureInfo.textureSet = TextureSet::New();
     }
     if(!textureInfo.textureSet)
     {
       textureInfo.textureSet = TextureSet::New();
     }
-    textureInfo.textureSet.SetTexture(0u, texture);
+
+    uint32_t index = 0;
+    for(auto&& pixelBuffer : pixelBuffers)
+    {
+      Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
+
+      PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
+      texture.Upload(pixelData);
+      textureInfo.textureSet.SetTexture(index++, texture);
+    }
   }
 
   // Update the load state.
   }
 
   // Update the load state.
index 4248904..5601052 100644 (file)
@@ -492,14 +492,18 @@ private:
    * @param[in] samplingMode          The SamplingMode to use
    * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
    *                                  e.g., from portrait to landscape
    * @param[in] samplingMode          The SamplingMode to use
    * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
    *                                  e.g., from portrait to landscape
+   * @param[in] loadYuvPlanes         True if the image should be loaded as yuv planes
+   * @param[out] pixelBuffers         The image pixelBuffer
    * @return PixelBuffer of loaded image.
    */
    * @return PixelBuffer of loaded image.
    */
-  Devel::PixelBuffer LoadImageSynchronously(
-    const VisualUrl&                url,
-    const Dali::ImageDimensions&    desiredSize,
-    const Dali::FittingMode::Type&  fittingMode,
-    const Dali::SamplingMode::Type& samplingMode,
-    const bool&                     orientationCorrection);
+  void LoadImageSynchronously(
+    const VisualUrl&                 url,
+    const Dali::ImageDimensions&     desiredSize,
+    const Dali::FittingMode::Type&   fittingMode,
+    const Dali::SamplingMode::Type&  samplingMode,
+    const bool&                      orientationCorrection,
+    const bool&                      loadYuvPlanes,
+    std::vector<Devel::PixelBuffer>& pixelBuffers);
 
 private:
   // Load and queue
 
 private:
   // Load and queue
@@ -559,11 +563,11 @@ private:
 
   /**
    * @brief Performs Post-Load steps including atlasing.
 
   /**
    * @brief Performs Post-Load steps including atlasing.
-   * @param[in] textureInfo The struct associated with this Texture
-   * @param[in] pixelBuffer The image pixelBuffer
+   * @param[in] textureInfo  The struct associated with this Texture
+   * @param[in] pixelBuffers The image pixelBuffer
    * @return    True if successful
    */
    * @return    True if successful
    */
-  void PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer);
+  void PostLoad(TextureManager::TextureInfo& textureInfo, std::vector<Devel::PixelBuffer>& pixelBuffers);
 
   /**
    * Check if there is a texture waiting to be masked. If there
 
   /**
    * Check if there is a texture waiting to be masked. If there
@@ -581,11 +585,10 @@ private:
 
   /**
    * Upload the texture specified in pixelBuffer to the appropriate location
 
   /**
    * 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.
+   * @param[in] pixelBuffers The image data to upload
+   * @param[in] textureInfo  The texture info containing the location to store the data to.
    */
    */
-  void UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureManager::TextureInfo& textureInfo);
+  void UploadTextures(std::vector<Devel::PixelBuffer>& pixelBuffers, TextureManager::TextureInfo& textureInfo);
 
   /**
    * Notify the current observers that the texture upload is complete,
 
   /**
    * Notify the current observers that the texture upload is complete,
@@ -607,10 +610,10 @@ public:
   /**
    * @brief Common method to handle loading completion.
    * TextureAsyncLoadingHelper will call this API After async loading finished.
   /**
    * @brief Common method to handle loading completion.
    * TextureAsyncLoadingHelper will call this API After async loading finished.
-   * @param[in] textureId   The ID of the texture load complete.
-   * @param[in] pixelBuffer The loaded image data
+   * @param[in] textureId    The ID of the texture load complete.
+   * @param[in] pixelBuffers The loaded image data
    */
    */
-  void AsyncLoadComplete(const TextureManager::TextureId& textureId, Devel::PixelBuffer pixelBuffer);
+  void AsyncLoadComplete(const TextureManager::TextureId& textureId, std::vector<Devel::PixelBuffer>& pixelBuffers);
 
 private:
   /**
 
 private:
   /**
@@ -640,6 +643,7 @@ private:                                    // Member Variables:
   Dali::Vector<LoadQueueElement>          mLoadQueue;          ///< Queue of textures to load after NotifyObservers
   Dali::Vector<TextureManager::TextureId> mRemoveQueue;        ///< Queue of textures to remove after NotifyObservers
   bool                                    mQueueLoadFlag;      ///< Flag that causes Load Textures to be queued.
   Dali::Vector<LoadQueueElement>          mLoadQueue;          ///< Queue of textures to load after NotifyObservers
   Dali::Vector<TextureManager::TextureId> mRemoveQueue;        ///< Queue of textures to remove after NotifyObservers
   bool                                    mQueueLoadFlag;      ///< Flag that causes Load Textures to be queued.
+  bool                                    mLoadYuvPlanes;      ///< A global flag to specify if the image should be loaded as yuv planes
 };
 
 } // namespace Internal
 };
 
 } // namespace Internal
index 567d876..98c5baa 100644 (file)
@@ -243,7 +243,8 @@ struct TextureInfo
               const bool&                       orientationCorrection,
               const bool&                       preMultiplyOnLoad,
               const Dali::AnimatedImageLoading& animatedImageLoading,
               const bool&                       orientationCorrection,
               const bool&                       preMultiplyOnLoad,
               const Dali::AnimatedImageLoading& animatedImageLoading,
-              const std::uint32_t&              frameIndex)
+              const std::uint32_t&              frameIndex,
+              const bool&                       loadYuvPlanes)
   : url(url),
     desiredSize(desiredSize),
     useSize(desiredSize),
   : url(url),
     desiredSize(desiredSize),
     useSize(desiredSize),
@@ -266,7 +267,8 @@ struct TextureInfo
     cropToMask(cropToMask),
     orientationCorrection(true),
     preMultiplyOnLoad(preMultiplyOnLoad),
     cropToMask(cropToMask),
     orientationCorrection(true),
     preMultiplyOnLoad(preMultiplyOnLoad),
-    preMultiplied(false)
+    preMultiplied(false),
+    loadYuvPlanes(loadYuvPlanes)
   {
     isAnimatedImageFormat = (animatedImageLoading) ? true : false;
   }
   {
     isAnimatedImageFormat = (animatedImageLoading) ? true : false;
   }
@@ -305,6 +307,7 @@ struct TextureInfo
   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 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
 };
 
 } // namespace TextureManagerType
 };
 
 } // namespace TextureManagerType
index ceb5848..728c219 100644 (file)
@@ -46,13 +46,14 @@ const int NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMA
 // enum of required list when we select shader
 enum class ImageVisualRequireFlag : uint32_t
 {
 // 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,
+  COLOR_CONVERSION = 1 << 3,
 };
 
 };
 
-static constexpr auto          SHADER_TYPE_COUNT = 8u;
+static constexpr auto          SHADER_TYPE_COUNT = 12u;
 VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
   {
     VisualFactoryCache::IMAGE_SHADER,
 VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
   {
     VisualFactoryCache::IMAGE_SHADER,
@@ -62,8 +63,11 @@ VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
     VisualFactoryCache::IMAGE_SHADER_MASKING,
     VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
     VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
     VisualFactoryCache::IMAGE_SHADER_MASKING,
     VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
     VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING};
-
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
+    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};
 } // unnamed namespace
 
 namespace ImageVisualShaderFeature
 } // unnamed namespace
 
 namespace ImageVisualShaderFeature
@@ -73,31 +77,42 @@ FeatureBuilder& FeatureBuilder::EnableTextureAtlas(bool enableAtlas)
   mTextureAtlas = (enableAtlas ? TextureAtlas::ENABLED : TextureAtlas::DISABLED);
   return *this;
 }
   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::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::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::EnableBorderline(bool enableBorderline)
 {
   mBorderline = (enableBorderline ? Borderline::ENABLED : Borderline::DISABLED);
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
 {
   mTexture = texture;
   return *this;
 }
 FeatureBuilder& FeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
 {
   mTexture = texture;
   return *this;
 }
+
 FeatureBuilder& FeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
 {
   mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? AlphaMaskingOnRendering::ENABLED : AlphaMaskingOnRendering::DISABLED);
   return *this;
 }
 FeatureBuilder& FeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
 {
   mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? AlphaMaskingOnRendering::ENABLED : AlphaMaskingOnRendering::DISABLED);
   return *this;
 }
+
+FeatureBuilder& FeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb)
+{
+  mColorConversion = (enableYuvToRgb ? ColorConversion::YUV_TO_RGB : ColorConversion::DONT_NEED);
+  return *this;
+}
 } // namespace ImageVisualShaderFeature
 
 ImageVisualShaderFactory::ImageVisualShaderFactory()
 } // namespace ImageVisualShaderFeature
 
 ImageVisualShaderFactory::ImageVisualShaderFactory()
@@ -119,9 +134,10 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
   const auto& roundedCorner           = featureBuilder.mRoundedCorner;
   const auto& borderline              = featureBuilder.mBorderline;
   const auto& alphaMaskingOnRendering = featureBuilder.mAlphaMaskingOnRendering;
   const auto& roundedCorner           = featureBuilder.mRoundedCorner;
   const auto& borderline              = featureBuilder.mBorderline;
   const auto& alphaMaskingOnRendering = featureBuilder.mAlphaMaskingOnRendering;
+  const auto& colorConversion         = featureBuilder.mColorConversion;
   const auto& changeFragmentShader    = (featureBuilder.mTexture && DevelTexture::IsNative(featureBuilder.mTexture))
   const auto& changeFragmentShader    = (featureBuilder.mTexture && DevelTexture::IsNative(featureBuilder.mTexture))
-                                       ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
-                                       : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
+                                          ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
+                                          : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
 
   if(atlasing == ImageVisualShaderFeature::TextureAtlas::ENABLED)
   {
 
   if(atlasing == ImageVisualShaderFeature::TextureAtlas::ENABLED)
   {
@@ -149,6 +165,10 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ALPHA_MASKING);
     }
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ALPHA_MASKING);
     }
+    else if(colorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB) // Not support gpu masking and color conversion at the same time now
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
+    }
     shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
   }
 
     shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
   }
 
@@ -192,6 +212,10 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
         vertexShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
         fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
       }
         vertexShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
         fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
       }
+      else if(colorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB)
+      {
+        fragmentShaderPrefixList += "#define IS_REQUIRED_YUV_TO_RGB\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());
index e0070ed..7dfefbc 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
 
 /*
 #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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@ namespace Toolkit
 {
 namespace Internal
 {
 {
 namespace Internal
 {
-
 /**
  * ImageVisualShaderFeature contains feature lists what image visual shader need to know.
  */
 /**
  * ImageVisualShaderFeature contains feature lists what image visual shader need to know.
  */
@@ -108,6 +107,18 @@ enum Type
 };
 } // namespace AlphaMaskingOnRendering
 
 };
 } // namespace AlphaMaskingOnRendering
 
+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()
  */
 /**
  * @brief Collection of current image visual feature. Only use for ImageVisualShaderFactory::GetShader()
  */
@@ -119,6 +130,7 @@ struct FeatureBuilder
     mRoundedCorner(RoundedCorner::DISABLED),
     mBorderline(Borderline::DISABLED),
     mAlphaMaskingOnRendering(AlphaMaskingOnRendering::DISABLED),
     mRoundedCorner(RoundedCorner::DISABLED),
     mBorderline(Borderline::DISABLED),
     mAlphaMaskingOnRendering(AlphaMaskingOnRendering::DISABLED),
+    mColorConversion(ColorConversion::DONT_NEED),
     mTexture()
   {
   }
     mTexture()
   {
   }
@@ -129,12 +141,14 @@ struct FeatureBuilder
   FeatureBuilder& EnableBorderline(bool enableBorderline);
   FeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
   FeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
   FeatureBuilder& EnableBorderline(bool enableBorderline);
   FeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
   FeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
+  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
   AlphaMaskingOnRendering::Type mAlphaMaskingOnRendering : 2; ///< Whether use runtime alpha masking, or not. default as AlphaMaskingOnRendering::DISABLED
 
   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
   AlphaMaskingOnRendering::Type mAlphaMaskingOnRendering : 2; ///< Whether use runtime alpha masking, or not. default as AlphaMaskingOnRendering::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
 };
 
   Dali::Texture                 mTexture;                     ///< Texture to check whether we need to change fragment shader or not
 };
 
@@ -146,7 +160,6 @@ struct FeatureBuilder
 class ImageVisualShaderFactory
 {
 public:
 class ImageVisualShaderFactory
 {
 public:
-
   /**
    * @brief Constructor
    */
   /**
    * @brief Constructor
    */
@@ -189,7 +202,6 @@ protected:
   ImageVisualShaderFactory& operator=(const ImageVisualShaderFactory& rhs);
 
 private:
   ImageVisualShaderFactory& operator=(const ImageVisualShaderFactory& rhs);
 
 private:
-
   /**
    * @brief Cached information whether native image should change fragment shader.
    * Default it is ChangeFragmentShader::UNDECIDED.
   /**
    * @brief Cached information whether native image should change fragment shader.
    * Default it is ChangeFragmentShader::UNDECIDED.
index ef71786..87d6ea6 100644 (file)
@@ -684,7 +684,19 @@ void ImageVisual::InitializeRenderer()
     mImpl->mRenderer.SetTextures(mTextures);
     ComputeTextureSize();
     CheckMaskTexture();
     mImpl->mRenderer.SetTextures(mTextures);
     ComputeTextureSize();
     CheckMaskTexture();
-    if(DevelTexture::IsNative(mTextures.GetTexture(0)))
+
+    bool needToUpdateShader = DevelTexture::IsNative(mTextures.GetTexture(0));
+
+    if(mTextures.GetTextureCount() == 3)
+    {
+      if(mTextures.GetTexture(0).GetPixelFormat() == Pixel::L8 && mTextures.GetTexture(1).GetPixelFormat() == Pixel::CHROMINANCE_U && mTextures.GetTexture(2).GetPixelFormat() == Pixel::CHROMINANCE_V)
+      {
+        mNeedYuvToRgb      = true;
+        needToUpdateShader = true;
+      }
+    }
+
+    if(needToUpdateShader)
     {
       UpdateShader();
     }
     {
       UpdateShader();
     }
@@ -906,6 +918,15 @@ void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureIn
       mImpl->mRenderer.SetTextures(textureInformation.textureSet);
       ComputeTextureSize();
       CheckMaskTexture();
       mImpl->mRenderer.SetTextures(textureInformation.textureSet);
       ComputeTextureSize();
       CheckMaskTexture();
+
+      if(textureInformation.textureSet.GetTextureCount() == 3)
+      {
+        if(textureInformation.textureSet.GetTexture(0).GetPixelFormat() == Pixel::L8 && textureInformation.textureSet.GetTexture(1).GetPixelFormat() == Pixel::CHROMINANCE_U && textureInformation.textureSet.GetTexture(2).GetPixelFormat() == Pixel::CHROMINANCE_V)
+        {
+          mNeedYuvToRgb = true;
+          UpdateShader();
+        }
+      }
     }
 
     if(actor)
     }
 
     if(actor)
@@ -1068,7 +1089,8 @@ Shader ImageVisual::GenerateShader() const
         .EnableRoundedCorner(IsRoundedCornerRequired())
         .EnableBorderline(IsBorderlineRequired())
         .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture())
         .EnableRoundedCorner(IsRoundedCornerRequired())
         .EnableBorderline(IsBorderlineRequired())
         .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture())
-        .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering));
+        .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering)
+        .EnableYuvToRgb(mNeedYuvToRgb));
   }
   else
   {
   }
   else
   {
index 17d5a6e..307ab19 100644 (file)
@@ -346,6 +346,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.
   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
 };
 
 } // namespace Internal
index c6e0a2c..768f743 100644 (file)
@@ -236,11 +236,15 @@ void SvgRasterizeThread::RemoveTask(SvgVisual* visual)
   ConditionalWait::ScopedLock lock(mConditionalWait);
   if(!mRasterizeTasks.empty())
   {
   ConditionalWait::ScopedLock lock(mConditionalWait);
   if(!mRasterizeTasks.empty())
   {
-    for(std::vector<SvgTaskPtr>::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it)
+    for(std::vector<SvgTaskPtr>::iterator it = mRasterizeTasks.begin(); it != mRasterizeTasks.end();)
     {
       if((*it) && (*it)->GetSvgVisual() == visual)
       {
     {
       if((*it) && (*it)->GetSvgVisual() == visual)
       {
-        mRasterizeTasks.erase(it);
+        it = mRasterizeTasks.erase(it);
+      }
+      else
+      {
+        it++;
       }
     }
   }
       }
     }
   }
index 193799c..52dbf61 100644 (file)
@@ -90,6 +90,10 @@ public:
     IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
     IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
     IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
     IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
     IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
     IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
+    IMAGE_SHADER_YUV_TO_RGB,
+    IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+    IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
+    IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB,
     NATIVE_IMAGE_SHADER,
     NATIVE_IMAGE_SHADER_ROUNDED_CORNER,
     NATIVE_IMAGE_SHADER_BORDERLINE,
     NATIVE_IMAGE_SHADER,
     NATIVE_IMAGE_SHADER_ROUNDED_CORNER,
     NATIVE_IMAGE_SHADER_BORDERLINE,
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.
  *
  * 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)
 {
 
 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)
 {
 }
 
 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,
 }
 
 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)
 {
                                 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)
 }
 
 bool AsyncImageLoader::Cancel(uint32_t loadingTaskId)