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