Refactoring VisualActions
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / color / color-visual.cpp
index 68dc04a..73b0931 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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 "color-visual.h"
 
 // EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/integration-api/debug.h>
 
 //INTERNAL INCLUDES
-#include <dali-toolkit/public-api/visuals/color-visual-properties.h>
-#include <dali-toolkit/public-api/visuals/visual-properties.h>
 #include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
-#include <dali-toolkit/devel-api/visuals/color-visual-actions-devel.h>
-#include <dali-toolkit/internal/visuals/visual-factory-impl.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>
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
+#include <dali-toolkit/public-api/visuals/color-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
 
 namespace Dali
 {
-
 namespace Toolkit
 {
-
 namespace Internal
 {
-
 namespace
 {
-
-const char* VERTEX_SHADER =
-  "INPUT mediump vec2 aPosition;\n"
-
-  "uniform highp mat4 uMvpMatrix;\n"
-  "uniform highp vec3 uSize;\n"
-
-  "//Visual size and offset\n"
-  "uniform mediump vec2 offset;\n"
-  "uniform highp vec2 size;\n"
-  "uniform mediump vec4 offsetSizeMode;\n"
-  "uniform mediump vec2 origin;\n"
-  "uniform mediump vec2 anchorPoint;\n"
-  "uniform mediump vec2 extraSize;\n"
-
-  "vec4 ComputeVertexPosition()\n"
-  "{\n"
-  "  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;\n"
-  "  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n"
-  "  return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n"
-  "}\n"
-
-  "void main()\n"
-  "{\n"
-  "  gl_Position = uMvpMatrix * ComputeVertexPosition();\n"
-  "}\n";
-
-
-const char* FRAGMENT_SHADER =
-  "uniform lowp vec4 uColor;\n"
-  "uniform lowp vec3 mixColor;\n"
-
-  "void main()\n"
-  "{\n"
-  "  OUT_COLOR = vec4(mixColor, 1.0) * uColor;\n"
-  "}\n";
-
-const char* VERTEX_SHADER_ROUNDED_CORNER =
-  "INPUT mediump vec2 aPosition;\n"
-  "OUTPUT mediump vec2 vPosition;\n"
-  "OUTPUT mediump vec2 vRectSize;\n"
-  "OUTPUT mediump float vCornerRadius;\n"
-
-  "uniform highp mat4 uMvpMatrix;\n"
-  "uniform highp vec3 uSize;\n"
-
-  "//Visual size and offset\n"
-  "uniform mediump vec2 offset;\n"
-  "uniform highp vec2 size;\n"
-  "uniform mediump vec2 extraSize;\n"
-  "uniform mediump vec4 offsetSizeMode;\n"
-  "uniform mediump vec2 origin;\n"
-  "uniform mediump vec2 anchorPoint;\n"
-  "uniform mediump float cornerRadius;\n"
-  "uniform mediump float cornerRadiusPolicy;\n"
-
-  "vec4 ComputeVertexPosition()\n"
-  "{\n"
-  "  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;\n"
-  "  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n"
-  "  mediump float minSize = min( visualSize.x, visualSize.y );\n"
-  "  vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);\n"
-  "  vCornerRadius = min( vCornerRadius, minSize * 0.5 );\n"
-  "  vRectSize = visualSize / 2.0 - vCornerRadius;\n"
-  "  vPosition = aPosition* visualSize;\n"
-  "  return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n"
-  "}\n"
-
-  "void main()\n"
-  "{\n"
-  "  gl_Position = uMvpMatrix * ComputeVertexPosition();\n"
-  "}\n";
-
-//float distance = length( max( abs( position - center ), size ) - size ) - radius;
-const char* FRAGMENT_SHADER_ROUNDED_CORNER =
-  "INPUT mediump vec2 vPosition;\n"
-  "INPUT mediump vec2 vRectSize;\n"
-  "INPUT mediump float vCornerRadius;\n"
-
-  "uniform lowp vec4 uColor;\n"
-  "uniform lowp vec3 mixColor;\n"
-
-  "void main()\n"
-  "{\n"
-  "  mediump float dist = length( max( abs( vPosition ), vRectSize ) - vRectSize ) - vCornerRadius;\n"
-  "  OUT_COLOR = vec4(mixColor, 1.0) * uColor;\n"
-  "  OUT_COLOR.a *= 1.0 - smoothstep( -1.0, 1.0, dist );\n"
-  "}\n";
-
-const char* VERTEX_SHADER_BLUR_EDGE =
-  "INPUT mediump vec2 aPosition;\n"
-  "OUTPUT mediump vec2 vPosition;\n"
-  "OUTPUT mediump vec2 vRectSize;\n"
-
-  "uniform highp   mat4 uMvpMatrix;\n"
-  "uniform highp vec3 uSize;\n"
-
-  "//Visual size and offset\n"
-  "uniform mediump vec2 offset;\n"
-  "uniform highp vec2 size;\n"
-  "uniform mediump vec2 extraSize;\n"
-  "uniform mediump vec4 offsetSizeMode;\n"
-  "uniform mediump vec2 origin;\n"
-  "uniform mediump vec2 anchorPoint;\n"
-  "uniform mediump float blurRadius;\n"
-
-  "vec4 ComputeVertexPosition()\n"
-  "{\n"
-  "  vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize + blurRadius * 2.0;\n"
-  "  vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n"
-  "  vRectSize = visualSize / 2.0;\n"
-  "  vPosition = aPosition* visualSize;\n"
-  "  return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n"
-  "}\n"
-
-  "void main()\n"
-  "{\n"
-  "  gl_Position = uMvpMatrix * ComputeVertexPosition();\n"
-  "}\n";
-
-const char* FRAGMENT_SHADER_BLUR_EDGE =
-  "INPUT mediump vec2 vPosition;\n"
-  "INPUT mediump vec2 vRectSize;\n"
-
-  "uniform lowp vec4 uColor;\n"
-  "uniform lowp vec3 mixColor;\n"
-  "uniform mediump float blurRadius;\n"
-
-  "void main()\n"
-  "{\n"
-  "  mediump vec2 blur = 1.0 - smoothstep( vRectSize - blurRadius * 2.0, vRectSize, abs( vPosition ) );\n"
-  "  OUT_COLOR = vec4(mixColor, 1.0) * uColor;\n"
-  "  OUT_COLOR.a *= blur.x * blur.y;\n"
-  "}\n";
-
-}
-
-ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache, const Property::Map& properties )
+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 ) );
-  colorVisualPtr->SetProperties( properties );
+  ColorVisualPtr colorVisualPtr(new ColorVisual(factoryCache));
+  colorVisualPtr->SetProperties(properties);
+  colorVisualPtr->Initialize();
   return colorVisualPtr;
 }
 
