Add function for npatch in shader-precompile 98/316798/5
authorsunghyun kim <scholb.kim@samsung.com>
Wed, 28 Aug 2024 08:15:28 +0000 (17:15 +0900)
committersunghyun kim <scholb.kim@samsung.com>
Tue, 3 Sep 2024 08:47:54 +0000 (17:47 +0900)
Change-Id: I09f010409fb36701cd59cd52ca6cfc96c75574f7

automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/devel-api/visual-factory/precompile-shader-option.cpp
dali-toolkit/devel-api/visual-factory/precompile-shader-option.h
dali-toolkit/internal/file.list
dali-toolkit/internal/visuals/custom-shader-factory.cpp
dali-toolkit/internal/visuals/custom-shader-factory.h
dali-toolkit/internal/visuals/npatch-shader-factory.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch-shader-factory.h [new file with mode: 0644]
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h

index f6c58d8..7316c91 100644 (file)
@@ -2960,6 +2960,14 @@ int UtcDaliVisualFactoryUsePreCompiledShader(void)
                                     .Add("ROUNDED_CORNER,", true)
                                     .Add("BLUR_EDGE", true);
 
+  Property::Map npatchShader;
+  npatchShader["shaderType"]   = "npatch";
+
+  Property::Map npatchShader2;
+  npatchShader2["shaderType"]   = "npatch";
+  npatchShader2["shaderOption"] = Property::Map() .Add("MASKING", true);
+  npatchShader2["xStretchCount"] = 4;
+  npatchShader2["yStretchCount"] = 3;
 
   Property::Map customSHader;
   customSHader["shaderType"]   = "custom";
@@ -2977,6 +2985,8 @@ int UtcDaliVisualFactoryUsePreCompiledShader(void)
   factory.AddPrecompileShader(textShader2);
   factory.AddPrecompileShader(colorShader);
   factory.AddPrecompileShader(colorShader2);
+  factory.AddPrecompileShader(npatchShader);
+  factory.AddPrecompileShader(npatchShader2);
   factory.AddPrecompileShader(customSHader);
 
   factory.UsePreCompiledShader();
index fc96f95..39e924a 100644 (file)
@@ -29,6 +29,7 @@ namespace
   const char* TOKEN_TYPE_TEXT("text");
   const char* TOKEN_TYPE_COLOR("color");
   const char* TOKEN_TYPE_MODEL_3D("3d");
+  const char* TOKEN_TYPE_NPATCH("npatch");
   const char* TOKEN_TYPE_CUSTOM("custom");
 
   // OPTION
@@ -46,6 +47,9 @@ namespace
   const char* TOKEN_OPTION_STYLES("STYLES");
   const char* TOKEN_OPTION_OVERLAY("OVERLAY");
   const char* TOKEN_OPTION_EMOJI("EMOJI");
+  const char* TOKEN_OPTION_STRETCH_X("xStretchCount");
+  const char* TOKEN_OPTION_STRETCH_Y("yStretchCount");
+
 
   // CUSTOM
   const char* TOKEN_CUSTOM_VERTEX("vertexShader");
@@ -64,7 +68,9 @@ PrecompileShaderOption::PrecompileShaderOption(const Property::Map& shaderOption
   mShaderOptions(),
   mShaderName(""),
   mVertexShader(""),
-  mFragmentShader("")
+  mFragmentShader(""),
+  mNpatchXStretchCount(0),
+  mNpatchYStretchCount(0)
 {
   ConvertShaderMap(shaderOption);
 }
@@ -103,6 +109,10 @@ void PrecompileShaderOption::ConvertShaderMap(const Property::Map& shaderOption)
         {
           mShaderType = ShaderType::MODEL_3D;
         }
+        else if(shaderType == TOKEN_TYPE_NPATCH)
+        {
+          mShaderType = ShaderType::NPATCH;
+        }
         else if(shaderType == TOKEN_TYPE_CUSTOM)
         {
           mShaderType = ShaderType::CUSTOM;
@@ -251,6 +261,20 @@ void PrecompileShaderOption::ConvertShaderMap(const Property::Map& shaderOption)
         mShaderName = value.Get<std::string>();
       }
     }
+    else if(key == TOKEN_OPTION_STRETCH_X)
+    {
+      if(value.GetType() == Property::INTEGER)
+      {
+        mNpatchXStretchCount = value.Get<int>();
+      }
+    }
+    else if(key == TOKEN_OPTION_STRETCH_Y)
+    {
+      if(value.GetType() == Property::INTEGER)
+      {
+        mNpatchYStretchCount = value.Get<int>();
+      }
+    }
   }
 }
 
