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