Fix blur to use pixel radius input properly 38/317338/11
authorjmm <j0064423.lee@samsung.com>
Mon, 9 Sep 2024 06:07:48 +0000 (15:07 +0900)
committerjmm <j0064423.lee@samsung.com>
Fri, 13 Sep 2024 05:26:08 +0000 (14:26 +0900)
Change-Id: I9959f9f0098fd195b508a852d3338c50a1629c6d

dali-toolkit/internal/controls/render-effects/blur-effect-impl.cpp
dali-toolkit/internal/controls/render-effects/blur-effect-impl.h

index 8060b50526df853938acf43abd97c0bf5726dc3b..e360d31435134b8aa412e9f65292ac45a30bf330 100644 (file)
@@ -36,22 +36,24 @@ namespace
 {
 // Default values
 static constexpr float    BLUR_EFFECT_DOWNSCALE_FACTOR = 0.4f;
-static constexpr uint32_t BLUR_EFFECT_PIXEL_RADIUS     = 5u;
+static constexpr uint32_t BLUR_EFFECT_PIXEL_RADIUS     = 10u;
 static constexpr int32_t  BLUR_EFFECT_ORDER_INDEX      = 101;
 
-static constexpr float MINIMUM_DOWNSCALE_FACTOR = Dali::Math::MACHINE_EPSILON_100;
+static constexpr float MINIMUM_DOWNSCALE_FACTOR = 0.1f;
 static constexpr float MAXIMUM_DOWNSCALE_FACTOR = 1.0f;
 
-static constexpr uint32_t MAXIMUM_BLUR_RADIUS = 1339u; ///< Maximum pixel radius for blur effect. (GL_MAX_FRAGMENT_UNIFORM_COMPONENTS(Usually 1024) - 19 (vertex shader used)) / 3 float = 335
-static_assert(BLUR_EFFECT_PIXEL_RADIUS < ((MAXIMUM_BLUR_RADIUS >> 2) + 1));
+static constexpr uint32_t MINIMUM_BLUR_RADIUS = 3u;   ///< 1-pixel blur(No blur). Blur radius will be compressed to half size(mPixelRadius / 2 >= 1).
+static constexpr uint32_t MAXIMUM_BLUR_RADIUS = 500u; ///< Maximum pixel radius for blur effect. (GL_MAX_FRAGMENT_UNIFORM_COMPONENTS(Usually 1024) - 19 (vertex shader used)) / 3 float
 
 /**
   * @brief Calculates gaussian weight
-  * @param[in] localOffset Input to the function
+  * @param[in] localOffset Input variable of gaussian distribution
+  * @param[in] sigma Standard deviation of gaussian distribution, the width of the "bell"
+  * @note Expected value of this gaussian distribution is 0.
   */
 inline float CalculateGaussianWeight(float localOffset, float sigma)
 {
-  return (1.0f / sqrt(2.0f * Dali::Math::PI * sigma)) * exp(-(localOffset / sigma * localOffset / sigma) * 0.5f);
+  return (1.0f / (sigma * sqrt(2.0f * Dali::Math::PI))) * exp(-0.5f * (localOffset / sigma * localOffset / sigma));
 }
 } // namespace
 
@@ -70,7 +72,7 @@ BlurEffectImpl::BlurEffectImpl(bool isBackground)
   mInternalRoot(Actor::New()),
   mDownscaleFactor(BLUR_EFFECT_DOWNSCALE_FACTOR),
   mPixelRadius(BLUR_EFFECT_PIXEL_RADIUS),
-  mBellCurveWidth(0.001f),
+  mBellCurveWidth(Math::MACHINE_EPSILON_1),
   mIsBackground(isBackground)
 {
 }
@@ -79,26 +81,20 @@ BlurEffectImpl::BlurEffectImpl(float downscaleFactor, uint32_t blurRadius, bool
 : RenderEffectImpl(),
   mInternalRoot(Actor::New()),
   mDownscaleFactor(downscaleFactor),
-  mPixelRadius((blurRadius >> 2) + 1),
-  mBellCurveWidth(0.001f),
+  mPixelRadius(blurRadius),
+  mBellCurveWidth(Math::MACHINE_EPSILON_1),
   mIsBackground(isBackground)
 {
-  if(DALI_UNLIKELY(mDownscaleFactor < MINIMUM_DOWNSCALE_FACTOR || mDownscaleFactor > MAXIMUM_DOWNSCALE_FACTOR))
-  {
-    const float fixedDownScaleFactor = Dali::Clamp(mDownscaleFactor, MINIMUM_DOWNSCALE_FACTOR, MAXIMUM_DOWNSCALE_FACTOR);
-    DALI_LOG_ERROR("Downscale factor is out of bound: %f. Use %f instead.\n", mDownscaleFactor, fixedDownScaleFactor);
-    mDownscaleFactor = fixedDownScaleFactor;
-  }
-  if(DALI_UNLIKELY(blurRadius > MAXIMUM_BLUR_RADIUS))
+  mDownscaleFactor = Dali::Clamp(mDownscaleFactor, MINIMUM_DOWNSCALE_FACTOR, MAXIMUM_DOWNSCALE_FACTOR);
+  mPixelRadius     = Dali::Clamp(mPixelRadius, MINIMUM_BLUR_RADIUS, MAXIMUM_BLUR_RADIUS);
+
+  mPixelRadius = static_cast<uint32_t>(mPixelRadius * mDownscaleFactor);
+  if(mPixelRadius <= MINIMUM_BLUR_RADIUS)
   {
-    const uint32_t fixedBlurRadius      = MAXIMUM_BLUR_RADIUS;
-    const float    fixedDownScaleFactor = Dali::Clamp(mDownscaleFactor * static_cast<float>(fixedBlurRadius) / static_cast<float>(blurRadius), MINIMUM_DOWNSCALE_FACTOR, MAXIMUM_DOWNSCALE_FACTOR);
-    DALI_LOG_ERROR("Blur radius is out of bound: %u. Use %u and make downscale factor %f to %f.\n", blurRadius, fixedBlurRadius, mDownscaleFactor, fixedDownScaleFactor);
-    mDownscaleFactor = fixedDownScaleFactor;
-    mPixelRadius     = (fixedBlurRadius >> 2) + 1;
+    DALI_LOG_ERROR("Downscaled pixel radius %u is too small. Ignore blur.", mPixelRadius);
+    mDownscaleFactor = MAXIMUM_DOWNSCALE_FACTOR;
+    mPixelRadius     = MINIMUM_BLUR_RADIUS;
   }
-
-  DALI_ASSERT_DEBUG((mPixelRadius != 0u) && "mPixelRadius chould not be zero! their was some logical error occured.");
 }
 
 BlurEffectImpl::~BlurEffectImpl()
@@ -121,77 +117,77 @@ BlurEffectImplPtr BlurEffectImpl::New(float downscaleFactor, uint32_t blurRadius
 
 void BlurEffectImpl::OnInitialize()
 {
-  mRenderFullSizeCamera = CameraActor::New();
-  mRenderFullSizeCamera.SetInvertYAxis(true);
-  mRenderFullSizeCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-  mRenderFullSizeCamera.SetNearClippingPlane(1.0f);
-  mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK);
-  mRenderFullSizeCamera.SetFieldOfView(Math::PI / 4.0f);
-  mInternalRoot.Add(mRenderFullSizeCamera);
-
-  mRenderDownsampledCamera = CameraActor::New();
-  mRenderDownsampledCamera.SetInvertYAxis(true);
-  mRenderDownsampledCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-  mRenderDownsampledCamera.SetNearClippingPlane(1.0f);
-  mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK);
-  mRenderDownsampledCamera.SetFieldOfView(Math::PI / 4.0f);
-  mInternalRoot.Add(mRenderDownsampledCamera);
-
-  //////////////////////////////////////////////////////
-  // Create shaders
-
-  std::ostringstream fragmentStringStream;
-  fragmentStringStream << "#define NUM_SAMPLES " << (DALI_LIKELY(mPixelRadius > 1u) ? mPixelRadius : 2u) << "\n";
-  fragmentStringStream << SHADER_BLUR_EFFECT_FRAG;
-  std::string fragmentSource(fragmentStringStream.str());
+  // Create CameraActors
+  {
+    mRenderFullSizeCamera = CameraActor::New();
+    mRenderFullSizeCamera.SetInvertYAxis(true);
+    mRenderFullSizeCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    mRenderFullSizeCamera.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    mRenderFullSizeCamera.SetType(Dali::Camera::FREE_LOOK);
+    mInternalRoot.Add(mRenderFullSizeCamera);
+
+    mRenderDownsampledCamera = CameraActor::New();
+    mRenderDownsampledCamera.SetInvertYAxis(true);
+    mRenderDownsampledCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    mRenderDownsampledCamera.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+    mRenderDownsampledCamera.SetType(Dali::Camera::FREE_LOOK);
+    mInternalRoot.Add(mRenderDownsampledCamera);
+  }
 
   // Calculate bell curve width
   {
     const float epsilon     = 1e-2f / (mPixelRadius * 2);
     const float localOffset = (mPixelRadius * 2) - 1;
 
-    float lowerBoundSigma = 0.001f;
-    float upperBoundSigma = 171.352f; ///< bell curve width for MAXIMUM_BLUR_RADIUS case
+    float lowerBoundBellCurveWidth = 0.001f;
+    float upperBoundBellCurveWidth = 171.352f; ///< bell curve width for MAXIMUM_BLUR_RADIUS case
 
     int       trialCount        = 0;
     const int maximumTrialCount = 50;
-    while(trialCount++ < maximumTrialCount && upperBoundSigma - lowerBoundSigma > Math::MACHINE_EPSILON_10000)
+    while(trialCount++ < maximumTrialCount && upperBoundBellCurveWidth - lowerBoundBellCurveWidth > Math::MACHINE_EPSILON_10000)
     {
-      const float sigma = (lowerBoundSigma + upperBoundSigma) * 0.5f;
-      if(CalculateGaussianWeight(localOffset, sigma) < epsilon)
+      const float bellCurveWidth = (lowerBoundBellCurveWidth + upperBoundBellCurveWidth) * 0.5f;
+      if(CalculateGaussianWeight(localOffset, bellCurveWidth) < epsilon)
       {
-        lowerBoundSigma = sigma;
+        lowerBoundBellCurveWidth = bellCurveWidth;
       }
       else
       {
-        upperBoundSigma = sigma;
+        upperBoundBellCurveWidth = bellCurveWidth;
       }
     }
 
-    mBellCurveWidth = (lowerBoundSigma + upperBoundSigma) * 0.5f;
+    mBellCurveWidth = (lowerBoundBellCurveWidth + upperBoundBellCurveWidth) * 0.5f;
   }
 
-  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Verbose, "[BlurEffect:%p] mBellCurveWidth calculated! [radius:%u][sigma:%f]\n", this, mPixelRadius, mBellCurveWidth);
-
-  //////////////////////////////////////////////////////
-  // Create actors
-  mInternalRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-
-  // Create an actor for performing a horizontal blur on the texture
-  mHorizontalBlurActor = Actor::New();
-  mHorizontalBlurActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-  Renderer horizontalBlurRenderer = CreateRenderer(BASIC_VERTEX_SOURCE, fragmentSource.c_str());
-  horizontalBlurRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha
-  mHorizontalBlurActor.AddRenderer(horizontalBlurRenderer);
-  mInternalRoot.Add(mHorizontalBlurActor);
-
-  // Create an actor for performing a vertical blur on the texture
-  mVerticalBlurActor = Actor::New();
-  mVerticalBlurActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-  Renderer verticalBlurRenderer = CreateRenderer(BASIC_VERTEX_SOURCE, fragmentSource.c_str());
-  verticalBlurRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha
-  mVerticalBlurActor.AddRenderer(verticalBlurRenderer);
-  mInternalRoot.Add(mVerticalBlurActor);
+  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Verbose, "[BlurEffect:%p] mBellCurveWidth calculated! [radius:%u][bellCurveWidth:%f]\n", this, mPixelRadius, mBellCurveWidth);
+
+  // Create blur actors
+  {
+    mInternalRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+    // shader
+    std::ostringstream fragmentStringStream;
+    fragmentStringStream << "#define NUM_SAMPLES " << (mPixelRadius >> 1) << "\n";
+    fragmentStringStream << SHADER_BLUR_EFFECT_FRAG;
+    std::string fragmentSource(fragmentStringStream.str());
+
+    // Create an actor for performing a horizontal blur on the texture
+    mHorizontalBlurActor = Actor::New();
+    mHorizontalBlurActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    Renderer horizontalBlurRenderer = CreateRenderer(BASIC_VERTEX_SOURCE, fragmentSource.c_str());
+    horizontalBlurRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha
+    mHorizontalBlurActor.AddRenderer(horizontalBlurRenderer);
+    mInternalRoot.Add(mHorizontalBlurActor);
+
+    // Create an actor for performing a vertical blur on the texture
+    mVerticalBlurActor = Actor::New();
+    mVerticalBlurActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    Renderer verticalBlurRenderer = CreateRenderer(BASIC_VERTEX_SOURCE, fragmentSource.c_str());
+    verticalBlurRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha
+    mVerticalBlurActor.AddRenderer(verticalBlurRenderer);
+    mInternalRoot.Add(mVerticalBlurActor);
+  }
 }
 
 void BlurEffectImpl::OnActivate()
@@ -199,7 +195,7 @@ void BlurEffectImpl::OnActivate()
   Toolkit::Control ownerControl = GetOwnerControl();
   DALI_ASSERT_ALWAYS(ownerControl && "Set the owner of RenderEffect before you activate.");
 
-  // Get/Set sizes
+  // Get size
   Vector2 size = GetTargetSizeForValidTexture();
   DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[BlurEffect:%p] OnActivated! [ID:%d][size:%fx%f]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1, size.x, size.y);
 
@@ -207,70 +203,112 @@ void BlurEffectImpl::OnActivate()
   {
     return;
   }
-  uint32_t downsampledWidth  = static_cast<uint32_t>(size.width * mDownscaleFactor);
-  uint32_t downsampledHeight = static_cast<uint32_t>(size.height * mDownscaleFactor);
-  if(downsampledWidth == 0u)
-  {
-    downsampledWidth = 1u;
-  }
-  if(downsampledHeight == 0u)
-  {
-    downsampledHeight = 1u;
-  }
+  uint32_t downsampledWidth  = std::max(static_cast<uint32_t>(size.width * mDownscaleFactor), 1u);
+  uint32_t downsampledHeight = std::max(static_cast<uint32_t>(size.height * mDownscaleFactor), 1u);
+
+  // Set size
+  mRenderFullSizeCamera.SetPerspectiveProjection(size);
+  mRenderDownsampledCamera.SetPerspectiveProjection(Size(downsampledWidth, downsampledHeight));
 
+  mHorizontalBlurActor.SetProperty(Actor::Property::SIZE, Vector2(downsampledWidth, downsampledHeight));
+  mVerticalBlurActor.SetProperty(Actor::Property::SIZE, Vector2(downsampledWidth, downsampledHeight));
+
+  // Keep sceneHolder as week handle.
   Integration::SceneHolder sceneHolder = Integration::SceneHolder::Get(ownerControl);
   if(DALI_UNLIKELY(!sceneHolder))
   {
     DALI_LOG_ERROR("BlurEffect Could not be activated due to ownerControl's SceneHolder is not exist\n");
     return;
   }
-
-  // Keep sceneHolder as week handle.
   mPlacementSceneHolder = sceneHolder;
 
-  RenderTaskList taskList = sceneHolder.GetRenderTaskList();
+  // Set blur
+  CreateFrameBuffers(size, Size(downsampledWidth, downsampledHeight));
+  CreateRenderTasks(sceneHolder, ownerControl);
+  SetShaderConstants(downsampledWidth, downsampledHeight);
+
+  // Inject blurred output to control
+  Renderer renderer = GetTargetRenderer();
+  if(mIsBackground)
+  {
+    renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, Dali::Toolkit::DepthIndex::BACKGROUND - 3);
+  }
+  else
+  {
+    renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, Dali::Toolkit::DepthIndex::CONTENT);
+  }
+  ownerControl.AddRenderer(renderer);
+  SetRendererTexture(renderer, mSourceFrameBuffer);
+
+  ownerControl.Add(mInternalRoot);
+}
+
+void BlurEffectImpl::OnDeactivate()
+{
+  auto ownerControl = GetOwnerControl();
+  if(DALI_LIKELY(ownerControl))
+  {
+    Renderer renderer = GetTargetRenderer();
+    ownerControl.RemoveRenderer(renderer);
+  }
+  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[BlurEffect:%p] OnDeactivated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1);
+
+  mInternalRoot.Unparent();
+
+  mInputBackgroundFrameBuffer.Reset();
+  mTemporaryFrameBuffer.Reset();
+  mSourceFrameBuffer.Reset();
+
+  auto sceneHolder = mPlacementSceneHolder.GetHandle();
+  if(DALI_LIKELY(sceneHolder))
+  {
+    RenderTaskList taskList = sceneHolder.GetRenderTaskList();
+    taskList.RemoveTask(mHorizontalBlurTask);
+    taskList.RemoveTask(mVerticalBlurTask);
+    taskList.RemoveTask(mSourceRenderTask);
+    mPlacementSceneHolder.Reset();
+  }
 
