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