dee09e905b2de76e9c4fe6cbf151b1d415f82dac
[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/filters/blur-two-pass-filter.h>
36 #include <dali-toolkit/internal/filters/emboss-filter.h>
37 #include <dali-toolkit/internal/filters/spread-filter.h>
38 #include <dali-toolkit/internal/controls/control/control-renderers.h>
39 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
40
41 namespace Dali
42 {
43
44 namespace Toolkit
45 {
46
47 namespace Internal
48 {
49
50 namespace
51 {
52
53 Dali::BaseHandle Create()
54 {
55   return EffectsView::New();
56 }
57
58 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::EffectsView, Toolkit::Control, Create )
59 DALI_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectSize", INTEGER, EFFECT_SIZE )
60 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectOffset", VECTOR3, EFFECT_OFFSET )
61 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, EffectsView, "effectColor", Color::WHITE, EFFECT_COLOR )
62 DALI_TYPE_REGISTRATION_END()
63
64 const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
65 const float         ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
66 const Vector4       EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR( 0.0f, 0.0f, 0.0f, 0.0 );
67 const bool          EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
68
69 #define DALI_COMPOSE_SHADER(STR) #STR
70
71 const char* EFFECTS_VIEW_VERTEX_SOURCE = DALI_COMPOSE_SHADER(
72   attribute mediump vec2 aPosition;\n
73   varying mediump vec2 vTexCoord;\n
74   uniform mediump mat4 uMvpMatrix;\n
75   uniform mediump vec3 uSize;\n
76   uniform mediump vec3 effectOffset;\n
77   \n
78   void main()\n
79   {\n
80     mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
81     vertexPosition.xyz *= uSize;\n
82     vertexPosition.xyz += effectOffset;\n
83     vertexPosition = uMvpMatrix * vertexPosition;\n
84     \n
85     vTexCoord = aPosition + vec2(0.5);\n
86     gl_Position = vertexPosition;\n
87   }\n
88 );
89
90 const char* EFFECTS_VIEW_FRAGMENT_SOURCE = DALI_COMPOSE_SHADER(
91   varying mediump vec2 vTexCoord;\n
92   uniform sampler2D sTexture;\n
93   uniform lowp vec4 effectColor;\n
94   \n
95   void main()\n
96   {\n
97      gl_FragColor = effectColor;\n
98      gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n
99   }\n
100 );
101
102 const float BLUR_KERNEL0[] = { 12.0f/16.0f,
103                                2.0f/16.0f, 2.0f/16.0f };
104
105 const float BLUR_KERNEL1[] = { 8.0f/16.0f,
106                                4.0f/16.0f, 4.0f/16.0f };
107
108 const float BLUR_KERNEL2[] = { 6.0f/16.0f,
109                                2.5f/16.0f, 2.5f/16.0f,
110                                1.5f/16.0f, 1.5f/16.0f,
111                                1.0f/16.0f, 1.0f/16.0f };
112
113 const float BLUR_KERNEL3[] = { 4.0f/16.0f,
114                                3.0f/16.0f, 2.0f/16.0f,
115                                2.0f/16.0f, 2.0f/16.0f,
116                                1.0f/16.0f, 1.0f/16.0f };
117
118 const float BLUR_KERNEL4[] = { 3.0f/16.0f,
119                                2.5f/16.0f,  2.5f/16.0f,
120                                1.75f/16.0f, 1.75f/16.0f,
121                                1.25f/16.0f, 1.25f/16.0f,
122                                1.0f/16.0f,  1.0f/16.0f };
123
124 } // namespace
125
126 Toolkit::EffectsView EffectsView::New()
127 {
128   EffectsView* effectsView = new EffectsView;
129
130   Toolkit::EffectsView handle = Toolkit::EffectsView( *effectsView );
131
132   // Second-phase init of the implementation
133   // This can only be done after the CustomActor connection has been made...
134   effectsView->Initialize();
135
136   return handle;
137 }
138
139 EffectsView::EffectsView()
140 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
141   mChildrenRoot(Actor::New()),
142   mBackgroundColor( EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR ),
143   mTargetSize( Vector2::ZERO ),
144   mLastSize( Vector2::ZERO ),
145   mEffectSize(0),
146   mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
147   mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
148   mEnabled( false ),
149   mRefreshOnDemand( EFFECTS_VIEW_REFRESH_ON_DEMAND )
150 {
151   DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
152     return std::unique_ptr< Dali::Accessibility::Accessible >(
153       new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::FILLER ) );
154   } );
155 }
156
157 EffectsView::~EffectsView()
158 {
159   RemoveFilters();
160 }
161
162 void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
163 {
164   if( mEffectType != type )
165   {
166     RemoveFilters();
167
168     Actor self = Self();
169
170     switch( type )
171     {
172       case Toolkit::EffectsView::DROP_SHADOW:
173       {
174         mFilters.PushBack( new SpreadFilter );
175         mFilters.PushBack( new BlurTwoPassFilter );
176         break;
177       }
178       case Toolkit::EffectsView::EMBOSS:
179       {
180         mFilters.PushBack( new SpreadFilter );
181         mFilters.PushBack( new EmbossFilter );
182         mFilters.PushBack( new BlurTwoPassFilter );
183         break;
184       }
185       default:
186       {
187         break;
188       }
189     }
190
191     mEffectType = type;
192   }
193 }
194
195 Toolkit::EffectsView::EffectType EffectsView::GetType() const
196 {
197   return mEffectType;
198 }
199
200 void EffectsView::Enable()
201 {
202   // make sure resources are allocated and start the render tasks processing
203   AllocateResources();
204   CreateRenderTasks();
205   mEnabled = true;
206 }
207
208 void EffectsView::Disable()
209 {
210   // stop render tasks processing
211   RemoveRenderTasks();
212   mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
213   mEnabled = false;
214 }
215
216 void EffectsView::Refresh()
217 {
218   RefreshRenderTasks();
219 }
220
221 void EffectsView::SetRefreshOnDemand( bool onDemand )
222 {
223   mRefreshOnDemand = onDemand;
224
225   RefreshRenderTasks();
226 }
227
228 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
229 {
230   mPixelFormat = pixelFormat;
231 }
232
233 void EffectsView::SetBackgroundColor( const Vector4& color )
234 {
235   mBackgroundColor = color;
236 }
237
238 Vector4 EffectsView::GetBackgroundColor() const
239 {
240   return mBackgroundColor;
241 }
242
243 void EffectsView::SetEffectSize( int effectSize )
244 {
245   mEffectSize = effectSize;
246
247   if( mEnabled )
248   {
249     const size_t numFilters( mFilters.Size() );
250     for( size_t i = 0; i < numFilters; ++i )
251     {
252       mFilters[i]->Disable();
253     }
254
255     SetupFilters();
256
257     for( size_t i = 0; i < numFilters; ++i )
258     {
259       mFilters[i]->Enable();
260     }
261   }
262 }
263
264 int EffectsView::GetEffectSize()
265 {
266   return mEffectSize;
267 }
268
269 // From Control
270 void EffectsView::OnInitialize()
271 {
272   CustomActor self = Self();
273   mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
274   self.Add( mChildrenRoot );
275 }
276
277 void EffectsView::OnSizeSet(const Vector3& targetSize)
278 {
279   mTargetSize = Vector2(targetSize);
280
281   // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
282   if(mEnabled)
283   {
284     if( mLastSize != Vector2::ZERO )
285     {
286       Disable();
287     }
288     Enable();
289   }
290
291   mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize );
292
293   Control::OnSizeSet( targetSize );
294 }
295
296 void EffectsView::OnSceneConnection( int depth )
297 {
298   Actor self( Self() );
299
300   // Create renderers
301   mRendererPostFilter = CreateRenderer( EFFECTS_VIEW_VERTEX_SOURCE, EFFECTS_VIEW_FRAGMENT_SOURCE );
302   mRendererPostFilter.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT );
303   self.AddRenderer( mRendererPostFilter );
304
305   mRendererForChildren = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
306   mRendererForChildren.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + 1 );
307   self.AddRenderer( mRendererForChildren );
308
309   Enable();
310
311   Control::OnSceneConnection( depth );
312 }
313
314 void EffectsView::OnSceneDisconnection()
315 {
316   Actor self( Self() );
317
318   Disable();
319
320   const size_t numFilters( mFilters.Size() );
321   for( size_t i = 0; i < numFilters; ++i )
322   {
323     mFilters[i]->Disable();
324   }
325
326   // Remove renderers
327   self.RemoveRenderer( mRendererForChildren );
328   mRendererForChildren.Reset();
329
330   self.RemoveRenderer( mRendererPostFilter );
331   mRendererPostFilter.Reset();
332
333   Control::OnSceneDisconnection();
334 }
335
336 void EffectsView::OnChildAdd( Actor& child )
337 {
338   if( child != mChildrenRoot && child != mCameraForChildren )
339   {
340     mChildrenRoot.Add( child );
341   }
342
343   Control::OnChildAdd( child );
344 }
345
346 void EffectsView::OnChildRemove( Actor& child )
347 {
348   mChildrenRoot.Remove( child );
349
350   Control::OnChildRemove( child );
351 }
352
353 void EffectsView::SetupFilters()
354 {
355   switch( mEffectType )
356   {
357     case Toolkit::EffectsView::DROP_SHADOW:
358     {
359       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
360       spreadFilter->SetInputTexture( mFrameBufferForChildren.GetColorTexture() );
361       spreadFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
362       spreadFilter->SetRootActor( mChildrenRoot );
363       spreadFilter->SetBackgroundColor( mBackgroundColor );
364       spreadFilter->SetPixelFormat( mPixelFormat );
365       spreadFilter->SetSize( mTargetSize );
366       spreadFilter->SetSpread( mEffectSize );
367
368       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
369       blurFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
370       blurFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
371       blurFilter->SetRootActor( mChildrenRoot );
372       blurFilter->SetBackgroundColor( mBackgroundColor );
373       blurFilter->SetPixelFormat( mPixelFormat );
374       blurFilter->SetSize( mTargetSize );
375
376       const float* kernel(NULL);
377       size_t kernelSize(0);
378       switch( mEffectSize )
379       {
380         case 4:  {  kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
381         case 3:  {  kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
382         case 2:  {  kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
383         case 1:  {  kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
384         case 0:
385         default: {  kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
386       }
387       blurFilter->CreateKernel( kernel, kernelSize );
388       break;
389     }
390     case Toolkit::EffectsView::EMBOSS:
391     {
392       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
393       spreadFilter->SetInputTexture( mFrameBufferForChildren.GetColorTexture() );
394       spreadFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
395       spreadFilter->SetRootActor( mChildrenRoot );
396       spreadFilter->SetBackgroundColor( mBackgroundColor );
397       spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
398       spreadFilter->SetSize( mTargetSize );
399       spreadFilter->SetSpread( mEffectSize );
400
401       EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
402       embossFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
403       embossFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
404       embossFilter->SetRootActor( mChildrenRoot );
405       embossFilter->SetBackgroundColor( mBackgroundColor );
406       embossFilter->SetPixelFormat( Pixel::RGBA8888 );
407       embossFilter->SetSize( mTargetSize );
408
409       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
410       blurFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
411       blurFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
412       blurFilter->SetRootActor( mChildrenRoot );
413       blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
414       blurFilter->SetPixelFormat( Pixel::RGBA8888 );
415       blurFilter->SetSize( mTargetSize );
416       blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
417
418       break;
419     }
420     default:
421     {
422       break;
423     }
424   }
425 }
426
427 void EffectsView::AllocateResources()
428 {
429   if(mTargetSize != mLastSize)
430   {
431     mLastSize = mTargetSize;
432     SetupCameras();
433
434     Actor self( Self() );
435
436     mFrameBufferForChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
437     Texture textureForChildren = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
438     mFrameBufferForChildren.AttachColorTexture( textureForChildren );
439
440     SetRendererTexture( mRendererForChildren, textureForChildren );
441
442     mFrameBufferPostFilter = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
443     Texture texturePostFilter = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
444     mFrameBufferPostFilter.AttachColorTexture( texturePostFilter );
445
446     SetRendererTexture( mRendererPostFilter, texturePostFilter );
447
448     SetupFilters();
449   }
450 }
451
452 void EffectsView::SetupCameras()
453 {
454   if( !mCameraForChildren )
455   {
456     // Create a camera for the children render, corresponding to its render target size
457     mCameraForChildren = CameraActor::New(mTargetSize);
458     mCameraForChildren.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
459     mCameraForChildren.SetInvertYAxis( true );
460     Self().Add( mCameraForChildren );
461   }
462   else
463   {
464     // place the camera for the children render, corresponding to its render target size
465     const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
466     mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
467     mCameraForChildren.SetNearClippingPlane(1.0f);
468     mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
469     mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
470     mCameraForChildren.SetProperty( Actor::Property::POSITION, Vector3( 0.0f, 0.0f, mTargetSize.height * cameraPosScale ) );
471     mCameraForChildren.SetProperty( Actor::Property::POSITION_Z,  mTargetSize.height * cameraPosScale );
472   }
473 }
474
475 void EffectsView::CreateRenderTasks()
476 {
477   if( mTargetSize == Vector2::ZERO )
478   {
479     return;
480   }
481   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
482
483   // create render task to render our child actors to offscreen buffer
484   mRenderTaskForChildren = taskList.CreateTask();
485   mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
486   mRenderTaskForChildren.SetSourceActor( mChildrenRoot );
487   mRenderTaskForChildren.SetExclusive(true);
488   mRenderTaskForChildren.SetInputEnabled( false );
489   mRenderTaskForChildren.SetClearColor( mBackgroundColor );
490   mRenderTaskForChildren.SetClearEnabled( true );
491   mRenderTaskForChildren.SetFrameBuffer( mFrameBufferForChildren );
492   mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
493
494   // Enable image filters
495   const size_t numFilters( mFilters.Size() );
496   for( size_t i = 0; i < numFilters; ++i )
497   {
498     mFilters[i]->Enable();
499   }
500 }
501
502 void EffectsView::RemoveRenderTasks()
503 {
504   if( mTargetSize == Vector2::ZERO )
505   {
506     return;
507   }
508
509   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
510
511   taskList.RemoveTask(mRenderTaskForChildren);
512
513   const size_t numFilters( mFilters.Size() );
514   for( size_t i = 0; i < numFilters; ++i )
515   {
516     mFilters[i]->Disable();
517   }
518 }
519
520 void EffectsView::RefreshRenderTasks()
521 {
522   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
523
524   if( mRenderTaskForChildren )
525   {
526     mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
527   }
528
529   const size_t numFilters( mFilters.Size() );
530   for( size_t i = 0; i < numFilters; ++i )
531   {
532     mFilters[i]->Refresh();
533   }
534 }
535
536 void EffectsView::RemoveFilters()
537 {
538   const size_t numFilters( mFilters.Size() );
539   for( size_t i = 0; i < numFilters; ++i )
540   {
541     delete mFilters[i];
542   }
543   mFilters.Release();
544 }
545
546 void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
547 {
548   Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
549
550   if ( effectsView )
551   {
552     switch ( index )
553     {
554       case Toolkit::EffectsView::Property::EFFECT_SIZE:
555       {
556         int effectSize;
557         if( value.Get( effectSize ) )
558         {
559           GetImpl( effectsView ).SetEffectSize( effectSize );
560         }
561         break;
562       }
563       default:
564       {
565         break;
566       }
567     }
568   }
569 }
570
571 Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
572 {
573   Property::Value value;
574
575   Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
576
577   if ( imageview )
578   {
579     EffectsView& impl = GetImpl( imageview );
580     switch ( propertyIndex )
581     {
582       case Toolkit::EffectsView::Property::EFFECT_SIZE:
583       {
584          value = impl.GetEffectSize();
585         break;
586       }
587       default:
588       {
589         break;
590       }
591     }
592   }
593
594   return value;
595 }
596
597 } // namespace Internal
598
599 } // namespace Toolkit
600
601 } // namespace Dali