[Tizen] Apply precompile shader
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / image-visual-shader-factory.cpp
index 523c374..9af065d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/rendering/texture-devel.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #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
 {
-
 namespace
 {
-
 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 
-// global string variable to caching complate vertex shader
-static std::string gVertexShader;
-
-// global string variable to caching complate fragment shader (no atlas)
-static std::string gFragmentShaderNoAtlas;
+const int NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER;
 
 } // unnamed namespace
 
+static constexpr auto SHADER_TYPE_COUNT = 16u;
+
+const std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
+  "",                                                                                                        // VisualFactoryCache::IMAGE_SHADER,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                                                    //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  "#define IS_REQUIRED_BORDERLINE\n",                                                                        //VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n",                                    //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
+  "#define IS_REQUIRED_ALPHA_MASKING\n",                                                                     // VisualFactoryCache::IMAGE_SHADER_MASKING,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_ALPHA_MASKING\n",                                 //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+  "#define IS_REQUIRED_BORDERLINE\n#define IS_REQUIRED_ALPHA_MASKING\n",                                     //VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n#define IS_REQUIRED_ALPHA_MASKING\n", //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
+  "",                                                                                                        //VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                                                    //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  "#define IS_REQUIRED_BORDERLINE\n",                                                                        //VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n",                                    //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB};
+  "",                                                                                                        //VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                                                    //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+  "#define IS_REQUIRED_BORDERLINE\n",                                                                        //VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n"                                     //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB};
+};
+const std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
+  "",                                                                                                             // VisualFactoryCache::IMAGE_SHADER,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                                                         //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  "#define IS_REQUIRED_BORDERLINE\n",                                                                             //VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n",                                         //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
+  "#define IS_REQUIRED_ALPHA_MASKING\n",                                                                          // VisualFactoryCache::IMAGE_SHADER_MASKING,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_ALPHA_MASKING\n",                                      //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+  "#define IS_REQUIRED_BORDERLINE\n#define IS_REQUIRED_ALPHA_MASKING\n",                                          //VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n#define IS_REQUIRED_ALPHA_MASKING\n",      //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
+  "#define IS_REQUIRED_YUV_TO_RGB\n",                                                                             //VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+  "#define IS_REQUIRED_YUV_TO_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n",                                         //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  "#define IS_REQUIRED_YUV_TO_RGB\n#define IS_REQUIRED_BORDERLINE\n",                                             //VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
+  "#define IS_REQUIRED_YUV_TO_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n",         //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB};
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n",                                                                    //VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n",                                //VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n#define IS_REQUIRED_BORDERLINE\n",                                    //VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_BORDERLINE\n" //VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB};
+};
+
 ImageVisualShaderFactory::ImageVisualShaderFactory()
+: mFragmentShaderNeedChange(ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED)
 {
 }
 
@@ -54,65 +87,67 @@ ImageVisualShaderFactory::~ImageVisualShaderFactory()
 {
 }
 
-Shader ImageVisualShaderFactory::GetShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping, bool roundedCorner )
+Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, ImageVisualShaderFeatureBuilder& featureBuilder)
 {
-  Shader shader;
-  if( atlasing )
+  Shader                         shader;
+  VisualFactoryCache::ShaderType shaderType = featureBuilder.GetShaderType();
+
+  if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE &&
+     (mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED ||
+      mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE))
   {
-    if( defaultTextureWrapping )
-    {
-      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
-      if( !shader )
-      {
-        shader = Shader::New( Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
-                              Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ATLAS_CLAMP_SHADER_FRAG.data() );
-        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
-      }
-    }
-    else
-    {
-      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP );
-      if( !shader )
-      {
-        shader = Shader::New( Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
-                              Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ATLAS_VARIOUS_WRAP_SHADER_FRAG.data() );
-        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader );
-      }
-    }
+    shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) + NATIVE_SHADER_TYPE_OFFSET);
+  }
+
+  shader = factoryCache.GetShader(shaderType);
+  if(shader)
+  {
+    return shader;
   }
-  else
+
+  std::string vertexShaderPrefixList;
+  std::string fragmentShaderPrefixList;
+  featureBuilder.GetVertexShaderPrefixList(vertexShaderPrefixList);
+  featureBuilder.GetFragmentShaderPrefixList(fragmentShaderPrefixList);
+
+  std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
+  std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
+
+  if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
   {
-    if( roundedCorner )
+    bool modified = DevelTexture::ApplyNativeFragmentShader(featureBuilder.GetTexture(), fragmentShader);
+    if(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
     {
-      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER );
-      if( !shader )
-      {
-        shader = Shader::New( Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_ROUNDED_CORNER_SHADER_VERT.data(),
-                              Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ROUNDED_CORNER_SHADER_FRAG.data() );
-        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER, shader );
-      }
+      DALI_ASSERT_ALWAYS(modified && "NativeImageTexture need to change fragment shader. But DALI default image shader doesn't changed!");
     }
-    else
+    else if(DALI_UNLIKELY(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED))
     {
-      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
-      if( !shader )
+      mFragmentShaderNeedChange = (modified) ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
+
+      if(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE)
       {
-        shader = Shader::New( Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
-                              Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG.data() );
-        shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
+        shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) - NATIVE_SHADER_TYPE_OFFSET);
+        shader     = factoryCache.GetShader(shaderType);
       }
     }
   }
 
+  if(shader)
+  {
+    return shader;
+  }
+
+  shader = Shader::New(vertexShader, fragmentShader);
+  shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
+  factoryCache.SaveShader(shaderType, shader);
+
   return shader;
 }
 
 std::string_view ImageVisualShaderFactory::GetVertexShaderSource()
 {
+  // static string variable to cache complete vertex shader
+  static std::string gVertexShader;
   if(gVertexShader.empty())
   {
     gVertexShader = Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data();
@@ -123,13 +158,35 @@ std::string_view ImageVisualShaderFactory::GetVertexShaderSource()
 
 std::string_view ImageVisualShaderFactory::GetFragmentShaderSource()
 {
+  // static string variable to cache complete fragment shader (no atlas)
+  static std::string gFragmentShaderNoAtlas;
   if(gFragmentShaderNoAtlas.empty())
   {
-    gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG.data();
+    gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_FRAG.data();
   }
   return gFragmentShaderNoAtlas;
 }
 
+void ImageVisualShaderFactory::GetPrecompiledShader(RawShaderData& shaders)
+{
+  std::vector<std::string_view> vertexPrefix;
+  std::vector<std::string_view> fragmentPrefix;
+  shaders.shaderCount = 0;
+  int shaderCount     = 0;
+  for(int i = 0; i < SHADER_TYPE_COUNT; ++i)
+  {
+    vertexPrefix.push_back(VertexPredefines[i]);
+    fragmentPrefix.push_back(FragmentPredefines[i]);
+    shaderCount++;
+  }
+
+  shaders.vertexPrefix   = vertexPrefix;
+  shaders.fragmentPrefix = fragmentPrefix;
+  shaders.vertexShader   = SHADER_IMAGE_VISUAL_SHADER_VERT;
+  shaders.fragmentShader = SHADER_IMAGE_VISUAL_SHADER_FRAG;
+  shaders.shaderCount += shaderCount;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit