Supports precompile function 73/315273/13
authorsunghyun kim <scholb.kim@samsung.com>
Mon, 29 Jul 2024 08:54:27 +0000 (17:54 +0900)
committersunghyun kim <scholb.kim@samsung.com>
Mon, 2 Sep 2024 08:20:18 +0000 (17:20 +0900)
supports the precompile function that allows you to select a shader in the app

Change-Id: Ifda65fc292ac000d63164fac10f64bf11a953786

28 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-ImageVisualShaderFeatureBuilder.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/visual-factory/precompile-shader-option.cpp [new file with mode: 0644]
dali-toolkit/devel-api/visual-factory/precompile-shader-option.h [new file with mode: 0644]
dali-toolkit/devel-api/visual-factory/visual-factory.cpp
dali-toolkit/devel-api/visual-factory/visual-factory.h
dali-toolkit/internal/file.list
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/color/color-visual-shader-factory.cpp
dali-toolkit/internal/visuals/color/color-visual-shader-factory.h
dali-toolkit/internal/visuals/color/color-visual.cpp
dali-toolkit/internal/visuals/custom-shader-factory.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/custom-shader-factory.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-factory.cpp
dali-toolkit/internal/visuals/image/image-visual-shader-factory.h
dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.cpp
dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/text/text-visual-shader-factory.cpp
dali-toolkit/internal/visuals/text/text-visual-shader-factory.h
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h
dali-toolkit/internal/visuals/visual-shader-factory-interface.h [moved from dali-toolkit/devel-api/visual-factory/visual-shader-factory-interface.h with 51% similarity]

