Use RegisterUniqueProperty for some more renderers
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / color / color-visual.cpp
index 9ce3a29..21a1a70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,8 +23,8 @@
 #include <dali/integration-api/debug.h>
 
 //INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/visuals/color-visual-actions-devel.h>
 #include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
@@ -39,6 +39,29 @@ namespace Toolkit
 {
 namespace Internal
 {
+namespace
+{
+const int CUSTOM_PROPERTY_COUNT(12); // 5 transform properties + Blur Radius + Mix Color + border/corner
+
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[6] =
+  {
+    VisualFactoryCache::COLOR_SHADER,
+    VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER,
+    VisualFactoryCache::COLOR_SHADER_BORDERLINE,
+    VisualFactoryCache::COLOR_SHADER_ROUNDED_BORDERLINE,
+    VisualFactoryCache::COLOR_SHADER_BLUR_EDGE,
+    VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE,
+};
+
+// enum of required list when we select shader
+enum ColorVisualRequireFlag
+{
+  DEFAULT        = 0,
+  ROUNDED_CORNER = 1 << 0,
+  BORDERLINE     = 1 << 1,
+  BLUR           = 1 << 2,
+};
+} // unnamed namespace
 ColorVisualPtr ColorVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
 {
   ColorVisualPtr colorVisualPtr(new ColorVisual(factoryCache));
@@ -51,8 +74,7 @@ ColorVisual::ColorVisual(VisualFactoryCache& factoryCache)
 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR),
   mBlurRadius(0.0f),
   mBlurRadiusIndex(Property::INVALID_INDEX),
-  mRenderIfTransparent(false),
-  mNeedBlurRadius(false)
+  mAlwaysUsingBlurRadius(false)
 {
 }
 
@@ -87,15 +109,6 @@ void ColorVisual::DoSetProperties(const Property::Map& propertyMap)
     }
   }
 
-  Property::Value* renderIfTransparentValue = propertyMap.Find(Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, RENDER_IF_TRANSPARENT_NAME);
-  if(renderIfTransparentValue)
-  {
-    if(!renderIfTransparentValue->Get(mRenderIfTransparent))
-    {
-      DALI_LOG_ERROR("ColorVisual: renderIfTransparent property has incorrect type: %d\n", renderIfTransparentValue->GetType());
-    }
-  }
-
   Property::Value* blurRadiusValue = propertyMap.Find(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME);
   if(blurRadiusValue)
   {
@@ -103,17 +116,33 @@ void ColorVisual::DoSetProperties(const Property::Map& propertyMap)
     {
       DALI_LOG_ERROR("ColorVisual:DoSetProperties:: BLUR_RADIUS property has incorrect type: %d\n", blurRadiusValue->GetType());
     }
+
+    if(mBlurRadiusIndex != Property::INVALID_INDEX)
+    {
+      mImpl->mRenderer.SetProperty(mBlurRadiusIndex, mBlurRadius);
+    }
+    else if(DALI_UNLIKELY(mImpl->mRenderer && (!EqualsZero(mBlurRadius) || mAlwaysUsingBlurRadius)))
+    {
+      // Unusual case. SetProperty called after OnInitialize().
+      // Assume that DoAction call UPDATE_PROPERTY.
+      // We must regist properies into renderer, and update shader.
+
+      // BlurRadius added by this action. Regist property to renderer.
+      mBlurRadiusIndex = mImpl->mRenderer.RegisterUniqueProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+      mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+
+      // Change the shader must not be occured many times. we always have to use blur feature.
+      mAlwaysUsingBlurRadius = true;
+
+      // Change shader
+      UpdateShader();
+    }
   }
 }
 
 void ColorVisual::DoSetOnScene(Actor& actor)
 {
-  // Only add the renderer if it's not fully transparent
-  // We cannot avoid creating a renderer as it's used in the base class
-  if(mRenderIfTransparent || mImpl->mMixColor.a > 0.0f)
-  {
-    actor.AddRenderer(mImpl->mRenderer);
-  }
+  actor.AddRenderer(mImpl->mRenderer);
 
   // Color Visual generated and ready to display
   ResourceReady(Toolkit::Visual::ResourceStatus::READY);
@@ -129,7 +158,6 @@ void ColorVisual::DoCreatePropertyMap(Property::Map& map) const
   map.Clear();
   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   map.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor);
