[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / effects-view / effects-view-impl.cpp
index fcd9939..5f132c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 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 "effects-view-impl.h"
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/animation/active-constraint.h>
+#include <dali/devel-api/common/stage.h>
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/constraints.h>
-#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/public-api/rendering/renderer.h>
 
 // INTERNAL INCLUDES
-#include "../../filters/blur-two-pass-filter.h"
-#include "../../filters/emboss-filter.h"
-#include "../../filters/spread-filter.h"
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/control/control-renderers.h>
+#include <dali-toolkit/internal/filters/blur-two-pass-filter.h>
+#include <dali-toolkit/internal/filters/emboss-filter.h>
+#include <dali-toolkit/internal/filters/spread-filter.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 
 namespace Dali
 {
-
 namespace Toolkit
 {
-
 namespace Internal
 {
-
 namespace
 {
-
 Dali::BaseHandle Create()
 {
-  return Toolkit::EffectsView::New();
+  return EffectsView::New();
 }
 
-Dali::TypeRegistration mType( typeid(Dali::Toolkit::EffectsView), typeid(Dali::Toolkit::Control), Create );
+DALI_TYPE_REGISTRATION_BEGIN(Toolkit::EffectsView, Toolkit::Control, Create)
+DALI_PROPERTY_REGISTRATION(Toolkit, EffectsView, "effectSize", INTEGER, EFFECT_SIZE)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION(Toolkit, EffectsView, "effectOffset", VECTOR3, EFFECT_OFFSET)
+DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, EffectsView, "effectColor", Color::WHITE, EFFECT_COLOR)
+DALI_TYPE_REGISTRATION_END()
 
 const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
-const float         ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
-const Vector4       EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR( 1.0f, 1.0f, 1.0f, 0.0 );
+const float         ARBITRARY_FIELD_OF_VIEW           = Math::PI / 4.0f;
+const Vector4       EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR(0.0f, 0.0f, 0.0f, 0.0);
 const bool          EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
-// custom properties
-const float         EFFECT_SIZE_DEFAULT( 1.0f );
-const std::string   EFFECT_SIZE_PROPERTY_NAME( "EffectSize" );
-const float         EFFECT_STRENGTH_DEFAULT( 0.5f );
-const std::string   EFFECT_STRENGTH_PROPERTY_NAME( "EffectStrength" );
-const Vector3       EFFECT_OFFSET_DEFAULT( 0.0f, 0.0f, 0.0f );
-const std::string   EFFECT_OFFSET_PROPERTY_NAME( "EffectOffset" );
-const Vector4       EFFECT_COLOR_DEFAULT( Color::WHITE );
-const std::string   EFFECT_COLOR_PROPERTY_NAME( "EffectColor" );
-
-const char* const EFFECTS_VIEW_FRAGMENT_SOURCE =
-    "void main()\n"
-    "{\n"
-    "  gl_FragColor = uColor;\n"
-    "  gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n"
-    "}\n";
-
-const float BLUR_KERNEL0[] = { 12.0f/16.0f,
-                               2.0f/16.0f, 2.0f/16.0f };
-
-const float BLUR_KERNEL1[] = { 8.0f/16.0f,
-                               4.0f/16.0f, 4.0f/16.0f };
-
-const float BLUR_KERNEL2[] = { 6.0f/16.0f,
-                               2.5f/16.0f, 2.5f/16.0f,
-                               1.5f/16.0f, 1.5f/16.0f,
-                               1.0f/16.0f, 1.0f/16.0f };
-
-const float BLUR_KERNEL3[] = { 4.0f/16.0f,
-                               3.0f/16.0f, 2.0f/16.0f,
-                               2.0f/16.0f, 2.0f/16.0f,
-                               1.0f/16.0f, 1.0f/16.0f };
-
-const float BLUR_KERNEL4[] = { 3.0f/16.0f,
-                               2.5f/16.0f,  2.5f/16.0f,
-                               1.75f/16.0f, 1.75f/16.0f,
-                               1.25f/16.0f, 1.25f/16.0f,
-                               1.0f/16.0f,  1.0f/16.0f };
 
+// clang-format off
+const float BLUR_KERNEL0[] = {12.0f/16.0f,
+                              2.0f/16.0f, 2.0f/16.0f};
+
+const float BLUR_KERNEL1[] = {8.0f/16.0f,
+                              4.0f/16.0f, 4.0f/16.0f };
+
+const float BLUR_KERNEL2[] = {6.0f/16.0f,
+                              2.5f/16.0f, 2.5f/16.0f,
+                              1.5f/16.0f, 1.5f/16.0f,
+                              1.0f/16.0f, 1.0f/16.0f};
+
+const float BLUR_KERNEL3[] = {4.0f/16.0f,
+                              3.0f/16.0f, 2.0f/16.0f,
+                              2.0f/16.0f, 2.0f/16.0f,
+                              1.0f/16.0f, 1.0f/16.0f};
+
+const float BLUR_KERNEL4[] = {3.0f/16.0f,
+                              2.5f/16.0f,  2.5f/16.0f,
+                              1.75f/16.0f, 1.75f/16.0f,
+                              1.25f/16.0f, 1.25f/16.0f,
+                              1.0f/16.0f,  1.0f/16.0f};
+// clang-format on
 } // namespace
 
 Toolkit::EffectsView EffectsView::New()
 {
   EffectsView* effectsView = new EffectsView;
 
-  Toolkit::EffectsView handle = Toolkit::EffectsView( *effectsView );
+  Toolkit::EffectsView handle = Toolkit::EffectsView(*effectsView);
 
   // Second-phase init of the implementation
   // This can only be done after the CustomActor connection has been made...
@@ -109,18 +102,16 @@ Toolkit::EffectsView EffectsView::New()
 }
 
 EffectsView::EffectsView()
-: Control( CONTROL_BEHAVIOUR_NONE ),
-  mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
-  mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
-  mSpread(0.0f),
-  mBackgroundColor( EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR ),
-  mTargetSize( Vector2::ZERO ),
-  mLastSize( Vector2::ZERO ),
-  mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND),
-  mEffectSizePropertyIndex(Property::INVALID_INDEX),
-  mEffectStrengthPropertyIndex(Property::INVALID_INDEX),
-  mEffectOffsetPropertyIndex(Property::INVALID_INDEX),
-  mEffectColorPropertyIndex(Property::INVALID_INDEX)
+: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
+  mChildrenRoot(Actor::New()),
+  mBackgroundColor(EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR),
+  mTargetSize(Vector2::ZERO),
+  mLastSize(Vector2::ZERO),
+  mEffectSize(0),
+  mEffectType(Toolkit::EffectsView::INVALID_TYPE),
+  mPixelFormat(EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT),
+  mEnabled(false),
+  mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND)
 {
 }
 
@@ -129,28 +120,27 @@ EffectsView::~EffectsView()
   RemoveFilters();
 }
 