@@ -191,8 +71,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)
 {
 }
 
@@ -200,25 +79,25 @@ ColorVisual::~ColorVisual()
 {
 }
 
-void ColorVisual::DoSetProperties( const Property::Map& propertyMap )
+void ColorVisual::DoSetProperties(const Property::Map& propertyMap)
 {
   // By virtue of DoSetProperties being called last, this will override
   // anything set by Toolkit::Visual::Property::MIX_COLOR
-  Property::Value* colorValue = propertyMap.Find( Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR );
-  if( colorValue )
+  Property::Value* colorValue = propertyMap.Find(Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR);
+  if(colorValue)
   {
     Vector4 color;
-    if( colorValue->Get( color ) )
+    if(colorValue->Get(color))
     {
       Property::Type type = colorValue->GetType();
-      if( type == Property::VECTOR4 )
+      if(type == Property::VECTOR4)
       {
-        SetMixColor( color );
+        SetMixColor(color);
       }
-      else if( type == Property::VECTOR3 )
+      else if(type == Property::VECTOR3)
       {
         Vector3 color3(color);
-        SetMixColor( color3 );
+        SetMixColor(color3);
       }
     }
     else
@@ -227,59 +106,34 @@ 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 )
+  Property::Value* blurRadiusValue = propertyMap.Find(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME);
+  if(blurRadiusValue)
   {
-    if( !blurRadiusValue->Get( mBlurRadius ) )
+    if(!blurRadiusValue->Get(mBlurRadius))
     {
-      DALI_LOG_ERROR( "ColorVisual:DoSetProperties:: BLUR_RADIUS property has incorrect type: %d\n", blurRadiusValue->GetType() );
+      DALI_LOG_ERROR("ColorVisual:DoSetProperties:: BLUR_RADIUS property has incorrect type: %d\n", blurRadiusValue->GetType());
     }
   }
 }
 
