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