bd12e33f536dcb0bf5793c5271ac8b61b22b5683
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / effects-view / effects-view-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include "effects-view-impl.h"
20
21 // EXTERNAL INCLUDES
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>
31
32 // INTERNAL INCLUDES
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>
41
42 namespace Dali
43 {
44
45 namespace Toolkit
46 {
47
48 namespace Internal
49 {
50
51 namespace
52 {
53
54 Dali::BaseHandle Create()
55 {
56   return EffectsView::New();
57 }
58
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()
64
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);
69
70 const float BLUR_KERNEL0[] = { 12.0f/16.0f,
71                                2.0f/16.0f, 2.0f/16.0f };
72
73 const float BLUR_KERNEL1[] = { 8.0f/16.0f,
74                                4.0f/16.0f, 4.0f/16.0f };
75
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 };
80
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 };
85
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 };
91
92 } // namespace
93
94 Toolkit::EffectsView EffectsView::New()
95 {
96   EffectsView* effectsView = new EffectsView;
97
98   Toolkit::EffectsView handle = Toolkit::EffectsView( *effectsView );
99
100   // Second-phase init of the implementation
101   // This can only be done after the CustomActor connection has been made...
102   effectsView->Initialize();
103
104   return handle;
105 }
106
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 ),
113   mEffectSize(0),
114   mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
115   mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
116   mEnabled( false ),
117   mRefreshOnDemand( EFFECTS_VIEW_REFRESH_ON_DEMAND )
118 {
119 }
120
121 EffectsView::~EffectsView()
122 {
123   RemoveFilters();
124 }
125
126 void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
127 {
128   if( mEffectType != type )
129   {
130     RemoveFilters();
131
132     Actor self = Self();
133
134     switch( type )
135     {
136       case Toolkit::EffectsView::DROP_SHADOW:
137       {
138         mFilters.PushBack( new SpreadFilter );
139         mFilters.PushBack( new BlurTwoPassFilter );
140         break;
141       }
142       case Toolkit::EffectsView::EMBOSS:
143       {
144         mFilters.PushBack( new SpreadFilter );
145         mFilters.PushBack( new EmbossFilter );
146         mFilters.PushBack( new BlurTwoPassFilter );
147         break;
148       }
149       default:
150       {
151         break;
152       }
153     }
154
155     mEffectType = type;
156   }
157 }
158
159 Toolkit::EffectsView::EffectType EffectsView::GetType() const
160 {
161   return mEffectType;
162 }
163
164 void EffectsView::Enable()
165 {
166   // make sure resources are allocated and start the render tasks processing
167   AllocateResources();
168   CreateRenderTasks();
169   mEnabled = true;
170 }
171
172 void EffectsView::Disable()
173 {
174   // stop render tasks processing
175   RemoveRenderTasks();
176   mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
177   mEnabled = false;
178 }
179
180 void EffectsView::Refresh()
181 {
182   RefreshRenderTasks();
183 }
184
185 void EffectsView::SetRefreshOnDemand( bool onDemand )
186 {
187   mRefreshOnDemand = onDemand;
188
189   RefreshRenderTasks();
190 }
191
192 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
193 {
194   mPixelFormat = pixelFormat;
195 }
196
197 void EffectsView::SetBackgroundColor( const Vector4& color )
198 {
199   mBackgroundColor = color;
200 }
201
202 Vector4 EffectsView::GetBackgroundColor() const
203 {
204   return mBackgroundColor;
205 }
206
207 void EffectsView::SetEffectSize( int effectSize )
208 {
209   mEffectSize = effectSize;
210
211   if( mEnabled )
212   {
213     const size_t numFilters( mFilters.Size() );
214     for( size_t i = 0; i < numFilters; ++i )
215     {
216       mFilters[i]->Disable();
217     }
218
219     SetupFilters();
220
221     for( size_t i = 0; i < numFilters; ++i )
222     {
223       mFilters[i]->Enable();
224     }
225   }
226 }
227
228 int EffectsView::GetEffectSize()
229 {
230   return mEffectSize;
231 }
232
233 // From Control
234 void EffectsView::OnInitialize()
235 {
236   CustomActor self = Self();
237   mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
238   self.Add( mChildrenRoot );
239
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 ) );
243   } );
244 }
245
246 void EffectsView::OnSizeSet(const Vector3& targetSize)
247 {
248   mTargetSize = Vector2(targetSize);
249
250   // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
251   if(mEnabled)
252   {
253     if( mLastSize != Vector2::ZERO )
254     {
255       Disable();
256     }
257     Enable();
258   }
259
260   mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize );
261
262   Control::OnSizeSet( targetSize );
263 }
264
265 void EffectsView::OnSceneConnection( int depth )
266 {
267   Actor self( Self() );
268
269   // Create renderers
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 );
274
275   mRendererForChildren = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
276   mRendererForChildren.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + 1 );
277   self.AddRenderer( mRendererForChildren );
278
279   Enable();
280
281   Control::OnSceneConnection( depth );
282 }
283
284 void EffectsView::OnSceneDisconnection()
285 {
286   Actor self( Self() );
287
288   Disable();
289
290   const size_t numFilters( mFilters.Size() );
291   for( size_t i = 0; i < numFilters; ++i )
292   {
293     mFilters[i]->Disable();
294   }
295
296   // Remove renderers
297   self.RemoveRenderer( mRendererForChildren );
298   mRendererForChildren.Reset();
299
300   self.RemoveRenderer( mRendererPostFilter );
301   mRendererPostFilter.Reset();
302
303   Control::OnSceneDisconnection();
304 }
305
306 void EffectsView::OnChildAdd( Actor& child )
307 {
308   if( child != mChildrenRoot && child != mCameraForChildren )
309   {
310     mChildrenRoot.Add( child );
311   }
312
313   Control::OnChildAdd( child );
314 }
315
316 void EffectsView::OnChildRemove( Actor& child )
317 {
318   mChildrenRoot.Remove( child );
319
320   Control::OnChildRemove( child );
321 }
322
323 void EffectsView::SetupFilters()
324 {
325   switch( mEffectType )
326   {
327     case Toolkit::EffectsView::DROP_SHADOW:
328     {
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 );
337
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 );
345
346       const float* kernel(NULL);
347       size_t kernelSize(0);
348       switch( mEffectSize )
349       {
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; }
354         case 0:
355         default: {  kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
356       }
357       blurFilter->CreateKernel( kernel, kernelSize );
358       break;
359     }
360     case Toolkit::EffectsView::EMBOSS:
361     {
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 );
370
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 );
378
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]) );
387
388       break;
389     }
390     default:
391     {
392       break;
393     }
394   }
395 }
396
397 void EffectsView::AllocateResources()
398 {
399   if(mTargetSize != mLastSize)
400   {
401     mLastSize = mTargetSize;
402     SetupCameras();
403
404     Actor self( Self() );
405
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 );
409
410     SetRendererTexture( mRendererForChildren, textureForChildren );
411
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 );
415
416     SetRendererTexture( mRendererPostFilter, texturePostFilter );
417
418     SetupFilters();
419   }
420 }
421
422 void EffectsView::SetupCameras()
423 {
424   if( !mCameraForChildren )
425   {
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 );
431   }
432   else
433   {
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 );
442   }
443 }
444
445 void EffectsView::CreateRenderTasks()
446 {
447   if( mTargetSize == Vector2::ZERO )
448   {
449     return;
450   }
451   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
452
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
463
464   // Enable image filters
465   const size_t numFilters( mFilters.Size() );
466   for( size_t i = 0; i < numFilters; ++i )
467   {
468     mFilters[i]->Enable();
469   }
470 }
471
472 void EffectsView::RemoveRenderTasks()
473 {
474   if( mTargetSize == Vector2::ZERO )
475   {
476     return;
477   }
478
479   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
480
481   taskList.RemoveTask(mRenderTaskForChildren);
482
483   const size_t numFilters( mFilters.Size() );
484   for( size_t i = 0; i < numFilters; ++i )
485   {
486     mFilters[i]->Disable();
487   }
488 }
489
490 void EffectsView::RefreshRenderTasks()
491 {
492   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
493
494   if( mRenderTaskForChildren )
495   {
496     mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
497   }
498
499   const size_t numFilters( mFilters.Size() );
500   for( size_t i = 0; i < numFilters; ++i )
501   {
502     mFilters[i]->Refresh();
503   }
504 }
505
506 void EffectsView::RemoveFilters()
507 {
508   const size_t numFilters( mFilters.Size() );
509   for( size_t i = 0; i < numFilters; ++i )
510   {
511     delete mFilters[i];
512   }
513   mFilters.Release();
514 }
515
516 void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
517 {
518   Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
519
520   if ( effectsView )
521   {
522     switch ( index )
523     {
524       case Toolkit::EffectsView::Property::EFFECT_SIZE:
525       {
526         int effectSize;
527         if( value.Get( effectSize ) )
528         {
529           GetImpl( effectsView ).SetEffectSize( effectSize );
530         }
531         break;
532       }
533       default:
534       {
535         break;
536       }
537     }
538   }
539 }
540
541 Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
542 {
543   Property::Value value;
544
545   Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
546
547   if ( imageview )
548   {
549     EffectsView& impl = GetImpl( imageview );
550     switch ( propertyIndex )
551     {
552       case Toolkit::EffectsView::Property::EFFECT_SIZE:
553       {
554          value = impl.GetEffectSize();
555         break;
556       }
557       default:
558       {
559         break;
560       }
561     }
562   }
563
564   return value;
565 }
566
567 } // namespace Internal
568
569 } // namespace Toolkit
570
571 } // namespace Dali