-  map.Insert(Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, mRenderIfTransparent);
 
   if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX)
   {
@@ -156,28 +184,11 @@ void ColorVisual::OnSetTransform()
   }
 }
 
-void ColorVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
-{
-  // Check if action is valid for this visual type and perform action if possible
-  switch(actionId)
-  {
-    case DevelColorVisual::Action::UPDATE_PROPERTY:
-    {
-      const Property::Map* map = attributes.GetMap();
-      if(map)
-      {
-        DoSetProperties(*map);
-      }
-      break;
-    }
-  }
-}
-
 void ColorVisual::UpdateShader()
 {
   if(mImpl->mRenderer)
   {
-    Shader shader = GetShader();
+    Shader shader = GenerateShader();
     mImpl->mRenderer.SetShader(shader);
   }
 }
@@ -186,9 +197,10 @@ void ColorVisual::OnInitialize()
 {
   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
 
-  Shader shader = GetShader();
+  Shader shader = GenerateShader();
 
   mImpl->mRenderer = Renderer::New(geometry, shader);
+  mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
 
   // ColorVisual has it's own index key for mix color - use this instead
   // of using the new base index to avoid changing existing applications
@@ -197,7 +209,7 @@ void ColorVisual::OnInitialize()
 
   if(!EqualsZero(mBlurRadius))
   {
-    mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+    mBlurRadiusIndex = mImpl->mRenderer.RegisterUniqueProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
     mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
   }
 
@@ -205,35 +217,55 @@ void ColorVisual::OnInitialize()
   mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 }
 
-Shader ColorVisual::GetShader()
+Shader ColorVisual::GenerateShader() const
 {
-  Shader shader;
-  if(!EqualsZero(mBlurRadius) || mNeedBlurRadius)
+  Shader                         shader;
+  VisualFactoryCache::ShaderType shaderType;
+
+  bool roundedCorner  = IsRoundedCornerRequired();
+  bool borderline     = IsBorderlineRequired();
+  bool blur           = !EqualsZero(mBlurRadius) || mAlwaysUsingBlurRadius;
+  int  shaderTypeFlag = ColorVisualRequireFlag::DEFAULT;
+
+  if(roundedCorner)
   {
-    shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER_BLUR_EDGE);
-    if(!shader)
-    {
-      shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_BLUR_EDGE_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_BLUR_EDGE_SHADER_FRAG.data());
-      mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER_BLUR_EDGE, shader);
-    }
+    shaderTypeFlag |= ColorVisualRequireFlag::ROUNDED_CORNER;
   }
-  else if(!IsRoundedCornerRequired())
+  if(blur)
   {
-    shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER);
-    if(!shader)
-    {
-      shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_SHADER_FRAG.data());
-      mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER, shader);
-    }
+    // If we use blur, just ignore borderline
+    borderline = false;
+    shaderTypeFlag |= ColorVisualRequireFlag::BLUR;
   }
-  else
+  if(borderline)
+  {
+    shaderTypeFlag |= ColorVisualRequireFlag::BORDERLINE;
+  }
+
+  shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+  shader     = mFactoryCache.GetShader(shaderType);
+  if(!shader)
   {
-    shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER);
-    if(!shader)
+    std::string vertexShaderPrefixList;
+    std::string fragmentShaderPrefixList;
+    if(roundedCorner)
     {
-      shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_ROUNDED_CORNER_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_ROUNDED_CORNER_SHADER_FRAG.data());
-      mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER, shader);
+      vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
     }
+    if(blur)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n";
+    }
+    if(borderline)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+    }
+    shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_VERT.data(),
+                         Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_FRAG.data());
+    mFactoryCache.SaveShader(shaderType, shader);
   }
 
   return shader;
@@ -251,9 +283,10 @@ Dali::Property ColorVisual::OnGetPropertyObject(Dali::Property::Key key)
   {
     mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
 
-    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+    // Blur is animated now. we always have to use blur feature.
+    mAlwaysUsingBlurRadius = true;
 
-    mNeedBlurRadius = true;
+    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
 
     // Change shader
     UpdateShader();