-  // Prepare resource
-  // original texture output
+  mHorizontalBlurTask.Reset();
+  mVerticalBlurTask.Reset();
+  mSourceRenderTask.Reset();
+}
+
+void BlurEffectImpl::CreateFrameBuffers(const Size size, const Size downsampledSize)
+{
+  uint32_t downsampledWidth  = downsampledSize.width;
+  uint32_t downsampledHeight = downsampledSize.height;
+
+  // buffer to draw input texture
   mInputBackgroundFrameBuffer    = FrameBuffer::New(downsampledWidth, downsampledHeight, FrameBuffer::Attachment::DEPTH_STENCIL);
   Texture inputBackgroundTexture = Texture::New(TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, downsampledWidth, downsampledHeight);
   mInputBackgroundFrameBuffer.AttachColorTexture(inputBackgroundTexture);
 
-  // half-blurred output
+  // buffer to draw half-blurred output
   mTemporaryFrameBuffer    = FrameBuffer::New(downsampledWidth, downsampledHeight, FrameBuffer::Attachment::DEPTH_STENCIL);
   Texture temporaryTexture = Texture::New(TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, downsampledWidth, downsampledHeight);
   mTemporaryFrameBuffer.AttachColorTexture(temporaryTexture);
 
-  // blurred output
+  // buffer to draw blurred output
   mSourceFrameBuffer    = FrameBuffer::New(downsampledWidth, downsampledHeight, FrameBuffer::Attachment::DEPTH_STENCIL);
   Texture sourceTexture = Texture::New(TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, downsampledWidth, downsampledHeight);
   mSourceFrameBuffer.AttachColorTexture(sourceTexture);
+}
 