-void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
+void EffectsView::SetType(Toolkit::EffectsView::EffectType type)
 {
-  if( mEffectType != type )
+  if(mEffectType != type)
   {
-    mEffectType = type;
-
     RemoveFilters();
 
-    switch( mEffectType )
+    Actor self = Self();
+
+    switch(type)
     {
       case Toolkit::EffectsView::DROP_SHADOW:
       {
-        mFilters.push_back( new SpreadFilter );
-        mFilters.push_back( new BlurTwoPassFilter );
+        mFilters.PushBack(new SpreadFilter);
+        mFilters.PushBack(new BlurTwoPassFilter);
         break;
       }
       case Toolkit::EffectsView::EMBOSS:
       {
-        mFilters.push_back( new SpreadFilter );
-        mFilters.push_back( new EmbossFilter );
-        mFilters.push_back( new BlurTwoPassFilter );
-        mActorPostFilter.RemoveShaderEffect();
+        mFilters.PushBack(new SpreadFilter);
+        mFilters.PushBack(new EmbossFilter);
+        mFilters.PushBack(new BlurTwoPassFilter);
         break;
       }
       default:
@@ -158,6 +148,8 @@ void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
         break;
       }
     }
+
+    mEffectType = type;
   }
 }
 
@@ -171,13 +163,15 @@ void EffectsView::Enable()
   // make sure resources are allocated and start the render tasks processing
   AllocateResources();
   CreateRenderTasks();
