Change the precision of size and uSize from mediumP to highP
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / color / color-visual.cpp
index 82c6254..63d02ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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,7 +23,9 @@
 
 //INTERNAL INCLUDES
 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
-#include <dali-toolkit/devel-api/visual-factory/devel-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/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
@@ -40,24 +42,24 @@ namespace Internal
 
 namespace
 {
-const char * const COLOR_NAME("mixColor");
 
 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
   attribute mediump vec2 aPosition;\n
-  uniform mediump mat4 uMvpMatrix;\n
-  uniform mediump vec3 uSize;\n
+  uniform highp   mat4 uMvpMatrix;\n
+  uniform highp   vec3 uSize;\n
   \n
 
   //Visual size and offset
   uniform mediump vec2 offset;\n
-  uniform mediump vec2 size;\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 );\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
@@ -70,23 +72,125 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
 
 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
   uniform lowp vec4 uColor;\n
-  uniform lowp vec4 mixColor;\n
+  uniform lowp vec3 mixColor;\n
   \n
   void main()\n
   {\n
-    gl_FragColor = mixColor*uColor;\n
+    gl_FragColor = vec4(mixColor, 1.0)*uColor;\n
   }\n
 );
+
+const char* VERTEX_SHADER_ROUNDED_CORNER = DALI_COMPOSE_SHADER(
+  attribute mediump vec2 aPosition;\n
+  uniform highp   mat4 uMvpMatrix;\n
+  uniform highp   vec3 uSize;\n
+  varying mediump vec2 vPosition;\n
+  varying mediump vec2 vRectSize;\n
+  varying mediump float vCornerRadius;\n
+  \n
+  //Visual size and offset
+  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
+  \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
+  \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 = DALI_COMPOSE_SHADER(
+  varying mediump vec2 vPosition;\n
+  varying mediump vec2 vRectSize;\n
+  varying mediump float vCornerRadius;\n
+  uniform lowp vec4 uColor;\n
+  uniform lowp vec3 mixColor;\n
+  \n
+  void main()\n
+  {\n
+      mediump float dist = length( max( abs( vPosition ), vRectSize ) - vRectSize ) - vCornerRadius;\n
+      gl_FragColor = uColor * vec4( mixColor, 1.0 );\n
+      gl_FragColor.a *= 1.0 - smoothstep( -1.0, 1.0, dist );\n
+  }\n
+);
+
+const char* VERTEX_SHADER_BLUR_EDGE = DALI_COMPOSE_SHADER(
+  attribute mediump vec2 aPosition;\n
+  uniform highp   mat4 uMvpMatrix;\n
+  uniform highp vec3 uSize;\n
+  varying mediump vec2 vPosition;\n
+  varying mediump vec2 vRectSize;\n
+  \n
+  //Visual size and offset
+  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
+  \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
+  \n
+  void main()\n
+  {\n
+    gl_Position = uMvpMatrix * ComputeVertexPosition();\n
+  }\n
+);
+
+const char* FRAGMENT_SHADER_BLUR_EDGE = DALI_COMPOSE_SHADER(
+  varying mediump vec2 vPosition;\n
+  varying mediump vec2 vRectSize;\n
+  uniform lowp vec4 uColor;\n
+  uniform lowp vec3 mixColor;\n
+  uniform mediump float blurRadius;\n
+  \n
+  void main()\n
+  {\n
+      mediump vec2 blur = 1.0 - smoothstep( vRectSize - blurRadius * 2.0, vRectSize, abs( vPosition ) );\n
+      gl_FragColor = uColor * vec4( mixColor, 1.0 );\n
+      gl_FragColor.a *= blur.x * blur.y;\n
+  }\n
+);
+
 }
 
-ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache )
+ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache, const Property::Map& properties )
 {
-  return new ColorVisual( factoryCache );
+  ColorVisualPtr colorVisualPtr( new ColorVisual( factoryCache ) );
+  colorVisualPtr->SetProperties( properties );
+  return colorVisualPtr;
 }
 
 ColorVisual::ColorVisual( VisualFactoryCache& factoryCache )
-: Visual::Base( factoryCache ),
-  mMixColorIndex( Property::INVALID_INDEX )
+: Visual::Base( factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR ),
+  mBlurRadius( 0.0f ),
+  mRenderIfTransparent( false )
 {
 }
 
@@ -96,54 +200,79 @@ ColorVisual::~ColorVisual()
 
 void ColorVisual::DoSetProperties( const Property::Map& propertyMap )
 {
-  Property::Value* color = propertyMap.Find( Toolkit::ColorVisual::Property::MIX_COLOR, COLOR_NAME );
-  if( !( color && color->Get(mMixColor) ) )
+  // 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 )
   {
-    DALI_LOG_ERROR( "Fail to provide a color to the ColorVisual object\n" );
+    Vector4 color;
+    if( colorValue->Get( color ) )
+    {
+      Property::Type type = colorValue->GetType();
+      if( type == Property::VECTOR4 )
+      {
+        SetMixColor( color );
+      }
+      else if( type == Property::VECTOR3 )
+      {
+        Vector3 color3(color);
+        SetMixColor( color3 );
+      }
+    }
+    else
+    {
+      DALI_LOG_ERROR("ColorVisual: mixColor property has incorrect type\n");
+    }
   }
-}
 
