Disabling EmbossFilter now removes all render tasks.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / effects-view / effects-view-impl.cpp
1 /*
2  * Copyright (c) 2016 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/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>
29 #include <dali/public-api/rendering/renderer.h>
30 #include <dali/devel-api/images/texture-set-image.h>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/public-api/visuals/visual-properties.h>
34 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
35 #include <dali-toolkit/devel-api/visual-factory/visual-factory.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/visuals/visual-base-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( 1.0f, 1.0f, 1.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     FrameBufferImage dummyImage = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
188
189     InitializeVisual( self, mVisualPostFilter, dummyImage );
190     Property::Map customShader;
191     customShader[ Toolkit::Visual::Shader::Property::VERTEX_SHADER ] = EFFECTS_VIEW_VERTEX_SOURCE;
192     customShader[ Toolkit::Visual::Shader::Property::FRAGMENT_SHADER ] = EFFECTS_VIEW_FRAGMENT_SOURCE;
193     Toolkit::GetImplementation( mVisualPostFilter ).SetCustomShader( customShader );
194
195     mEffectType = type;
196   }
197 }
198
199 Toolkit::EffectsView::EffectType EffectsView::GetType() const
200 {
201   return mEffectType;
202 }
203
204 void EffectsView::Enable()
205 {
206   // make sure resources are allocated and start the render tasks processing
207   AllocateResources();
208   CreateRenderTasks();
209   mEnabled = true;
210 }
211
212 void EffectsView::Disable()
213 {
214   // stop render tasks processing
215   // Note: render target resources are automatically freed since we set the Image::Unused flag
216   RemoveRenderTasks();
217   mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
218   mEnabled = false;
219 }
220
221 void EffectsView::Refresh()
222 {
223   RefreshRenderTasks();
224 }
225
226 void EffectsView::SetRefreshOnDemand( bool onDemand )
227 {
228   mRefreshOnDemand = onDemand;
229
230   RefreshRenderTasks();
231 }
232
233 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
234 {
235   mPixelFormat = pixelFormat;
236 }
237
238 void EffectsView::SetBackgroundColor( const Vector4& color )
239 {
240   mBackgroundColor = color;
241 }
242
243 Vector4 EffectsView::GetBackgroundColor() const
244 {
245   return mBackgroundColor;
246 }
247
248 void EffectsView::SetEffectSize( int effectSize )
249 {
250   mEffectSize = effectSize;
251
252   if( mEnabled )
253   {
254     const size_t numFilters( mFilters.Size() );
255     for( size_t i = 0; i < numFilters; ++i )
256     {
257       mFilters[i]->Disable();
258     }
259
260     SetupFilters();
261
262     for( size_t i = 0; i < numFilters; ++i )
263     {
264       mFilters[i]->Enable();
265     }
266   }
267 }
268
269 int EffectsView::GetEffectSize()
270 {
271   return mEffectSize;
272 }
273
274 // From Control
275 void EffectsView::OnInitialize()
276 {
277   CustomActor self = Self();
278   mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
279   self.Add( mChildrenRoot );
280 }
281
282 void EffectsView::OnSizeSet(const Vector3& targetSize)
283 {
284   Control::OnSizeSet( targetSize );
285
286   mTargetSize = Vector2(targetSize);
287
288   // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
289   if(mEnabled)
290   {
291     if( mLastSize != Vector2::ZERO )
292     {
293       Disable();
294     }
295     Enable();
296   }
297
298   mChildrenRoot.SetSize( targetSize );
299 }
300
301 void EffectsView::OnStageConnection( int depth )
302 {
303   Control::OnStageConnection( depth );
304
305   Enable();
306
307   Actor self = Self();
308   if( mVisualPostFilter )
309   {
310     mVisualPostFilter.SetOnStage( self );
311   }
312   if( mVisualForChildren )
313   {
314     mVisualForChildren.SetOnStage( self );
315   }
316 }
317
318 void EffectsView::OnStageDisconnection()
319 {
320   Disable();
321
322   const size_t numFilters( mFilters.Size() );
323   for( size_t i = 0; i < numFilters; ++i )
324   {
325     mFilters[i]->Disable();
326   }
327
328   Actor self = Self();
329   if( mVisualPostFilter )
330   {
331     mVisualPostFilter.SetOffStage( self );
332   }
333   if( mVisualForChildren )
334   {
335     mVisualForChildren.SetOffStage( self );
336   }
337
338   Control::OnStageDisconnection();
339 }
340
341 void EffectsView::OnChildAdd( Actor& child )
342 {
343   Control::OnChildAdd( child );
344
345   if( child != mChildrenRoot && child != mCameraForChildren )
346   {
347     mChildrenRoot.Add( child );
348   }
349 }
350
351 void EffectsView::OnChildRemove( Actor& child )
352 {
353   mChildrenRoot.Remove( child );
354
355   Control::OnChildRemove( child );
356 }
357
358 void EffectsView::SetupFilters()
359 {
360   switch( mEffectType )
361   {
362     case Toolkit::EffectsView::DROP_SHADOW:
363     {
364       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
365       spreadFilter->SetInputImage( mImageForChildren );
366       spreadFilter->SetOutputImage( mImagePostFilter );
367       spreadFilter->SetRootActor( mChildrenRoot );
368       spreadFilter->SetBackgroundColor( mBackgroundColor );
369       spreadFilter->SetPixelFormat( mPixelFormat );
370       spreadFilter->SetSize( mTargetSize );
371       spreadFilter->SetSpread( mEffectSize );
372
373       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
374       blurFilter->SetInputImage( mImagePostFilter );
375       blurFilter->SetOutputImage( mImagePostFilter );
376       blurFilter->SetRootActor( mChildrenRoot );
377       blurFilter->SetBackgroundColor( mBackgroundColor );
378       blurFilter->SetPixelFormat( mPixelFormat );
379       blurFilter->SetSize( mTargetSize );
380
381       const float* kernel(NULL);
382       size_t kernelSize(0);
383       switch( mEffectSize )
384       {
385         case 4:  {  kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
386         case 3:  {  kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
387         case 2:  {  kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
388         case 1:  {  kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
389         case 0:
390         default: {  kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
391       }
392       blurFilter->CreateKernel( kernel, kernelSize );
393       break;
394     }
395     case Toolkit::EffectsView::EMBOSS:
396     {
397       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
398       spreadFilter->SetInputImage( mImageForChildren );
399       spreadFilter->SetOutputImage( mImagePostFilter );
400       spreadFilter->SetRootActor( mChildrenRoot );
401       spreadFilter->SetBackgroundColor( mBackgroundColor );
402       spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
403       spreadFilter->SetSize( mTargetSize );
404       spreadFilter->SetSpread( mEffectSize );
405
406       EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
407       embossFilter->SetInputImage( mImagePostFilter );
408       embossFilter->SetOutputImage( mImagePostFilter );
409       embossFilter->SetRootActor( mChildrenRoot );
410       embossFilter->SetBackgroundColor( mBackgroundColor );
411       embossFilter->SetPixelFormat( Pixel::RGBA8888 );
412       embossFilter->SetSize( mTargetSize );
413
414       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
415       blurFilter->SetInputImage( mImagePostFilter );
416       blurFilter->SetOutputImage( mImagePostFilter );
417       blurFilter->SetRootActor( mChildrenRoot );
418       blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
419       blurFilter->SetPixelFormat( Pixel::RGBA8888 );
420       blurFilter->SetSize( mTargetSize );
421       blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
422
423       break;
424     }
425     default:
426     {
427       break;
428     }
429   }
430 }
431 void EffectsView::AllocateResources()
432 {
433   if(mTargetSize != mLastSize)
434   {
435     mLastSize = mTargetSize;
436     SetupCameras();
437
438     Actor self( Self() );
439
440     mImageForChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
441     InitializeVisual( self, mVisualForChildren, mImageForChildren );
442     mVisualForChildren.SetDepthIndex( DepthIndex::CONTENT+1 );
443
444     mImagePostFilter = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
445     TextureSet textureSet = TextureSet::New();
446     TextureSetImage( textureSet, 0u,  mImagePostFilter );
447     self.GetRendererAt( 0 ).SetTextures( textureSet );
448     mVisualPostFilter.SetDepthIndex( DepthIndex::CONTENT );
449
450     SetupFilters();
451   }
452 }
453
454 void EffectsView::SetupCameras()
455 {
456   if( !mCameraForChildren )
457   {
458     // Create a camera for the children render, corresponding to its render target size
459     mCameraForChildren = CameraActor::New(mTargetSize);
460     mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
461     mCameraForChildren.SetInvertYAxis( true );
462     Self().Add( mCameraForChildren );
463   }
464   else
465   {
466     // place the camera for the children render, corresponding to its render target size
467     const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
468     mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
469     mCameraForChildren.SetNearClippingPlane(1.0f);
470     mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
471     mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
472     mCameraForChildren.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosScale);
473     mCameraForChildren.SetZ( mTargetSize.height * cameraPosScale );
474   }
475 }
476
477 void EffectsView::CreateRenderTasks()
478 {
479   if( mTargetSize == Vector2::ZERO )
480   {
481     return;
482   }
483   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
484
485   // create render task to render our child actors to offscreen buffer
486   mRenderTaskForChildren = taskList.CreateTask();
487   mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
488   mRenderTaskForChildren.SetSourceActor( mChildrenRoot );
489   mRenderTaskForChildren.SetExclusive(true);
490   mRenderTaskForChildren.SetInputEnabled( false );
491   mRenderTaskForChildren.SetClearColor( mBackgroundColor );
492   mRenderTaskForChildren.SetClearEnabled( true );
493   mRenderTaskForChildren.SetTargetFrameBuffer( mImageForChildren );
494   mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
495
496   // Enable image filters
497   const size_t numFilters( mFilters.Size() );
498   for( size_t i = 0; i < numFilters; ++i )
499   {
500     mFilters[i]->Enable();
501   }
502 }
503
504 void EffectsView::RemoveRenderTasks()
505 {
506   if( mTargetSize == Vector2::ZERO )
507   {
508     return;
509   }
510
511   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
512
513   taskList.RemoveTask(mRenderTaskForChildren);
514
515   const size_t numFilters( mFilters.Size() );
516   for( size_t i = 0; i < numFilters; ++i )
517   {
518     mFilters[i]->Disable();
519   }
520 }
521
522 void EffectsView::RefreshRenderTasks()
523 {
524   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
525
526   if( mRenderTaskForChildren )
527   {
528     mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
529   }
530
531   const size_t numFilters( mFilters.Size() );
532   for( size_t i = 0; i < numFilters; ++i )
533   {
534     mFilters[i]->Refresh();
535   }
536 }
537
538 void EffectsView::RemoveFilters()
539 {
540   const size_t numFilters( mFilters.Size() );
541   for( size_t i = 0; i < numFilters; ++i )
542   {
543     delete mFilters[i];
544   }
545   mFilters.Release();
546 }
547
548 void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
549 {
550   Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
551
552   if ( effectsView )
553   {
554     switch ( index )
555     {
556       case Toolkit::EffectsView::Property::EFFECT_SIZE:
557       {
558         int effectSize;
559         if( value.Get( effectSize ) )
560         {
561           GetImpl( effectsView ).SetEffectSize( effectSize );
562         }
563         break;
564       }
565       default:
566       {
567         break;
568       }
569     }
570   }
571 }
572
573 Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
574 {
575   Property::Value value;
576
577   Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
578
579   if ( imageview )
580   {
581     EffectsView& impl = GetImpl( imageview );
582     switch ( propertyIndex )
583     {
584       case Toolkit::EffectsView::Property::EFFECT_SIZE:
585       {
586          value = impl.GetEffectSize();
587         break;
588       }
589       default:
590       {
591         break;
592       }
593     }
594   }
595
596   return value;
597 }
598
599 } // namespace Internal
600
601 } // namespace Toolkit
602
603 } // namespace Dali