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