Merge "Add APIs of webview settings." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / effects-view / effects-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 "effects-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/property.h>
27 #include <dali/public-api/object/type-registry-helper.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/render-tasks/render-task-list.h>
30 #include <dali/public-api/rendering/renderer.h>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
34 #include <dali-toolkit/devel-api/controls/control-devel.h>
35 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
36 #include <dali-toolkit/internal/controls/control/control-renderers.h>
37 #include <dali-toolkit/internal/filters/blur-two-pass-filter.h>
38 #include <dali-toolkit/internal/filters/emboss-filter.h>
39 #include <dali-toolkit/internal/filters/spread-filter.h>
40 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
41
42 namespace Dali
43 {
44 namespace Toolkit
45 {
46 namespace Internal
47 {
48 namespace
49 {
50 Dali::BaseHandle Create()
51 {
52   return EffectsView::New();
53 }
54
55 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::EffectsView, Toolkit::Control, Create)
56 DALI_PROPERTY_REGISTRATION(Toolkit, EffectsView, "effectSize", INTEGER, EFFECT_SIZE)
57 DALI_ANIMATABLE_PROPERTY_REGISTRATION(Toolkit, EffectsView, "effectOffset", VECTOR3, EFFECT_OFFSET)
58 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, EffectsView, "effectColor", Color::WHITE, EFFECT_COLOR)
59 DALI_TYPE_REGISTRATION_END()
60
61 const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
62 const float         ARBITRARY_FIELD_OF_VIEW           = Math::PI / 4.0f;
63 const Vector4       EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR(0.0f, 0.0f, 0.0f, 0.0);
64 const bool          EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
65
66 // clang-format off
67 const float BLUR_KERNEL0[] = {12.0f/16.0f,
68                               2.0f/16.0f, 2.0f/16.0f};
69
70 const float BLUR_KERNEL1[] = {8.0f/16.0f,
71                               4.0f/16.0f, 4.0f/16.0f };
72
73 const float BLUR_KERNEL2[] = {6.0f/16.0f,
74                               2.5f/16.0f, 2.5f/16.0f,
75                               1.5f/16.0f, 1.5f/16.0f,
76                               1.0f/16.0f, 1.0f/16.0f};
77
78 const float BLUR_KERNEL3[] = {4.0f/16.0f,
79                               3.0f/16.0f, 2.0f/16.0f,
80                               2.0f/16.0f, 2.0f/16.0f,
81                               1.0f/16.0f, 1.0f/16.0f};
82
83 const float BLUR_KERNEL4[] = {3.0f/16.0f,
84                               2.5f/16.0f,  2.5f/16.0f,
85                               1.75f/16.0f, 1.75f/16.0f,
86                               1.25f/16.0f, 1.25f/16.0f,
87                               1.0f/16.0f,  1.0f/16.0f};
88 // clang-format on
89 } // namespace
90
91 Toolkit::EffectsView EffectsView::New()
92 {
93   EffectsView* effectsView = new EffectsView;
94
95   Toolkit::EffectsView handle = Toolkit::EffectsView(*effectsView);
96
97   // Second-phase init of the implementation
98   // This can only be done after the CustomActor connection has been made...
99   effectsView->Initialize();
100
101   return handle;
102 }
103
104 EffectsView::EffectsView()
105 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
106   mChildrenRoot(Actor::New()),
107   mBackgroundColor(EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR),
108   mTargetSize(Vector2::ZERO),
109   mLastSize(Vector2::ZERO),
110   mEffectSize(0),
111   mEffectType(Toolkit::EffectsView::INVALID_TYPE),
112   mPixelFormat(EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT),
113   mEnabled(false),
114   mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND)
115 {
116 }
117
118 EffectsView::~EffectsView()
119 {
120   RemoveFilters();
121 }
122
123 void EffectsView::SetType(Toolkit::EffectsView::EffectType type)
124 {
125   if(mEffectType != type)
126   {
127     RemoveFilters();
128
129     Actor self = Self();
130
131     switch(type)
132     {
133       case Toolkit::EffectsView::DROP_SHADOW:
134       {
135         mFilters.PushBack(new SpreadFilter);
136         mFilters.PushBack(new BlurTwoPassFilter);
137         break;
138       }
139       case Toolkit::EffectsView::EMBOSS:
140       {
141         mFilters.PushBack(new SpreadFilter);
142         mFilters.PushBack(new EmbossFilter);
143         mFilters.PushBack(new BlurTwoPassFilter);
144         break;
145       }
146       default:
147       {
148         break;
149       }
150     }
151
152     mEffectType = type;
153   }
154 }
155
156 Toolkit::EffectsView::EffectType EffectsView::GetType() const
157 {
158   return mEffectType;
159 }
160
161 void EffectsView::Enable()
162 {
163   // make sure resources are allocated and start the render tasks processing
164   AllocateResources();
165   CreateRenderTasks();
166   mEnabled = true;
167 }
168
169 void EffectsView::Disable()
170 {
171   // stop render tasks processing
172   RemoveRenderTasks();
173   mLastSize = Vector2::ZERO; // Ensure resources are reallocated on subsequent enable
174   mEnabled  = false;
175 }
176
177 void EffectsView::Refresh()
178 {
179   RefreshRenderTasks();
180 }
181
182 void EffectsView::SetRefreshOnDemand(bool onDemand)
183 {
184   mRefreshOnDemand = onDemand;
185
186   RefreshRenderTasks();
187 }
188
189 void EffectsView::SetPixelFormat(Pixel::Format pixelFormat)
190 {
191   mPixelFormat = pixelFormat;
192 }
193
194 void EffectsView::SetBackgroundColor(const Vector4& color)
195 {
196   mBackgroundColor = color;
197 }
198
199 Vector4 EffectsView::GetBackgroundColor() const
200 {
201   return mBackgroundColor;
202 }
203
204 void EffectsView::SetEffectSize(int effectSize)
205 {
206   mEffectSize = effectSize;
207
208   if(mEnabled)
209   {
210     const size_t numFilters(mFilters.Size());
211     for(size_t i = 0; i < numFilters; ++i)
212     {
213       mFilters[i]->Disable();
214     }
215
216     SetupFilters();
217
218     for(size_t i = 0; i < numFilters; ++i)
219     {
220       mFilters[i]->Enable();
221     }
222   }
223 }
224
225 int EffectsView::GetEffectSize()
226 {
227   return mEffectSize;
228 }
229
230 // From Control
231 void EffectsView::OnInitialize()
232 {
233   CustomActor self = Self();
234   mChildrenRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
235   self.Add(mChildrenRoot);
236
237   DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
238     return std::unique_ptr<Dali::Accessibility::Accessible>(
239       new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::FILLER));
240   });
241 }
242
243 void EffectsView::OnSizeSet(const Vector3& targetSize)
244 {
245   mTargetSize = Vector2(targetSize);
246
247   // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
248   if(mEnabled)
249   {
250     if(mLastSize != Vector2::ZERO)
251     {
252       Disable();
253     }
254     Enable();
255   }
256
257   mChildrenRoot.SetProperty(Actor::Property::SIZE, targetSize);
258
259   Control::OnSizeSet(targetSize);
260 }
261
262 void EffectsView::OnSceneConnection(int depth)
263 {
264   Actor self(Self());
265
266   // Create renderers
267   mRendererPostFilter = CreateRenderer(SHADER_EFFECTS_VIEW_VERT,
268                                        SHADER_EFFECTS_VIEW_FRAG);
269   mRendererPostFilter.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
270   self.AddRenderer(mRendererPostFilter);
271
272   mRendererForChildren = CreateRenderer(BASIC_VERTEX_SOURCE, BASIC_FRAGMENT_SOURCE);
273   mRendererForChildren.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + 1);
274   self.AddRenderer(mRendererForChildren);
275
276   Enable();
277
278   Control::OnSceneConnection(depth);
279 }
280
281 void EffectsView::OnSceneDisconnection()
282 {
283   Actor self(Self());
284
285   Disable();
286
287   const size_t numFilters(mFilters.Size());
288   for(size_t i = 0; i < numFilters; ++i)
289   {
290     mFilters[i]->Disable();
291   }
292
293   // Remove renderers
294   self.RemoveRenderer(mRendererForChildren);
295   mRendererForChildren.Reset();
296
297   self.RemoveRenderer(mRendererPostFilter);
298   mRendererPostFilter.Reset();
299
300   Control::OnSceneDisconnection();
301 }
302
303 void EffectsView::OnChildAdd(Actor& child)
304 {
305   if(child != mChildrenRoot && child != mCameraForChildren)
306   {
307     mChildrenRoot.Add(child);
308   }
309
310   Control::OnChildAdd(child);
311 }
312
313 void EffectsView::OnChildRemove(Actor& child)
314 {
315   mChildrenRoot.Remove(child);
316
317   Control::OnChildRemove(child);
318 }
319
320 void EffectsView::SetupFilters()
321 {
322   switch(mEffectType)
323   {
324     case Toolkit::EffectsView::DROP_SHADOW:
325     {
326       SpreadFilter* spreadFilter = static_cast<SpreadFilter*>(mFilters[0]);
327       spreadFilter->SetInputTexture(mFrameBufferForChildren.GetColorTexture());
328       spreadFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
329       spreadFilter->SetRootActor(mChildrenRoot);
330       spreadFilter->SetBackgroundColor(mBackgroundColor);
331       spreadFilter->SetPixelFormat(mPixelFormat);
332       spreadFilter->SetSize(mTargetSize);
333       spreadFilter->SetSpread(mEffectSize);
334
335       BlurTwoPassFilter* blurFilter = static_cast<BlurTwoPassFilter*>(mFilters[1]);
336       blurFilter->SetInputTexture(mFrameBufferPostFilter.GetColorTexture());
337       blurFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
338       blurFilter->SetRootActor(mChildrenRoot);
339       blurFilter->SetBackgroundColor(mBackgroundColor);
340       blurFilter->SetPixelFormat(mPixelFormat);
341       blurFilter->SetSize(mTargetSize);
342
343       const float* kernel(NULL);
344       size_t       kernelSize(0);
345       switch(mEffectSize)
346       {
347         case 4:
348         {
349           kernel     = BLUR_KERNEL4;
350           kernelSize = sizeof(BLUR_KERNEL4) / sizeof(BLUR_KERNEL4[0]);
351           break;
352         }
353         case 3:
354         {
355           kernel     = BLUR_KERNEL3;
356           kernelSize = sizeof(BLUR_KERNEL3) / sizeof(BLUR_KERNEL3[0]);
357           break;
358         }
359         case 2:
360         {
361           kernel     = BLUR_KERNEL2;
362           kernelSize = sizeof(BLUR_KERNEL2) / sizeof(BLUR_KERNEL2[0]);
363           break;
364         }
365         case 1:
366         {
367           kernel     = BLUR_KERNEL1;
368           kernelSize = sizeof(BLUR_KERNEL1) / sizeof(BLUR_KERNEL1[0]);
369           break;
370         }
371         case 0:
372         default:
373         {
374           kernel     = BLUR_KERNEL0;
375           kernelSize = sizeof(BLUR_KERNEL0) / sizeof(BLUR_KERNEL0[0]);
376           break;
377         }
378       }
379       blurFilter->CreateKernel(kernel, kernelSize);
380       break;
381     }
382     case Toolkit::EffectsView::EMBOSS:
383     {
384       SpreadFilter* spreadFilter = static_cast<SpreadFilter*>(mFilters[0]);
385       spreadFilter->SetInputTexture(mFrameBufferForChildren.GetColorTexture());
386       spreadFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
387       spreadFilter->SetRootActor(mChildrenRoot);
388       spreadFilter->SetBackgroundColor(mBackgroundColor);
389       spreadFilter->SetPixelFormat(Pixel::RGBA8888);
390       spreadFilter->SetSize(mTargetSize);
391       spreadFilter->SetSpread(mEffectSize);
392
393       EmbossFilter* embossFilter = static_cast<EmbossFilter*>(mFilters[1]);
394       embossFilter->SetInputTexture(mFrameBufferPostFilter.GetColorTexture());
395       embossFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
396       embossFilter->SetRootActor(mChildrenRoot);
397       embossFilter->SetBackgroundColor(mBackgroundColor);
398       embossFilter->SetPixelFormat(Pixel::RGBA8888);
399       embossFilter->SetSize(mTargetSize);
400
401       BlurTwoPassFilter* blurFilter = static_cast<BlurTwoPassFilter*>(mFilters[2]);
402       blurFilter->SetInputTexture(mFrameBufferPostFilter.GetColorTexture());
403       blurFilter->SetOutputFrameBuffer(mFrameBufferPostFilter);
404       blurFilter->SetRootActor(mChildrenRoot);
405       blurFilter->SetBackgroundColor(Vector4(0.5f, 0.5f, 0.5f, 0.0));
406       blurFilter->SetPixelFormat(Pixel::RGBA8888);
407       blurFilter->SetSize(mTargetSize);
408       blurFilter->CreateKernel(BLUR_KERNEL0, sizeof(BLUR_KERNEL0) / sizeof(BLUR_KERNEL0[0]));
409
410       break;
411     }
412     default:
413     {
414       break;
415     }
416   }
417 }
418
419 void EffectsView::AllocateResources()
420 {
421   if(mTargetSize != mLastSize)
422   {
423     mLastSize = mTargetSize;
424     SetupCameras();
425
426     Actor self(Self());
427
428     mFrameBufferForChildren    = FrameBuffer::New(mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE);
429     Texture textureForChildren = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height));
430     mFrameBufferForChildren.AttachColorTexture(textureForChildren);
431
432     SetRendererTexture(mRendererForChildren, textureForChildren);
433
434     mFrameBufferPostFilter    = FrameBuffer::New(mTargetSize.width, mTargetSize.height, FrameBuffer::Attachment::NONE);
435     Texture texturePostFilter = Texture::New(TextureType::TEXTURE_2D, mPixelFormat, unsigned(mTargetSize.width), unsigned(mTargetSize.height));
436     mFrameBufferPostFilter.AttachColorTexture(texturePostFilter);
437
438     SetRendererTexture(mRendererPostFilter, texturePostFilter);
439
440     SetupFilters();
441   }
442 }
443
444 void EffectsView::SetupCameras()
445 {
446   if(!mCameraForChildren)
447   {
448     // Create a camera for the children render, corresponding to its render target size
449     mCameraForChildren = CameraActor::New(mTargetSize);
450     mCameraForChildren.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
451     mCameraForChildren.SetInvertYAxis(true);
452     Self().Add(mCameraForChildren);
453   }
454   else
455   {
456     // place the camera for the children render, corresponding to its render target size
457     const float cameraPosScale(0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f));
458     mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
459     mCameraForChildren.SetNearClippingPlane(1.0f);
460     mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
461     mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
462     mCameraForChildren.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, mTargetSize.height * cameraPosScale));
463     mCameraForChildren.SetProperty(Actor::Property::POSITION_Z, mTargetSize.height * cameraPosScale);
464   }
465 }
466
467 void EffectsView::CreateRenderTasks()
468 {
469   if(mTargetSize == Vector2::ZERO)
470   {
471     return;
472   }
473   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
474
475   // create render task to render our child actors to offscreen buffer
476   mRenderTaskForChildren = taskList.CreateTask();
477   mRenderTaskForChildren.SetRefreshRate(mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS);
478   mRenderTaskForChildren.SetSourceActor(mChildrenRoot);
479   mRenderTaskForChildren.SetExclusive(true);
480   mRenderTaskForChildren.SetInputEnabled(false);
481   mRenderTaskForChildren.SetClearColor(mBackgroundColor);
482   mRenderTaskForChildren.SetClearEnabled(true);
483   mRenderTaskForChildren.SetFrameBuffer(mFrameBufferForChildren);
484   mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
485
486   // Enable image filters
487   const size_t numFilters(mFilters.Size());
488   for(size_t i = 0; i < numFilters; ++i)
489   {
490     mFilters[i]->Enable();
491   }
492 }
493
494 void EffectsView::RemoveRenderTasks()
495 {
496   if(mTargetSize == Vector2::ZERO)
497   {
498     return;
499   }
500
501   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
502
503   taskList.RemoveTask(mRenderTaskForChildren);
504
505   const size_t numFilters(mFilters.Size());
506   for(size_t i = 0; i < numFilters; ++i)
507   {
508     mFilters[i]->Disable();
509   }
510 }
511
512 void EffectsView::RefreshRenderTasks()
513 {
514   RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
515
516   if(mRenderTaskForChildren)
517   {
518     mRenderTaskForChildren.SetRefreshRate(mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS);
519   }
520
521   const size_t numFilters(mFilters.Size());
522   for(size_t i = 0; i < numFilters; ++i)
523   {
524     mFilters[i]->Refresh();
525   }
526 }
527
528 void EffectsView::RemoveFilters()
529 {
530   const size_t numFilters(mFilters.Size());
531   for(size_t i = 0; i < numFilters; ++i)
532   {
533     delete mFilters[i];
534   }
535   mFilters.Release();
536 }
537
538 void EffectsView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
539 {
540   Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast(Dali::BaseHandle(object));
541
542   if(effectsView)
543   {
544     switch(index)
545     {
546       case Toolkit::EffectsView::Property::EFFECT_SIZE:
547       {
548         int effectSize;
549         if(value.Get(effectSize))
550         {
551           GetImpl(effectsView).SetEffectSize(effectSize);
552         }
553         break;
554       }
555       default:
556       {
557         break;
558       }
559     }
560   }
561 }
562
563 Property::Value EffectsView::GetProperty(BaseObject* object, Property::Index propertyIndex)
564 {
565   Property::Value value;
566
567   Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast(Dali::BaseHandle(object));
568
569   if(imageview)
570   {
571     EffectsView& impl = GetImpl(imageview);
572     switch(propertyIndex)
573     {
574       case Toolkit::EffectsView::Property::EFFECT_SIZE:
575       {
576         value = impl.GetEffectSize();
577         break;
578       }
579       default:
580       {
581         break;
582       }
583     }
584   }
585
586   return value;
587 }
588
589 } // namespace Internal
590
591 } // namespace Toolkit
592
593 } // namespace Dali