-void ColorVisual::SetSize( const Vector2& size )
-{
-  Visual::Base::SetSize( size );
+  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() );
+    }
+  }
 
-  // ToDo: renderer responds to the size change
+  Property::Value* blurRadiusValue = propertyMap.Find( Toolkit::DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME );
+  if( blurRadiusValue )
+  {
+    if( !blurRadiusValue->Get( mBlurRadius ) )
+    {
+      DALI_LOG_ERROR( "ColorVisual:DoSetProperties:: BLUR_RADIUS property has incorrect type: %d\n", blurRadiusValue->GetType() );
+    }
+  }
 }
 
-void ColorVisual::DoSetOnStage( Actor& actor )
+void ColorVisual::DoSetOnScene( Actor& actor )
 {
   InitializeRenderer();
 
-  actor.AddRenderer( mImpl->mRenderer );
+  // 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 );
+  }
+
+  // Color Visual generated and ready to display
+  ResourceReady( Toolkit::Visual::ResourceStatus::READY );
 }
 
 void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
-  map.Insert( Toolkit::VisualProperty::TYPE, Toolkit::Visual::COLOR );
-  map.Insert( Toolkit::ColorVisual::Property::MIX_COLOR, mMixColor );
+  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::DevelColorVisual::Property::BLUR_RADIUS, mBlurRadius );
 }
 
-void ColorVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue )
+void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
 {
-  // TODO
-  /* David Steele comented :
-
-     Some things to bear in mind:
-
-     We currently keep a copy of the mix color in the ColorVisual object, which is then used to instantiate the registered property on the renderer.
-
-     The user can get the renderer and animate the mixColor property (it's registered, so is automatically a scene-graph property).
-
-     The GetProperty method will have to read from the renderer, or from the cached value in the Visual, and the SetProperty will have to write to cache and to the renderer if present.
-  */
+  // Do nothing
 }
 
-Dali::Property::Value ColorVisual::DoGetProperty( Dali::Property::Index index )
-{
-  // TODO
-  return Dali::Property::Value();
-}
 
 void ColorVisual::OnSetTransform()
 {
@@ -153,48 +282,74 @@ 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:
+    {
+      Property::Map* map = attributes.GetMap();
+      if( map )
+      {
+        DoSetProperties( *map );
+      }
+      break;
+    }
+  }
+}
+
 void ColorVisual::InitializeRenderer()
 {
   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
-  if( !geometry )
+
+  Shader shader;
+  if( !EqualsZero( mBlurRadius ) )
   {
-    geometry =  VisualFactoryCache::CreateQuadGeometry();
-    mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry );
+    shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER_BLUR_EDGE );
+    if( !shader )
+    {
+      shader = Shader::New( VERTEX_SHADER_BLUR_EDGE, FRAGMENT_SHADER_BLUR_EDGE );
+      mFactoryCache.SaveShader( VisualFactoryCache::COLOR_SHADER_BLUR_EDGE, shader );
+    }
   }
-
-  Shader shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER );
-  if( !shader )
+  else if( !IsRoundedCornerRequired() )
+  {
+    shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER );
+    if( !shader )
+    {
+      shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+      mFactoryCache.SaveShader( VisualFactoryCache::COLOR_SHADER, shader );
+    }
+  }
+  else
   {
-    shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
-    mFactoryCache.SaveShader( VisualFactoryCache::COLOR_SHADER, shader );
+    shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER );
+    if( !shader )
+    {
+      shader = Shader::New( VERTEX_SHADER_ROUNDED_CORNER, FRAGMENT_SHADER_ROUNDED_CORNER );
+      mFactoryCache.SaveShader( VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER, shader );
+    }
   }
 
   mImpl->mRenderer = Renderer::New( geometry, shader );
 
-  mMixColorIndex = mImpl->mRenderer.RegisterProperty( Toolkit::ColorVisual::Property::MIX_COLOR, COLOR_NAME, mMixColor );
-  if( mMixColor.a < 1.f )
+  // ColorVisual has it's own index key for mix color - use this instead
+  // of using the new base index to avoid changing existing applications
+  // String keys will get to this property.
+  mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty( Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR, Vector3(mImpl->mMixColor) );
+
+  mImpl->mRenderer.RegisterProperty( BLUR_RADIUS_NAME, mBlurRadius );
+
+  if( mImpl->mMixColor.a < 1.f || !EqualsZero( mBlurRadius ) )
   {
     mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
   }
 
-  //Register transform properties
+  // Register transform properties
   mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
 }
 
-void ColorVisual::SetColor(const Vector4& color)
-{
-  mMixColor = color;
-
-  if( mImpl->mRenderer )
-  {
-    (mImpl->mRenderer).SetProperty( mMixColorIndex, color );
-    if( color.a < 1.f )
-    {
-      mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
-    }
-  }
-}
-
 } // namespace Internal
 
 } // namespace Toolkit