index 34122a2..0c9eef6 100644 (file)
@@ -35,7 +35,7 @@ int UtcImageVisualShaderFeatureBuilderSetGetProperty01(void)
 {
   ToolkitTestApplication application;
   tet_infoline("Register an ImageVisual and and perform an Action on Visual directly");
-  auto featureBuilder = Dali::Toolkit::Internal::ImageVisualShaderFeatureBuilder()
+  auto featureBuilder = Dali::Toolkit::Internal::ImageVisualShaderFeature::FeatureBuilder()
                           .EnableTextureAtlas(Dali::Toolkit::Internal::ImageVisualShaderFeature::TextureAtlas::ENABLED)
                           .ApplyDefaultTextureWrapMode(true);
 
@@ -63,7 +63,7 @@ int UtcImageVisualShaderFeatureBuilderSetGetProperty02(void)
 {
   ToolkitTestApplication application;
   tet_infoline("Register an ImageVisual and and perform an Action on Visual directly");
-  auto featureBuilder = Dali::Toolkit::Internal::ImageVisualShaderFeatureBuilder()
+  auto featureBuilder = Dali::Toolkit::Internal::ImageVisualShaderFeature::FeatureBuilder()
                           .EnableRoundedCorner(true)
                           .EnableBorderline(true)
                           .EnableAlphaMaskingOnRendering(true)
index 3ad2bb0..f6c58d8 100644 (file)
@@ -54,6 +54,15 @@ const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif";
 // resolution: 34*34, pixel format: RGBA8888
 static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
 
+// custom shader
+static const char* VertexSource =
+  "This is a custom vertex shader\n"
+  "made on purpose to look nothing like a normal vertex shader inside dali\n";
+
+static const char* FragmentSource =
+  "This is a custom fragment shader\n"
+  "made on purpose to look nothing like a normal fragment shader inside dali\n";
+
 Property::Map DefaultTransform()
 {
   Property::Map transformMap;
@@ -2890,10 +2899,10 @@ int UtcDaliVisualFactorySetGetDefaultCreationOptions(void)
   END_TEST;
 }
 
-int UtcDaliVisualFactoryGetPreCompiler(void)
+int UtcDaliVisualFactoryUsePreCompiledShader(void)
 {
   ToolkitTestApplication application;
-  tet_infoline("UtcDaliVisualFactoryGetAnimatedImageVisual2: Request animated image visual with a Property::Map, test custom wrap mode and pixel area");
+  tet_infoline("UtcDaliVisualFactoryUsePreCompiledShader: Test a UsePreCompiledShader fucntion");
 
   std::vector<RawShaderData> precompiledShaderList;
   DALI_TEST_CHECK(precompiledShaderList.size() == 0u); // before Get Shader
@@ -2903,6 +2912,73 @@ int UtcDaliVisualFactoryGetPreCompiler(void)
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK(factory);
 
+  Property::Map imageShader;
+  imageShader["shaderType"]   = "image";
+  imageShader["shaderOption"] = Property::Map().Add("YUV_AND_RGB", true);
+  imageShader["shaderName"]   = "IMAGE_SHADER_YUV_AND_RGB";
+
+  Property::Map imageShader2;
+  imageShader2["shaderType"]   = "image";
+  imageShader2["shaderOption"] = Property::Map()
+                                    .Add("ROUNDED_CORNER", true)
+                                    .Add("BORDERLINE", true)
+                                    .Add("MASKING", true);
+
+  Property::Map imageShader3;
+  imageShader3["shaderType"]   = "image";
+  imageShader3["shaderOption"] = Property::Map().Add("YUV_TO_RGB", true);
+
+  Property::Map imageShader4;
+  imageShader4["shaderType"]   = "image";
+  imageShader4["shaderOption"] = Property::Map().Add("ATLAS_DEFAULT", true);
+
+  Property::Map imageShader5;
+  imageShader5["shaderType"]   = "image";
+  imageShader5["shaderOption"] = Property::Map().Add("ATLAS_CUSTOM", true);
+
+  Property::Map textShader;
+  textShader["shaderType"]   = "text";
+  textShader["shaderOption"] = Property::Map()
+                                    .Add("MULTI_COLOR", true)
+                                    .Add("OVERLAY", true)
+                                    .Add("STYLES", true);
+
+  Property::Map textShader2;
+  textShader2["shaderType"]   = "text";
+  textShader2["shaderOption"] = Property::Map()
+                                    .Add("EMOJI", true);
+
+  Property::Map colorShader;
+  colorShader["shaderType"]   = "color";
+  colorShader["shaderOption"] = Property::Map()
+                                    .Add("CUTOUT", true)
+                                    .Add("BORDERLINE", true);
+
+  Property::Map colorShader2;
+  colorShader2["shaderType"]   = "color";
+  colorShader2["shaderOption"] = Property::Map()
+                                    .Add("ROUNDED_CORNER,", true)
+                                    .Add("BLUR_EDGE", true);
+
+
+  Property::Map customSHader;
+  customSHader["shaderType"]   = "custom";
+  customSHader["shaderName"]   = "myShader";
+  customSHader["vertexShader"] = VertexSource;
+  customSHader["fragmentShader"] = FragmentSource;
+
+  factory.AddPrecompileShader(imageShader);
+  factory.AddPrecompileShader(imageShader); // use same shader, because check line coverage
+  factory.AddPrecompileShader(imageShader2);
+  factory.AddPrecompileShader(imageShader3);
+  factory.AddPrecompileShader(imageShader4);
+  factory.AddPrecompileShader(imageShader5);
+  factory.AddPrecompileShader(textShader);
+  factory.AddPrecompileShader(textShader2);
+  factory.AddPrecompileShader(colorShader);
+  factory.AddPrecompileShader(colorShader2);
+  factory.AddPrecompileShader(customSHader);
+
   factory.UsePreCompiledShader();
 
   ShaderPreCompiler::Get().GetPreCompileShaderList(precompiledShaderList);
index b37f8a8..e260f49 100755 (executable)
@@ -84,6 +84,7 @@ SET( devel_api_src_files
   ${devel_api_src_dir}/visual-factory/transition-data.cpp
   ${devel_api_src_dir}/visual-factory/visual-factory.cpp
   ${devel_api_src_dir}/visual-factory/visual-base.cpp
+  ${devel_api_src_dir}/visual-factory/precompile-shader-option.cpp
   ${devel_api_src_dir}/controls/gaussian-blur-view/gaussian-blur-view.cpp
   ${devel_api_src_dir}/drag-drop-detector/drag-and-drop-detector.cpp
   ${devel_api_src_dir}/text/text-geometry-devel.cpp
@@ -183,7 +184,7 @@ SET( devel_api_visual_factory_header_files
   ${devel_api_src_dir}/visual-factory/transition-data.h
   ${devel_api_src_dir}/visual-factory/visual-factory.h
   ${devel_api_src_dir}/visual-factory/visual-base.h
-  ${devel_api_src_dir}/visual-factory/visual-shader-factory-interface.h
+  ${devel_api_src_dir}/visual-factory/precompile-shader-option.h
 )
 
 SET( devel_api_visuals_header_files
diff --git a/dali-toolkit/devel-api/visual-factory/precompile-shader-option.cpp b/dali-toolkit/devel-api/visual-factory/precompile-shader-option.cpp
new file mode 100644 (file)
index 0000000..fc96f95
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/visual-factory/precompile-shader-option.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace
+{
+  // TYPE
+  const char* TOKEN_TYPE("shaderType");
+  const char* TOKEN_TYPE_IMAGE("image");
+  const char* TOKEN_TYPE_TEXT("text");
+  const char* TOKEN_TYPE_COLOR("color");
+  const char* TOKEN_TYPE_MODEL_3D("3d");
+  const char* TOKEN_TYPE_CUSTOM("custom");
+
+  // OPTION
+  const char* TOKEN_OPTION("shaderOption");
+  const char* TOKEN_OPTION_ROUNDED_CORNER("ROUNDED_CORNER");
+  const char* TOKEN_OPTION_BORDERLINE("BORDERLINE");
+  const char* TOKEN_OPTION_BLUR_EDGE("BLUR_EDGE");
+  const char* TOKEN_OPTION_CUTOUT("CUTOUT");
+  const char* TOKEN_OPTION_ATLAS_DEFAULT("ATLAS_DEFAULT");
+  const char* TOKEN_OPTION_ATLAS_CUSTOM("ATLAS_CUSTOM");
+  const char* TOKEN_OPTION_MASKING("MASKING");
+  const char* TOKEN_OPTION_YUV_TO_RGB("YUV_TO_RGB");
+  const char* TOKEN_OPTION_YUV_AND_RGB("YUV_AND_RGB");
+  const char* TOKEN_OPTION_MULTI_COLOR("MULTI_COLOR");
+  const char* TOKEN_OPTION_STYLES("STYLES");
+  const char* TOKEN_OPTION_OVERLAY("OVERLAY");
+  const char* TOKEN_OPTION_EMOJI("EMOJI");
+
+  // CUSTOM
+  const char* TOKEN_CUSTOM_VERTEX("vertexShader");
+  const char* TOKEN_CUSTOM_FRAMENT("fragmentShader");
+  const char* TOKEN_CUSTOM_NAME("shaderName");
+}
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+PrecompileShaderOption::PrecompileShaderOption(const Property::Map& shaderOption)
+: mShaderType(ShaderType::UNKNOWN),
+  mShaderOptions(),
+  mShaderName(""),
+  mVertexShader(""),
+  mFragmentShader("")
+{
+  ConvertShaderMap(shaderOption);
+}
+
+void PrecompileShaderOption::ConvertShaderMap(const Property::Map& shaderOption)
+{
+  for(unsigned int shaderIdx = 0; shaderIdx < shaderOption.Count(); ++shaderIdx)
+  {
+    const KeyValuePair pair(shaderOption.GetKeyValue(shaderIdx));
+    if(pair.first.type == Property::Key::INDEX)
+    {
+        continue; // We don't consider index keys.
+    }
+
+    const std::string&     key(pair.first.stringKey);
+    const Property::Value& value(pair.second);
+
+    if(key == TOKEN_TYPE)
+    {
+      if(value.GetType() == Property::STRING)
+      {
+        auto shaderType = value.Get<std::string>();
+        if(shaderType == TOKEN_TYPE_IMAGE)
+        {
+          mShaderType = ShaderType::IMAGE;
+        }
+        else if(shaderType == TOKEN_TYPE_TEXT)
+        {
+          mShaderType = ShaderType::TEXT;
+        }
+        else if(shaderType == TOKEN_TYPE_COLOR)
+        {
+          mShaderType = ShaderType::COLOR;
+        }
+        else if(shaderType == TOKEN_TYPE_MODEL_3D)
+        {
+          mShaderType = ShaderType::MODEL_3D;
+        }
+        else if(shaderType == TOKEN_TYPE_CUSTOM)
+        {
+          mShaderType = ShaderType::CUSTOM;
+        }
+        else
+        {
+          mShaderType = ShaderType::UNKNOWN;
+        }
+      }
+
+      if(mShaderType == ShaderType::UNKNOWN)
+      {
+        DALI_LOG_ERROR("Can't find proper type.");
+        break;
+      }
+    }
+    else if(key == TOKEN_OPTION)
+    {
+      Property::Map optionMap = value.Get<Property::Map>();
+      for(size_t optionMapIdx = 0; optionMapIdx < optionMap.Count(); ++optionMapIdx)
+      {
+        const KeyValuePair optionPair(optionMap.GetKeyValue(optionMapIdx));
+
+        if(optionPair.first.type == Property::Key::INDEX)
+        {
+          continue; // We don't consider index keys.
+        }
+
+        const std::string&     optionKey(optionPair.first.stringKey);
+
+        if(optionKey == TOKEN_OPTION_ROUNDED_CORNER)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::ROUNDED_CORNER);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_BORDERLINE)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::BORDERLINE);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_CUTOUT)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::CUTOUT);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_ATLAS_DEFAULT)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::ATLAS_DEFAULT);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_ATLAS_CUSTOM)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::ATLAS_CUSTOM);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_BLUR_EDGE)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::BLUR_EDGE);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_MASKING)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::MASKING);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_YUV_TO_RGB)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::YUV_TO_RGB);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_YUV_AND_RGB)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::YUV_AND_RGB);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_MULTI_COLOR)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::MULTI_COLOR);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_STYLES)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::STYLES);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_OVERLAY)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::OVERLAY);
+          }
+        }
+        else if(optionKey == TOKEN_OPTION_EMOJI)
+        {
+          if(optionPair.second.Get<bool>())
+          {
+            mShaderOptions.push_back(Flag::EMOJI);
+          }
+        }
+        else
+        {
+          DALI_LOG_WARNING("Can't find this flag[%s] \n",optionKey.c_str());
+        }
+      }
+    }
+    else if(key == TOKEN_CUSTOM_VERTEX)
+    {
+      if(value.GetType() == Property::STRING)
+      {
+        mVertexShader = value.Get<std::string>();
+      }
+    }
+    else if(key == TOKEN_CUSTOM_FRAMENT)
+    {
+      if(value.GetType() == Property::STRING)
+      {
+        mFragmentShader = value.Get<std::string>();
+      }
+    }
+    else if(key == TOKEN_CUSTOM_NAME)
+    {
+      if(value.GetType() == Property::STRING)
+      {
+        mShaderName = value.Get<std::string>();
+      }
+    }
+  }
+}
+
+PrecompileShaderOption::ShaderType PrecompileShaderOption::GetShaderType() const
+{
+  return mShaderType;
+}
+
+std::vector<PrecompileShaderOption::Flag> PrecompileShaderOption::GetShaderOptions() const
+{
+  return mShaderOptions;
+}
+
+std::string PrecompileShaderOption::GetShaderName() const
+{
+  return mShaderName;
+}
+
+std::string PrecompileShaderOption::GetVertexShader() const
+{
+  return mVertexShader;
+}
+
+std::string PrecompileShaderOption::GetFragmentShader() const
+{
+  return mFragmentShader;
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/visual-factory/precompile-shader-option.h b/dali-toolkit/devel-api/visual-factory/precompile-shader-option.h
new file mode 100644 (file)
index 0000000..e6b5f89
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef DALI_TOOLKIT_PRECOMPILE_SHADER_OPTION_H_
+#define DALI_TOOLKIT_PRECOMPILE_SHADER_OPTION_H_
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <memory>
+#include <string>
+#include <string_view>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+/**
+ * @brief PrecompiledShaderOption is a class for precompiled shader option.
+ *
+ * Below is the available shader list for precompile
+ * -----------------------------------------------------------------
+ * COLOR_SHADER,
+ * COLOR_SHADER_ROUNDED_CORNER,
+ * COLOR_SHADER_BORDERLINE,
+ * COLOR_SHADER_ROUNDED_BORDERLINE,
+ * COLOR_SHADER_BLUR_EDGE,
+ * COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE,
+ * COLOR_SHADER_CUTOUT,
+ * COLOR_SHADER_CUTOUT_ROUNDED_CORNER,
+ * COLOR_SHADER_CUTOUT_BORDERLINE,
+ * COLOR_SHADER_CUTOUT_ROUNDED_BORDERLINE,
+ * COLOR_SHADER_CUTOUT_BLUR_EDGE,
+ * COLOR_SHADER_CUTOUT_ROUNDED_CORNER_BLUR_EDGE,
+ * IMAGE_SHADER,
+ * IMAGE_SHADER_ROUNDED_CORNER,
+ * IMAGE_SHADER_BORDERLINE,
+ * IMAGE_SHADER_ROUNDED_BORDERLINE,
+ * IMAGE_SHADER_MASKING,
+ * IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+ * IMAGE_SHADER_BORDERLINE_MASKING,
+ * 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,
+ * IMAGE_SHADER_YUV_AND_RGB,
+ * IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+ * IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
+ * IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY_AND_EMOJI,
+ * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY_AND_EMOJI,
+ * TEXT_SHADER_MULTI_COLOR_TEXT,
+ * TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
+ * TEXT_SHADER_MULTI_COLOR_TEXT_WITH_OVERLAY,
+ * TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
+ * -----------------------------------------------------------------
+ *
+ * Please refer to precompile-shader-option.cpp if you want to check string key for each shader flag
+ */
+class DALI_TOOLKIT_API PrecompileShaderOption
+{
+public:
+  enum class ShaderType
+  {
+    UNKNOWN = 0,
+    COLOR,
+    IMAGE,
+    TEXT,
+    MODEL_3D, // ToDO: Need to add more options
+    CUSTOM,
+  };
+
+  enum class Flag
+  {
+    ROUNDED_CORNER = 0,
+    BORDERLINE,
+    BLUR_EDGE,
+    CUTOUT,
+    ATLAS_DEFAULT,
+    ATLAS_CUSTOM,
+    MASKING,
+    YUV_TO_RGB,
+    YUV_AND_RGB,
+    NINE_PATCH,
+    MULTI_COLOR,
+    STYLES,
+    OVERLAY,
+    EMOJI,
+  };
+
+  PrecompileShaderOption(const Property::Map& shaderOption);
+  PrecompileShaderOption(const PrecompileShaderOption& rhs);
+  PrecompileShaderOption& operator=(const PrecompileShaderOption& rhs);
+
+  using ShaderOptions= std::vector<Flag>;
+
+public:
+  /**
+   * @brief Convert the shader option
+   * @param[in] shaderOption The shader option property map
+   */
+  void ConvertShaderMap(const Property::Map& shaderOption);
+
+  /**
+   * @brief Get the shader type
+   *
+   * @return The shader type
+   */
+  ShaderType GetShaderType() const;
+
+  /**
+   * @brief Get the shader optinons
+   *
+   * @return The shader options
+   */
+  ShaderOptions GetShaderOptions() const;
+
+  /**
+   * @brief Get the name of shader
+   * @return The shader name
+   */
+  std::string GetShaderName() const;
+
+  /**
+   * @brief Get the vertex shader
+   *
+   * @return The vertex shader
+   */
+  std::string GetVertexShader() const;
+
+  /**
+   * @brief Get the fragment shader
+   *
+   * @return The fragment shader
+   */
+  std::string GetFragmentShader() const;
+
+private:
+  ShaderType mShaderType;
+  std::vector<Flag> mShaderOptions;
+  std::string mShaderName;
+  std::string mVertexShader;
+  std::string mFragmentShader;
+};
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_PRECOMPILE_SHADER_OPTION_H_
index 24f4f7a..54fb3f3 100644 (file)
@@ -136,6 +136,11 @@ void VisualFactory::DiscardVisual(Visual::Base visual)
   GetImplementation(*this).DiscardVisual(visual);
 }
 