+  mEnabled = true;
 }
 
 void EffectsView::Disable()
 {
   // stop render tasks processing
-  // Note: render target resources are automatically freed since we set the Image::Unused flag
   RemoveRenderTasks();
+  mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
+  mEnabled  = false;
 }
 
 void EffectsView::Refresh()
@@ -185,244 +179,230 @@ void EffectsView::Refresh()
   RefreshRenderTasks();
 }
 
-void EffectsView::SetRefreshOnDemand( bool onDemand )
+void EffectsView::SetRefreshOnDemand(bool onDemand)
 {
   mRefreshOnDemand = onDemand;
 
   RefreshRenderTasks();
 }
 
-void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
+void EffectsView::SetPixelFormat(Pixel::Format pixelFormat)
 {
   mPixelFormat = pixelFormat;
 }
 
-void EffectsView::SetOutputImage( FrameBufferImage image )
+void EffectsView::SetBackgroundColor(const Vector4& color)
 {
-  CustomActor self = Self();
-
-  if( mImageForResult != image )
-  {
-    if( !image )
-    {
-      if( mImageForResult )
-      {
-        self.Remove( mActorForResult );
-        mActorForResult.Reset();
-
-        self.Add( mActorPostFilter );
-        self.Add( mActorForChildren );
-      }
-    }
-    else
-    {
-      if( mImageForResult )
-      {
-        self.Remove( mActorForResult );
-      }
-      mActorForResult = Actor::New();
-      mActorForResult.SetParentOrigin( ParentOrigin::CENTER );
-      mActorForResult.SetSize( mTargetSize );
-      mActorForResult.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-
-      Self().Add( mActorForResult );
-      mActorForResult.Add( mActorPostFilter );
-      mActorForResult.Add( mActorForChildren );
-    }
-    mImageForResult = image;
-  }
+  mBackgroundColor = color;
 }
 
-FrameBufferImage EffectsView::GetOutputImage()
+Vector4 EffectsView::GetBackgroundColor() const
 {
-  return mImageForResult;
+  return mBackgroundColor;
 }
 
-Property::Index EffectsView::GetEffectSizePropertyIndex() const
+void EffectsView::SetEffectSize(int effectSize)
 {
-  return mEffectSizePropertyIndex;
-}
+  mEffectSize = effectSize;
 
-Property::Index EffectsView::GetEffectStrengthPropertyIndex() const
-{
-  return mEffectStrengthPropertyIndex;
-}
+  if(mEnabled)
+  {
+    const size_t numFilters(mFilters.Size());
+    for(size_t i = 0; i < numFilters; ++i)
+    {
+      mFilters[i]->Disable();
+    }
 
-Property::Index EffectsView::GetEffectOffsetPropertyIndex() const
-{
-  return mEffectOffsetPropertyIndex;
+    SetupFilters();
+
+    for(size_t i = 0; i < numFilters; ++i)
+    {
+      mFilters[i]->Enable();
+    }
+  }
 }
 
-Property::Index EffectsView::GetEffectColorPropertyIndex() const
+int EffectsView::GetEffectSize()
 {
-  return mEffectColorPropertyIndex;
+  return mEffectSize;
 }
 
