Fix resource ready state
[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 }
152
153 EffectsView::~EffectsView()
154 {
155   RemoveFilters();
156 }
157
158 void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
159 {
160   if( mEffectType != type )
161   {
162     RemoveFilters();
163
164     Actor self = Self();
165
166     switch( type )
167     {
168       case Toolkit::EffectsView::DROP_SHADOW:
169       {
170         mFilters.PushBack( new SpreadFilter );
171         mFilters.PushBack( new BlurTwoPassFilter );
172         break;
173       }
174       case Toolkit::EffectsView::EMBOSS:
175       {
176         mFilters.PushBack( new SpreadFilter );
177         mFilters.PushBack( new EmbossFilter );
178         mFilters.PushBack( new BlurTwoPassFilter );
179         break;
180       }
181       default:
182       {
183         break;
184       }
185     }
186
187     mEffectType = type;
188   }
189 }
190
191 Toolkit::EffectsView::EffectType EffectsView::GetType() const
192 {
193   return mEffectType;
194 }
195
196 void EffectsView::Enable()
197 {
198   // make sure resources are allocated and start the render tasks processing
199   AllocateResources();
200   CreateRenderTasks();
201   mEnabled = true;
202 }
203
204 void EffectsView::Disable()
205 {
206   // stop render tasks processing
207   RemoveRenderTasks();
208   mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
209   mEnabled = false;
210 }
211
212 void EffectsView::Refresh()
213 {
214   RefreshRenderTasks();
215 }
216
217 void EffectsView::SetRefreshOnDemand( bool onDemand )
218 {
219   mRefreshOnDemand = onDemand;
220
221   RefreshRenderTasks();
222 }
223
224 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
225 {
226   mPixelFormat = pixelFormat;
227 }
228
229 void EffectsView::SetBackgroundColor( const Vector4& color )
230 {
231   mBackgroundColor = color;
232 }
233
234 Vector4 EffectsView::GetBackgroundColor() const
235 {
236   return mBackgroundColor;
237 }
238
239 void EffectsView::SetEffectSize( int effectSize )
240 {
241   mEffectSize = effectSize;
242
243   if( mEnabled )
244   {
245     const size_t numFilters( mFilters.Size() );
246     for( size_t i = 0; i < numFilters; ++i )
247     {
248       mFilters[i]->Disable();
249     }
250
251     SetupFilters();
252
253     for( size_t i = 0; i < numFilters; ++i )
254     {
255       mFilters[i]->Enable();
256     }
257   }
258 }
259
260 int EffectsView::GetEffectSize()
261 {
262   return mEffectSize;
263 }
264
265 // From Control
266 void EffectsView::OnInitialize()
267 {
268   CustomActor self = Self();
269   mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
270   self.Add( mChildrenRoot );
271
272   DevelControl::SetAccessibilityConstructor( self, []( Dali::Actor actor ) {
273     return std::unique_ptr< Dali::Accessibility::Accessible >(
274       new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::FILLER ) );
275   } );
276 }
277
278 void EffectsView::OnSizeSet(const Vector3& targetSize)
279 {
280   mTargetSize = Vector2(targetSize);
281
282   // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
283   if(mEnabled)
284   {
285     if( mLastSize != Vector2::ZERO )
286     {
287       Disable();
288     }
289     Enable();
290   }
291
292   mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize );
293
294   Control::OnSizeSet( targetSize );
295 }
296
297 void EffectsView::OnSceneConnection( int depth )
298 {
299   Actor self( Self() );
300
301   // Create renderers
302   mRendererPostFilter = CreateRenderer( EFFECTS_VIEW_VERTEX_SOURCE, EFFECTS_VIEW_FRAGMENT_SOURCE );
303   mRendererPostFilter.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT );
304   self.AddRenderer( mRendererPostFilter );
305
306   mRendererForChildren = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
307   mRendererForChildren.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + 1 );
308   self.AddRenderer( mRendererForChildren );
309
310   Enable();
311
312   Control::OnSceneConnection( depth );
313 }
314
315 void EffectsView::OnSceneDisconnection()
316 {
317   Actor self( Self() );
318
319   Disable();
320
321   const size_t numFilters( mFilters.Size() );
322   for( size_t i = 0; i < numFilters; ++i )
323   {
324     mFilters[i]->Disable();
325   }
326
327   // Remove renderers
328   self.RemoveRenderer( mRendererForChildren );
329   mRendererForChildren.Reset();
330
331   self.RemoveRenderer( mRendererPostFilter );
332   mRendererPostFilter.Reset();
333
334   Control::OnSceneDisconnection();
335 }
336
337 void EffectsView::OnChildAdd( Actor& child )
338 {
339   if( child != mChildrenRoot && child != mCameraForChildren )
340   {
341     mChildrenRoot.Add( child );
342   }
343
344   Control::OnChildAdd( child );
345 }
346
347 void EffectsView::OnChildRemove( Actor& child )
348 {
349   mChildrenRoot.Remove( child );
350
351   Control::OnChildRemove( child );
352 }
353
354 void EffectsView::SetupFilters()
355 {
356   switch( mEffectType )
357   {
358     case Toolkit::EffectsView::DROP_SHADOW:
359     {
360       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
361       spreadFilter->SetInputTexture( mFrameBufferForChildren.GetColorTexture() );
362       spreadFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
363       spreadFilter->SetRootActor( mChildrenRoot );
364       spreadFilter->SetBackgroundColor( mBackgroundColor );
365       spreadFilter->SetPixelFormat( mPixelFormat );
366       spreadFilter->SetSize( mTargetSize );
367       spreadFilter->SetSpread( mEffectSize );
368
369       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
370       blurFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
371       blurFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
372       blurFilter->SetRootActor( mChildrenRoot );
373       blurFilter->SetBackgroundColor( mBackgroundColor );
374       blurFilter->SetPixelFormat( mPixelFormat );
375       blurFilter->SetSize( mTargetSize );
376
377       const float* kernel(NULL);
378       size_t kernelSize(0);
379       switch( mEffectSize )
380       {
381         case 4:  {  kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
382         case 3:  {  kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
383         case 2:  {  kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
384         case 1:  {  kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
385         case 0:
386         default: {  kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
387       }
388       blurFilter->CreateKernel( kernel, kernelSize );
389       break;
390     }
391     case Toolkit::EffectsView::EMBOSS:
392     {
393       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
394       spreadFilter->SetInputTexture( mFrameBufferForChildren.GetColorTexture() );
395       spreadFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
396       spreadFilter->SetRootActor( mChildrenRoot );
397       spreadFilter->SetBackgroundColor( mBackgroundColor );
398       spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
399       spreadFilter->SetSize( mTargetSize );
400       spreadFilter->SetSpread( mEffectSize );
401
402       EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
403       embossFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
404       embossFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
405       embossFilter->SetRootActor( mChildrenRoot );
406       embossFilter->SetBackgroundColor( mBackgroundColor );
407       embossFilter->SetPixelFormat( Pixel::RGBA8888 );
408       embossFilter->SetSize( mTargetSize );
409
410       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
411       blurFilter->SetInputTexture( mFrameBufferPostFilter.GetColorTexture() );
412       blurFilter->SetOutputFrameBuffer( mFrameBufferPostFilter );
413       blurFilter->SetRootActor( mChildrenRoot );
414       blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
415       blurFilter->SetPixelFormat( Pixel::RGBA8888 );
416       blurFilter->SetSize( mTargetSize );
417       blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
418
419       break;
420     }
421     default:
422     {
423       break;
424     }
425   }
426 }
427
428 void EffectsView::AllocateResources()
429 {
430   if(mTargetSize != mLastSize)
431   {
432     mLastSize = mTargetSize;
433     SetupCameras();
434
435     Actor self( Self() );
436
437     mFrameBufferForChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
438     Texture textureForChildren = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
439     mFrameBufferForChildren.AttachColorTexture( textureForChildren );
440
441     SetRendererTexture( mRendererForChildren, textureForChildren );
442
443     mFrameBufferPostFilter = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
444     Texture texturePostFilter = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
445     mFrameBufferPostFilter.AttachColorTexture( texturePostFilter );
446
447     SetRendererTexture( mRendererPostFilter, texturePostFilter );
448
449     SetupFilters();
450   }
451 }
452
453 void EffectsView::SetupCameras()
454 {
455   if( !mCameraForChildren )
456   {
457     // Create a camera for the children render, corresponding to its render target size
458     mCameraForChildren = CameraActor::New(mTargetSize);
459     mCameraForChildren.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
460     mCameraForChildren.SetInvertYAxis( true );
461     Self().Add( mCameraForChildren );
462   }
463   else
464   {
465     // place the camera for the children render, corresponding to its render target size
466     const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
467     mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
468     mCameraForChildren.SetNearClippingPlane(1.0f);
469     mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
470     mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
471     mCameraForChildren.SetProperty( Actor::Property::POSITION, Vector3( 0.0f, 0.0f, mTargetSize.height * cameraPosScale ) );
472     mCameraForChildren.SetProperty( Actor::Property::POSITION_Z,  mTargetSize.height * cameraPosScale );
473   }
474 }
475
476 void EffectsView::CreateRenderTasks()
477 {
478   if( mTargetSize == Vector2::ZERO )
479   {
480     return;
481   }
482   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
483
484   // create render task to render our child actors to offscreen buffer
485   mRenderTaskForChildren = taskList.CreateTask();
486   mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
487   mRenderTaskForChildren.SetSourceActor( mChildrenRoot );
488   mRenderTaskForChildren.SetExclusive(true);
489   mRenderTaskForChildren.SetInputEnabled( false );
490   mRenderTaskForChildren.SetClearColor( mBackgroundColor );
491   mRenderTaskForChildren.SetClearEnabled( true );
492   mRenderTaskForChildren.SetFrameBuffer( mFrameBufferForChildren );
493   mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
494
495   // Enable image filters
496   const size_t numFilters( mFilters.Size() );
497   for( size_t i = 0; i < numFilters; ++i )
498   {
499     mFilters[i]->Enable();
500   }
501 }
502
503 void EffectsView::RemoveRenderTasks()
504 {
505   if( mTargetSize == Vector2::ZERO )
506   {
507     return;
508   }
509
510   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
511
512   taskList.RemoveTask(mRenderTaskForChildren);
513
514   const size_t numFilters( mFilters.Size() );
515   for( size_t i = 0; i < numFilters; ++i )
516   {
517     mFilters[i]->Disable();
518   }
519 }
520
521 void EffectsView::RefreshRenderTasks()
522 {
523   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
524
525   if( mRenderTaskForChildren )
526   {
527     mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
528   }
529
530   const size_t numFilters( mFilters.Size() );
531   for( size_t i = 0; i < numFilters; ++i )
532   {
533     mFilters[i]->Refresh();
534   }
535 }
536
537 void EffectsView::RemoveFilters()
538 {
539   const size_t numFilters( mFilters.Size() );
540   for( size_t i = 0; i < numFilters; ++i )
541   {
542     delete mFilters[i];
543   }
544   mFilters.Release();
545 }
546
547 void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
548 {
549   Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
550
551   if ( effectsView )
552   {
553     switch ( index )
554     {
555       case Toolkit::EffectsView::Property::EFFECT_SIZE:
556       {
557         int effectSize;
558         if( value.Get( effectSize ) )
559         {
560           GetImpl( effectsView ).SetEffectSize( effectSize );
561         }
562         break;
563       }
564       default:
565       {
566         break;
567       }
568     }
569   }
570 }
571
572 Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
573 {
574   Property::Value value;
575
576   Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
577
578   if ( imageview )
579   {
580     EffectsView& impl = GetImpl( imageview );
581     switch ( propertyIndex )
582     {
583       case Toolkit::EffectsView::Property::EFFECT_SIZE:
584       {
585          value = impl.GetEffectSize();
586         break;
587       }
588       default:
589       {
590         break;
591       }
592     }
593   }
594
595   return value;
596 }
597
598 } // namespace Internal
599
600 } // namespace Toolkit
601
602 } // namespace Dali