-  // Add BlurActors
-  mHorizontalBlurActor.SetProperty(Actor::Property::SIZE, Vector2(downsampledWidth, downsampledHeight)); // mTemporaryFrameBuffer
-  mVerticalBlurActor.SetProperty(Actor::Property::SIZE, Vector2(downsampledWidth, downsampledHeight));   // mSourceFrameBuffer
-
-  // Add CameraActors
-  float cameraPosConstraintScale = 0.5f / tanf(Math::PI / 4.0f * 0.5f);
-
-  mRenderFullSizeCamera.SetAspectRatio(size.width / size.height);
-  mRenderFullSizeCamera.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, cameraPosConstraintScale * size.height));
-
-  mRenderDownsampledCamera.SetAspectRatio(float(downsampledWidth) / float(downsampledHeight));
-  mRenderDownsampledCamera.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, cameraPosConstraintScale * size.height * mDownscaleFactor));
-
-  SetShaderConstants(downsampledWidth, downsampledHeight);
+void BlurEffectImpl::CreateRenderTasks(Integration::SceneHolder sceneHolder, const Toolkit::Control sourceControl)
+{
+  RenderTaskList taskList = sceneHolder.GetRenderTaskList();
 
-  // Prepare input texture
+  // draw input texture
   mSourceRenderTask = taskList.CreateTask();
   if(mIsBackground)
   {
     mSourceRenderTask.SetSourceActor(sceneHolder.GetRootLayer());
-    mSourceRenderTask.RenderUntil(ownerControl);
+    mSourceRenderTask.RenderUntil(sourceControl);
   }
   else
   {
-    mSourceRenderTask.SetSourceActor(ownerControl);
+    mSourceRenderTask.SetSourceActor(sourceControl);
   }
   mSourceRenderTask.SetOrderIndex(BLUR_EFFECT_ORDER_INDEX);
   mSourceRenderTask.SetCameraActor(mRenderFullSizeCamera);
@@ -282,7 +320,7 @@ void BlurEffectImpl::OnActivate()
   mSourceRenderTask.SetClearEnabled(true);
   mSourceRenderTask.SetClearColor(sceneHolder.GetBackgroundColor());
 
-  // Blur tasks
+  // draw half-blurred output
   SetRendererTexture(mHorizontalBlurActor.GetRendererAt(0), mInputBackgroundFrameBuffer);
   mHorizontalBlurTask = taskList.CreateTask();
   mHorizontalBlurTask.SetSourceActor(mHorizontalBlurActor);
@@ -296,6 +334,7 @@ void BlurEffectImpl::OnActivate()
   mHorizontalBlurTask.SetClearEnabled(true);
   mHorizontalBlurTask.SetClearColor(Color::TRANSPARENT);
 
+  // draw blurred output
   SetRendererTexture(mVerticalBlurActor.GetRendererAt(0), mTemporaryFrameBuffer);
   mVerticalBlurTask = taskList.CreateTask();
   mVerticalBlurTask.SetSourceActor(mVerticalBlurActor);
@@ -308,52 +347,6 @@ void BlurEffectImpl::OnActivate()
   // Clear sourceTexture as Transparent.
   mVerticalBlurTask.SetClearEnabled(true);
   mVerticalBlurTask.SetClearColor(Color::TRANSPARENT);
-
-  // Inject output to control
-  Renderer renderer = GetTargetRenderer();
-  if(mIsBackground)
-  {
-    renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, Dali::Toolkit::DepthIndex::BACKGROUND - 3);
-  }
-  else
-  {
-    renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, Dali::Toolkit::DepthIndex::CONTENT);
-  }
-  ownerControl.AddRenderer(renderer);
-  SetRendererTexture(renderer, mSourceFrameBuffer);
-
-  ownerControl.Add(mInternalRoot);
-}
-
-void BlurEffectImpl::OnDeactivate()
-{
-  auto ownerControl = GetOwnerControl();
-  if(DALI_LIKELY(ownerControl))
-  {
-    Renderer renderer = GetTargetRenderer();
-    ownerControl.RemoveRenderer(renderer);
-  }
-  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[BlurEffect:%p] OnDeactivated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1);
-
-  mInternalRoot.Unparent();
-
-  mInputBackgroundFrameBuffer.Reset();
-  mTemporaryFrameBuffer.Reset();
-  mSourceFrameBuffer.Reset();
-
-  auto sceneHolder = mPlacementSceneHolder.GetHandle();
-  if(DALI_LIKELY(sceneHolder))
-  {
-    RenderTaskList taskList = sceneHolder.GetRenderTaskList();
-    taskList.RemoveTask(mHorizontalBlurTask);
-    taskList.RemoveTask(mVerticalBlurTask);
-    taskList.RemoveTask(mSourceRenderTask);
-    mPlacementSceneHolder.Reset();
-  }
-
-  mHorizontalBlurTask.Reset();
-  mVerticalBlurTask.Reset();
-  mSourceRenderTask.Reset();
 }
 
 Vector2 BlurEffectImpl::GetTargetSizeForValidTexture() const
