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