Merge "Fix resource ready state" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / bloom-view / bloom-view-impl.cpp
1 /*
2  * Copyright (c) 2020 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 "bloom-view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <iomanip>
24 #include <dali/public-api/animation/constraint.h>
25 #include <dali/public-api/animation/constraints.h>
26 #include <dali/devel-api/common/stage.h>
27 #include <dali/public-api/object/property-map.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali/public-api/render-tasks/render-task-list.h>
31 #include <dali/public-api/rendering/renderer.h>
32
33 // INTERNAL INCLUDES
34 #include <dali-toolkit/devel-api/controls/gaussian-blur-view/gaussian-blur-view.h>
35 #include <dali-toolkit/devel-api/controls/bloom-view/bloom-view.h>
36 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
37 #include <dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.h>
38 #include <dali-toolkit/internal/controls/control/control-renderers.h>
39 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
40
41 namespace Dali
42 {
43
44 namespace Toolkit
45 {
46
47 namespace Internal
48 {
49
50 namespace
51 {
52
53 using namespace Dali;
54
55 BaseHandle Create()
56 {
57   return Toolkit::BloomView::New();
58 }
59
60 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::BloomView, Toolkit::Control, Create )
61 DALI_TYPE_REGISTRATION_END()
62
63 // default parameters
64 const float BLOOM_THRESHOLD_DEFAULT = 0.25f;
65 const float BLOOM_BLUR_STRENGTH_DEFAULT = 1.0f;
66 const float BLOOM_INTENSITY_DEFAULT = 1.0f;
67 const float IMAGE_INTENSITY_DEFAULT = 1.0f;
68 const float BLOOM_SATURATION_DEFAULT = 1.0f;
69 const float IMAGE_SATURATION_DEFAULT = 1.0f;
70
71 // gaussian blur
72 const unsigned int BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES = 5;
73 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH = 1.5f;
74 const Pixel::Format BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
75 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_FADE_IN = 1.0f;                                       // default, fully blurred
76 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
77 const float BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
78
79 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
80
81 const char* const BLOOM_BLUR_STRENGTH_PROPERTY_NAME = "BlurStrengthProperty";
82 const char* const BLOOM_THRESHOLD_PROPERTY_NAME = "uBloomThreshold";
83 const char* const RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME = "uRecipOneMinusBloomThreshold";
84 const char* const BLOOM_INTENSITY_PROPERTY_NAME = "uBloomIntensity";
85 const char* const BLOOM_SATURATION_PROPERTY_NAME = "uBloomSaturation";
86 const char* const IMAGE_INTENSITY_PROPERTY_NAME = "uImageIntensity";
87 const char* const IMAGE_SATURATION_PROPERTY_NAME = "uImageSaturation";
88
89 } // namespace
90
91
92
93 BloomView::BloomView()
94 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
95   mBlurNumSamples(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_NUM_SAMPLES),
96   mBlurBellCurveWidth(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH),
97   mPixelFormat(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_RENDER_TARGET_PIXEL_FORMAT),
98   mDownsampleWidthScale(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_WIDTH_SCALE),
99   mDownsampleHeightScale(BLOOM_GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE),
100   mDownsampledWidth( 0.0f ),
101   mDownsampledHeight( 0.0f ),
102   mTargetSize(Vector2::ZERO),
103   mLastSize(Vector2::ZERO),
104   mChildrenRoot(Actor::New()),
105   mInternalRoot(Actor::New() ),
106   mBloomThresholdPropertyIndex(Property::INVALID_INDEX),
107   mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
108   mBloomIntensityPropertyIndex(Property::INVALID_INDEX),
109   mBloomSaturationPropertyIndex(Property::INVALID_INDEX),
110   mImageIntensityPropertyIndex(Property::INVALID_INDEX),
111   mImageSaturationPropertyIndex(Property::INVALID_INDEX),
112   mActivated( false )
113 {
114 }
115
116 BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
117                                     const float downsampleWidthScale, const float downsampleHeightScale)
118 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
119   mBlurNumSamples(blurNumSamples),
120   mBlurBellCurveWidth(blurBellCurveWidth),
121   mPixelFormat(renderTargetPixelFormat),
122   mDownsampleWidthScale(downsampleWidthScale),
123   mDownsampleHeightScale(downsampleHeightScale),
124   mDownsampledWidth( 0.0f ),
125   mDownsampledHeight( 0.0f ),
126   mTargetSize(Vector2::ZERO),
127   mLastSize(Vector2::ZERO),
128   mChildrenRoot(Actor::New()),
129   mInternalRoot(Actor::New()),
130   mBloomThresholdPropertyIndex(Property::INVALID_INDEX),
131   mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
132   mBloomIntensityPropertyIndex(Property::INVALID_INDEX),
133   mBloomSaturationPropertyIndex(Property::INVALID_INDEX),
134   mImageIntensityPropertyIndex(Property::INVALID_INDEX),
135   mImageSaturationPropertyIndex(Property::INVALID_INDEX),
136   mActivated( false )
137 {
138 }
139
140 BloomView::~BloomView()
141 {
142 }
143
144 Toolkit::BloomView BloomView::New()
145 {
146   BloomView* impl = new BloomView();
147
148   Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
149
150   // Second-phase init of the implementation
151   // This can only be done after the CustomActor connection has been made...
152   impl->Initialize();
153
154   return handle;
155 }
156
157 Toolkit::BloomView BloomView::New(const unsigned int blurNumSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
158                                                 const float downsampleWidthScale, const float downsampleHeightScale)
159 {
160   BloomView* impl = new BloomView( blurNumSamples, blurBellCurveWidth, renderTargetPixelFormat, downsampleWidthScale, downsampleHeightScale);
161
162   Dali::Toolkit::BloomView handle = Dali::Toolkit::BloomView( *impl );
163
164   // Second-phase init of the implementation
165   // This can only be done after the CustomActor connection has been made...
166   impl->Initialize();
167
168   return handle;
169 }
170
171 ///////////////////////////////////////////////////////////
172 //
173 // Private methods
174 //
175
176 void BloomView::OnInitialize()
177 {
178   // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
179   mChildrenRoot.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
180   mInternalRoot.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
181
182   //////////////////////////////////////////////////////
183   // Create actors
184
185   // Create an image view for rendering from the scene texture to the bloom texture
186   mBloomExtractActor = Actor::New();
187   mBloomExtractActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
188
189   // Create an image view for compositing the result (scene and bloom textures) to output
190   mCompositeActor = Actor::New();
191   mCompositeActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
192
193   // Create an image view for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
194   mTargetActor = Actor::New();
195   mTargetActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
196
197   // Create the Gaussian Blur object + render tasks
198   // Note that we use mBloomExtractTarget as the source image and also re-use this as the gaussian blur final render target. This saves the gaussian blur code from creating it
199   // render targets etc internally, so we make better use of resources
200   // Note, this also internally creates the render tasks used by the Gaussian blur, this must occur after the bloom extraction and before the compositing
201   mGaussianBlurView = Dali::Toolkit::GaussianBlurView::New(mBlurNumSamples, mBlurBellCurveWidth, mPixelFormat, mDownsampleWidthScale, mDownsampleHeightScale, true);
202   mGaussianBlurView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
203
204
205   //////////////////////////////////////////////////////
206   // Create cameras for the renders corresponding to the (potentially downsampled) render targets' size
207   mRenderDownsampledCamera = CameraActor::New();
208   mRenderDownsampledCamera.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
209   mRenderDownsampledCamera.SetInvertYAxis( true );
210
211   mRenderFullSizeCamera = CameraActor::New();
212   mRenderFullSizeCamera.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER );
213   mRenderFullSizeCamera.SetInvertYAxis( true );
214
215
216   ////////////////////////////////
217   // Connect to actor tree
218   Self().Add( mChildrenRoot );
219   Self().Add( mInternalRoot );
220   mInternalRoot.Add( mBloomExtractActor );
221   mInternalRoot.Add( mGaussianBlurView );
222   mInternalRoot.Add( mCompositeActor );
223   mInternalRoot.Add( mTargetActor );
224   mInternalRoot.Add( mRenderDownsampledCamera );
225   mInternalRoot.Add( mRenderFullSizeCamera );
226
227   // bind properties for / set shader constants to defaults
228   SetupProperties();
229
230   DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
231     return std::unique_ptr< Dali::Accessibility::Accessible >(
232       new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::ANIMATION ) );
233   } );
234 }
235
236 void BloomView::OnSizeSet(const Vector3& targetSize)
237 {
238   mTargetSize = Vector2(targetSize);
239   mChildrenRoot.SetProperty( Actor::Property::SIZE, targetSize);
240   mCompositeActor.SetProperty( Actor::Property::SIZE, targetSize);
241   mTargetActor.SetProperty( Actor::Property::SIZE, targetSize);
242
243   // Children render camera must move when GaussianBlurView object is
244   // resized. This is since we cannot change render target size - so we need
245   // to remap the child actors' rendering accordingly so they still exactly
246   // fill the render target. Note that this means the effective resolution of
247   // the child render changes as the GaussianBlurView object changes size,
248   // this is the trade off for not being able to modify render target size
249   // Change camera z position based on GaussianBlurView actor height
250   float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
251   mRenderFullSizeCamera.SetProperty( Actor::Property::POSITION_Z,  mTargetSize.height * cameraPosConstraintScale);
252
253   // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
254   if(mActivated)
255   {
256     Deactivate();
257     Activate();
258   }
259
260   Control::OnSizeSet( targetSize );
261 }
262
263 void BloomView::OnChildAdd( Actor& child )
264 {
265   if( child != mChildrenRoot && child != mInternalRoot)
266   {
267     mChildrenRoot.Add( child );
268   }
269
270   Control::OnChildAdd( child );
271 }
272
273 void BloomView::OnChildRemove( Actor& child )
274 {
275   mChildrenRoot.Remove( child );
276
277   Control::OnChildRemove( child );
278 }
279
280 void BloomView::AllocateResources()
281 {
282   // size of render targets etc is based on the size of this actor, ignoring z
283   if(mTargetSize != mLastSize || !mActivated)
284   {
285     mLastSize = mTargetSize;
286
287     // get size of downsampled render targets
288     mDownsampledWidth = mTargetSize.width * mDownsampleWidthScale;
289     mDownsampledHeight = mTargetSize.height * mDownsampleHeightScale;
290
291
292     //////////////////////////////////////////////////////
293     // Create cameras
294
295     // Create and place a camera for the renders corresponding to the (potentially downsampled) render targets' size
296     mRenderDownsampledCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
297     mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
298     mRenderDownsampledCamera.SetAspectRatio(mDownsampledWidth / mDownsampledHeight);
299     mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
300
301     mRenderDownsampledCamera.SetProperty( Actor::Property::POSITION, Vector3( 0.0f, 0.0f, ( ( mDownsampledHeight * 0.5f ) / tanf( ARBITRARY_FIELD_OF_VIEW * 0.5f ) ) ) );
302
303     // Create and place a camera for the children render, corresponding to its render target size
304     mRenderFullSizeCamera.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
305     mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
306     mRenderFullSizeCamera.SetAspectRatio(mTargetSize.width / mTargetSize.height);
307     mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
308
309     float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
310     mRenderFullSizeCamera.SetProperty( Actor::Property::POSITION, Vector3( 0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale ) );
311
312     //////////////////////////////////////////////////////
313     // Pass size change onto GaussianBlurView, so it matches
314     mGaussianBlurView.SetProperty( Actor::Property::SIZE, mTargetSize );
315     GetImpl(mGaussianBlurView).AllocateResources();
316
317     mGaussianBlurView.SetProperty( Actor::Property::VISIBLE, true );
318
319     //////////////////////////////////////////////////////
320     // Create render targets
321
322     // create off screen buffer of new size to render our child actors to
323     mRenderTargetForRenderingChildren = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
324     Texture textureForChildren = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
325     mRenderTargetForRenderingChildren.AttachColorTexture( textureForChildren );
326
327     mBloomExtractTarget = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
328     Texture texture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight) );
329     mBloomExtractTarget.AttachColorTexture( texture );
330
331     FrameBuffer blurExtractTarget = FrameBuffer::New( mDownsampledWidth, mDownsampledHeight, FrameBuffer::Attachment::NONE );
332     texture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mDownsampledWidth), unsigned(mDownsampledHeight) );
333     blurExtractTarget.AttachColorTexture( texture );
334
335     mOutputRenderTarget = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
336     Texture outputTexture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
337     mOutputRenderTarget.AttachColorTexture( outputTexture );
338
339     //////////////////////////////////////////////////////
340     // Point actors and render tasks at new render targets
341
342     Renderer bloomRenderer = CreateRenderer( BASIC_VERTEX_SOURCE, SHADER_BLOOM_VIEW_EXTRACT_SHADER_FRAG );
343     SetRendererTexture( bloomRenderer, mRenderTargetForRenderingChildren );
344     mBloomExtractActor.AddRenderer( bloomRenderer );
345     mBloomExtractActor.SetProperty( Actor::Property::SIZE, Vector2( mDownsampledWidth, mDownsampledHeight ) ); // size needs to match render target
346
347     // set GaussianBlurView to blur our extracted bloom
348     mGaussianBlurView.SetUserImageAndOutputRenderTarget( mBloomExtractTarget.GetColorTexture(), blurExtractTarget );
349
350     // use the completed blur in the first buffer and composite with the original child actors render
351     Renderer compositeRenderer = CreateRenderer( BASIC_VERTEX_SOURCE, SHADER_BLOOM_VIEW_COMPOSITE_SHADER_FRAG );
352     SetRendererTexture( compositeRenderer, mRenderTargetForRenderingChildren );
353     TextureSet textureSet = compositeRenderer.GetTextures();
354     textureSet.SetTexture( 0u, mRenderTargetForRenderingChildren.GetColorTexture() );
355     textureSet.SetTexture( 1u, blurExtractTarget.GetColorTexture() );
356     mCompositeActor.AddRenderer( compositeRenderer );
357
358     // set up target actor for rendering result, i.e. the blurred image
359     Renderer targetRenderer = CreateRenderer( BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE );
360     SetRendererTexture( targetRenderer, mOutputRenderTarget );
361     mTargetActor.AddRenderer( targetRenderer );
362   }
363 }
364
365 void BloomView::CreateRenderTasks()
366 {
367   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
368
369   // create render task to render our child actors to offscreen buffer
370   mRenderChildrenTask = taskList.CreateTask();
371   mRenderChildrenTask.SetSourceActor( mChildrenRoot );
372   mRenderChildrenTask.SetExclusive(true);
373   mRenderChildrenTask.SetInputEnabled( false );
374   mRenderChildrenTask.SetClearEnabled( true );
375   mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
376   mRenderChildrenTask.SetFrameBuffer( mRenderTargetForRenderingChildren );
377
378   // Extract the bright part of the image and render to a new buffer. Downsampling also occurs at this stage to save pixel fill, if it is set up.
379   mBloomExtractTask = taskList.CreateTask();
380   mBloomExtractTask.SetSourceActor( mBloomExtractActor );
381   mBloomExtractTask.SetExclusive(true);
382   mBloomExtractTask.SetInputEnabled( false );
383   mBloomExtractTask.SetClearEnabled( true );
384   mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
385   mBloomExtractTask.SetFrameBuffer( mBloomExtractTarget );
386
387   // GaussianBlurView tasks must be created here, so they are executed in the correct order with respect to BloomView tasks
388   GetImpl(mGaussianBlurView).CreateRenderTasks();
389
390   // Use an image view displaying the children render and composite it with the blurred bloom buffer, targeting the output
391   mCompositeTask = taskList.CreateTask();
392   mCompositeTask.SetSourceActor( mCompositeActor );
393   mCompositeTask.SetExclusive(true);
394   mCompositeTask.SetInputEnabled( false );
395   mCompositeTask.SetClearEnabled( true );
396   mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
397   mCompositeTask.SetFrameBuffer( mOutputRenderTarget );
398 }
399
400 void BloomView::RemoveRenderTasks()
401 {
402   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
403
404   taskList.RemoveTask(mRenderChildrenTask);
405   taskList.RemoveTask(mBloomExtractTask);
406
407   GetImpl(mGaussianBlurView).RemoveRenderTasks();
408
409   taskList.RemoveTask(mCompositeTask);
410 }
411
412 void BloomView::Activate()
413 {
414   // make sure resources are allocated and start the render tasks processing
415   AllocateResources();
416   CreateRenderTasks();
417   mActivated = true;
418 }
419
420 void BloomView::Deactivate()
421 {
422   // stop render tasks processing
423   // Note: render target resources are automatically freed since we set the Image::Unused flag
424   RemoveRenderTasks();
425
426   mRenderTargetForRenderingChildren.Reset();
427   mBloomExtractTarget.Reset();
428   mOutputRenderTarget.Reset();
429
430   // Reset children
431   mBloomExtractActor.RemoveRenderer( 0u );
432   mTargetActor.RemoveRenderer( 0u );
433   mCompositeActor.RemoveRenderer( 0u );
434
435   mGaussianBlurView.SetProperty( Actor::Property::VISIBLE, false );
436
437   mActivated = false;
438 }
439
440 /**
441  * RecipOneMinusConstraint
442  *
443  * f(current, property) = property
444  */
445 struct RecipOneMinusConstraint
446 {
447   RecipOneMinusConstraint(){}
448
449   void operator()( float& current, const PropertyInputContainer& inputs )
450   {
451     current = 1.0f / ( 1.0f - inputs[0]->GetFloat() );
452   }
453 };
454
455 // create properties and constraints to tie internal shader etc settings to BloomView object. User can therefore animate / set them via BloomView object without knowing about
456 // internal implementation classes
457 void BloomView::SetupProperties()
458 {
459   CustomActor self = Self();
460
461
462   ///////////////////////////////////////////
463   // bloom threshold
464
465   // set defaults, makes sure properties are registered with shader
466   mBloomExtractActor.RegisterProperty( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
467   mBloomExtractActor.RegisterProperty( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
468
469   // Register a property that the user can control to change the bloom threshold
470   mBloomThresholdPropertyIndex = self.RegisterProperty(BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT);
471   Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractActor.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
472   Constraint bloomThresholdConstraint = Constraint::New<float>( mBloomExtractActor, shaderBloomThresholdPropertyIndex, EqualToConstraint());
473   bloomThresholdConstraint.AddSource( Source(self, mBloomThresholdPropertyIndex) );
474   bloomThresholdConstraint.Apply();
475
476   // precalc 1.0 / (1.0 - threshold) on CPU to save shader insns, using constraint to tie to the normal threshold property
477   Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractActor.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
478   Constraint thresholdConstraint = Constraint::New<float>( mBloomExtractActor, shaderRecipOneMinusBloomThresholdPropertyIndex, RecipOneMinusConstraint());
479   thresholdConstraint.AddSource( LocalSource(shaderBloomThresholdPropertyIndex) );
480   thresholdConstraint.Apply();
481
482
483   ////////////////////////////////////////////
484   // bloom strength
485
486   // Register a property that the user can control to fade the blur in / out via internal GaussianBlurView object
487   mBlurStrengthPropertyIndex = self.RegisterProperty(BLOOM_BLUR_STRENGTH_PROPERTY_NAME, BLOOM_BLUR_STRENGTH_DEFAULT);
488   Constraint blurStrengthConstraint = Constraint::New<float>( mGaussianBlurView, mGaussianBlurView.GetBlurStrengthPropertyIndex(), EqualToConstraint());
489   blurStrengthConstraint.AddSource( Source(self, mBlurStrengthPropertyIndex) );
490   blurStrengthConstraint.Apply();
491
492
493   ////////////////////////////////////////////
494   // bloom intensity
495
496   // Register a property that the user can control to fade the bloom intensity via internally hidden shader
497   mBloomIntensityPropertyIndex = self.RegisterProperty(BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT);
498   mCompositeActor.RegisterProperty( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
499   Property::Index shaderBloomIntensityPropertyIndex = mCompositeActor.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
500   Constraint bloomIntensityConstraint = Constraint::New<float>( mCompositeActor, shaderBloomIntensityPropertyIndex, EqualToConstraint());
501   bloomIntensityConstraint.AddSource( Source(self, mBloomIntensityPropertyIndex) );
502   bloomIntensityConstraint.Apply();
503
504
505   ////////////////////////////////////////////
506   // bloom saturation
507
508   // Register a property that the user can control to fade the bloom saturation via internally hidden shader
509   mBloomSaturationPropertyIndex = self.RegisterProperty(BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT);
510   mCompositeActor.RegisterProperty( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
511   Property::Index shaderBloomSaturationPropertyIndex = mCompositeActor.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
512   Constraint bloomSaturationConstraint = Constraint::New<float>( mCompositeActor, shaderBloomSaturationPropertyIndex, EqualToConstraint());
513   bloomSaturationConstraint.AddSource( Source(self, mBloomSaturationPropertyIndex) );
514   bloomSaturationConstraint.Apply();
515
516
517   ////////////////////////////////////////////
518   // image intensity
519
520   // Register a property that the user can control to fade the image intensity via internally hidden shader
521   mImageIntensityPropertyIndex = self.RegisterProperty(IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT);
522   mCompositeActor.RegisterProperty( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
523   Property::Index shaderImageIntensityPropertyIndex = mCompositeActor.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
524   Constraint imageIntensityConstraint = Constraint::New<float>( mCompositeActor, shaderImageIntensityPropertyIndex, EqualToConstraint());
525   imageIntensityConstraint.AddSource( Source(self, mImageIntensityPropertyIndex) );
526   imageIntensityConstraint.Apply();
527
528
529   ////////////////////////////////////////////
530   // image saturation
531
532   // Register a property that the user can control to fade the image saturation via internally hidden shader
533   mImageSaturationPropertyIndex = self.RegisterProperty(IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT);
534   mCompositeActor.RegisterProperty( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
535   Property::Index shaderImageSaturationPropertyIndex = mCompositeActor.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
536   Constraint imageSaturationConstraint = Constraint::New<float>( mCompositeActor, shaderImageSaturationPropertyIndex, EqualToConstraint());
537   imageSaturationConstraint.AddSource( Source(self, mImageSaturationPropertyIndex) );
538   imageSaturationConstraint.Apply();
539 }
540
541 } // namespace Internal
542
543 } // namespace Toolkit
544
545 } // namespace Dali