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