+bool VisualFactory::AddPrecompileShader(const Property::Map& map)
+{
+  return GetImplementation(*this).AddPrecompileShader(map);
+}
+
 void VisualFactory::UsePreCompiledShader()
 {
   GetImplementation(*this).UsePreCompiledShader();
index 13697d2..2ce5e8b 100644 (file)
@@ -175,6 +175,61 @@ public:
   void DiscardVisual(Visual::Base visual);
 
   /**
+   * @brief Adds a list of pre-compiled shaders to the visual factory.
+   *
+   * This function allows you to add the desired precompile shader to the list.
+   * you can set it through PropertyMap.
+   * you need to know the values for setting well to use them, so please refer to the explanation below.
+   *
+   * shaderType: Set the desired shader type. dali provides these type: "image","text","color","3d" and "custom"
+   * shaderOption: Set the desired shader option. dali provides these flag: dali provides a lot of shader options, so user need to check proper shader option.
+   * vertexShader: Set the vertext shader that user want. this is for custom shader.
+   * fragmentShader: Set the fragment shader that user want. this is for custom shader.
+   * shaderName: if user want to set shader name, use this. this is for custom shader.(optional)
+   *
+   *(example)
+   * // Precompile image and Custom shader
+   * // Image Case
+   *   Property::Map imageShader;
+   *   imageShader["shaderType"]   = "image";
+   *   imageShader["shaderOption"] = Property::Map().Add("YUV_AND_RGB", true);
+   *   imageShader["shaderName"]   = "IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB";
+   *
+   * // Text Case
+   *   Property::Map textShader;
+   *   textShader["shaderType"]   = "text";
+   *   textShader["shaderOption"] = Property::Map()
+   *                                       .Add("MULTI_COLOR", true)
+   *                                       .Add("OVERLAY", true);
+   * // Color Case
+   *   Property::Map colorShader;
+   *   colorShader["shaderType"]   = "color";
+   *   colorShader["shaderOption"] = Property::Map()
+   *                                   .Add("CUTOUT", true)
+   *                                   .Add("BORDERLINE", true);
+   * // Custom Case
+   *   Property::Map customShader;
+   *   customShader["shaderType"]      = "custom";
+   *   customShader["vertexShader"]    = "..."; // input vertexShader code
+   *   customShader["fragementShader"] = "..."; // input fragementShader code
+   *   customShader["shaderName"]      = "MyCustomShader";
+   *
+   *   // Add to Precompile Shader
+   *   VisualFactory factory = VisualFactory::Get();
+   *   factory.AddPrecompileShader(imageShader);
+   *   factory.AddPrecompileShader(textShader);
+   *   factory.AddPrecompileShader(colorShader);
+   *   factory.AddPrecompileShader(customShader);
+   *   factory.UsePreCompiledShader();
+   *
+   *  If you want to detail information about shader option. please refer to precompil-shader-option.h.
+   *
+   *  @param[in] map The shader information for precompile
+   *  @return True if shader is successfully added to the precompiled list, false otherwise.
+   */
+  bool AddPrecompileShader(const Property::Map& map);
+
+  /**
    * @brief Compile the visual shader in advance. Afterwards,
    * when a visual using a new shader is requested, the pre-compiled shader is used.
    *
index 735b3a4..48fd81e 100644 (file)
@@ -37,6 +37,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/visuals/border/border-visual.cpp
    ${toolkit_src_dir}/visuals/color/color-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/color/color-visual.cpp
+   ${toolkit_src_dir}/visuals/custom-shader-factory.cpp
    ${toolkit_src_dir}/visuals/gradient/gradient-visual.cpp
    ${toolkit_src_dir}/visuals/gradient/gradient.cpp
    ${toolkit_src_dir}/visuals/gradient/linear-gradient.cpp
index 803979a..79a57b6 100644 (file)
@@ -877,7 +877,7 @@ Shader AnimatedImageVisual::GenerateShader() const
   Shader shader;
   shader = mImageVisualShaderFactory.GetShader(
     mFactoryCache,
-    ImageVisualShaderFeatureBuilder()
+    ImageVisualShaderFeature::FeatureBuilder()
       .ApplyDefaultTextureWrapMode(defaultWrapMode)
       .EnableRoundedCorner(IsRoundedCornerRequired())
       .EnableBorderline(IsBorderlineRequired())
index 21c60ff..64c844d 100644 (file)
@@ -876,7 +876,7 @@ Shader AnimatedVectorImageVisual::GenerateShader() const
   {
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
-      ImageVisualShaderFeatureBuilder()
+      ImageVisualShaderFeature::FeatureBuilder()
         .EnableRoundedCorner(IsRoundedCornerRequired())
         .EnableBorderline(IsBorderlineRequired())
         .SetTextureForFragmentShaderCheck(mUseNativeImage ? mImpl->mRenderer.GetTextures().GetTexture(0) : Dali::Texture()));
index a79def5..c4ca4e9 100644 (file)
@@ -77,39 +77,42 @@ constexpr VisualFactoryCache::ShaderType ShaderTypePredefines[PREDEFINED_SHADER_
 };
 }
 
-ColorVisualShaderFeatureBuilder::ColorVisualShaderFeatureBuilder()
-: mColorRoundCorner(ColorVisualShaderFeature::RoundedCorner::DISABLED),
-  mColorBorderline(ColorVisualShaderFeature::Borderline::DISABLED),
-  mColorBlur(ColorVisualShaderFeature::Blur::DISABLED),
-  mColorCutout(ColorVisualShaderFeature::Cutout::DISABLED)
+namespace ColorVisualShaderFeature
+{
+
+FeatureBuilder::FeatureBuilder()
+: mColorRoundCorner(RoundedCorner::DISABLED),
+  mColorBorderline(Borderline::DISABLED),
+  mColorBlur(Blur::DISABLED),
+  mColorCutout(Cutout::DISABLED)
 {
 }
 
-ColorVisualShaderFeatureBuilder& ColorVisualShaderFeatureBuilder::EnableRoundCorner(bool enableRoundedCorner)
+FeatureBuilder& FeatureBuilder::EnableRoundCorner(bool enableRoundedCorner)
 {
-  mColorRoundCorner = (enableRoundedCorner ? ColorVisualShaderFeature::RoundedCorner::ENABLED : ColorVisualShaderFeature::RoundedCorner::DISABLED);
+  mColorRoundCorner = (enableRoundedCorner ? RoundedCorner::ENABLED : RoundedCorner::DISABLED);
   return *this;
 }
 
-ColorVisualShaderFeatureBuilder& ColorVisualShaderFeatureBuilder::EnableBorderLine(bool enableBorderLine)
+FeatureBuilder& FeatureBuilder::EnableBorderLine(bool enableBorderLine)
 {
-  mColorBorderline = (enableBorderLine ? ColorVisualShaderFeature::Borderline::ENABLED : ColorVisualShaderFeature::Borderline::DISABLED);
+  mColorBorderline = (enableBorderLine ? Borderline::ENABLED : Borderline::DISABLED);
   return *this;
 }
 
-ColorVisualShaderFeatureBuilder& ColorVisualShaderFeatureBuilder::EnableBlur(bool enableBlur)
+FeatureBuilder& FeatureBuilder::EnableBlur(bool enableBlur)
 {
-  mColorBlur = (enableBlur ? ColorVisualShaderFeature::Blur::ENABLED : ColorVisualShaderFeature::Blur::DISABLED);
+  mColorBlur = (enableBlur ? Blur::ENABLED : Blur::DISABLED);
   return *this;
 }
 
-ColorVisualShaderFeatureBuilder& ColorVisualShaderFeatureBuilder::EnableCutout(bool enableCutout)
+FeatureBuilder& FeatureBuilder::EnableCutout(bool enableCutout)
 {
-  mColorCutout = (enableCutout ? ColorVisualShaderFeature::Cutout::ENABLED : ColorVisualShaderFeature::Cutout::DISABLED);
+  mColorCutout = (enableCutout ? Cutout::ENABLED : Cutout::DISABLED);
   return *this;
 }
 
-VisualFactoryCache::ShaderType ColorVisualShaderFeatureBuilder::GetShaderType() const
+VisualFactoryCache::ShaderType FeatureBuilder::GetShaderType() const
 {
   VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::COLOR_SHADER;
   uint32_t  shaderTypeFlag = ColorVisualRequireFlag::DEFAULT;
@@ -131,33 +134,33 @@ VisualFactoryCache::ShaderType ColorVisualShaderFeatureBuilder::GetShaderType()
   return shaderType;
 }
 
-void ColorVisualShaderFeatureBuilder::GetVertexShaderPrefixList(std::string& vertexShaderPrefixList) const
+void FeatureBuilder::GetVertexShaderPrefixList(std::string& vertexShaderPrefixList) const
 {
-  if(mColorRoundCorner == ColorVisualShaderFeature::RoundedCorner::ENABLED)
+  if(mColorRoundCorner == RoundedCorner::ENABLED)
   {
     vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
   }
-  if(mColorBlur == ColorVisualShaderFeature::Blur::ENABLED)
+  if(mColorBlur == Blur::ENABLED)
   {
     vertexShaderPrefixList += "#define IS_REQUIRED_BLUR\n";
   }
-  if(mColorBorderline == ColorVisualShaderFeature::Borderline::ENABLED && mColorBlur == ColorVisualShaderFeature::RoundedCorner::DISABLED)
+  if(mColorBorderline == Borderline::ENABLED && mColorBlur == RoundedCorner::DISABLED)
   {
     vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
   }
-  if(mColorCutout == ColorVisualShaderFeature::Cutout::ENABLED)
+  if(mColorCutout == Cutout::ENABLED)
   {
     vertexShaderPrefixList += "#define IS_REQUIRED_CUTOUT\n";
   }
 }
 
-void ColorVisualShaderFeatureBuilder::GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList) const
+void FeatureBuilder::GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList) const
 {
-  if(mColorRoundCorner == ColorVisualShaderFeature::RoundedCorner::ENABLED)
+  if(mColorRoundCorner == RoundedCorner::ENABLED)
   {
     fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
   }
-  if(mColorBlur == ColorVisualShaderFeature::Blur::ENABLED)
+  if(mColorBlur == Blur::ENABLED)
   {
     fragmentShaderPrefixList += "#define IS_REQUIRED_BLUR\n";
     // If shader version doesn't support latest blur with corner radius, Let we use legacy code.
@@ -166,16 +169,18 @@ void ColorVisualShaderFeatureBuilder::GetFragmentShaderPrefixList(std::string& f
       fragmentShaderPrefixList += "#define SL_VERSION_LOW\n";
     }
   }
-  if(mColorBorderline == ColorVisualShaderFeature::Borderline::ENABLED && mColorBlur == ColorVisualShaderFeature::RoundedCorner::DISABLED)
+  if(mColorBorderline == Borderline::ENABLED && mColorBlur == RoundedCorner::DISABLED)
   {
     fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
   }
-  if(mColorCutout == ColorVisualShaderFeature::Cutout::ENABLED)
+  if(mColorCutout == Cutout::ENABLED)
   {
     fragmentShaderPrefixList += "#define IS_REQUIRED_CUTOUT\n";
   }
 }
 
+} // namespace ColorVisualShaderFeature
+
 ColorVisualShaderFactory::ColorVisualShaderFactory()
 {
 }
@@ -184,7 +189,7 @@ ColorVisualShaderFactory::~ColorVisualShaderFactory()
 {
 }
 
-Shader ColorVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const ColorVisualShaderFeatureBuilder& featureBuilder)
+Shader ColorVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const ColorVisualShaderFeature::FeatureBuilder& featureBuilder)
 {
   Shader                         shader;
   VisualFactoryCache::ShaderType  shaderType = featureBuilder.GetShaderType();
@@ -206,6 +211,21 @@ Shader ColorVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, con
 
 }
 
+bool ColorVisualShaderFactory::AddPrecompiledShader(PrecompileShaderOption& option)
+{
+  ShaderFlagList shaderOption = option.GetShaderOptions();
+
+  auto featureBuilder = ColorVisualShaderFeature::FeatureBuilder();
+  std::string vertexPrefixList;
+  std::string fragmentPrefixList;
+  CreatePrecompileShader(featureBuilder, shaderOption);
+
+  VisualFactoryCache::ShaderType type = featureBuilder.GetShaderType();
+  featureBuilder.GetVertexShaderPrefixList(vertexPrefixList);
+  featureBuilder.GetFragmentShaderPrefixList(fragmentPrefixList);
+  return SavePrecompileShader(type, vertexPrefixList, fragmentPrefixList );
+}
+
 void ColorVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
 {
   std::vector<std::string_view> vertexPrefix;
@@ -213,6 +233,16 @@ void ColorVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   std::vector<std::string_view> shaderName;
   int                           shaderCount = 0;
   shaders.shaderCount                       = 0;
+
+  // precompile requested shader first
+  for(uint32_t i = 0u; i < mRequestedPrecompileShader.size(); i++ )
+  {
+    vertexPrefix.push_back(mRequestedPrecompileShader[i].vertexPrefix);
+    fragmentPrefix.push_back(mRequestedPrecompileShader[i].fragmentPrefix);
+    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(mRequestedPrecompileShader[i].type, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+    shaderCount++;
+  }
+
   for(uint32_t i = 0u; i < PREDEFINED_SHADER_TYPE_COUNT; ++i)
   {
     vertexPrefix.push_back(VertexPredefines[i]);
@@ -227,6 +257,59 @@ void ColorVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   shaders.vertexShader   = SHADER_COLOR_VISUAL_SHADER_VERT;
   shaders.fragmentShader = SHADER_COLOR_VISUAL_SHADER_FRAG;
   shaders.shaderCount    = shaderCount;
+  shaders.custom = false;
+}
+
+void ColorVisualShaderFactory::CreatePrecompileShader(ColorVisualShaderFeature::FeatureBuilder& builder, const ShaderFlagList& option)
+{
+  for(uint32_t i = 0; i < option.size(); ++i)
+  {
+    if(option[i] == PrecompileShaderOption::Flag::ROUNDED_CORNER)
+    {
+      builder.EnableRoundCorner(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::BORDERLINE)
+    {
+      builder.EnableBorderLine(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::BLUR_EDGE)
+    {
+      builder.EnableBlur(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::CUTOUT)
+    {
+      builder.EnableCutout(true);
+    }
+  }
+}
+
+bool ColorVisualShaderFactory::SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix)
+{
+  for(uint32_t i = 0u; i< PREDEFINED_SHADER_TYPE_COUNT; i++)
+  {
+    if(ShaderTypePredefines[i] == shader)
+    {
+      DALI_LOG_WARNING("This shader already added list(%s).", Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+      return false;
+    }
+  }
+
+  for(uint32_t i = 0u; i< mRequestedPrecompileShader.size(); i++)
+  {
+    if(mRequestedPrecompileShader[i].type == shader)
+    {
+      DALI_LOG_WARNING("This shader already requsted(%s).", Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(mRequestedPrecompileShader[i].type, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+      return false;
+    }
+  }
+
+  RequestShaderInfo info;
+  info.type = shader;
+  info.vertexPrefix = vertexPrefix;
+  info.fragmentPrefix = fragmentPrefix;
+  mRequestedPrecompileShader.push_back(info);
+  DALI_LOG_RELEASE_INFO("Add precompile shader success!!(%s)",Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(shader, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+  return true;
 }
 
 } // namespace Internal
index f55ea45..7ef6f56 100644 (file)
@@ -22,7 +22,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-#include <dali-toolkit/devel-api/visual-factory/visual-shader-factory-interface.h>
+#include <dali-toolkit/internal/visuals/visual-shader-factory-interface.h>
 #include <string_view>
 
 namespace Dali
@@ -81,16 +81,15 @@ enum Type
   ENABLED       ///< Color visual uses Cutout
 };
 } // namespace Cutout
-} // namespace ColorVisualShaderFeature
 
-class ColorVisualShaderFeatureBuilder
+class FeatureBuilder
 {
 public:
-  ColorVisualShaderFeatureBuilder();
-  ColorVisualShaderFeatureBuilder& EnableRoundCorner(bool enableRoundCorner);
-  ColorVisualShaderFeatureBuilder& EnableBorderLine(bool enableBorderLine);
-  ColorVisualShaderFeatureBuilder& EnableBlur(bool enableBlur);
-  ColorVisualShaderFeatureBuilder& EnableCutout(bool enableCutout);
+  FeatureBuilder();
+  FeatureBuilder& EnableRoundCorner(bool enableRoundCorner);
+  FeatureBuilder& EnableBorderLine(bool enableBorderLine);
+  FeatureBuilder& EnableBlur(bool enableBlur);
+  FeatureBuilder& EnableCutout(bool enableCutout);
 
   VisualFactoryCache::ShaderType GetShaderType() const;
   void GetVertexShaderPrefixList(std::string& vertexShaderPrefixList) const;
@@ -114,11 +113,12 @@ public:
   }
 
 private:
-  ColorVisualShaderFeature::RoundedCorner::Type mColorRoundCorner : 2; ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
-  ColorVisualShaderFeature::Borderline::Type    mColorBorderline : 2;  ///< Whether use border line, or not. default as Borderline::DISABLED
-  ColorVisualShaderFeature::Blur::Type          mColorBlur : 2;        ///< Whether use blur, or not. default as Blur::DISABLED
-  ColorVisualShaderFeature::Cutout::Type        mColorCutout : 2;      ///< Whether use cutout, or not. default as Cutout::DISABLED
+  RoundedCorner::Type mColorRoundCorner : 2; ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
+  Borderline::Type    mColorBorderline : 2;  ///< Whether use border line, or not. default as Borderline::DISABLED
+  Blur::Type          mColorBlur : 2;        ///< Whether use blur, or not. default as Blur::DISABLED
+  Cutout::Type        mColorCutout : 2;      ///< Whether use cutout, or not. default as Cutout::DISABLED
 };
+} // namespace ColorVisualShaderFeature
 
 /**
  * ColorVisualShaderFactory is an object that provides and shares shaders between color visuals
@@ -143,14 +143,29 @@ public:
    * @param[in] featureBuilder Collection of current text shader's features
    * @return The standard text rendering shader with features.
   */
-  Shader GetShader(VisualFactoryCache& factoryCache, const ColorVisualShaderFeatureBuilder& featureBuilder);
+  Shader GetShader(VisualFactoryCache& factoryCache, const ColorVisualShaderFeature::FeatureBuilder& featureBuilder);
 
 public: // Implementation of VisualShaderFactoryInterface
   /**
+   * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::AddPrecompiledShader
+   */
+  bool AddPrecompiledShader(PrecompileShaderOption& option) override;
+
+  /**
    * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::GetPreCompiledShader
    */
   void GetPreCompiledShader(RawShaderData& shaders) override;
 
+private:
+  /**
+   * @brief Create pre-compiled shader for image with builder and option.
+   */
+  void CreatePrecompileShader(ColorVisualShaderFeature::FeatureBuilder& builder, const ShaderFlagList& option);
+  /**
+   * @brief Check if cached hash value is valid or not.
+   */
+  bool SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix);
+
 protected:
   /**
    * Undefined copy constructor.
index 9434672..5f3365c 100644 (file)
@@ -244,7 +244,7 @@ Shader ColorVisual::GenerateShader() const
 {
   Shader shader = mColorVisualShaderFactory.GetShader(
     mFactoryCache,
-    ColorVisualShaderFeatureBuilder()
+    ColorVisualShaderFeature::FeatureBuilder()
     .EnableBlur(IsBlurRequired())
     .EnableBorderLine(IsBorderlineRequired())
     .EnableRoundCorner(IsRoundedCornerRequired())
diff --git a/dali-toolkit/internal/visuals/custom-shader-factory.cpp b/dali-toolkit/internal/visuals/custom-shader-factory.cpp
new file mode 100644 (file)
index 0000000..3c86f13
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/custom-shader-factory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+CustomShaderFactory::CustomShaderFactory()
+{
+}
+
+CustomShaderFactory::~CustomShaderFactory()
+{
+}
+
+bool CustomShaderFactory::AddPrecompiledShader(PrecompileShaderOption& option)
+{
+  auto shaderName = option.GetShaderName();
+  auto vertexShader = option.GetVertexShader();
+  auto framentShader = option.GetFragmentShader();
+
+  RequestShaderInfo info;
+  info.name = shaderName;
+  info.vertexPrefix = vertexShader;
+  info.fragmentPrefix = framentShader;
+  mRequestedPrecompileShader.push_back(info);
+  DALI_LOG_RELEASE_INFO("Add custom precompile shader success!!(%s)", shaderName.c_str());
+  return true;
+}
+
+void CustomShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
+{
+  std::vector<std::string_view> vertexPrefix;
+  std::vector<std::string_view> fragmentPrefix;
+  std::vector<std::string_view> shaderName;
+  int                           shaderCount = 0;
+  shaders.shaderCount                       = 0;
+
+  // precompile requested shader first
+  for(uint32_t i = 0; i < mRequestedPrecompileShader.size(); i++ )
+  {
+    vertexPrefix.push_back(mRequestedPrecompileShader[i].vertexPrefix);
+    fragmentPrefix.push_back(mRequestedPrecompileShader[i].fragmentPrefix);
+    shaderName.push_back(mRequestedPrecompileShader[i].name);
+    shaderCount++;
+  }
+
+  shaders.vertexPrefix   = std::move(vertexPrefix);
+  shaders.fragmentPrefix = std::move(fragmentPrefix);
+  shaders.shaderName     = std::move(shaderName);
+  shaders.vertexShader   = ""; // Custom shader use prefix shader only. No need to set vertexShader and fragmentShader.
+  shaders.fragmentShader = ""; // Custom shader use prefix shader only. No need to set vertexShader and fragmentShader.
+  shaders.shaderCount    = std::move(shaderCount);
+  shaders.custom = true;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/custom-shader-factory.h b/dali-toolkit/internal/visuals/custom-shader-factory.h
new file mode 100644 (file)
index 0000000..b7e929f
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef DALI_TOOLKIT_CUSTOM_SHADER_FACTORY_H
+#define DALI_TOOLKIT_CUSTOM_SHADER_FACTORY_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/shader-precompiler.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <dali-toolkit/internal/visuals/visual-shader-factory-interface.h>
+#include <string_view>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+/**
+ * CustomShaderFactory is an object that provides custom shader
+ */
+class CustomShaderFactory : public VisualShaderFactoryInterface
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  CustomShaderFactory();
+
+  /**
+   * @brief Destructor
+   */
+  ~CustomShaderFactory() override;
+
+public: // Implementation of VisualShaderFactoryInterface
+  /**
+   * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::AddPrecompiledShader
+   */
+  bool AddPrecompiledShader(PrecompileShaderOption& option) override;
+
+  /**
+   * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::GetPreCompiledShader
+   */
+  void GetPreCompiledShader(RawShaderData& shaders) override;
+
+protected:
+  /**
+   * Undefined copy constructor.
+   */
+  CustomShaderFactory(const CustomShaderFactory&) = delete;
+
+  /**
+   * Undefined assignment operator.
+   */
+  CustomShaderFactory& operator=(const CustomShaderFactory& rhs) = delete;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_CUSTOM_SHADER_FACTORY_H
index b254426..81e2b85 100644 (file)
@@ -77,7 +77,7 @@ ImageVisualShaderFactory::~ImageVisualShaderFactory()
 {
 }
 
-Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const ImageVisualShaderFeatureBuilder& featureBuilder)
+Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const ImageVisualShaderFeature::FeatureBuilder& featureBuilder)
 {
   Shader                         shader;
   VisualFactoryCache::ShaderType shaderType = featureBuilder.GetShaderType();
@@ -174,6 +174,21 @@ std::string_view ImageVisualShaderFactory::GetFragmentShaderSource()
   return gFragmentShaderNoAtlas;
 }
 
+bool ImageVisualShaderFactory::AddPrecompiledShader(PrecompileShaderOption& option)
+{
+  ShaderFlagList shaderOption = option.GetShaderOptions();
+
+  auto featureBuilder = ImageVisualShaderFeature::FeatureBuilder();
+  std::string vertexPrefixList;
+  std::string fragmentPrefixList;
+  CreatePrecompileShader(featureBuilder, shaderOption);
+
+  VisualFactoryCache::ShaderType type = featureBuilder.GetShaderType();
+  featureBuilder.GetVertexShaderPrefixList(vertexPrefixList);
+  featureBuilder.GetFragmentShaderPrefixList(fragmentPrefixList);
+  return SavePrecompileShader(type, vertexPrefixList, fragmentPrefixList );
+}
+
 void ImageVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
 {
   std::vector<std::string_view> vertexPrefix;
@@ -181,7 +196,16 @@ void ImageVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   std::vector<std::string_view> shaderName;
   shaders.shaderCount = 0;
   int shaderCount     = 0;
-  for(uint32_t i = 0; i < PREDEFINED_SHADER_TYPE_COUNT; ++i)
+
+  for(uint32_t i = 0u; i < mRequestedPrecompileShader.size(); i++ )
+  {
+    vertexPrefix.push_back(mRequestedPrecompileShader[i].vertexPrefix);
+    fragmentPrefix.push_back(mRequestedPrecompileShader[i].fragmentPrefix);
+    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(mRequestedPrecompileShader[i].type, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+    shaderCount++;
+  }
+
+  for(uint32_t i = 0u; i < PREDEFINED_SHADER_TYPE_COUNT; ++i)
   {
     vertexPrefix.push_back(VertexPredefines[i]);
     fragmentPrefix.push_back(FragmentPredefines[i]);
@@ -195,6 +219,73 @@ void ImageVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   shaders.vertexShader   = SHADER_IMAGE_VISUAL_SHADER_VERT;
   shaders.fragmentShader = SHADER_IMAGE_VISUAL_SHADER_FRAG;
   shaders.shaderCount    = shaderCount;
+  shaders.custom = false;
+}
+
+void ImageVisualShaderFactory::CreatePrecompileShader(ImageVisualShaderFeature::FeatureBuilder& builder, const ShaderFlagList& option)
+{
+  for(uint32_t i = 0; i < option.size(); ++i)
+  {
+    if(option[i] == PrecompileShaderOption::Flag::ATLAS_DEFAULT)
+    {
+      builder.EnableTextureAtlas(true);
+      builder.ApplyDefaultTextureWrapMode(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::ATLAS_CUSTOM)
+    {
+      builder.EnableTextureAtlas(true);
+      builder.ApplyDefaultTextureWrapMode(false);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::ROUNDED_CORNER)
+    {
+      builder.EnableRoundedCorner(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::BORDERLINE)
+    {
+      builder.EnableBorderline(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::MASKING)
+    {
+      builder.EnableAlphaMaskingOnRendering(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::YUV_TO_RGB)
+    {
+      builder.EnableYuvToRgb(true, false);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::YUV_AND_RGB)
+    {
+      builder.EnableYuvToRgb(false, true);
+    }
+  }
+}
+
+bool ImageVisualShaderFactory::SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix)
+{
+  for(uint32_t i = 0u; i< PREDEFINED_SHADER_TYPE_COUNT; i++)
+  {
+    if(ShaderTypePredefines[i] == shader)
+    {
+      DALI_LOG_WARNING("This shader already added list(%s).", Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+      return false;
+    }
+  }
+
+  for(uint32_t i = 0u; i< mRequestedPrecompileShader.size(); i++)
+  {
+    if(mRequestedPrecompileShader[i].type == shader)
+    {
+      DALI_LOG_WARNING("This shader already requsted(%s).", Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(mRequestedPrecompileShader[i].type, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+      return false;
+    }
+  }
+
+  RequestShaderInfo info;
+  info.type = shader;
+  info.vertexPrefix = vertexPrefix;
+  info.fragmentPrefix = fragmentPrefix;
+  mRequestedPrecompileShader.push_back(info);
+  DALI_LOG_RELEASE_INFO("Add precompile shader success!!(%s)",Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(shader, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+  return true;
 }
 
 } // namespace Internal
index d79d258..e7af94a 100644 (file)
@@ -23,7 +23,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-#include <dali-toolkit/devel-api/visual-factory/visual-shader-factory-interface.h>
+#include <dali-toolkit/internal/visuals/visual-shader-factory-interface.h>
 #include <string_view>
 
 namespace Dali
@@ -32,6 +32,7 @@ namespace Toolkit
 {
 namespace Internal
 {
+
 /**
  * ImageVisualShaderFactory is an object that provides and shares shaders between image visuals
  */
@@ -54,7 +55,7 @@ public:
    * @param[in] featureBuilder Collection of current image shader's features
    * @return The standard image rendering shader with features.
    */
-  Shader GetShader(VisualFactoryCache& factoryCache, const ImageVisualShaderFeatureBuilder& featureBuilder);
+  Shader GetShader(VisualFactoryCache& factoryCache, const ImageVisualShaderFeature::FeatureBuilder& featureBuilder);
 
   /**
    * @brief Request the default vertex shader source.
@@ -70,10 +71,24 @@ public:
 
 public: // Implementation of VisualShaderFactoryInterface
   /**
+   * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::AddPrecompiledShader
+   */
+  bool AddPrecompiledShader(PrecompileShaderOption& option) override;
+  /**
    * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::GetPreCompiledShader
    */
   void GetPreCompiledShader(RawShaderData& shaders) override;
 
+private:
+  /**
+   * @brief Create pre-compiled shader for image with builder and option.
+   */
+  void CreatePrecompileShader(ImageVisualShaderFeature::FeatureBuilder& builder, const ShaderFlagList& option);
+  /**
+   * @brief Check if cached hash value is valid or not.
+   */
+  bool SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix);
+
 protected:
   /**
    * Undefined copy constructor.
index 34aab0c..de9b32d 100644 (file)
@@ -58,65 +58,67 @@ VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
     VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB};
 } // unnamed namespace
 
-ImageVisualShaderFeatureBuilder::ImageVisualShaderFeatureBuilder()
-: mTextureAtlas(ImageVisualShaderFeature::TextureAtlas::DISABLED),
-  mDefaultTextureWrapMode(ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY),
-  mRoundedCorner(ImageVisualShaderFeature::RoundedCorner::DISABLED),
-  mBorderline(ImageVisualShaderFeature::Borderline::DISABLED),
-  mAlphaMaskingOnRendering(ImageVisualShaderFeature::AlphaMaskingOnRendering::DISABLED),
-  mColorConversion(ImageVisualShaderFeature::ColorConversion::DONT_NEED),
+namespace ImageVisualShaderFeature
+{
+FeatureBuilder::FeatureBuilder()
+: mTextureAtlas(TextureAtlas::DISABLED),
+  mDefaultTextureWrapMode(DefaultTextureWrapMode::APPLY),
+  mRoundedCorner(RoundedCorner::DISABLED),
+  mBorderline(Borderline::DISABLED),
+  mAlphaMaskingOnRendering(AlphaMaskingOnRendering::DISABLED),
+  mColorConversion(ColorConversion::DONT_NEED),
   mTexture()
 {
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableTextureAtlas(bool enableTextureAtlas)
+FeatureBuilder& FeatureBuilder::EnableTextureAtlas(bool enableTextureAtlas)
 {
-  mTextureAtlas = (enableTextureAtlas ? ImageVisualShaderFeature::TextureAtlas::ENABLED : ImageVisualShaderFeature::TextureAtlas::DISABLED);
+  mTextureAtlas = (enableTextureAtlas ? TextureAtlas::ENABLED : TextureAtlas::DISABLED);
   return *this;
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode)
+FeatureBuilder& FeatureBuilder::ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode)
 {
-  mDefaultTextureWrapMode = (applyDefaultTextureWrapMode ? ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY : ImageVisualShaderFeature::DefaultTextureWrapMode::DO_NOT_APPLY);
+  mDefaultTextureWrapMode = (applyDefaultTextureWrapMode ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY);
   return *this;
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableRoundedCorner(bool enableRoundedCorner)
+FeatureBuilder& FeatureBuilder::EnableRoundedCorner(bool enableRoundedCorner)
 {
-  mRoundedCorner = (enableRoundedCorner ? ImageVisualShaderFeature::RoundedCorner::ENABLED : ImageVisualShaderFeature::RoundedCorner::DISABLED);
+  mRoundedCorner = (enableRoundedCorner ? RoundedCorner::ENABLED : RoundedCorner::DISABLED);
   return *this;
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableBorderline(bool enableBorderline)
+FeatureBuilder& FeatureBuilder::EnableBorderline(bool enableBorderline)
 {
-  mBorderline = (enableBorderline ? ImageVisualShaderFeature::Borderline::ENABLED : ImageVisualShaderFeature::Borderline::DISABLED);
+  mBorderline = (enableBorderline ? Borderline::ENABLED : Borderline::DISABLED);
   return *this;
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
+FeatureBuilder& FeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
 {
   mTexture = texture;
   return *this;
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
+FeatureBuilder& FeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
 {
-  mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED : ImageVisualShaderFeature::AlphaMaskingOnRendering::DISABLED);
+  mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? AlphaMaskingOnRendering::ENABLED : AlphaMaskingOnRendering::DISABLED);
   return *this;
 }
 
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb)
+FeatureBuilder& FeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb)
 {
-  mColorConversion = (enableUnifiedYuvAndRgb ? ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB : (enableYuvToRgb ? ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB : ImageVisualShaderFeature::ColorConversion::DONT_NEED));
+  mColorConversion = (enableUnifiedYuvAndRgb ? ColorConversion::UNIFIED_YUV_AND_RGB : (enableYuvToRgb ? ColorConversion::YUV_TO_RGB : ColorConversion::DONT_NEED));
   return *this;
 }
 
-VisualFactoryCache::ShaderType ImageVisualShaderFeatureBuilder::GetShaderType() const
+VisualFactoryCache::ShaderType FeatureBuilder::GetShaderType() const
 {
   VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER;
-  if(mTextureAtlas == ImageVisualShaderFeature::TextureAtlas::ENABLED)
+  if(mTextureAtlas == TextureAtlas::ENABLED)
   {
-    if(mDefaultTextureWrapMode == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
+    if(mDefaultTextureWrapMode == DefaultTextureWrapMode::APPLY)
     {
       shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP;
     }
@@ -128,23 +130,23 @@ VisualFactoryCache::ShaderType ImageVisualShaderFeatureBuilder::GetShaderType()
   else
   {
     uint32_t shaderTypeFlag = static_cast<uint32_t>(ImageVisualRequireFlag::DEFAULT);
-    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+    if(mRoundedCorner == RoundedCorner::ENABLED)
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ROUNDED_CORNER);
     }
-    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
+    if(mBorderline == Borderline::ENABLED)
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::BORDERLINE);
     }
-    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    if(mAlphaMaskingOnRendering == AlphaMaskingOnRendering::ENABLED)
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ALPHA_MASKING);
     }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB) // Not support gpu masking and color conversion at the same time now
+    else if(mColorConversion == ColorConversion::YUV_TO_RGB) // Not support gpu masking and color conversion at the same time now
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
     }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
+    else if(mColorConversion == ColorConversion::UNIFIED_YUV_AND_RGB)
     {
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
       shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::UNIFIED_YUV_AND_RGB);
@@ -155,37 +157,37 @@ VisualFactoryCache::ShaderType ImageVisualShaderFeatureBuilder::GetShaderType()
   return shaderType;
 }
 
-ImageVisualShaderFeature::ChangeFragmentShader::Type ImageVisualShaderFeatureBuilder::NeedToChangeFragmentShader() const
+ChangeFragmentShader::Type FeatureBuilder::NeedToChangeFragmentShader() const
 {
   return (mTexture && DevelTexture::IsNative(mTexture))
-           ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
-           : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
+           ? ChangeFragmentShader::NEED_CHANGE
+           : ChangeFragmentShader::DONT_CHANGE;
 }
 
-void ImageVisualShaderFeatureBuilder::GetVertexShaderPrefixList(std::string& vertexShaderPrefixList) const
+void FeatureBuilder::GetVertexShaderPrefixList(std::string& vertexShaderPrefixList) const
 {
-  if(mTextureAtlas != ImageVisualShaderFeature::TextureAtlas::ENABLED)
+  if(mTextureAtlas != TextureAtlas::ENABLED)
   {
-    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+    if(mRoundedCorner == RoundedCorner::ENABLED)
     {
       vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
     }
-    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
+    if(mBorderline == Borderline::ENABLED)
     {
       vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
     }
-    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    if(mAlphaMaskingOnRendering == AlphaMaskingOnRendering::ENABLED)
     {
       vertexShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
     }
   }
 }
 
-void ImageVisualShaderFeatureBuilder::GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList) const
+void FeatureBuilder::GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList) const
 {
-  if(mTextureAtlas == ImageVisualShaderFeature::TextureAtlas::ENABLED)
+  if(mTextureAtlas == TextureAtlas::ENABLED)
   {
-    if(mDefaultTextureWrapMode == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
+    if(mDefaultTextureWrapMode == DefaultTextureWrapMode::APPLY)
     {
       fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP\n";
     }
@@ -196,39 +198,41 @@ void ImageVisualShaderFeatureBuilder::GetFragmentShaderPrefixList(std::string& f
   }
   else
   {
-    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+    if(mRoundedCorner == RoundedCorner::ENABLED)
     {
       fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
     }
-    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
+    if(mBorderline == Borderline::ENABLED)
     {
       fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
     }
-    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    if(mAlphaMaskingOnRendering == AlphaMaskingOnRendering::ENABLED)
     {
       fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
     }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB)
+    else if(mColorConversion == ColorConversion::YUV_TO_RGB)
     {
       fragmentShaderPrefixList += "#define IS_REQUIRED_YUV_TO_RGB\n";
     }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
+    else if(mColorConversion == ColorConversion::UNIFIED_YUV_AND_RGB)
     {
       fragmentShaderPrefixList += "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n";
     }
   }
 }
 
-Dali::Texture ImageVisualShaderFeatureBuilder::GetTexture() const
+Dali::Texture FeatureBuilder::GetTexture() const
 {
   return mTexture;
 }
 
-bool ImageVisualShaderFeatureBuilder::IsEnabledAlphaMaskingOnRendering() const
+bool FeatureBuilder::IsEnabledAlphaMaskingOnRendering() const
 {
-  return mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED;
+  return mAlphaMaskingOnRendering == AlphaMaskingOnRendering::ENABLED;
 }
 
+} // namespace ImageVisualShaderFeature
+
 } // namespace Internal
 
 } // namespace Toolkit
index bef845f..d819cd3 100644 (file)
@@ -121,33 +121,31 @@ enum Type
 };
 } // namespace ColorConversion
 
-} // namespace ImageVisualShaderFeature
-
 /**
  * @brief Collection of current image visual feature. Only use for ImageVisualShaderFactory::GetShader()
  */
-class ImageVisualShaderFeatureBuilder
+class FeatureBuilder
 {
 public:
-  ImageVisualShaderFeatureBuilder();
+  FeatureBuilder();
 
-  ImageVisualShaderFeatureBuilder& EnableTextureAtlas(bool enableTextureAtlas);
+  FeatureBuilder& EnableTextureAtlas(bool enableTextureAtlas);
 
-  ImageVisualShaderFeatureBuilder& ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode);
+  FeatureBuilder& ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode);
 
-  ImageVisualShaderFeatureBuilder& EnableRoundedCorner(bool enableRoundedCorner);
+  FeatureBuilder& EnableRoundedCorner(bool enableRoundedCorner);
 
-  ImageVisualShaderFeatureBuilder& EnableBorderline(bool enableBorderline);
+  FeatureBuilder& EnableBorderline(bool enableBorderline);
 
-  ImageVisualShaderFeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
+  FeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
 
-  ImageVisualShaderFeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
+  FeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
 
-  ImageVisualShaderFeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb = false);
+  FeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb = false);
 
   VisualFactoryCache::ShaderType GetShaderType() const;
 
-  ImageVisualShaderFeature::ChangeFragmentShader::Type NeedToChangeFragmentShader() const;
+  ChangeFragmentShader::Type NeedToChangeFragmentShader() const;
 
   void GetVertexShaderPrefixList(std::string& vertexShaderPrefixList) const;
   void GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList) const;
@@ -157,15 +155,17 @@ public:
   bool IsEnabledAlphaMaskingOnRendering() const;
 
 private:
-  ImageVisualShaderFeature::TextureAtlas::Type            mTextureAtlas : 2;            ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED
-  ImageVisualShaderFeature::DefaultTextureWrapMode::Type  mDefaultTextureWrapMode : 2;  ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY
-  ImageVisualShaderFeature::RoundedCorner::Type           mRoundedCorner : 2;           ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
-  ImageVisualShaderFeature::Borderline::Type              mBorderline : 2;              ///< Whether use borderline, or not. default as Borderline::DISABLED
-  ImageVisualShaderFeature::AlphaMaskingOnRendering::Type mAlphaMaskingOnRendering : 2; ///< Whether use runtime alpha masking, or not. default as AlphaMaskingOnRendering::DISABLED
-  ImageVisualShaderFeature::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
+  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
 };
 
+} // namespace ImageVisualShaderFeature
+
 } // namespace Internal
 
 } // namespace Toolkit
index dff156f..a8342ac 100644 (file)
@@ -1314,7 +1314,7 @@ Shader ImageVisual::GenerateShader() const
     // Create and cache the standard shader
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
-      ImageVisualShaderFeatureBuilder()
+      ImageVisualShaderFeature::FeatureBuilder()
         .EnableTextureAtlas(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED && !useNativeImage)
         .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE)
         .EnableRoundedCorner(IsRoundedCornerRequired())
index f6cbe2f..f877b62 100644 (file)
@@ -332,7 +332,7 @@ void NPatchVisual::OnInitialize()
 {
   // Get basic geometry and shader
   Geometry geometry                        = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
-  auto     imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder();
+  auto     imageVisualShaderFeatureBuilder = ImageVisualShaderFeature::FeatureBuilder();
   Shader   shader                          = mImageVisualShaderFactory.GetShader(
     mFactoryCache,
     imageVisualShaderFeatureBuilder);
index 4597727..b84be14 100644 (file)
@@ -528,7 +528,7 @@ Shader SvgVisual::GenerateShader() const
   {
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
-      ImageVisualShaderFeatureBuilder()
+      ImageVisualShaderFeature::FeatureBuilder()
         .EnableTextureAtlas(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED)
         .EnableRoundedCorner(IsRoundedCornerRequired())
         .EnableBorderline(IsBorderlineRequired()));
index 62928b4..269754e 100644 (file)
@@ -184,13 +184,39 @@ Shader TextVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, cons
   return shader;
 }
 
+bool TextVisualShaderFactory::AddPrecompiledShader(PrecompileShaderOption& option)
+{
+  ShaderFlagList shaderOption = option.GetShaderOptions();
+
+  auto featureBuilder = TextVisualShaderFeature::FeatureBuilder();
+  std::string vertexPrefixList;
+  std::string fragmentPrefixList;
+  CreatePrecompileShader(featureBuilder, shaderOption);
+
+  VisualFactoryCache::ShaderType type = featureBuilder.GetShaderType();
+  featureBuilder.GetVertexShaderPrefixList(vertexPrefixList);
+  featureBuilder.GetFragmentShaderPrefixList(fragmentPrefixList);
+  return SavePrecompileShader(type, vertexPrefixList, fragmentPrefixList );
+}
+
+
 void TextVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
 {
   std::vector<std::string_view> vertexPrefix;
   std::vector<std::string_view> fragmentPrefix;
   std::vector<std::string_view> shaderName;
   int                           shaderCount = 0;
-  for(uint32_t i = 0; i < PREDEFINED_SHADER_TYPE_COUNT; ++i)
+
+  // precompile requested shader first
+  for(uint32_t i = 0u; i < mRequestedPrecompileShader.size(); i++ )
+  {
+    vertexPrefix.push_back(mRequestedPrecompileShader[i].vertexPrefix);
+    fragmentPrefix.push_back(mRequestedPrecompileShader[i].fragmentPrefix);
+    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(mRequestedPrecompileShader[i].type, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+    shaderCount++;
+  }
+
+  for(uint32_t i = 0u; i < PREDEFINED_SHADER_TYPE_COUNT; ++i)
   {
     vertexPrefix.push_back(VertexPredefines[i]);
     fragmentPrefix.push_back(FragmentPredefines[i]);
@@ -204,8 +230,64 @@ void TextVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   shaders.vertexShader   = SHADER_TEXT_VISUAL_SHADER_VERT;
   shaders.fragmentShader = SHADER_TEXT_VISUAL_SHADER_FRAG;
   shaders.shaderCount    = shaderCount;
+  shaders.custom = false;
+}
+
+void TextVisualShaderFactory::CreatePrecompileShader(TextVisualShaderFeature::FeatureBuilder& builder, const ShaderFlagList& option)
+{
+  for(uint32_t i = 0; i < option.size(); ++i)
+  {
+    if(option[i] == PrecompileShaderOption::Flag::STYLES)
+    {
+      builder.EnableStyle(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::OVERLAY)
+    {
+      builder.EnableOverlay(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::EMOJI)
+    {
+      builder.EnableEmoji(true);
+    }
+    else if(option[i] == PrecompileShaderOption::Flag::MULTI_COLOR)
+    {
+      builder.EnableMultiColor(true);
+    }
+    else
+    {
+      DALI_LOG_WARNING("Unknown option[%d]. maybe this type can't use this flag \n", option[i]);
+    }
+  }
 }
 
+bool TextVisualShaderFactory::SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix)
+{
+  for(uint32_t i = 0u; i< PREDEFINED_SHADER_TYPE_COUNT; i++)
+  {
+    if(ShaderTypePredefines[i] == shader)
+    {
+      DALI_LOG_WARNING("This shader already added list(%s).", Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+      return false;
+    }
+  }
+
+  for(uint32_t i = 0u; i< mRequestedPrecompileShader.size(); i++)
+  {
+    if(mRequestedPrecompileShader[i].type == shader)
+    {
+      DALI_LOG_WARNING("This shader already requsted(%s).", Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(mRequestedPrecompileShader[i].type, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+      return false;
+    }
+  }
+
+  RequestShaderInfo info;
+  info.type = shader;
+  info.vertexPrefix = vertexPrefix;
+  info.fragmentPrefix = fragmentPrefix;
+  mRequestedPrecompileShader.push_back(info);
+  DALI_LOG_RELEASE_INFO("Add precompile shader success!!(%s)",Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(shader, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+  return true;
+}
 } // namespace Internal
 
 } // namespace Toolkit
index f354f64..183f149 100644 (file)
@@ -22,7 +22,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-#include <dali-toolkit/devel-api/visual-factory/visual-shader-factory-interface.h>
+#include <dali-toolkit/internal/visuals/visual-shader-factory-interface.h>
 #include <string_view>
 
 namespace Dali
@@ -152,10 +152,26 @@ public:
 
 public: // Implementation of VisualShaderFactoryInterface
   /**
+   * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::AddPrecompiledShader
+   */
+  bool AddPrecompiledShader(PrecompileShaderOption& option) override;
+
+  /**
    * @copydoc Dali::Toolkit::VisualShaderFactoryInterface::GetPreCompiledShader
    */
   void GetPreCompiledShader(RawShaderData& shaders) override;
 
+private:
+  /**
+   * @brief Create pre-compiled shader for image with builder and option.
+   */
+  void CreatePrecompileShader(TextVisualShaderFeature::FeatureBuilder& builder, const ShaderFlagList& option);
+
+  /**
+   * @brief Check if cached hash value is valid or not.
+   */
+  bool SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix);
+
 protected:
   /**
    * Undefined copy constructor.
@@ -166,8 +182,6 @@ protected:
    * Undefined assignment operator.
    */
   TextVisualShaderFactory& operator=(const TextVisualShaderFactory& rhs);
-
-private:
 };
 
 } // namespace Internal
index da1874c..39b5720 100644 (file)
@@ -302,7 +302,7 @@ void TextVisual::OnInitialize()
 {
   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
   auto featureBuilder = TextVisualShaderFeature::FeatureBuilder();
-  Shader   shader   = GetTextShader(mFactoryCache, featureBuilder);
+  Shader shader = GetTextShader(mFactoryCache, featureBuilder);
 
   mImpl->mRenderer = VisualRenderer::New(geometry, shader);
   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
index 4c4c736..107cac4 100644 (file)
@@ -38,6 +38,7 @@
 #include <dali-toolkit/internal/visuals/border/border-visual.h>
 #include <dali-toolkit/internal/visuals/color/color-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
+#include <dali-toolkit/internal/visuals/custom-shader-factory.h>
 #include <dali-toolkit/internal/visuals/gradient/gradient-visual.h>
 #include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/image/image-visual.h>
@@ -417,6 +418,19 @@ void VisualFactory::DiscardVisual(Toolkit::Visual::Base visual)
   RegisterDiscardCallback();
 }
 
+bool VisualFactory::AddPrecompileShader(const Property::Map& map)
+{
+  PrecompileShaderOption shaderOption(map);
+  auto type = shaderOption.GetShaderType();
+  if(type == PrecompileShaderOption::ShaderType::UNKNOWN)
+  {
+    DALI_LOG_ERROR("AddPrecompileShader is failed. we can't find shader type");
+    return false;
+  }
+
+  return AddPrecompileShader(shaderOption);
+}
+
 void VisualFactory::UsePreCompiledShader()
 {
   if(mPrecompiledShaderRequested)
@@ -427,8 +441,6 @@ void VisualFactory::UsePreCompiledShader()
 
   ShaderPreCompiler::Get().Enable();
 
-  // To DO : Create all visual shader factory here.
-
   // Get image shader
   std::vector<RawShaderData> rawShaderList;
   RawShaderData              imageShaderData;
@@ -445,6 +457,12 @@ void VisualFactory::UsePreCompiledShader()
   GetColorVisualShaderFactory().GetPreCompiledShader(colorShaderData);
   rawShaderList.push_back(colorShaderData);
 
+  // Get 3D shader
+  // Get Custom shader
+  RawShaderData customShaderData;
+  GetCustomShaderFactory().GetPreCompiledShader(customShaderData);
+  rawShaderList.push_back(customShaderData);
+
   // Save all shader
   ShaderPreCompiler::Get().SavePreCompileShaderList(rawShaderList);
 }
@@ -523,6 +541,56 @@ ColorVisualShaderFactory& VisualFactory::GetColorVisualShaderFactory()
   return *mColorVisualShaderFactory;
 }
 
+CustomShaderFactory& VisualFactory::GetCustomShaderFactory()
+{
+  if(!mCustomShaderFactory)
+  {
+    mCustomShaderFactory = std::unique_ptr<CustomShaderFactory>(new CustomShaderFactory());
+  }
+  return *mCustomShaderFactory;
+}
+
+bool VisualFactory::AddPrecompileShader(PrecompileShaderOption& option)
+{
+  auto type = option.GetShaderType();
+  bool ret = false;
+  switch(type)
+  {
+    case PrecompileShaderOption::ShaderType::COLOR:
+    {
+      ret = GetColorVisualShaderFactory().AddPrecompiledShader(option);
+      break;
+    }
+    case PrecompileShaderOption::ShaderType::IMAGE:
+    {
+      ret = GetImageVisualShaderFactory().AddPrecompiledShader(option);
+      break;
+    }
+    case PrecompileShaderOption::ShaderType::TEXT:
+    {
+      ret = GetTextVisualShaderFactory().AddPrecompiledShader(option);
+      break;
+    }
+    case PrecompileShaderOption::ShaderType::MODEL_3D:
+    {
+      // TODO
+      break;
+    }
+    case PrecompileShaderOption::ShaderType::CUSTOM:
+    {
+      ret = GetCustomShaderFactory().AddPrecompiledShader(option);
+      break;
+    }
+    default:
+    {
+      DALI_LOG_ERROR("AddPrecompileShader is failed. we can't find shader factory type:%d",type);
+      break;
+    }
+  }
+
+  return ret;
+}
+
 void VisualFactory::OnDiscardCallback()
 {
   mIdleCallback = nullptr;
index 913ded2..5703f97 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
+#include <dali-toolkit/devel-api/visual-factory/precompile-shader-option.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/public-api/styling/style-manager.h>
 
@@ -38,6 +39,7 @@ class VisualFactoryCache;
 class ImageVisualShaderFactory;
 class TextVisualShaderFactory;
 class ColorVisualShaderFactory;
+class CustomShaderFactory;
 
 /**
  * @copydoc Toolkit::VisualFactory
@@ -113,6 +115,11 @@ public:
   void DiscardVisual(Toolkit::Visual::Base visual);
 
   /**
+   * @copydoc Toolkit::VisualFactory::AddPrecompileShader()
+   */
+  bool AddPrecompileShader(const Property::Map& map);
+
+  /**
    * @copydoc Toolkit::VisualFactory::UsePreCompiledShader()
    */
   void UsePreCompiledShader();
@@ -161,6 +168,19 @@ private:
   ColorVisualShaderFactory& GetColorVisualShaderFactory();
 
   /**
+   * Get the custom shader factory, creating it if necessary.
+   */
+   CustomShaderFactory& GetCustomShaderFactory();
+
+  /**
+   * @brief Add precompiled shader
+   * @param[in] shaderOption The option of precompiled shader
+   *
+   * @return True if add success, false otherwise.
+   */
+  bool AddPrecompileShader(PrecompileShaderOption& shaderOption);
+
+  /**
    * @brief Callbacks called for clear discarded visuals.
    */
   void OnDiscardCallback();
@@ -184,6 +204,7 @@ private:
   std::unique_ptr<ImageVisualShaderFactory> mImageVisualShaderFactory;
   std::unique_ptr<TextVisualShaderFactory>  mTextVisualShaderFactory;
   std::unique_ptr<ColorVisualShaderFactory> mColorVisualShaderFactory;
+  std::unique_ptr<CustomShaderFactory>      mCustomShaderFactory;
   SlotDelegate<VisualFactory>               mSlotDelegate;
   CallbackBase*                             mIdleCallback;
   using DiscardedVisualContainer = std::vector<Toolkit::Visual::Base>;
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
+#include <dali-toolkit/devel-api/visual-factory/precompile-shader-option.h>
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 
 namespace Dali
 {
 namespace Toolkit
 {
 
+using HashType = uint64_t;
+using ShaderFlagList = std::vector<PrecompileShaderOption::Flag>;
+
+namespace Internal
+{
 /**
  * @brief The VisualShaderFactoryInterface class provides a factory interface for creating visual shader
  */
-class DALI_TOOLKIT_API VisualShaderFactoryInterface
+class VisualShaderFactoryInterface
 {
 public:
-    VisualShaderFactoryInterface() = default;
-    virtual ~VisualShaderFactoryInterface() = default;
-
-    /**
-     * @brief Get precompiled shader for precompile
-     * @param[out] shaders shaderList for precompile
-     */
-    virtual void GetPreCompiledShader(RawShaderData& shaders) = 0;
+
+  /**
+   * @brief Structure to request shader info from visual shader factory.
+   */
+  struct RequestShaderInfo
+  {
+    VisualFactoryCache::ShaderType type;
+    std::string name;
+    std::string vertexPrefix;
+    std::string fragmentPrefix;
+  };
+
+  VisualShaderFactoryInterface() = default;
+  virtual ~VisualShaderFactoryInterface() = default;
+
+  /**
+   * @brief Add precompiled shader for precompile
+   * @param[in] option shaderList for precompile
+   */
+  virtual bool AddPrecompiledShader(PrecompileShaderOption& option) = 0;
+
+  /**
+   * @brief Get precompiled shader for precompile
+   * @param[out] shaders shaderList for precompile
+   */
+  virtual void GetPreCompiledShader(RawShaderData& shaders) = 0;
+
+protected:
+  std::vector<RequestShaderInfo> mRequestedPrecompileShader;
 };
 
+} // namespace Internal
 } // namespace Toolkit
 } // namespace Dali