@@ -381,38 +374,40 @@ Vector2 BlurEffectImpl::GetTargetSizeForValidTexture() const
 
 void BlurEffectImpl::SetShaderConstants(float downsampledWidth, float downsampledHeight)
 {
-  const uint32_t numSamples = DALI_LIKELY(mPixelRadius > 1u) ? mPixelRadius : 2u;
+  const uint32_t sampleCount    = mPixelRadius >> 1; // compression
+  const uint32_t kernelSize     = sampleCount * 4 - 1;
+  const uint32_t halfKernelSize = kernelSize / 2; // Gaussian curve is symmetric
 
-  std::vector<float> uvOffsets(numSamples);
-  std::vector<float> weights(numSamples);
+  // Output: Gaussian kernel compressed to half size
+  std::vector<float> uvOffsets(sampleCount);
+  std::vector<float> weights(sampleCount);
 
-  // generate bell curve kernel
-  unsigned int       halfSize = numSamples * 2;
-  std::vector<float> halfSideKernel(halfSize);
+  // Generate half size kernel
+  std::vector<float> halfSideKernel(halfKernelSize);
 
   halfSideKernel[0]  = CalculateGaussianWeight(0.0f, mBellCurveWidth);
   float totalWeights = halfSideKernel[0];
-  for(unsigned int i = 1; i < halfSize; i++)
+  for(unsigned int i = 1; i < halfKernelSize; i++)
   {
     float w           = CalculateGaussianWeight(i, mBellCurveWidth);
     halfSideKernel[i] = w;
     totalWeights += w * 2.0f;
   }
-  for(unsigned int i = 0; i < halfSize; i++)
+  for(unsigned int i = 0; i < halfKernelSize; i++)
   {
     halfSideKernel[i] /= totalWeights;
   }
   halfSideKernel[0] *= 0.5f;
 
-  // compress kernel
-  for(unsigned int i = 0; i < numSamples; i++)
+  // Compress kernel to half size
+  for(unsigned int i = 0; i < sampleCount; i++)
   {
     weights[i]   = halfSideKernel[2 * i] + halfSideKernel[2 * i + 1];
     uvOffsets[i] = 2.0f * i + halfSideKernel[2 * i + 1] / weights[i];
   }
 
-  // set shader constants
-  for(unsigned int i = 0; i < numSamples; ++i)
+  // Set shader constants
+  for(unsigned int i = 0; i < sampleCount; ++i)
   {
     mHorizontalBlurActor.RegisterProperty(GetSampleOffsetsPropertyName(i), Vector2(uvOffsets[i] / downsampledWidth, 0.0f));
     mHorizontalBlurActor.RegisterProperty(GetSampleWeightsPropertyName(i), weights[i]);
@@ -421,6 +416,7 @@ void BlurEffectImpl::SetShaderConstants(float downsampledWidth, float downsample
     mVerticalBlurActor.RegisterProperty(GetSampleWeightsPropertyName(i), weights[i]);
   }
 
+  // Apply background properties
   if(mIsBackground)
   {
     SynchronizeBackgroundCornerRadius();
index c32ecccdfdff5bc03b51a1eefa562136dcc05fda..4331255c6782bb8ecc35a04a16b69e5ff5362923 100644 (file)
@@ -105,6 +105,21 @@ protected:
 
 private:
   // Inner functions
+  /**
+   * @brief Sets frame buffers to draw blurred output.
+   * @param[in] size Full size of input.
+   * @param[in] downsampledSize Downsampled size for performance.
+   */
+  void CreateFrameBuffers(const Size size, const Size downsampledSize);
+
+  /**
+   * @brief Sets blur render tasks.
+   * Requires initialized buffers, source actors, and source cameras.
+   * @param[in] sceneHolder SceneHolder of source control
+   * @param[in] sourceControl Input source control
+   */
+  void CreateRenderTasks(Integration::SceneHolder sceneHolder, const Toolkit::Control sourceControl);
+
   /**
    * @brief Gets or Calculates a valid target size for texture.
    * Invalid cases include: zero vector, minus numbers or large numbers(larger than the maximum).