2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "effects-view-impl.h"
22 #include <dali/public-api/animation/constraint.h>
23 #include <dali/public-api/animation/constraints.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/object/property-map.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/public-api/object/type-registry-helper.h>
28 #include <dali/public-api/render-tasks/render-task-list.h>
31 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
32 #include <dali-toolkit/internal/filters/blur-two-pass-filter.h>
33 #include <dali-toolkit/internal/filters/emboss-filter.h>
34 #include <dali-toolkit/internal/filters/spread-filter.h>
48 Dali::BaseHandle Create()
50 return EffectsView::New();
53 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::EffectsView, Toolkit::Control, Create )
54 DALI_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectSize", INTEGER, EFFECT_SIZE )
55 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectOffset", VECTOR3, EFFECT_OFFSET )
56 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, EffectsView, "effectColor", Color::WHITE, EFFECT_COLOR )
57 DALI_TYPE_REGISTRATION_END()
59 const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
60 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
61 const Vector4 EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR( 1.0f, 1.0f, 1.0f, 0.0 );
62 const bool EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
64 const char* EFFECTS_VIEW_VERTEX_SOURCE = DALI_COMPOSE_SHADER(
65 attribute mediump vec2 aPosition;\n
66 varying mediump vec2 vTexCoord;\n
67 uniform mediump mat4 uMvpMatrix;\n
68 uniform mediump vec3 uSize;\n
69 uniform mediump vec3 effectOffset;\n
73 mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
74 vertexPosition.xyz *= uSize;\n
75 vertexPosition.xyz += effectOffset;\n
76 vertexPosition = uMvpMatrix * vertexPosition;\n
78 vTexCoord = aPosition + vec2(0.5);\n
79 gl_Position = vertexPosition;\n
83 const char* EFFECTS_VIEW_FRAGMENT_SOURCE = DALI_COMPOSE_SHADER(
84 varying mediump vec2 vTexCoord;\n
85 uniform sampler2D sTexture;\n
86 uniform lowp vec4 effectColor;\n
90 gl_FragColor = effectColor;\n
91 gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n
95 const float BLUR_KERNEL0[] = { 12.0f/16.0f,
96 2.0f/16.0f, 2.0f/16.0f };
98 const float BLUR_KERNEL1[] = { 8.0f/16.0f,
99 4.0f/16.0f, 4.0f/16.0f };
101 const float BLUR_KERNEL2[] = { 6.0f/16.0f,
102 2.5f/16.0f, 2.5f/16.0f,
103 1.5f/16.0f, 1.5f/16.0f,
104 1.0f/16.0f, 1.0f/16.0f };
106 const float BLUR_KERNEL3[] = { 4.0f/16.0f,
107 3.0f/16.0f, 2.0f/16.0f,
108 2.0f/16.0f, 2.0f/16.0f,
109 1.0f/16.0f, 1.0f/16.0f };
111 const float BLUR_KERNEL4[] = { 3.0f/16.0f,
112 2.5f/16.0f, 2.5f/16.0f,
113 1.75f/16.0f, 1.75f/16.0f,
114 1.25f/16.0f, 1.25f/16.0f,
115 1.0f/16.0f, 1.0f/16.0f };
119 Toolkit::EffectsView EffectsView::New()
121 EffectsView* effectsView = new EffectsView;
123 Toolkit::EffectsView handle = Toolkit::EffectsView( *effectsView );
125 // Second-phase init of the implementation
126 // This can only be done after the CustomActor connection has been made...
127 effectsView->Initialize();
132 EffectsView::EffectsView()
133 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
134 mChildrenRoot(Actor::New()),
135 mBackgroundColor( EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR ),
136 mTargetSize( Vector2::ZERO ),
137 mLastSize( Vector2::ZERO ),
139 mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
140 mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
142 mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND)
146 EffectsView::~EffectsView()
151 void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
153 if( mEffectType != type )
158 Property::Map rendererMap;
159 rendererMap.Insert( "rendererType", "image" );
163 case Toolkit::EffectsView::DROP_SHADOW:
165 mFilters.PushBack( new SpreadFilter );
166 mFilters.PushBack( new BlurTwoPassFilter );
169 case Toolkit::EffectsView::EMBOSS:
171 mFilters.PushBack( new SpreadFilter );
172 mFilters.PushBack( new EmbossFilter );
173 mFilters.PushBack( new BlurTwoPassFilter );
182 Property::Map customShader;
183 customShader[ "vertexShader" ] = EFFECTS_VIEW_VERTEX_SOURCE;
184 customShader[ "fragmentShader" ] = EFFECTS_VIEW_FRAGMENT_SOURCE;
185 rendererMap[ "shader" ] = customShader;
186 Toolkit::RendererFactory::Get().ResetRenderer( mRendererPostFilter, self, rendererMap );
192 Toolkit::EffectsView::EffectType EffectsView::GetType() const
197 void EffectsView::Enable()
199 // make sure resources are allocated and start the render tasks processing
205 void EffectsView::Disable()
207 // stop render tasks processing
208 // Note: render target resources are automatically freed since we set the Image::Unused flag
213 void EffectsView::Refresh()
215 RefreshRenderTasks();
218 void EffectsView::SetRefreshOnDemand( bool onDemand )
220 mRefreshOnDemand = onDemand;
222 RefreshRenderTasks();
225 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
227 mPixelFormat = pixelFormat;
230 void EffectsView::SetBackgroundColor( const Vector4& color )
232 mBackgroundColor = color;
235 Vector4 EffectsView::GetBackgroundColor() const
237 return mBackgroundColor;
240 void EffectsView::SetEffectSize( int effectSize )
242 mEffectSize = effectSize;
246 const size_t numFilters( mFilters.Size() );
247 for( size_t i = 0; i < numFilters; ++i )
249 mFilters[i]->Disable();
254 for( size_t i = 0; i < numFilters; ++i )
256 mFilters[i]->Enable();
261 int EffectsView::GetEffectSize()
267 void EffectsView::OnInitialize()
269 CustomActor self = Self();
270 mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
271 self.Add( mChildrenRoot );
274 void EffectsView::OnSizeSet(const Vector3& targetSize)
276 Control::OnSizeSet( targetSize );
278 mTargetSize = Vector2(targetSize);
280 // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
283 if( mLastSize != Vector2::ZERO )
290 mChildrenRoot.SetSize( targetSize );
293 void EffectsView::OnStageConnection( int depth )
295 Control::OnStageConnection( depth );
300 if( mRendererPostFilter )
302 mRendererPostFilter.SetOnStage( self );
304 if( mRendererForChildren )
306 mRendererForChildren.SetOnStage( self );
310 void EffectsView::OnStageDisconnection()
314 const size_t numFilters( mFilters.Size() );
315 for( size_t i = 0; i < numFilters; ++i )
317 mFilters[i]->Disable();
321 if( mRendererPostFilter )
323 mRendererPostFilter.SetOffStage( self );
325 if( mRendererForChildren )
327 mRendererForChildren.SetOffStage( self );
330 Control::OnStageDisconnection();
333 void EffectsView::OnChildAdd( Actor& child )
335 Control::OnChildAdd( child );
337 if( child != mChildrenRoot && child != mCameraForChildren )
339 mChildrenRoot.Add( child );
343 void EffectsView::OnChildRemove( Actor& child )
345 mChildrenRoot.Remove( child );
347 Control::OnChildRemove( child );
350 void EffectsView::SetupFilters()
352 switch( mEffectType )
354 case Toolkit::EffectsView::DROP_SHADOW:
356 SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
357 spreadFilter->SetInputImage( mImageForChildren );
358 spreadFilter->SetOutputImage( mImagePostFilter );
359 spreadFilter->SetRootActor( mChildrenRoot );
360 spreadFilter->SetBackgroundColor( mBackgroundColor );
361 spreadFilter->SetPixelFormat( mPixelFormat );
362 spreadFilter->SetSize( mTargetSize );
363 spreadFilter->SetSpread( mEffectSize );
365 BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
366 blurFilter->SetInputImage( mImagePostFilter );
367 blurFilter->SetOutputImage( mImagePostFilter );
368 blurFilter->SetRootActor( mChildrenRoot );
369 blurFilter->SetBackgroundColor( mBackgroundColor );
370 blurFilter->SetPixelFormat( mPixelFormat );
371 blurFilter->SetSize( mTargetSize );
373 const float* kernel(NULL);
374 size_t kernelSize(0);
375 switch( mEffectSize )
377 case 4: { kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
378 case 3: { kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
379 case 2: { kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
380 case 1: { kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
382 default: { kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
384 blurFilter->CreateKernel( kernel, kernelSize );
387 case Toolkit::EffectsView::EMBOSS:
389 SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
390 spreadFilter->SetInputImage( mImageForChildren );
391 spreadFilter->SetOutputImage( mImagePostFilter );
392 spreadFilter->SetRootActor( mChildrenRoot );
393 spreadFilter->SetBackgroundColor( mBackgroundColor );
394 spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
395 spreadFilter->SetSize( mTargetSize );
396 spreadFilter->SetSpread( mEffectSize );
398 EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
399 embossFilter->SetInputImage( mImagePostFilter );
400 embossFilter->SetOutputImage( mImagePostFilter );
401 embossFilter->SetRootActor( mChildrenRoot );
402 embossFilter->SetBackgroundColor( mBackgroundColor );
403 embossFilter->SetPixelFormat( Pixel::RGBA8888 );
404 embossFilter->SetSize( mTargetSize );
406 BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
407 blurFilter->SetInputImage( mImagePostFilter );
408 blurFilter->SetOutputImage( mImagePostFilter );
409 blurFilter->SetRootActor( mChildrenRoot );
410 blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
411 blurFilter->SetPixelFormat( Pixel::RGBA8888 );
412 blurFilter->SetSize( mTargetSize );
413 blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
423 void EffectsView::AllocateResources()
425 if(mTargetSize != mLastSize)
427 mLastSize = mTargetSize;
430 Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get();
433 mImageForChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
434 rendererFactory.ResetRenderer(mRendererForChildren, self, mImageForChildren);
435 mRendererForChildren.SetDepthIndex( DepthIndex::CONTENT+1 );
437 mImagePostFilter = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
438 rendererFactory.ResetRenderer(mRendererPostFilter, self, mImagePostFilter);
439 mRendererPostFilter.SetDepthIndex( DepthIndex::CONTENT );
445 void EffectsView::SetupCameras()
447 if( !mCameraForChildren )
449 // Create a camera for the children render, corresponding to its render target size
450 mCameraForChildren = CameraActor::New(mTargetSize);
451 mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
452 mCameraForChildren.SetInvertYAxis( true );
453 Self().Add( mCameraForChildren );
457 // place the camera for the children render, corresponding to its render target size
458 const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
459 mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
460 mCameraForChildren.SetNearClippingPlane(1.0f);
461 mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
462 mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
463 mCameraForChildren.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosScale);
464 mCameraForChildren.SetZ( mTargetSize.height * cameraPosScale );
468 void EffectsView::CreateRenderTasks()
470 if( mTargetSize == Vector2::ZERO )
474 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
476 // create render task to render our child actors to offscreen buffer
477 mRenderTaskForChildren = taskList.CreateTask();
478 mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
479 mRenderTaskForChildren.SetSourceActor( mChildrenRoot );
480 mRenderTaskForChildren.SetExclusive(true);
481 mRenderTaskForChildren.SetInputEnabled( false );
482 mRenderTaskForChildren.SetClearColor( mBackgroundColor );
483 mRenderTaskForChildren.SetClearEnabled( true );
484 mRenderTaskForChildren.SetTargetFrameBuffer( mImageForChildren );
485 mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
487 // Enable image filters
488 const size_t numFilters( mFilters.Size() );
489 for( size_t i = 0; i < numFilters; ++i )
491 mFilters[i]->Enable();
495 void EffectsView::RemoveRenderTasks()
497 if( mTargetSize == Vector2::ZERO )
502 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
504 taskList.RemoveTask(mRenderTaskForChildren);
506 const size_t numFilters( mFilters.Size() );
507 for( size_t i = 0; i < numFilters; ++i )
509 mFilters[i]->Disable();
513 void EffectsView::RefreshRenderTasks()
515 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
517 if( mRenderTaskForChildren )
519 mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
522 const size_t numFilters( mFilters.Size() );
523 for( size_t i = 0; i < numFilters; ++i )
525 mFilters[i]->Refresh();
529 void EffectsView::RemoveFilters()
531 const size_t numFilters( mFilters.Size() );
532 for( size_t i = 0; i < numFilters; ++i )
539 void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
541 Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
547 case Toolkit::EffectsView::Property::EFFECT_SIZE:
550 if( value.Get( effectSize ) )
552 GetImpl( effectsView ).SetEffectSize( effectSize );
564 Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
566 Property::Value value;
568 Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
572 EffectsView& impl = GetImpl( imageview );
573 switch ( propertyIndex )
575 case Toolkit::EffectsView::Property::EFFECT_SIZE:
577 value = impl.GetEffectSize();
590 } // namespace Internal
592 } // namespace Toolkit