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