-void EffectsView::SetupProperties()
+// From Control
+void EffectsView::OnInitialize()
 {
   CustomActor self = Self();
+  mChildrenRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  self.Add(mChildrenRoot);
 
-  // Register a property that the user can control the drop shadow offset
-  mEffectSizePropertyIndex     = self.RegisterProperty(EFFECT_SIZE_PROPERTY_NAME, EFFECT_SIZE_DEFAULT, Property::READ_WRITE);
-  mEffectStrengthPropertyIndex = self.RegisterProperty(EFFECT_STRENGTH_PROPERTY_NAME, EFFECT_STRENGTH_DEFAULT, Property::READ_WRITE);
-  mEffectOffsetPropertyIndex   = self.RegisterProperty(EFFECT_OFFSET_PROPERTY_NAME, EFFECT_OFFSET_DEFAULT);
-  mEffectColorPropertyIndex    = self.RegisterProperty(EFFECT_COLOR_PROPERTY_NAME, EFFECT_COLOR_DEFAULT);
-  mActorPostFilter.ApplyConstraint( Constraint::New<Vector3>( Actor::POSITION, Source( self, mEffectOffsetPropertyIndex ), EqualToConstraint() ) );
-  mActorPostFilter.ApplyConstraint( Constraint::New<Vector4>( Actor::COLOR, Source( self, mEffectColorPropertyIndex ), EqualToConstraint() ) );
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
-void EffectsView::SetBackgroundColor( const Vector4& color )
+void EffectsView::OnSizeSet(const Vector3& targetSize)
 {
-  mBackgroundColor = color;
-}
+  mTargetSize = Vector2(targetSize);
 
-Vector4 EffectsView::GetBackgroundColor() const
-{
-  return mBackgroundColor;
+  // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
+  if(mEnabled)
+  {
+    if(mLastSize != Vector2::ZERO)
+    {
+      Disable();
+    }
+    Enable();
+  }
+
+  mChildrenRoot.SetProperty(Actor::Property::SIZE, targetSize);
+
+  Control::OnSizeSet(targetSize);
 }
 
-// From Control
-void EffectsView::OnInitialize()
+void EffectsView::OnSceneConnection(int depth)
 {
-  //////////////////////////////////////////////////////
-  // Create cameras
-  mCameraForChildren = CameraActor::New();
-  mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
+  Actor self(Self());
 
-  mActorForChildren = ImageActor::New();
-  mActorForChildren.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mActorForChildren.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
+  // Create renderers
+  mRendererPostFilter = CreateRenderer(SHADER_EFFECTS_VIEW_VERT,
+                                       SHADER_EFFECTS_VIEW_FRAG);
+  mRendererPostFilter.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
+  self.AddRenderer(mRendererPostFilter);
 
-  mActorPostFilter = ImageActor::New();
-  mActorPostFilter.SetParentOrigin( ParentOrigin::CENTER );
-  mActorPostFilter.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-  mActorPostFilter.SetShaderEffect( ShaderEffect::New( "", EFFECTS_VIEW_FRAGMENT_SOURCE ) );
+  mRendererForChildren = CreateRenderer(BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE);
+  mRendererForChildren.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + 1);
+  self.AddRenderer(mRendererForChildren);
 
-  // Connect to actor tree
-  Self().Add( mActorPostFilter );
-  Self().Add( mActorForChildren );
-  Self().Add( mCameraForChildren );
+  Enable();
 
-  SetupProperties();
+  Control::OnSceneConnection(depth);
 }
 
