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