@@ -279,6 +303,16 @@ std::string PrecompileShaderOption::GetFragmentShader() const
   return mFragmentShader;
 }
 
+uint32_t PrecompileShaderOption::GetNpatchXStretchCount() const
+{
+  return mNpatchXStretchCount;
+}
+
+uint32_t PrecompileShaderOption::GetNpatchYStretchCount()  const
+{
+  return mNpatchYStretchCount;
+}
+
 } // namespace Toolkit
 
 } // namespace Dali
index e6b5f89..4dc46e0 100644 (file)
@@ -69,6 +69,18 @@ namespace Toolkit
  * IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
  * IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
  * IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB,
+ * NATIVE_IMAGE_SHADER,
+ * NATIVE_IMAGE_SHADER_ROUNDED_CORNER,
+ * NATIVE_IMAGE_SHADER_BORDERLINE,
+ * NATIVE_IMAGE_SHADER_ROUNDED_BORDERLINE,
+ * NATIVE_IMAGE_SHADER_MASKING,
+ * NATIVE_IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+ * NATIVE_IMAGE_SHADER_BORDERLINE_MASKING,
+ * NATIVE_IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
+ * NATIVE_IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
+ * NATIVE_IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
+ * NINE_PATCH_SHADER,
+ * NINE_PATCH_MASK_SHADER,
  * TEXT_SHADER_SINGLE_COLOR_TEXT,
  * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE,
  * TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY,
@@ -94,6 +106,7 @@ public:
     COLOR,
     IMAGE,
     TEXT,
+    NPATCH,
     MODEL_3D, // ToDO: Need to add more options
     CUSTOM,
   };
@@ -114,6 +127,9 @@ public:
     STYLES,
     OVERLAY,
     EMOJI,
+    NATIVE,
+    STRETCH_X,
+    STRETCH_Y,
   };
 
   PrecompileShaderOption(const Property::Map& shaderOption);
@@ -163,12 +179,28 @@ public:
    */
   std::string GetFragmentShader() const;
 
+  /**
+   * @brief Get the XStretchCount for npatch
+   *
+   * @return The NpatchXStretchCount
+   */
+  uint32_t GetNpatchXStretchCount() const;
+
+    /**
+   * @brief Get the YStretchCount for npatch
+   *
+   * @return The NpatchYStretchCount
+   */
+  uint32_t GetNpatchYStretchCount() const;
+
 private:
   ShaderType mShaderType;
   std::vector<Flag> mShaderOptions;
   std::string mShaderName;
   std::string mVertexShader;
   std::string mFragmentShader;
+  uint32_t mNpatchXStretchCount;
+  uint32_t mNpatchYStretchCount;
 };
 
 } // namespace Toolkit
index 48fd81e..4464dbb 100644 (file)
@@ -38,6 +38,7 @@ SET( toolkit_src_files
    ${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/npatch-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 3c86f13..e0b345c 100644 (file)
@@ -41,15 +41,8 @@ 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;
+  auto fragmentShader = option.GetFragmentShader();
+  return SavePrecompileShader(shaderName, vertexShader, fragmentShader);
 }
 
 void CustomShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
@@ -78,6 +71,17 @@ void CustomShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
   shaders.custom = true;
 }
 