-void EffectsView::OnControlSizeSet(const Vector3& targetSize)
+void EffectsView::OnSceneDisconnection()
 {
-  mTargetSize = Vector2(targetSize);
+  Actor self(Self());
 
-  // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
-  if(Self().OnStage())
-  {
-    AllocateResources();
-  }
+  Disable();
 
-  if( mActorForResult )
-  {
-    mActorForResult.SetSize( targetSize );
-  }
-  if( mActorForChildren )
+  const size_t numFilters(mFilters.Size());
+  for(size_t i = 0; i < numFilters; ++i)
   {
-    mActorForChildren.SetSize( targetSize );
-  }
-  if( mActorPostFilter )
-  {
-    mActorPostFilter.SetSize( targetSize );
+    mFilters[i]->Disable();
   }
 
-  // Children render camera must move when EffectsView object is resized.
-  // This is since we cannot change render target size - so we need to remap the child actors' rendering
-  // accordingly so they still exactly fill the render target.
-  // Note that this means the effective resolution of the child render changes as the EffectsView object
-  // changes size, this is the trade off for not being able to modify render target size
-  // Change camera z position based on EffectsView actor height
-  if( mCameraForChildren )
-  {
-    const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
-    mCameraForChildren.SetZ( targetSize.height * cameraPosScale );
-  }
+  // Remove renderers
+  self.RemoveRenderer(mRendererForChildren);
+  mRendererForChildren.Reset();
 
-  const size_t numFilters( mFilters.size() );
-  for( size_t i = 0; i < numFilters; ++i )
-  {
-    mFilters[i]->SetSize( mTargetSize );
-  }
+  self.RemoveRenderer(mRendererPostFilter);
+  mRendererPostFilter.Reset();
 
+  Control::OnSceneDisconnection();
 }
 
