2 * Copyright (c) 2020 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/devel-api/common/stage.h>
25 #include <dali/public-api/object/property.h>
26 #include <dali/public-api/object/property-map.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/public-api/render-tasks/render-task-list.h>
30 #include <dali/public-api/rendering/renderer.h>
33 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
34 #include <dali-toolkit/devel-api/controls/control-devel.h>
35 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
36 #include <dali-toolkit/internal/filters/blur-two-pass-filter.h>
37 #include <dali-toolkit/internal/filters/emboss-filter.h>
38 #include <dali-toolkit/internal/filters/spread-filter.h>
39 #include <dali-toolkit/internal/controls/control/control-renderers.h>
40 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
54 Dali::BaseHandle Create()
56 return EffectsView::New();
59 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::EffectsView, Toolkit::Control, Create )
60 DALI_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectSize", INTEGER, EFFECT_SIZE )
61 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectOffset", VECTOR3, EFFECT_OFFSET )
62 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, EffectsView, "effectColor", Color::WHITE, EFFECT_COLOR )
63 DALI_TYPE_REGISTRATION_END()
65 const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
66 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
67 const Vector4 EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR( 0.0f, 0.0f, 0.0f, 0.0 );
68 const bool EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
70 const float BLUR_KERNEL0[] = { 12.0f/16.0f,
71 2.0f/16.0f, 2.0f/16.0f };
73 const float BLUR_KERNEL1[] = { 8.0f/16.0f,
74 4.0f/16.0f, 4.0f/16.0f };
76 const float BLUR_KERNEL2[] = { 6.0f/16.0f,
77 2.5f/16.0f, 2.5f/16.0f,
78 1.5f/16.0f, 1.5f/16.0f,
79 1.0f/16.0f, 1.0f/16.0f };
81 const float BLUR_KERNEL3[] = { 4.0f/16.0f,
82 3.0f/16.0f, 2.0f/16.0f,
83 2.0f/16.0f, 2.0f/16.0f,
84 1.0f/16.0f, 1.0f/16.0f };
86 const float BLUR_KERNEL4[] = { 3.0f/16.0f,
87 2.5f/16.0f, 2.5f/16.0f,
88 1.75f/16.0f, 1.75f/16.0f,
89 1.25f/16.0f, 1.25f/16.0f,
90 1.0f/16.0f, 1.0f/16.0f };
94 Toolkit::EffectsView EffectsView::New()
96 EffectsView* effectsView = new EffectsView;
98 Toolkit::EffectsView handle = Toolkit::EffectsView( *effectsView );
100 // Second-phase init of the implementation
101 // This can only be done after the CustomActor connection has been made...
102 effectsView->Initialize();
107 EffectsView::EffectsView()
108 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
109 mChildrenRoot(Actor::New()),
110 mBackgroundColor( EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR ),
111 mTargetSize( Vector2::ZERO ),
112 mLastSize( Vector2::ZERO ),
114 mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
115 mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
117 mRefreshOnDemand( EFFECTS_VIEW_REFRESH_ON_DEMAND )
121 EffectsView::~EffectsView()
126 void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
128 if( mEffectType != type )
136 case Toolkit::EffectsView::DROP_SHADOW:
138 mFilters.PushBack( new SpreadFilter );
139 mFilters.PushBack( new BlurTwoPassFilter );
142 case Toolkit::EffectsView::EMBOSS:
144 mFilters.PushBack( new SpreadFilter );
145 mFilters.PushBack( new EmbossFilter );
146 mFilters.PushBack( new BlurTwoPassFilter );
159 Toolkit::EffectsView::EffectType EffectsView::GetType() const
164 void EffectsView::Enable()
166 // make sure resources are allocated and start the render tasks processing
172 void EffectsView::Disable()
174 // stop render tasks processing
176 mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
180 void EffectsView::Refresh()
182 RefreshRenderTasks();
185 void EffectsView::SetRefreshOnDemand( bool onDemand )
187 mRefreshOnDemand = onDemand;
189 RefreshRenderTasks();
192 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
194 mPixelFormat = pixelFormat;
197 void EffectsView::SetBackgroundColor( const Vector4& color )
199 mBackgroundColor = color;
202 Vector4 EffectsView::GetBackgroundColor() const
204 return mBackgroundColor;
207 void EffectsView::SetEffectSize( int effectSize )
209 mEffectSize = effectSize;
213 const size_t numFilters( mFilters.Size() );
214 for( size_t i = 0; i < numFilters; ++i )
216 mFilters[i]->Disable();
221 for( size_t i = 0; i < numFilters; ++i )
223 mFilters[i]->Enable();
228 int EffectsView::GetEffectSize()
234 void EffectsView::OnInitialize()
236 CustomActor self = Self();
237 mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
238 self.Add( mChildrenRoot );
240 DevelControl::SetAccessibilityConstructor( self, []( Dali::Actor actor ) {
241 return std::unique_ptr< Dali::Accessibility::Accessible >(
242 new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::FILLER ) );
246 void EffectsView::OnSizeSet(const Vector3& targetSize)
248 mTargetSize = Vector2(targetSize);
250 // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
253 if( mLastSize != Vector2::ZERO )
260 mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize );
262 Control::OnSizeSet( targetSize );
265 void EffectsView::OnSceneConnection( int depth )
267 Actor self( Self() );
270 mRendererPostFilter = CreateRenderer( SHADER_EFFECTS_VIEW_VERT,
271 SHADER_EFFECTS_VIEW_FRAG );
272 mRendererPostFilter.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT );
273 self.AddRenderer( mRendererPostFilter );
275 mRendererForChildren = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
276 mRendererForChildren.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + 1 );
277 self.AddRenderer( mRendererForChildren );
281 Control::OnSceneConnection( depth );
284 void EffectsView::OnSceneDisconnection()
286 Actor self( Self() );
290 const size_t numFilters( mFilters.Size() );
291 for( size_t i = 0; i < numFilters; ++i )
293 mFilters[i]->Disable();
297 self.RemoveRenderer( mRendererForChildren );
298 mRendererForChildren.Reset();
300 self.RemoveRenderer( mRendererPostFilter );
301 mRendererPostFilter.Reset();
303 Control::OnSceneDisconnection();
306 void EffectsView::OnChildAdd( Actor& child )
308 if( child != mChildrenRoot && child != mCameraForChildren )
310 mChildrenRoot.Add( child );
313 Control::OnChildAdd( child );
316 void EffectsView::OnChildRemove( Actor& child )
318 mChildrenRoot.Remove( child );
320 Control::OnChildRemove( child );
323 void EffectsView::SetupFilters()
325 switch( mEffectType )
327 case Toolkit::EffectsView::DROP_SHADOW:
329 SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
330 spreadFilter->SetInputTexture( mFrameBufferForChildren.GetColorTexture() );
331 spreadFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
332 spreadFilter->SetRootActor( mChildrenRoot );
333 spreadFilter->SetBackgroundColor( mBackgroundColor );
334 spreadFilter->SetPixelFormat( mPixelFormat );
335 spreadFilter->SetSize( mTargetSize );
336 spreadFilter->SetSpread( mEffectSize );
338 BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
339 blurFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
340 blurFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
341 blurFilter->SetRootActor( mChildrenRoot );
342 blurFilter->SetBackgroundColor( mBackgroundColor );
343 blurFilter->SetPixelFormat( mPixelFormat );
344 blurFilter->SetSize( mTargetSize );
346 const float* kernel(NULL);
347 size_t kernelSize(0);
348 switch( mEffectSize )
350 case 4: { kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
351 case 3: { kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
352 case 2: { kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
353 case 1: { kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
355 default: { kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
357 blurFilter->CreateKernel( kernel, kernelSize );
360 case Toolkit::EffectsView::EMBOSS:
362 SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
363 spreadFilter->SetInputTexture( mFrameBufferForChildren.GetColorTexture() );
364 spreadFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
365 spreadFilter->SetRootActor( mChildrenRoot );
366 spreadFilter->SetBackgroundColor( mBackgroundColor );
367 spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
368 spreadFilter->SetSize( mTargetSize );
369 spreadFilter->SetSpread( mEffectSize );
371 EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
372 embossFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
373 embossFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
374 embossFilter->SetRootActor( mChildrenRoot );
375 embossFilter->SetBackgroundColor( mBackgroundColor );
376 embossFilter->SetPixelFormat( Pixel::RGBA8888 );
377 embossFilter->SetSize( mTargetSize );
379 BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
380 blurFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
381 blurFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
382 blurFilter->SetRootActor( mChildrenRoot );
383 blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
384 blurFilter->SetPixelFormat( Pixel::RGBA8888 );
385 blurFilter->SetSize( mTargetSize );
386 blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
397 void EffectsView::AllocateResources()
399 if(mTargetSize != mLastSize)
401 mLastSize = mTargetSize;
404 Actor self( Self() );
406 mFrameBufferForChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
407 Texture textureForChildren = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
408 mFrameBufferForChildren.AttachColorTexture( textureForChildren );
410 SetRendererTexture( mRendererForChildren, textureForChildren );
412 mFrameBufferPostFilter = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
413 Texture texturePostFilter = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
414 mFrameBufferPostFilter.AttachColorTexture( texturePostFilter );
416 SetRendererTexture( mRendererPostFilter, texturePostFilter );
422 void EffectsView::SetupCameras()
424 if( !mCameraForChildren )
426 // Create a camera for the children render, corresponding to its render target size
427 mCameraForChildren = CameraActor::New(mTargetSize);
428 mCameraForChildren.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
429 mCameraForChildren.SetInvertYAxis( true );
430 Self().Add( mCameraForChildren );
434 // place the camera for the children render, corresponding to its render target size
435 const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
436 mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
437 mCameraForChildren.SetNearClippingPlane(1.0f);
438 mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
439 mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
440 mCameraForChildren.SetProperty( Actor::Property::POSITION, Vector3( 0.0f, 0.0f, mTargetSize.height * cameraPosScale ) );
441 mCameraForChildren.SetProperty( Actor::Property::POSITION_Z, mTargetSize.height * cameraPosScale );
445 void EffectsView::CreateRenderTasks()
447 if( mTargetSize == Vector2::ZERO )
451 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
453 // create render task to render our child actors to offscreen buffer
454 mRenderTaskForChildren = taskList.CreateTask();
455 mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
456 mRenderTaskForChildren.SetSourceActor( mChildrenRoot );
457 mRenderTaskForChildren.SetExclusive(true);
458 mRenderTaskForChildren.SetInputEnabled( false );
459 mRenderTaskForChildren.SetClearColor( mBackgroundColor );
460 mRenderTaskForChildren.SetClearEnabled( true );
461 mRenderTaskForChildren.SetFrameBuffer( mFrameBufferForChildren );
462 mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
464 // Enable image filters
465 const size_t numFilters( mFilters.Size() );
466 for( size_t i = 0; i < numFilters; ++i )
468 mFilters[i]->Enable();
472 void EffectsView::RemoveRenderTasks()
474 if( mTargetSize == Vector2::ZERO )
479 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
481 taskList.RemoveTask(mRenderTaskForChildren);
483 const size_t numFilters( mFilters.Size() );
484 for( size_t i = 0; i < numFilters; ++i )
486 mFilters[i]->Disable();
490 void EffectsView::RefreshRenderTasks()
492 RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
494 if( mRenderTaskForChildren )
496 mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
499 const size_t numFilters( mFilters.Size() );
500 for( size_t i = 0; i < numFilters; ++i )
502 mFilters[i]->Refresh();
506 void EffectsView::RemoveFilters()
508 const size_t numFilters( mFilters.Size() );
509 for( size_t i = 0; i < numFilters; ++i )
516 void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
518 Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
524 case Toolkit::EffectsView::Property::EFFECT_SIZE:
527 if( value.Get( effectSize ) )
529 GetImpl( effectsView ).SetEffectSize( effectSize );
541 Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
543 Property::Value value;
545 Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
549 EffectsView& impl = GetImpl( imageview );
550 switch ( propertyIndex )
552 case Toolkit::EffectsView::Property::EFFECT_SIZE:
554 value = impl.GetEffectSize();
567 } // namespace Internal
569 } // namespace Toolkit