-void ColorVisual::DoSetOnScene( Actor& actor )
+void ColorVisual::DoSetOnScene(Actor& actor)
 {
-  InitializeRenderer();
-
-  // 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 );
+  ResourceReady(Toolkit::Visual::ResourceStatus::READY);
 }
 
 void ColorVisual::DoSetOffScene(Actor& actor)
 {
-  if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX)
-  {
-    // Update values from Renderer
-    mBlurRadius = mImpl->mRenderer.GetProperty<float>(mBlurRadiusIndex);
-  }
-
   actor.RemoveRenderer(mImpl->mRenderer);
-  mImpl->mRenderer.Reset();
-  mBlurRadiusIndex = Property::INVALID_INDEX;
 }
 
-void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const
+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 );
+  map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+  map.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor);
 
   if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX)
   {
@@ -293,33 +147,16 @@ void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const
   }
 }
 
-void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
+void ColorVisual::DoCreateInstancePropertyMap(Property::Map& map) const
 {
   // Do nothing
 }
 
 void ColorVisual::OnSetTransform()
 {
-  if( mImpl->mRenderer )
-  {
-    mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
-  }
-}
-
-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 )
+  if(mImpl->mRenderer)
   {
-    case DevelColorVisual::Action::UPDATE_PROPERTY:
-    {
-      const Property::Map* map = attributes.GetMap();
-      if( map )
-      {
-        DoSetProperties( *map );
-      }
-      break;
-    }
+    mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
   }
 }
 
@@ -327,16 +164,16 @@ void ColorVisual::UpdateShader()
 {
   if(mImpl->mRenderer)
   {
-    Shader shader = GetShader();
+    Shader shader = GenerateShader();
     mImpl->mRenderer.SetShader(shader);
   }
 }
 
-void ColorVisual::InitializeRenderer()
+void ColorVisual::OnInitialize()
 {
-  Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
+  Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
 
-  Shader shader = GetShader();
+  Shader shader = GenerateShader();
 
   mImpl->mRenderer = Renderer::New(geometry, shader);
 
@@ -355,35 +192,55 @@ void ColorVisual::InitializeRenderer()
   mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 }
 
-Shader ColorVisual::GetShader()
+Shader ColorVisual::GenerateShader() const
 {
   Shader shader;
-  if(!EqualsZero(mBlurRadius) || mNeedBlurRadius)
+  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() + VERTEX_SHADER_BLUR_EDGE, Dali::Shader::GetFragmentShaderPrefix() + FRAGMENT_SHADER_BLUR_EDGE );
-      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() + VERTEX_SHADER, Dali::Shader::GetFragmentShaderPrefix() + FRAGMENT_SHADER );
-      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)
+    {
+      vertexShaderPrefixList   += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+    }
+    if(blur)
     {
-      shader = Shader::New( Dali::Shader::GetVertexShaderPrefix() + VERTEX_SHADER_ROUNDED_CORNER, Dali::Shader::GetFragmentShaderPrefix() + FRAGMENT_SHADER_ROUNDED_CORNER );
-      mFactoryCache.SaveShader( VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER, shader );
+      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;
@@ -401,9 +258,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();