+bool CustomShaderFactory::SavePrecompileShader(std::string& shaderName, std::string& vertexShader, std::string& fragmentShader)
+{
+  RequestShaderInfo info;
+  info.name = shaderName;
+  info.vertexPrefix = vertexShader;
+  info.fragmentPrefix = fragmentShader;
+  mRequestedPrecompileShader.push_back(info);
+  DALI_LOG_RELEASE_INFO("Add precompile shader success!!(%s)",shaderName.c_str());
+  return true;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index b7e929f..5401c73 100644 (file)
@@ -59,6 +59,12 @@ public: // Implementation of VisualShaderFactoryInterface
    */
   void GetPreCompiledShader(RawShaderData& shaders) override;
 
+private:
+  /**
+   * @brief Save the custom shader
+   */
+  bool SavePrecompileShader(std::string& shaderName, std::string& vertexPrefix, std::string& fragmentPrefix);
+
 protected:
   /**
    * Undefined copy constructor.
diff --git a/dali-toolkit/internal/visuals/npatch-shader-factory.cpp b/dali-toolkit/internal/visuals/npatch-shader-factory.cpp
new file mode 100644 (file)
index 0000000..26fa64c
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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/npatch-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
+{
+
+NpatchShaderFactory::NpatchShaderFactory()
+: mNpatchXStretchCount(0),
+  mNpatchYStretchCount(0),
+  mNpatchMaskingEnable(false)
+{
+}
+
+NpatchShaderFactory::~NpatchShaderFactory()
+{
+}
+
+bool NpatchShaderFactory::AddPrecompiledShader(PrecompileShaderOption& option)
+{
+  ShaderFlagList shaderOption = option.GetShaderOptions();
+
+  // Find Masking flag
+  for(uint32_t i = 0; i < shaderOption.size(); ++i)
+  {
+    if(shaderOption[i] == PrecompileShaderOption::Flag::MASKING)
+    {
+      mNpatchMaskingEnable = true;
+    }
+  }
+
+  mNpatchXStretchCount = option.GetNpatchXStretchCount();
+  mNpatchYStretchCount = option.GetNpatchYStretchCount();
+
+  std::string vertexShader;
+  std::string fragmentShader;
+  GetVertexShader(vertexShader);
+  GetFragmentShader(fragmentShader);
+
+  VisualFactoryCache::ShaderType shaderType =  mNpatchMaskingEnable? VisualFactoryCache::ShaderType::NINE_PATCH_MASK_SHADER : VisualFactoryCache::ShaderType::NINE_PATCH_SHADER;
+  return SavePrecompileShader(shaderType, vertexShader, fragmentShader);
+}
+
+void NpatchShaderFactory::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;
+}
+
+void NpatchShaderFactory::GetVertexShader(std::string& vertexShader) const
+{
+  if(DALI_LIKELY((mNpatchXStretchCount == 1 && mNpatchYStretchCount == 1) ||
+                  (mNpatchXStretchCount == 0 && mNpatchYStretchCount == 0)))
+  {
+    vertexShader += SHADER_NPATCH_VISUAL_3X3_SHADER_VERT;
+  }
+  else if(mNpatchXStretchCount > 0 || mNpatchYStretchCount > 0)
+  {
+    std::stringstream vertextShaderStream;
+    vertextShaderStream << "#define FACTOR_SIZE_X " << mNpatchXStretchCount + 2 << "\n"
+                        << "#define FACTOR_SIZE_Y " << mNpatchYStretchCount + 2 << "\n"
+                        << SHADER_NPATCH_VISUAL_SHADER_VERT;
+    vertexShader += vertextShaderStream.str();
+  }
+}
+
+void NpatchShaderFactory::GetFragmentShader(std::string& fragmentShader) const
+{
+  fragmentShader += (mNpatchMaskingEnable ? SHADER_NPATCH_VISUAL_MASK_SHADER_FRAG : SHADER_NPATCH_VISUAL_SHADER_FRAG);
+}
+
+bool NpatchShaderFactory::SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexShader, std::string& fragmentShader)
+{
+  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;
+    }
+  }
+
+  std::string shaderName = Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(shader, VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT);
+  if(!((mNpatchXStretchCount == 1 && mNpatchYStretchCount == 1) || (mNpatchXStretchCount == 0 && mNpatchYStretchCount == 0)))
+  {
+    if(mNpatchXStretchCount > 0 || mNpatchYStretchCount > 0)
+    {
+      std::stringstream shaderNameStream;
+      shaderNameStream << "NINE_PATCH_SHADER_" << mNpatchXStretchCount << "x" << mNpatchYStretchCount;
+      shaderName = shaderNameStream.str();
+    }
+  }
+
+  RequestShaderInfo info;
+  info.type = shader;
+  info.name = shaderName;
+  info.vertexPrefix = vertexShader;
+  info.fragmentPrefix = fragmentShader;
+  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
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/npatch-shader-factory.h b/dali-toolkit/internal/visuals/npatch-shader-factory.h
new file mode 100644 (file)
index 0000000..c3c42f4
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef DALI_TOOLKIT_NPATCH_SHADER_FACTORY_H
+#define DALI_TOOLKIT_NPATCH_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
+{
+
+/**
+ * NpatchShaderFactory is an object that provides custom shader
+ */
+class NpatchShaderFactory : public VisualShaderFactoryInterface
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  NpatchShaderFactory();
+
+  /**
+   * @brief Destructor
+   */
+  ~NpatchShaderFactory() 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;
+
+private:
+  /**
+   * @brief Get the NPatch vertex shader. this is used for generating pre-compiled shader.
+   */
+  void GetVertexShader(std::string& vertexShader) const;
+
+  /**
+   * @brief Get the NPatch fragment shader. this is used for generating pre-compiled shader
+   */
+  void GetFragmentShader(std::string& fragmentShader) const;
+
+  /**
+   * @brief Save the npatch shader
+   */
+  bool SavePrecompileShader(VisualFactoryCache::ShaderType shader, std::string& vertexPrefix, std::string& fragmentPrefix);
+
+protected:
+  /**
+   * Undefined copy constructor.
+   */
+  NpatchShaderFactory(const NpatchShaderFactory&) = delete;
+
+  /**
+   * Undefined assignment operator.
+   */
+  NpatchShaderFactory& operator=(const NpatchShaderFactory& rhs) = delete;
+
+private:
+  // For Npatch
+  uint32_t mNpatchXStretchCount;
+  uint32_t mNpatchYStretchCount;
+  bool     mNpatchMaskingEnable;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_NPATCH_SHADER_FACTORY_H
index 107cac4..8242f75 100644 (file)
@@ -39,6 +39,7 @@
 #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/npatch-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>
@@ -457,6 +458,10 @@ void VisualFactory::UsePreCompiledShader()
   GetColorVisualShaderFactory().GetPreCompiledShader(colorShaderData);
   rawShaderList.push_back(colorShaderData);
 
+  RawShaderData npatchShaderData;
+  GetNpatchShaderFactory().GetPreCompiledShader(npatchShaderData);
+  rawShaderList.push_back(npatchShaderData);
+
   // Get 3D shader
   // Get Custom shader
   RawShaderData customShaderData;
@@ -541,6 +546,15 @@ ColorVisualShaderFactory& VisualFactory::GetColorVisualShaderFactory()
   return *mColorVisualShaderFactory;
 }
 
