Merge "Implement some new ewk apis in web view." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / filters / blur-two-pass-filter.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 "blur-two-pass-filter.h"
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <dali/public-api/animation/constraints.h>
24 #include <dali/devel-api/common/stage.h>
25 #include <dali/public-api/object/property-map.h>
26 #include <dali/public-api/render-tasks/render-task-list.h>
27 #include <dali/public-api/rendering/renderer.h>
28
29 // INTERNAL INCLUDES
30 #include <dali-toolkit/internal/controls/control/control-renderers.h>
31 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
32
33 namespace Dali
34 {
35
36 namespace Toolkit
37 {
38
39 namespace Internal
40 {
41
42 namespace
43 {
44
45 const float DEFAULT_KERNEL0[] = { 12.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f };
46
47 const float DEFAULT_KERNEL1[] = { 8.0f/16.0f, 2.75f/16.0f, 2.75f/16.0f, 1.25f/16.0f,
48                                   1.25f/16.0f };
49
50 const float DEFAULT_KERNEL2[] = { 5.0f/16.0f, 2.75f/16.0f, 2.75f/16.0f, 1.75f/16.0f,
51                                   1.75f/16.0f, 1.5f/16.0f, 1.5f/16.0f };
52
53 const float DEFAULT_KERNEL3[] = { 3.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f,
54                                   2.0f/16.0f, 2.0f/16.0f, 2.0f/16.0f, 0.5f/16.0f,
55                                   0.5f/16.0f };
56
57 const float DEFAULT_KERNEL4[] = { 2.0f/16.0f, 1.5f/16.0f, 1.5f/16.0f, 1.5f/16.0f,
58                                   1.5f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f,
59                                   1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 0.5f/16.0f,
60                                   0.5f/16.0f, 0.5f/16.0f, 0.5f/16.0f };
61
62 std::string GetOffsetUniformName( int index )
63 {
64   std::ostringstream oss;
65   oss << "uSampleOffsets[" << index << "]";
66   return oss.str();
67 }
68
69 std::string GetWeightUniformName( int index )
70 {
71   std::ostringstream oss;
72   oss << "uSampleWeights[" << index << "]";
73   return oss.str();
74 }
75
76 const char* const BLUR_STRENGTH_UNIFORM_NAME( "uBlurStrength"  );
77 const char* const EFFECT_IMAGE_NAME( "sEffect" );
78
79 } // namespace
80
81
82 BlurTwoPassFilter::BlurTwoPassFilter()
83 : ImageFilter()
84 {
85   // create blending actor and register the property in constructor
86   // to make sure that GetBlurStrengthPropertyIndex() always returns a valid index
87   mActorForBlending = Actor::New();
88   mBlurStrengthPropertyIndex = mActorForBlending.RegisterProperty( BLUR_STRENGTH_UNIFORM_NAME, 1.f );
89 }
90
91 BlurTwoPassFilter::~BlurTwoPassFilter()
92 {
93 }
94
95 void BlurTwoPassFilter::Enable()
96 {
97   // create custom shader effect
98   if( !GetKernelSize() )
99   {
100     CreateKernel( DEFAULT_KERNEL4, sizeof(DEFAULT_KERNEL4)/sizeof(DEFAULT_KERNEL4[0]) );
101   }
102   int kernelSize( static_cast< int >(GetKernelSize()) );
103
104   // Set up blur-two-pass custom shader
105   std::ostringstream sstream;
106   sstream << "#define NUM_SAMPLES " << kernelSize << "\n";
107   sstream << SHADER_BLUR_TWO_PASS_SHADER_FRAG;
108   std::string fragmentSource( sstream.str() );
109
110   // create actor to render input with applied emboss effect
111   mActorForInput = Actor::New();
112   mActorForInput.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
113   mActorForInput.SetProperty( Actor::Property::SIZE, mTargetSize );
114   Renderer rendererForInput = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
115   SetRendererTexture( rendererForInput, mInputTexture );
116   mActorForInput.AddRenderer( rendererForInput );
117
118   // create internal offscreen for result of horizontal pass
119   mFrameBufferForHorz = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
120   Texture textureForHorz = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
121   mFrameBufferForHorz.AttachColorTexture( textureForHorz );
122
123   // create an actor to render mImageForHorz for vertical blur pass
124   mActorForHorz = Actor::New();
125   mActorForHorz.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
126   mActorForHorz.SetProperty( Actor::Property::SIZE, mTargetSize );
127   Renderer rendererForHorz = CreateRenderer( BASIC_VERTEX_SOURCE, fragmentSource.c_str() );
128   SetRendererTexture( rendererForHorz, textureForHorz );
129   mActorForHorz.AddRenderer( rendererForHorz );
130
131   // create internal offscreen for result of the two pass blurred image
132   mBlurredFrameBuffer = FrameBuffer::New( mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE );
133   Texture blurredTexture = Texture::New( TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height) );
134   mBlurredFrameBuffer.AttachColorTexture( blurredTexture );
135
136   // create an actor to blend the blurred image and the input image with the given blur strength
137   Renderer rendererForBlending = CreateRenderer( BASIC_VERTEX_SOURCE, SHADER_BLUR_TWO_IMAGES_SHADER_FRAG );
138   TextureSet textureSetForBlending = rendererForBlending.GetTextures();
139   textureSetForBlending.SetTexture( 0u, blurredTexture );
140   textureSetForBlending.SetTexture( 1u, mInputTexture );
141   mActorForBlending.AddRenderer( rendererForBlending );
142   mActorForBlending.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
143   mActorForBlending.SetProperty( Actor::Property::SIZE, mTargetSize );
144
145   for( int i = 0; i < kernelSize; ++i )
146   {
147     const std::string offsetUniform( GetOffsetUniformName( i ) );
148     const std::string weightUniform( GetWeightUniformName( i ) );
149
150     mActorForInput.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::XAXIS );
151     mActorForInput.RegisterProperty( weightUniform, mKernel[i].z );
152
153     mActorForHorz.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::YAXIS );
154     mActorForHorz.RegisterProperty( weightUniform, mKernel[i].z );
155   }
156
157   mRootActor.Add( mActorForInput );
158   mRootActor.Add( mActorForHorz );
159   mRootActor.Add( mActorForBlending );
160
161   SetupCamera();
162   CreateRenderTasks();
163 }
164
165 void BlurTwoPassFilter::Disable()
166 {
167   if( mRootActor )
168   {
169     if( mCameraActor )
170     {
171       mRootActor.Remove( mCameraActor );
172       mCameraActor.Reset();
173     }
174
175     if( mActorForInput )
176     {
177       mRootActor.Remove( mActorForInput );
178       mActorForInput.Reset();
179     }
180
181     if( mActorForHorz )
182     {
183       mRootActor.Remove( mActorForHorz );
184       mActorForHorz.Reset();
185     }
186
187     RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
188
189     if( mRenderTaskForHorz )
190     {
191       taskList.RemoveTask(mRenderTaskForHorz);
192     }
193     if( mRenderTaskForVert )
194     {
195       taskList.RemoveTask(mRenderTaskForVert);
196     }
197     if( mRenderTaskForBlending )
198     {
199       taskList.RemoveTask(mRenderTaskForBlending);
200     }
201
202     mRootActor.Reset();
203   }
204 }
205
206 void BlurTwoPassFilter::Refresh()
207 {
208   if( mRenderTaskForHorz )
209   {
210     mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
211   }
212
213   if( mRenderTaskForVert )
214   {
215     mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
216   }
217
218   if( mRenderTaskForBlending )
219   {
220     mRenderTaskForBlending.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
221   }
222 }
223
224 void BlurTwoPassFilter::SetSize( const Vector2& size )
225 {
226   mTargetSize = size;
227   if( mActorForInput )
228   {
229     mActorForInput.SetProperty( Actor::Property::SIZE, mTargetSize);
230   }
231   if( mActorForHorz )
232   {
233     mActorForHorz.SetProperty( Actor::Property::SIZE, mTargetSize);
234   }
235   if( mActorForBlending )
236   {
237     mActorForBlending.SetProperty( Actor::Property::SIZE, mTargetSize);
238   }
239 }
240
241 Handle BlurTwoPassFilter::GetHandleForAnimateBlurStrength()
242 {
243   return mActorForBlending;
244 }
245
246 void BlurTwoPassFilter::CreateRenderTasks()
247 {
248   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
249
250   // perform a horizontal blur targeting the internal buffer
251   mRenderTaskForHorz = taskList.CreateTask();
252   mRenderTaskForHorz.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
253   mRenderTaskForHorz.SetSourceActor( mActorForInput );
254   mRenderTaskForHorz.SetExclusive(true);
255   mRenderTaskForHorz.SetInputEnabled( false );
256   mRenderTaskForHorz.SetClearEnabled( true );
257   mRenderTaskForHorz.SetClearColor( mBackgroundColor );
258   mRenderTaskForHorz.SetFrameBuffer( mFrameBufferForHorz );
259   mRenderTaskForHorz.SetCameraActor( mCameraActor );
260
261   // use the internal buffer and perform a horizontal blur targeting the output buffer
262   mRenderTaskForVert = taskList.CreateTask();
263   mRenderTaskForVert.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
264   mRenderTaskForVert.SetSourceActor( mActorForHorz );
265   mRenderTaskForVert.SetExclusive(true);
266   mRenderTaskForVert.SetInputEnabled( false );
267   mRenderTaskForVert.SetClearEnabled( true );
268   mRenderTaskForVert.SetClearColor( mBackgroundColor );
269   mRenderTaskForVert.SetFrameBuffer( mBlurredFrameBuffer );
270   mRenderTaskForVert.SetCameraActor( mCameraActor );
271
272   //Perform a blending between the blurred image and the input image
273   mRenderTaskForBlending = taskList.CreateTask();
274   mRenderTaskForBlending.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
275   mRenderTaskForBlending.SetSourceActor( mActorForBlending );
276   mRenderTaskForBlending.SetExclusive(true);
277   mRenderTaskForBlending.SetInputEnabled( false );
278   mRenderTaskForBlending.SetClearEnabled( true );
279   mRenderTaskForBlending.SetClearColor( mBackgroundColor );
280   mRenderTaskForBlending.SetFrameBuffer( mOutputFrameBuffer );
281   mRenderTaskForBlending.SetCameraActor( mCameraActor );
282 }
283
284 } // namespace Internal
285
286 } // namespace Toolkit
287
288 } // namespace Dali