-void EffectsView::OnStageDisconnection()
+void EffectsView::OnChildAdd(Actor& child)
 {
-  const size_t numFilters( mFilters.size() );
-  for( size_t i = 0; i < numFilters; ++i )
+  if(child != mChildrenRoot && child != mCameraForChildren)
   {
-    mFilters[i]->Disable();
+    mChildrenRoot.Add(child);
   }
+
+  Control::OnChildAdd(child);
+}
+
+void EffectsView::OnChildRemove(Actor& child)
+{
+  mChildrenRoot.Remove(child);
+
+  Control::OnChildRemove(child);
 }
 
 void EffectsView::SetupFilters()
 {
-  int effectSize = static_cast< int >( Self().GetProperty( mEffectSizePropertyIndex ).Get<float>() );
-  switch( mEffectType )
+  switch(mEffectType)
   {
     case Toolkit::EffectsView::DROP_SHADOW:
     {
-      SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
-      spreadFilter->SetInputImage( mImageForChildren );
-      spreadFilter->SetOutputImage( mImagePostFilter );
-      spreadFilter->SetRootActor( Self() );
-      spreadFilter->SetBackgroundColor( mBackgroundColor );
-      spreadFilter->SetPixelFormat( mPixelFormat );
-      spreadFilter->SetSize( mTargetSize );
-      spreadFilter->SetSpread( effectSize );
-
-      BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
-      blurFilter->SetInputImage( mImagePostFilter );
-      blurFilter->SetOutputImage( mImagePostFilter );
-      blurFilter->SetRootActor( Self() );
-      blurFilter->SetBackgroundColor( mBackgroundColor );
-      blurFilter->SetPixelFormat( mPixelFormat );
-      blurFilter->SetSize( mTargetSize );
+      SpreadFilter* spreadFilter = static_cast<SpreadFilter*>(mFilters[0]);
+      spreadFilter->SetInputTexture(mFrameBufferForChildren.GetColorTexture());
+      spreadFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
+      spreadFilter->SetRootActor(mChildrenRoot);
+      spreadFilter->SetBackgroundColor(mBackgroundColor);
+      spreadFilter->SetPixelFormat(mPixelFormat);
+      spreadFilter->SetSize(mTargetSize);
+      spreadFilter->SetSpread(mEffectSize);
+
+      BlurTwoPassFilter* blurFilter = static_cast<BlurTwoPassFilter*>(mFilters[1]);
+      blurFilter->SetInputTexture(mFrameBufferPostFilter.GetColorTexture());
+      blurFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
+      blurFilter->SetRootActor(mChildrenRoot);
+      blurFilter->SetBackgroundColor(mBackgroundColor);
+      blurFilter->SetPixelFormat(mPixelFormat);
+      blurFilter->SetSize(mTargetSize);
 
       const float* kernel(NULL);
-      size_t kernelSize(0);
-      switch( effectSize )
+      size_t       kernelSize(0);
+      switch(mEffectSize)
       {
-        case 4:  {  kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
-        case 3:  {  kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
-        case 2:  {  kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
-        case 1:  {  kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
+        case 4:
+        {
+          kernel     = BLUR_KERNEL4;
+          kernelSize = sizeof(BLUR_KERNEL4) / sizeof(BLUR_KERNEL4[0]);
+          break;
+        }
+        case 3:
+        {
+          kernel     = BLUR_KERNEL3;
+          kernelSize = sizeof(BLUR_KERNEL3) / sizeof(BLUR_KERNEL3[0]);
+          break;
+        }
+        case 2:
+        {
+          kernel     = BLUR_KERNEL2;
+          kernelSize = sizeof(BLUR_KERNEL2) / sizeof(BLUR_KERNEL2[0]);
+          break;
+        }
+        case 1:
+        {
+          kernel     = BLUR_KERNEL1;
+          kernelSize = sizeof(BLUR_KERNEL1) / sizeof(BLUR_KERNEL1[0]);
+          break;
+        }
         case 0:
-        default: {  kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
+        default:
+        {
+          kernel     = BLUR_KERNEL0;
+          kernelSize = sizeof(BLUR_KERNEL0) / sizeof(BLUR_KERNEL0[0]);
+          break;
+        }
       }
-      blurFilter->CreateKernel( kernel, kernelSize );
+      blurFilter->CreateKernel(kernel, kernelSize);
       break;
     }
     case Toolkit::EffectsView::EMBOSS:
     {
-      SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
-      spreadFilter->SetInputImage( mImageForChildren );
-      spreadFilter->SetOutputImage( mImagePostFilter );
-      spreadFilter->SetRootActor( Self() );
-      spreadFilter->SetBackgroundColor( mBackgroundColor );
-      spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
-      spreadFilter->SetSize( mTargetSize );
-      spreadFilter->SetSpread( effectSize );
-
-      EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
-      embossFilter->SetInputImage( mImagePostFilter );
-      embossFilter->SetOutputImage( mImagePostFilter );
-      embossFilter->SetRootActor( Self() );
-      embossFilter->SetBackgroundColor( mBackgroundColor );
-      embossFilter->SetPixelFormat( Pixel::RGBA8888 );
-      embossFilter->SetSize( mTargetSize );
-
-      BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
-      blurFilter->SetInputImage( mImagePostFilter );
-      blurFilter->SetOutputImage( mImagePostFilter );
-      blurFilter->SetRootActor( Self() );
-      blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
-      blurFilter->SetPixelFormat( Pixel::RGBA8888 );
-      blurFilter->SetSize( mTargetSize );
-      blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
+      SpreadFilter* spreadFilter = static_cast<SpreadFilter*>(mFilters[0]);
+      spreadFilter->SetInputTexture(mFrameBufferForChildren.GetColorTexture());
+      spreadFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
+      spreadFilter->SetRootActor(mChildrenRoot);
+      spreadFilter->SetBackgroundColor(mBackgroundColor);
+      spreadFilter->SetPixelFormat(Pixel::RGBA8888);
+      spreadFilter->SetSize(mTargetSize);
+      spreadFilter->SetSpread(mEffectSize);
+
+      EmbossFilter* embossFilter = static_cast<EmbossFilter*>(mFilters[1]);
+      embossFilter->SetInputTexture(mFrameBufferPostFilter.GetColorTexture());
+      embossFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
+      embossFilter->SetRootActor(mChildrenRoot);
+      embossFilter->SetBackgroundColor(mBackgroundColor);
+      embossFilter->SetPixelFormat(Pixel::RGBA8888);
+      embossFilter->SetSize(mTargetSize);
+
+      BlurTwoPassFilter* blurFilter = static_cast<BlurTwoPassFilter*>(mFilters[2]);
+      blurFilter->SetInputTexture(mFrameBufferPostFilter.GetColorTexture());
+      blurFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
+      blurFilter->SetRootActor(mChildrenRoot);
+      blurFilter->SetBackgroundColor(Vector4(0.5f, 0.5f, 0.5f, 0.0));
+      blurFilter->SetPixelFormat(Pixel::RGBA8888);
+      blurFilter->SetSize(mTargetSize);
+      blurFilter->CreateKernel(BLUR_KERNEL0, sizeof(BLUR_KERNEL0) / sizeof(BLUR_KERNEL0[0]));
 
       break;
     }
@@ -432,19 +412,27 @@ void EffectsView::SetupFilters()
     }
   }
 }
+
 void EffectsView::AllocateResources()
 {
   if(mTargetSize != mLastSize)
   {
     mLastSize = mTargetSize;
-
     SetupCameras();
 
-    mImageForChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
-    mActorForChildren.SetImage(mImageForChildren);
+    Actor self(Self());
 
-    mImagePostFilter = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
-    mActorPostFilter.SetImage(mImagePostFilter);
+    mFrameBufferForChildren    = FrameBuffer::New(mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE);
+    Texture textureForChildren = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height));
+    mFrameBufferForChildren.AttachColorTexture(textureForChildren);
+
+    SetRendererTexture(mRendererForChildren, textureForChildren);
+
+    mFrameBufferPostFilter    = FrameBuffer::New(mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE);
+    Texture texturePostFilter = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height));
+    mFrameBufferPostFilter.AttachColorTexture(texturePostFilter);
+
+    SetRendererTexture(mRendererPostFilter, texturePostFilter);
 
     SetupFilters();
   }
@@ -452,65 +440,67 @@ void EffectsView::AllocateResources()
 
 void EffectsView::SetupCameras()
 {
-  const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
-
-  // Create and place a camera for the children render, corresponding to its render target size
-  mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
-  // TODO: how do we pick a reasonable value for near clip? Needs to relate to normal camera the user renders with, but we don't have a handle on it
-  mCameraForChildren.SetNearClippingPlane(1.0f);
-  mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
-  mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
-  mCameraForChildren.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosScale);
-  mCameraForChildren.SetRotation(Quaternion(M_PI, Vector3::YAXIS));
-  mCameraForChildren.SetZ( mTargetSize.height * cameraPosScale );
+  if(!mCameraForChildren)
+  {
+    // Create a camera for the children render, corresponding to its render target size
+    mCameraForChildren = CameraActor::New(mTargetSize);
+    mCameraForChildren.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    mCameraForChildren.SetInvertYAxis(true);
+    Self().Add(mCameraForChildren);
+  }
+  else
+  {
+    // place the camera for the children render, corresponding to its render target size
+    const float cameraPosScale(0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f));
+    mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
+    mCameraForChildren.SetNearClippingPlane(1.0f);
+    mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
+    mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
+    mCameraForChildren.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, mTargetSize.height * cameraPosScale));
+    mCameraForChildren.SetProperty(Actor::Property::POSITION_Z, mTargetSize.height * cameraPosScale);
+  }
 }
 
 void EffectsView::CreateRenderTasks()
 {
+  if(mTargetSize == Vector2::ZERO)
+  {
+    return;
+  }
   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
 
   // create render task to render our child actors to offscreen buffer
   mRenderTaskForChildren = taskList.CreateTask();
-  mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
-  mRenderTaskForChildren.SetSourceActor( Self() );
+  mRenderTaskForChildren.SetRefreshRate(mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS);
+  mRenderTaskForChildren.SetSourceActor(mChildrenRoot);
   mRenderTaskForChildren.SetExclusive(true);
-  mRenderTaskForChildren.SetInputEnabled( false );
-  mRenderTaskForChildren.SetClearColor( mBackgroundColor );
-  mRenderTaskForChildren.SetClearEnabled( true );
-  mRenderTaskForChildren.SetTargetFrameBuffer( mImageForChildren );
+  mRenderTaskForChildren.SetInputEnabled(false);
+  mRenderTaskForChildren.SetClearColor(mBackgroundColor);
+  mRenderTaskForChildren.SetClearEnabled(true);
+  mRenderTaskForChildren.SetFrameBuffer(mFrameBufferForChildren);
   mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
 
   // Enable image filters
-  const size_t numFilters( mFilters.size() );
-  for( size_t i = 0; i < numFilters; ++i )
+  const size_t numFilters(mFilters.Size());
+  for(size_t i = 0; i < numFilters; ++i)
   {
     mFilters[i]->Enable();
   }
-
-  // create render task to render result of the image filters to the final offscreen
-  if( mImageForResult )
-  {
-    mRenderTaskForResult = taskList.CreateTask();
-    mRenderTaskForResult.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
-    mRenderTaskForResult.SetSourceActor( mActorForResult );
-    mRenderTaskForResult.SetExclusive(true);
-    mRenderTaskForResult.SetInputEnabled( false );
-    mRenderTaskForResult.SetClearColor( mBackgroundColor );
-    mRenderTaskForResult.SetClearEnabled( true );
-    mRenderTaskForResult.SetTargetFrameBuffer( mImageForResult );
-    mRenderTaskForResult.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
-  }
 }
 
 void EffectsView::RemoveRenderTasks()
 {
+  if(mTargetSize == Vector2::ZERO)
+  {
+    return;
+  }
+
   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
 
   taskList.RemoveTask(mRenderTaskForChildren);
-  taskList.RemoveTask(mRenderTaskForResult);
 
-  const size_t numFilters( mFilters.size() );
-  for( size_t i = 0; i < numFilters; ++i )
+  const size_t numFilters(mFilters.Size());
+  for(size_t i = 0; i < numFilters; ++i)
   {
     mFilters[i]->Disable();
   }
@@ -520,18 +510,13 @@ void EffectsView::RefreshRenderTasks()
 {
   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
 
-  if( mRenderTaskForChildren )
+  if(mRenderTaskForChildren)
   {
-    mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
+    mRenderTaskForChildren.SetRefreshRate(mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS);
   }
 
-  if( mRenderTaskForResult )
-  {
-    mRenderTaskForResult.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
-  }
-
-  const size_t numFilters( mFilters.size() );
-  for( size_t i = 0; i < numFilters; ++i )
+  const size_t numFilters(mFilters.Size());
+  for(size_t i = 0; i < numFilters; ++i)
   {
     mFilters[i]->Refresh();
   }
@@ -539,12 +524,63 @@ void EffectsView::RefreshRenderTasks()
 
 void EffectsView::RemoveFilters()
 {
-  const size_t numFilters( mFilters.size() );
-  for( size_t i = 0; i < numFilters; ++i )
+  const size_t numFilters(mFilters.Size());
+  for(size_t i = 0; i < numFilters; ++i)
   {
     delete mFilters[i];
   }
-  mFilters.clear();
+  mFilters.Release();
+}
+
+void EffectsView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
+{
+  Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast(Dali::BaseHandle(object));
+
+  if(effectsView)
+  {
+    switch(index)
+    {
+      case Toolkit::EffectsView::Property::EFFECT_SIZE:
+      {
+        int effectSize;
+        if(value.Get(effectSize))
+        {
+          GetImpl(effectsView).SetEffectSize(effectSize);
+        }
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
+  }
+}
+
+Property::Value EffectsView::GetProperty(BaseObject* object, Property::Index propertyIndex)
+{
+  Property::Value value;
+
+  Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast(Dali::BaseHandle(object));
+
+  if(imageview)
+  {
+    EffectsView& impl = GetImpl(imageview);
+    switch(propertyIndex)
+    {
+      case Toolkit::EffectsView::Property::EFFECT_SIZE:
+      {
+        value = impl.GetEffectSize();
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
+  }
+
+  return value;
 }
 
 } // namespace Internal