+NpatchShaderFactory& VisualFactory::GetNpatchShaderFactory()
+{
+  if(!mNpatchShaderFactory)
+  {
+    mNpatchShaderFactory = std::unique_ptr<NpatchShaderFactory>(new NpatchShaderFactory());
+  }
+  return *mNpatchShaderFactory;
+}
+
 CustomShaderFactory& VisualFactory::GetCustomShaderFactory()
 {
   if(!mCustomShaderFactory)
@@ -571,6 +585,10 @@ bool VisualFactory::AddPrecompileShader(PrecompileShaderOption& option)
       ret = GetTextVisualShaderFactory().AddPrecompiledShader(option);
       break;
     }
+    case PrecompileShaderOption::ShaderType::NPATCH:
+    {
+      ret = GetNpatchShaderFactory().AddPrecompiledShader(option);
+    }
     case PrecompileShaderOption::ShaderType::MODEL_3D:
     {
       // TODO
index 5703f97..9aec117 100644 (file)
@@ -39,6 +39,7 @@ class VisualFactoryCache;
 class ImageVisualShaderFactory;
 class TextVisualShaderFactory;
 class ColorVisualShaderFactory;
+class NpatchShaderFactory;
 class CustomShaderFactory;
 
 /**
@@ -168,9 +169,14 @@ private:
   ColorVisualShaderFactory& GetColorVisualShaderFactory();
 
   /**
+   * Get the npatch shader factory, creating it if necessary.
+   */
+  NpatchShaderFactory& GetNpatchShaderFactory();
+
+  /**
    * Get the custom shader factory, creating it if necessary.
    */
-   CustomShaderFactory& GetCustomShaderFactory();
+  CustomShaderFactory& GetCustomShaderFactory();
 
   /**
    * @brief Add precompiled shader
@@ -204,6 +210,7 @@ private:
   std::unique_ptr<ImageVisualShaderFactory> mImageVisualShaderFactory;
   std::unique_ptr<TextVisualShaderFactory>  mTextVisualShaderFactory;
   std::unique_ptr<ColorVisualShaderFactory> mColorVisualShaderFactory;
+  std::unique_ptr<NpatchShaderFactory>      mNpatchShaderFactory;
   std::unique_ptr<CustomShaderFactory>      mCustomShaderFactory;
   SlotDelegate<VisualFactory>               mSlotDelegate;
   CallbackBase*                             mIdleCallback;