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