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