Remove OnControl methods & add up-calls
[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/type-registry.h>
26 #include <dali/devel-api/object/type-registry-helper.h>
27 #include <dali/public-api/render-tasks/render-task-list.h>
28
29 // INTERNAL INCLUDES
30 #include "../../filters/blur-two-pass-filter.h"
31 #include "../../filters/emboss-filter.h"
32 #include "../../filters/spread-filter.h"
33
34 namespace Dali
35 {
36
37 namespace Toolkit
38 {
39
40 namespace Internal
41 {
42
43 namespace
44 {
45
46 Dali::BaseHandle Create()
47 {
48   return Toolkit::EffectsView::New();
49 }
50
51 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::EffectsView, Toolkit::Control, Create )
52 DALI_TYPE_REGISTRATION_END()
53
54 const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
55 const float         ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
56 const Vector4       EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR( 1.0f, 1.0f, 1.0f, 0.0 );
57 const bool          EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
58
59 // Custom properties
60 const char* const   EFFECT_SIZE_PROPERTY_NAME = "EffectSize";
61 const char* const   EFFECT_STRENGTH_PROPERTY_NAME = "EffectStrength";
62 const char* const   EFFECT_OFFSET_PROPERTY_NAME = "EffectOffset";
63 const char* const   EFFECT_COLOR_PROPERTY_NAME = "EffectColor";
64
65 const float         EFFECT_SIZE_DEFAULT( 1.0f );
66 const float         EFFECT_STRENGTH_DEFAULT( 0.5f );
67 const Vector3       EFFECT_OFFSET_DEFAULT( 0.0f, 0.0f, 0.0f );
68 const Vector4       EFFECT_COLOR_DEFAULT( Color::WHITE );
69
70 const char* const EFFECTS_VIEW_FRAGMENT_SOURCE =
71     "void main()\n"
72     "{\n"
73     "  gl_FragColor = uColor;\n"
74     "  gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n"
75     "}\n";
76
77 const float BLUR_KERNEL0[] = { 12.0f/16.0f,
78                                2.0f/16.0f, 2.0f/16.0f };
79
80 const float BLUR_KERNEL1[] = { 8.0f/16.0f,
81                                4.0f/16.0f, 4.0f/16.0f };
82
83 const float BLUR_KERNEL2[] = { 6.0f/16.0f,
84                                2.5f/16.0f, 2.5f/16.0f,
85                                1.5f/16.0f, 1.5f/16.0f,
86                                1.0f/16.0f, 1.0f/16.0f };
87
88 const float BLUR_KERNEL3[] = { 4.0f/16.0f,
89                                3.0f/16.0f, 2.0f/16.0f,
90                                2.0f/16.0f, 2.0f/16.0f,
91                                1.0f/16.0f, 1.0f/16.0f };
92
93 const float BLUR_KERNEL4[] = { 3.0f/16.0f,
94                                2.5f/16.0f,  2.5f/16.0f,
95                                1.75f/16.0f, 1.75f/16.0f,
96                                1.25f/16.0f, 1.25f/16.0f,
97                                1.0f/16.0f,  1.0f/16.0f };
98
99 } // namespace
100
101 Toolkit::EffectsView EffectsView::New()
102 {
103   EffectsView* effectsView = new EffectsView;
104
105   Toolkit::EffectsView handle = Toolkit::EffectsView( *effectsView );
106
107   // Second-phase init of the implementation
108   // This can only be done after the CustomActor connection has been made...
109   effectsView->Initialize();
110
111   return handle;
112 }
113
114 EffectsView::EffectsView()
115 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
116   mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
117   mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
118   mSpread(0.0f),
119   mBackgroundColor( EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR ),
120   mTargetSize( Vector2::ZERO ),
121   mLastSize( Vector2::ZERO ),
122   mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND),
123   mEffectSizePropertyIndex(Property::INVALID_INDEX),
124   mEffectStrengthPropertyIndex(Property::INVALID_INDEX),
125   mEffectOffsetPropertyIndex(Property::INVALID_INDEX),
126   mEffectColorPropertyIndex(Property::INVALID_INDEX)
127 {
128 }
129
130 EffectsView::~EffectsView()
131 {
132   RemoveFilters();
133 }
134
135 void EffectsView::SetType( Toolkit::EffectsView::EffectType type )
136 {
137   if( mEffectType != type )
138   {
139     mEffectType = type;
140
141     RemoveFilters();
142
143     switch( mEffectType )
144     {
145       case Toolkit::EffectsView::DROP_SHADOW:
146       {
147         mFilters.push_back( new SpreadFilter );
148         mFilters.push_back( new BlurTwoPassFilter );
149         break;
150       }
151       case Toolkit::EffectsView::EMBOSS:
152       {
153         mFilters.push_back( new SpreadFilter );
154         mFilters.push_back( new EmbossFilter );
155         mFilters.push_back( new BlurTwoPassFilter );
156         mActorPostFilter.RemoveShaderEffect();
157         break;
158       }
159       default:
160       {
161         break;
162       }
163     }
164   }
165 }
166
167 Toolkit::EffectsView::EffectType EffectsView::GetType() const
168 {
169   return mEffectType;
170 }
171
172 void EffectsView::Enable()
173 {
174   // make sure resources are allocated and start the render tasks processing
175   AllocateResources();
176   CreateRenderTasks();
177 }
178
179 void EffectsView::Disable()
180 {
181   // stop render tasks processing
182   // Note: render target resources are automatically freed since we set the Image::Unused flag
183   RemoveRenderTasks();
184 }
185
186 void EffectsView::Refresh()
187 {
188   RefreshRenderTasks();
189 }
190
191 void EffectsView::SetRefreshOnDemand( bool onDemand )
192 {
193   mRefreshOnDemand = onDemand;
194
195   RefreshRenderTasks();
196 }
197
198 void EffectsView::SetPixelFormat( Pixel::Format pixelFormat )
199 {
200   mPixelFormat = pixelFormat;
201 }
202
203 void EffectsView::SetOutputImage( FrameBufferImage image )
204 {
205   CustomActor self = Self();
206
207   if( mImageForResult != image )
208   {
209     if( !image )
210     {
211       if( mImageForResult )
212       {
213         self.Remove( mActorForResult );
214         mActorForResult.Reset();
215
216         self.Add( mActorPostFilter );
217         self.Add( mActorForChildren );
218       }
219     }
220     else
221     {
222       if( mImageForResult )
223       {
224         self.Remove( mActorForResult );
225       }
226       mActorForResult = Actor::New();
227       mActorForResult.SetParentOrigin( ParentOrigin::CENTER );
228       mActorForResult.SetSize( mTargetSize );
229       mActorForResult.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
230
231       Self().Add( mActorForResult );
232       mActorForResult.Add( mActorPostFilter );
233       mActorForResult.Add( mActorForChildren );
234     }
235     mImageForResult = image;
236   }
237 }
238
239 FrameBufferImage EffectsView::GetOutputImage()
240 {
241   return mImageForResult;
242 }
243
244 Property::Index EffectsView::GetEffectSizePropertyIndex() const
245 {
246   return mEffectSizePropertyIndex;
247 }
248
249 Property::Index EffectsView::GetEffectStrengthPropertyIndex() const
250 {
251   return mEffectStrengthPropertyIndex;
252 }
253
254 Property::Index EffectsView::GetEffectOffsetPropertyIndex() const
255 {
256   return mEffectOffsetPropertyIndex;
257 }
258
259 Property::Index EffectsView::GetEffectColorPropertyIndex() const
260 {
261   return mEffectColorPropertyIndex;
262 }
263
264 void EffectsView::SetupProperties()
265 {
266   CustomActor self = Self();
267
268   // Register a property that the user can control the drop shadow offset
269   mEffectSizePropertyIndex     = self.RegisterProperty(EFFECT_SIZE_PROPERTY_NAME, EFFECT_SIZE_DEFAULT, Property::READ_WRITE);
270   mEffectStrengthPropertyIndex = self.RegisterProperty(EFFECT_STRENGTH_PROPERTY_NAME, EFFECT_STRENGTH_DEFAULT, Property::READ_WRITE);
271   mEffectOffsetPropertyIndex   = self.RegisterProperty(EFFECT_OFFSET_PROPERTY_NAME, EFFECT_OFFSET_DEFAULT);
272   mEffectColorPropertyIndex    = self.RegisterProperty(EFFECT_COLOR_PROPERTY_NAME, EFFECT_COLOR_DEFAULT);
273
274   Constraint positionConstraint = Constraint::New<Vector3>( mActorPostFilter, Actor::Property::POSITION, EqualToConstraint() );
275   positionConstraint.AddSource( Source( self, mEffectOffsetPropertyIndex ) );
276   positionConstraint.Apply();
277
278   Constraint colorConstraint = Constraint::New<Vector4>( mActorPostFilter, Actor::Property::COLOR, EqualToConstraint() );
279   colorConstraint.AddSource( Source( self, mEffectColorPropertyIndex ) );
280   colorConstraint.Apply();
281 }
282
283 void EffectsView::SetBackgroundColor( const Vector4& color )
284 {
285   mBackgroundColor = color;
286 }
287
288 Vector4 EffectsView::GetBackgroundColor() const
289 {
290   return mBackgroundColor;
291 }
292
293 // From Control
294 void EffectsView::OnInitialize()
295 {
296   //////////////////////////////////////////////////////
297   // Create cameras
298   mCameraForChildren = CameraActor::New();
299   mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
300
301   mActorForChildren = ImageActor::New();
302   mActorForChildren.SetParentOrigin( ParentOrigin::CENTER );
303   mActorForChildren.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
304
305   mActorPostFilter = ImageActor::New();
306   mActorPostFilter.SetParentOrigin( ParentOrigin::CENTER );
307   mActorPostFilter.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
308   mActorPostFilter.SetShaderEffect( ShaderEffect::New( "", EFFECTS_VIEW_FRAGMENT_SOURCE ) );
309
310   // Connect to actor tree
311   Self().Add( mActorPostFilter );
312   Self().Add( mActorForChildren );
313   Self().Add( mCameraForChildren );
314
315   SetupProperties();
316 }
317
318 void EffectsView::OnSizeSet(const Vector3& targetSize)
319 {
320   Control::OnSizeSet( targetSize );
321
322   mTargetSize = Vector2(targetSize);
323
324   // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
325   if(Self().OnStage())
326   {
327     AllocateResources();
328   }
329
330   if( mActorForResult )
331   {
332     mActorForResult.SetSize( targetSize );
333   }
334   if( mActorForChildren )
335   {
336     mActorForChildren.SetSize( targetSize );
337   }
338   if( mActorPostFilter )
339   {
340     mActorPostFilter.SetSize( targetSize );
341   }
342
343   // Children render camera must move when EffectsView object is resized.
344   // This is since we cannot change render target size - so we need to remap the child actors' rendering
345   // accordingly so they still exactly fill the render target.
346   // Note that this means the effective resolution of the child render changes as the EffectsView object
347   // changes size, this is the trade off for not being able to modify render target size
348   // Change camera z position based on EffectsView actor height
349   if( mCameraForChildren )
350   {
351     const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
352     mCameraForChildren.SetZ( targetSize.height * cameraPosScale );
353   }
354
355   const size_t numFilters( mFilters.size() );
356   for( size_t i = 0; i < numFilters; ++i )
357   {
358     mFilters[i]->SetSize( mTargetSize );
359   }
360
361 }
362
363 void EffectsView::OnStageDisconnection()
364 {
365   const size_t numFilters( mFilters.size() );
366   for( size_t i = 0; i < numFilters; ++i )
367   {
368     mFilters[i]->Disable();
369   }
370
371   Control::OnStageDisconnection();
372 }
373
374 void EffectsView::SetupFilters()
375 {
376   int effectSize = static_cast< int >( Self().GetProperty( mEffectSizePropertyIndex ).Get<float>() );
377   switch( mEffectType )
378   {
379     case Toolkit::EffectsView::DROP_SHADOW:
380     {
381       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
382       spreadFilter->SetInputImage( mImageForChildren );
383       spreadFilter->SetOutputImage( mImagePostFilter );
384       spreadFilter->SetRootActor( Self() );
385       spreadFilter->SetBackgroundColor( mBackgroundColor );
386       spreadFilter->SetPixelFormat( mPixelFormat );
387       spreadFilter->SetSize( mTargetSize );
388       spreadFilter->SetSpread( effectSize );
389
390       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
391       blurFilter->SetInputImage( mImagePostFilter );
392       blurFilter->SetOutputImage( mImagePostFilter );
393       blurFilter->SetRootActor( Self() );
394       blurFilter->SetBackgroundColor( mBackgroundColor );
395       blurFilter->SetPixelFormat( mPixelFormat );
396       blurFilter->SetSize( mTargetSize );
397
398       const float* kernel(NULL);
399       size_t kernelSize(0);
400       switch( effectSize )
401       {
402         case 4:  {  kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
403         case 3:  {  kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
404         case 2:  {  kernel = BLUR_KERNEL2; kernelSize = sizeof(BLUR_KERNEL2)/sizeof(BLUR_KERNEL2[0]); break; }
405         case 1:  {  kernel = BLUR_KERNEL1; kernelSize = sizeof(BLUR_KERNEL1)/sizeof(BLUR_KERNEL1[0]); break; }
406         case 0:
407         default: {  kernel = BLUR_KERNEL0; kernelSize = sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]); break; }
408       }
409       blurFilter->CreateKernel( kernel, kernelSize );
410       break;
411     }
412     case Toolkit::EffectsView::EMBOSS:
413     {
414       SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
415       spreadFilter->SetInputImage( mImageForChildren );
416       spreadFilter->SetOutputImage( mImagePostFilter );
417       spreadFilter->SetRootActor( Self() );
418       spreadFilter->SetBackgroundColor( mBackgroundColor );
419       spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
420       spreadFilter->SetSize( mTargetSize );
421       spreadFilter->SetSpread( effectSize );
422
423       EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
424       embossFilter->SetInputImage( mImagePostFilter );
425       embossFilter->SetOutputImage( mImagePostFilter );
426       embossFilter->SetRootActor( Self() );
427       embossFilter->SetBackgroundColor( mBackgroundColor );
428       embossFilter->SetPixelFormat( Pixel::RGBA8888 );
429       embossFilter->SetSize( mTargetSize );
430
431       BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
432       blurFilter->SetInputImage( mImagePostFilter );
433       blurFilter->SetOutputImage( mImagePostFilter );
434       blurFilter->SetRootActor( Self() );
435       blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
436       blurFilter->SetPixelFormat( Pixel::RGBA8888 );
437       blurFilter->SetSize( mTargetSize );
438       blurFilter->CreateKernel( BLUR_KERNEL0, sizeof(BLUR_KERNEL0)/sizeof(BLUR_KERNEL0[0]) );
439
440       break;
441     }
442     default:
443     {
444       break;
445     }
446   }
447 }
448 void EffectsView::AllocateResources()
449 {
450   if(mTargetSize != mLastSize)
451   {
452     mLastSize = mTargetSize;
453
454     SetupCameras();
455
456     mImageForChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
457     mActorForChildren.SetImage(mImageForChildren);
458
459     mImagePostFilter = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
460     mActorPostFilter.SetImage(mImagePostFilter);
461
462     SetupFilters();
463   }
464 }
465
466 void EffectsView::SetupCameras()
467 {
468   const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
469
470   // Create and place a camera for the children render, corresponding to its render target size
471   mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
472   // TODO: how do we pick a reasonable value for near clip? Needs to relate to normal camera the user renders with, but we don't have a handle on it
473   mCameraForChildren.SetNearClippingPlane(1.0f);
474   mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
475   mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
476   mCameraForChildren.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosScale);
477   mCameraForChildren.SetZ( mTargetSize.height * cameraPosScale );
478 }
479
480 void EffectsView::CreateRenderTasks()
481 {
482   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
483
484   // create render task to render our child actors to offscreen buffer
485   mRenderTaskForChildren = taskList.CreateTask();
486   mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
487   mRenderTaskForChildren.SetSourceActor( Self() );
488   mRenderTaskForChildren.SetExclusive(true);
489   mRenderTaskForChildren.SetInputEnabled( false );
490   mRenderTaskForChildren.SetClearColor( mBackgroundColor );
491   mRenderTaskForChildren.SetClearEnabled( true );
492   mRenderTaskForChildren.SetTargetFrameBuffer( mImageForChildren );
493   mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
494
495   // Enable image filters
496   const size_t numFilters( mFilters.size() );
497   for( size_t i = 0; i < numFilters; ++i )
498   {
499     mFilters[i]->Enable();
500   }
501
502   // create render task to render result of the image filters to the final offscreen
503   if( mImageForResult )
504   {
505     mRenderTaskForResult = taskList.CreateTask();
506     mRenderTaskForResult.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
507     mRenderTaskForResult.SetSourceActor( mActorForResult );
508     mRenderTaskForResult.SetExclusive(true);
509     mRenderTaskForResult.SetInputEnabled( false );
510     mRenderTaskForResult.SetClearColor( mBackgroundColor );
511     mRenderTaskForResult.SetClearEnabled( true );
512     mRenderTaskForResult.SetTargetFrameBuffer( mImageForResult );
513     mRenderTaskForResult.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
514   }
515 }
516
517 void EffectsView::RemoveRenderTasks()
518 {
519   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
520
521   taskList.RemoveTask(mRenderTaskForChildren);
522   taskList.RemoveTask(mRenderTaskForResult);
523
524   const size_t numFilters( mFilters.size() );
525   for( size_t i = 0; i < numFilters; ++i )
526   {
527     mFilters[i]->Disable();
528   }
529 }
530
531 void EffectsView::RefreshRenderTasks()
532 {
533   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
534
535   if( mRenderTaskForChildren )
536   {
537     mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
538   }
539
540   if( mRenderTaskForResult )
541   {
542     mRenderTaskForResult.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
543   }
544
545   const size_t numFilters( mFilters.size() );
546   for( size_t i = 0; i < numFilters; ++i )
547   {
548     mFilters[i]->Refresh();
549   }
550 }
551
552 void EffectsView::RemoveFilters()
553 {
554   const size_t numFilters( mFilters.size() );
555   for( size_t i = 0; i < numFilters; ++i )
556   {
557     delete mFilters[i];
558   }
559   mFilters.clear();
560 }
561
562 } // namespace Internal
563
564 } // namespace Toolkit
565
566 } // namespace Dali