#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/public-api/controls/render-effects/background-blur-effect.h>
+#include <dali-toolkit/public-api/controls/render-effects/mask-effect.h>
#include <dali/devel-api/adaptor-framework/image-loading.h>
using namespace Dali;
RenderEffect blurEffect2 = BackgroundBlurEffect::New(0.5f, 10);
DALI_TEST_CHECK(blurEffect2);
+ Control control = Control::New();
+
+ RenderEffect maskEffect1 = MaskEffect::New(control);
+ DALI_TEST_CHECK(maskEffect1);
+
+ RenderEffect maskEffect2 = MaskEffect::New(control, MaskEffect::MaskMode::LUMINANCE, Vector2(0.f, 0.f), Vector2(1.f, 1.f));
+ DALI_TEST_CHECK(maskEffect2);
+
+ MaskEffect maskEffect3 = MaskEffect::New(control);
+ DALI_TEST_CHECK(maskEffect3);
+
+ MaskEffect maskEffect4 = maskEffect3;
+ DALI_TEST_CHECK(maskEffect4);
+
END_TEST;
}
taskList = scene.GetRenderTaskList();
DALI_TEST_EQUALS(4u, taskList.GetTaskCount(), TEST_LOCATION);
+ Control newControl = Control::New();
+ childControl.SetRenderEffect(MaskEffect::New(newControl));
+
+ taskList = scene.GetRenderTaskList();
+ DALI_TEST_EQUALS(3u, taskList.GetTaskCount(), TEST_LOCATION);
+
END_TEST;
}
END_TEST;
}
+int UtcDaliRenderEffectActivateP03(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliRenderEffectActivateP03");
+
+ Integration::Scene scene = application.GetScene();
+
+ Control control = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+ scene.Add(control);
+
+ Control newControl = Control::New();
+ RenderEffect maskEffect = MaskEffect::New(newControl);
+ control.SetRenderEffect(maskEffect);
+
+ RenderTaskList taskList = scene.GetRenderTaskList();
+ DALI_TEST_EQUALS(3u, taskList.GetTaskCount(), TEST_LOCATION);
+
+ Control control2 = Control::New();
+ control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control2.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+ scene.Add(control2);
+
+ control2.SetRenderEffect(maskEffect);
+ taskList = scene.GetRenderTaskList();
+ DALI_TEST_EQUALS(3u, taskList.GetTaskCount(), TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliRenderEffectDeactivateP(void)
{
ToolkitTestApplication application;
DALI_TEST_EQUALS(1u, taskList.GetTaskCount(), TEST_LOCATION);
DALI_TEST_EQUALS(count, control.GetRendererCount(), TEST_LOCATION);
+ Control newControl = Control::New();
+ count = control.GetRendererCount();
+ control.SetRenderEffect(MaskEffect::New(newControl));
+
+ taskList = scene.GetRenderTaskList();
+ DALI_TEST_EQUALS(3u, taskList.GetTaskCount(), TEST_LOCATION);
+
+ control.ClearRenderEffect();
+ taskList = scene.GetRenderTaskList();
+ DALI_TEST_EQUALS(1u, taskList.GetTaskCount(), TEST_LOCATION);
+
END_TEST;
}
END_TEST;
}
+
+int UtcDaliMaskEffect(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliMaskEffect");
+
+ Integration::Scene scene = application.GetScene();
+
+ Control control = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ scene.Add(control);
+
+ Control maskControl = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+ // Add render effect during scene on.
+ control.SetRenderEffect(MaskEffect::New(maskControl));
+
+ // send notification.
+ application.SendNotification();
+ application.Render();
+
+ RenderTaskList taskList = scene.GetRenderTaskList();
+
+ control.SetProperty(Actor::Property::SIZE, Vector2(3.0f, 3.0f));
+
+ // send notification twice to refresh.
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+
+ // Render effect activated.
+ DALI_TEST_EQUALS(3u, taskList.GetTaskCount(), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMaskEffectScaleN(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliMaskEffect");
+
+ Integration::Scene scene = application.GetScene();
+
+ Control control = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ scene.Add(control);
+
+ Control maskControl = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ // adjust to epsilon.
+ control.SetRenderEffect(MaskEffect::New(maskControl, MaskEffect::MaskMode::ALPHA, Vector2(0.f, 0.f), Vector2(0.f, 0.f)));
+
+ // send notification.
+ application.SendNotification();
+ application.Render();
+
+ RenderTaskList taskList = scene.GetRenderTaskList();
+
+ // Render effect activated.
+ DALI_TEST_EQUALS(3u, taskList.GetTaskCount(), TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/render-effects/mask-effect-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/custom-actor-impl.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/public-api/rendering/renderer.h>
+#include <dali/public-api/rendering/shader.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/controls/control/control-renderers.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+
+namespace
+{
+const uint32_t maskSourceIndex = 0u;
+const uint32_t maskTargetIndex = 1u;
+constexpr const char* UNIFORM_MASK_MODE_NAME = "uMaskMode";
+constexpr const char* UNIFORM_MASK_POSITION_NAME = "uMaskPosition";
+constexpr const char* UNIFORM_MASK_SCALE_NAME = "uMaskScale";
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+#ifdef DEBUG_ENABLED
+extern Debug::Filter* gRenderEffectLogFilter; ///< Define at render-effect-impl.cpp
+#endif
+
+MaskEffectImpl::MaskEffectImpl(Toolkit::Control maskControl)
+: RenderEffectImpl(),
+ mMaskControl(maskControl),
+ mMaskMode(MaskEffect::MaskMode::ALPHA),
+ mMaskPosition(Vector2(0.f, 0.f)),
+ mMaskScale(Vector2(1.f, 1.f))
+{
+}
+
+MaskEffectImpl::MaskEffectImpl(Toolkit::Control maskControl, MaskEffect::MaskMode maskMode, Vector2 maskPosition, Vector2 maskScale)
+: RenderEffectImpl(),
+ mMaskControl(maskControl),
+ mMaskMode(maskMode),
+ mMaskPosition(maskPosition),
+ mMaskScale(maskScale)
+{
+ if(mMaskScale.x < Math::MACHINE_EPSILON_100)
+ {
+ DALI_LOG_DEBUG_INFO("maskScale.x is less or equal to zero. Adjust to epsilon.\n");
+ mMaskScale.x = Math::MACHINE_EPSILON_100;
+ }
+
+ if(mMaskScale.y < Math::MACHINE_EPSILON_100)
+ {
+ DALI_LOG_DEBUG_INFO("maskScale.y is less or equal to zero. Adjust to epsilon.\n");
+ mMaskScale.y = Math::MACHINE_EPSILON_100;
+ }
+}
+
+MaskEffectImpl::~MaskEffectImpl()
+{
+}
+
+MaskEffectImplPtr MaskEffectImpl::New(Toolkit::Control maskControl)
+{
+ MaskEffectImplPtr handle = new MaskEffectImpl(maskControl);
+ handle->Initialize();
+ return handle;
+}
+
+MaskEffectImplPtr MaskEffectImpl::New(Toolkit::Control maskControl, MaskEffect::MaskMode maskMode, Vector2 maskPosition, Vector2 maskScale)
+{
+ MaskEffectImplPtr handle = new MaskEffectImpl(maskControl, maskMode, maskPosition, maskScale);
+ handle->Initialize();
+ return handle;
+}
+
+OffScreenRenderable::Type MaskEffectImpl::GetOffScreenRenderableType()
+{
+ return OffScreenRenderable::FORWARD;
+}
+
+void MaskEffectImpl::GetOffScreenRenderTasks(std::vector<Dali::RenderTask>& tasks, bool isForward)
+{
+ tasks.clear();
+ if(isForward)
+ {
+ if(mMaskTargetRenderTask)
+ {
+ tasks.push_back(mMaskTargetRenderTask);
+ }
+ if(mMaskSourceRenderTask)
+ {
+ tasks.push_back(mMaskSourceRenderTask);
+ }
+ }
+}
+
+void MaskEffectImpl::OnInitialize()
+{
+ // Create CameraActors
+ mCamera = CameraActor::New();
+ mCamera.SetInvertYAxis(true);
+ mCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ mCamera.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+
+ // renderer
+ Renderer maskRenderer = GetTargetRenderer();
+ Shader shader = Dali::Shader::New(BASIC_VERTEX_SOURCE, SHADER_MASK_EFFECT_FRAG);
+ maskRenderer.SetShader(shader);
+ maskRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha
+}
+
+void MaskEffectImpl::OnActivate()
+{
+ Toolkit::Control ownerControl = GetOwnerControl();
+ DALI_ASSERT_ALWAYS(ownerControl && "Set the owner of RenderEffect before you activate.");
+
+ ownerControl.Add(mCamera);
+ Renderer maskRenderer = GetTargetRenderer();
+ ownerControl.GetImplementation().SetCacheRenderer(maskRenderer);
+ ownerControl.GetImplementation().SetOffScreenRenderableType(OffScreenRenderable::Type::FORWARD);
+
+ Vector2 size = GetTargetSize();
+ mCamera.SetPerspectiveProjection(size);
+
+ CreateFrameBuffers(ImageDimensions(size.x, size.y));
+ CreateRenderTasks(ownerControl);
+ SetShaderConstants(ownerControl);
+
+ mMaskTargetRenderTask.SetScreenToFrameBufferMappingActor(ownerControl);
+
+ TextureSet textureSet = TextureSet::New();
+
+ Texture maskSourceTexture = mMaskSourceFrameBuffer.GetColorTexture();
+ Texture maskTargetTexture = mMaskTargetFrameBuffer.GetColorTexture();
+
+ textureSet.SetTexture(maskSourceIndex, maskSourceTexture);
+ textureSet.SetTexture(maskTargetIndex, maskTargetTexture);
+
+ maskRenderer.SetTextures(textureSet);
+}
+
+void MaskEffectImpl::OnDeactivate()
+{
+ mCamera.Unparent();
+ mMaskTargetFrameBuffer.Reset();
+ mMaskSourceFrameBuffer.Reset();
+
+ auto sceneHolder = GetSceneHolder();
+ if(DALI_LIKELY(sceneHolder))
+ {
+ RenderTaskList taskList = sceneHolder.GetRenderTaskList();
+ taskList.RemoveTask(mMaskTargetRenderTask);
+ mMaskTargetRenderTask.Reset();
+ taskList.RemoveTask(mMaskSourceRenderTask);
+ mMaskSourceRenderTask.Reset();
+ }
+}
+
+void MaskEffectImpl::OnRefresh()
+{
+ mMaskTargetFrameBuffer.Reset();
+ mMaskSourceFrameBuffer.Reset();
+
+ Vector2 size = GetTargetSize();
+ mCamera.SetPerspectiveProjection(size);
+ CreateFrameBuffers(ImageDimensions(size.x, size.y));
+
+ mMaskTargetRenderTask.SetFrameBuffer(mMaskTargetFrameBuffer);
+ mMaskSourceRenderTask.SetFrameBuffer(mMaskSourceFrameBuffer);
+}
+
+void MaskEffectImpl::CreateFrameBuffers(const ImageDimensions size)
+{
+ uint32_t width = size.GetWidth();
+ uint32_t height = size.GetHeight();
+
+ mMaskTargetFrameBuffer = FrameBuffer::New(width, height, FrameBuffer::Attachment::DEPTH_STENCIL);
+ Texture mMaskTargetTexture = Texture::New(TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, width, height);
+ mMaskTargetFrameBuffer.AttachColorTexture(mMaskTargetTexture);
+
+ mMaskSourceFrameBuffer = FrameBuffer::New(width, height, FrameBuffer::Attachment::DEPTH_STENCIL);
+ Texture mMaskSourceTexture = Texture::New(TextureType::TEXTURE_2D, Dali::Pixel::RGBA8888, width, height);
+ mMaskSourceFrameBuffer.AttachColorTexture(mMaskSourceTexture);
+}
+
+void MaskEffectImpl::CreateRenderTasks(Toolkit::Control ownerControl)
+{
+ RenderTaskList taskList = GetSceneHolder().GetRenderTaskList();
+
+ mMaskTargetRenderTask = taskList.CreateTask();
+ mMaskTargetRenderTask.SetCameraActor(mCamera);
+ mMaskTargetRenderTask.SetExclusive(true);
+ mMaskTargetRenderTask.SetInputEnabled(true);
+ mMaskTargetRenderTask.SetSourceActor(ownerControl);
+ mMaskTargetRenderTask.SetFrameBuffer(mMaskTargetFrameBuffer);
+ mMaskTargetRenderTask.SetClearEnabled(true);
+ mMaskTargetRenderTask.SetClearColor(Color::TRANSPARENT);
+
+ mMaskSourceRenderTask = taskList.CreateTask();
+ mMaskSourceRenderTask.SetCameraActor(mCamera);
+ mMaskSourceRenderTask.SetExclusive(true);
+ mMaskSourceRenderTask.SetInputEnabled(false);
+ mMaskSourceRenderTask.SetSourceActor(mMaskControl.GetHandle());
+ mMaskSourceRenderTask.SetFrameBuffer(mMaskSourceFrameBuffer);
+ mMaskSourceRenderTask.SetClearEnabled(true);
+ mMaskSourceRenderTask.SetClearColor(Color::TRANSPARENT);
+}
+
+void MaskEffectImpl::SetShaderConstants(Toolkit::Control ownerControl)
+{
+ ownerControl.RegisterProperty(UNIFORM_MASK_MODE_NAME, static_cast<float>(mMaskMode));
+
+ Vector2 newMaskPosition;
+ newMaskPosition.x = -mMaskPosition.x;
+ newMaskPosition.y = -mMaskPosition.y;
+ ownerControl.RegisterProperty(UNIFORM_MASK_POSITION_NAME, newMaskPosition);
+
+ Vector2 newMaskScale;
+ newMaskScale.x = 1.0f / std::max(Math::MACHINE_EPSILON_100, mMaskScale.x);
+ newMaskScale.y = 1.0f / std::max(Math::MACHINE_EPSILON_100, mMaskScale.y);
+
+ ownerControl.RegisterProperty(UNIFORM_MASK_SCALE_NAME, newMaskScale);
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_INTERNAL_MASK_EFFECT_H
+#define DALI_TOOLKIT_INTERNAL_MASK_EFFECT_H
+
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/scene-holder.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/public-api/rendering/frame-buffer.h>
+#include <dali-toolkit/public-api/controls/render-effects/mask-effect.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/render-effects/render-effect-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class MaskEffectImpl;
+using MaskEffectImplPtr = IntrusivePtr<MaskEffectImpl>;
+
+class MaskEffectImpl : public RenderEffectImpl
+{
+public:
+ /**
+ * @brief Creates an initialized MaskEffect with control, using default settings. The default settings are:
+ *
+ * maskMode = MaskEffect::MaskMode::ALPHA
+ * maskPosition = Vector2(0.f, 0.f)
+ * maskScale = Vector2(1.f, 1.f)
+ *
+ * @param[in] maskControl The source Control to affect mask.
+ * @return A handle to a newly allocated Dali resource
+ */
+ static MaskEffectImplPtr New(Toolkit::Control maskControl);
+
+ /**
+ * @brief Creates an initialized MaskEffect.
+ * @param[in] maskControl The source Control to affect mask.
+ * @param[in] maskMode Defines pixel data type (alpha, luminance) used as the mask source.
+ * @param[in] maskPosition The Position of mask source.
+ * @param[in] maskScale The Scale of mask source.
+ * @return A handle to a newly allocated Dali resource
+ */
+ static MaskEffectImplPtr New(Toolkit::Control maskControl, MaskEffect::MaskMode maskMode, Vector2 maskPosition, Vector2 maskScale);
+
+ /**
+ * @copydoc Toolkit::Internal::RenderEffectImpl::GetOffScreenRenderableType
+ */
+ OffScreenRenderable::Type GetOffScreenRenderableType() override;
+
+ /**
+ * @copydoc Toolkit::Internal::RenderEffectImpl::GetOffScreenRenderTasks
+ */
+ void GetOffScreenRenderTasks(std::vector<Dali::RenderTask>& tasks, bool isForward) override;
+
+protected:
+ /**
+ * @brief Creates an uninitialized mask effect implementation
+ * @param[in] maskControl
+ */
+ MaskEffectImpl(Toolkit::Control maskControl);
+
+ /**
+ * @brief Creates an uninitialized mask effect implementation
+ * @param[in] maskControl
+ * @param[in] maskMode
+ * @param[in] maskPosition
+ * @param[in] maskScale
+ */
+ MaskEffectImpl(Toolkit::Control maskControl, MaskEffect::MaskMode maskMode, Vector2 maskPosition, Vector2 maskScale);
+
+ /**
+ * @brief Destructor
+ */
+ virtual ~MaskEffectImpl();
+
+ /**
+ * @brief Initializes mask effect
+ */
+ void OnInitialize() override;
+
+ /**
+ * @brief Activates mask effect
+ * @note If the mask source actor is an ancestor of the target actor,
+ * the target will not be rendered due to scene hierarchy.
+ */
+ void OnActivate() override;
+
+ /**
+ * @brief Dectivates mask effect
+ */
+ void OnDeactivate() override;
+
+ /**
+ * @brief Redraw effect without deactivation
+ */
+ void OnRefresh() override;
+
+private:
+ // inner functions
+ /**
+ * @brief Sets frame buffers to draw masked output.
+ * @param[in] size The size of target.
+ */
+ void CreateFrameBuffers(const ImageDimensions size);
+
+ /**
+ * @brief Sets mask render tasks.
+ * @param[in] sceneHolder SceneHolder of owner control
+ * @param[in] ownerControl Input owner control
+ */
+ void CreateRenderTasks(Toolkit::Control ownerControl);
+
+ /**
+ * @brief Sets shader constants, mask mode, position, and scale.
+ * @param[in] ownerControl Input owner control
+ */
+ void SetShaderConstants(Toolkit::Control ownerControl);
+
+private:
+
+ MaskEffectImpl(const MaskEffectImpl&) = delete;
+ MaskEffectImpl(MaskEffectImpl&&) = delete;
+ MaskEffectImpl& operator=(MaskEffectImpl&&) = delete; // no move()
+ MaskEffectImpl& operator=(const MaskEffectImpl&) = delete; // no copy()
+
+private:
+ // Camera actors
+ CameraActor mCamera;
+
+ // Resource
+ RenderTask mMaskTargetRenderTask;
+ FrameBuffer mMaskTargetFrameBuffer;
+
+ WeakHandle<Toolkit::Control> mMaskControl;
+
+ RenderTask mMaskSourceRenderTask;
+ FrameBuffer mMaskSourceFrameBuffer;
+
+ // Variables
+ MaskEffect::MaskMode mMaskMode;
+ Vector2 mMaskPosition;
+ Vector2 mMaskScale;
+};
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_BACKGROUND_MASK_EFFECT_H
${toolkit_src_dir}/controls/alignment/alignment-impl.cpp
${toolkit_src_dir}/controls/render-effects/render-effect-impl.cpp
${toolkit_src_dir}/controls/render-effects/blur-effect-impl.cpp
+ ${toolkit_src_dir}/controls/render-effects/mask-effect-impl.cpp
${toolkit_src_dir}/controls/render-effects/offscreen-rendering-impl.cpp
${toolkit_src_dir}/controls/bloom-view/bloom-view-impl.cpp
${toolkit_src_dir}/controls/bubble-effect/bubble-emitter-impl.cpp
--- /dev/null
+//@name mask-effect.frag
+
+//@version 100
+
+precision highp float;
+
+INPUT highp vec2 vTexCoord;
+
+UNIFORM sampler2D uMaskTexture;
+UNIFORM sampler2D uTargetTexture;
+
+UNIFORM_BLOCK FragBlock
+{
+ UNIFORM lowp vec4 uColor;
+ UNIFORM highp float uMaskMode;
+ UNIFORM highp vec2 uMaskPosition;
+ UNIFORM highp vec2 uMaskScale;
+};
+
+void main()
+{
+ highp vec2 transformedUV = vTexCoord * uMaskScale + uMaskPosition;
+
+ highp vec4 baseColor = TEXTURE(uTargetTexture, vTexCoord);
+ highp vec4 maskColor = TEXTURE(uMaskTexture, transformedUV);
+ highp float maskAlpha = 0.0f;
+
+ highp float alphaMask = maskColor.a;
+ highp float luminanceMask = dot(maskColor.rgb, vec3(0.299, 0.587, 0.114));
+
+ highp float uInBounds = step(0.0, transformedUV.x) * step(transformedUV.x, 1.0) * step(0.0, transformedUV.y) * step(transformedUV.y, 1.0);
+
+ maskAlpha = mix(alphaMask, luminanceMask, clamp(uMaskMode, 0.0f, 1.0f));
+ maskAlpha *= uInBounds;
+
+ gl_FragColor = baseColor * uColor * maskAlpha;
+}
--- /dev/null
+
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/public-api/controls/render-effects/mask-effect.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/render-effects/mask-effect-impl.h>
+namespace Dali
+{
+namespace Toolkit
+{
+MaskEffect::MaskEffect() = default;
+MaskEffect::MaskEffect(const MaskEffect& handle)
+: RenderEffect(handle)
+{
+}
+MaskEffect::MaskEffect(Internal::MaskEffectImpl* maskEffectImpl)
+: RenderEffect(maskEffectImpl)
+{
+}
+MaskEffect::~MaskEffect() = default;
+MaskEffect MaskEffect::New(Toolkit::Control maskControl)
+{
+ Internal::MaskEffectImplPtr internal = Internal::MaskEffectImpl::New(maskControl);
+ return MaskEffect(internal.Get());
+}
+MaskEffect MaskEffect::New(Toolkit::Control maskControl, MaskMode maskMode, Vector2 maskPosition, Vector2 maskScale)
+{
+ Internal::MaskEffectImplPtr internal = Internal::MaskEffectImpl::New(maskControl, maskMode, maskPosition, maskScale);
+ return MaskEffect(internal.Get());
+}
+} // namespace Toolkit
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_MASK_EFFECT_H
+#define DALI_TOOLKIT_MASK_EFFECT_H
+
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/render-effects/render-effect.h>
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal DALI_INTERNAL
+{
+class MaskEffectImpl;
+} // namespace Internal DALI_INTERNAL
+
+/**
+ * @brief MaskEffect is a visual effect that masks owner control.
+ * This class is a concrete class from RenderEffect interface.
+ * Add this effect to a control, clear manually to deactivate.
+ *
+ * Toolkit::Control control = Toolkit::Control::New();
+ * parent.Add(control);
+ * control.SetRenderEffect(MaskEffect::New(maskControl)); // Activate
+ * ...
+ * control.ClearRenderEffect(); // Deactivate
+ *
+ * @SINCE_2_4.15
+ */
+class DALI_TOOLKIT_API MaskEffect : public RenderEffect
+{
+public:
+
+ /**
+ * @brief Enumeration for selecting how the mask source interprets pixel data.
+ * @SINCE_2_4.15
+ */
+ enum MaskMode
+ {
+ ALPHA, ///< Uses the alpha channel of the mask texture. (Default) @SINCE_2_4.15
+ LUMINANCE, ///< Converts RGB to grayscale and uses the luminance as mask value. @SINCE_2_4.15
+ };
+
+ /**
+ * @brief Creates an initialized MaskEffect with control, using default settings. The default settings are:
+ *
+ * maskMode = MaskMode::ALPHA
+ * maskPosition = Vector2(0.f, 0.f)
+ * maskScale = Vector2(1.f, 1.f)
+ *
+ * @param[in] maskControl The source Control to affect mask.
+ *
+ * @SINCE_2_4.15
+ * @return A handle to a newly allocated Dali resource
+ */
+ static MaskEffect New(Toolkit::Control maskControl);
+
+ /**
+ * @brief Creates an initialized MaskEffect.
+ *
+ * @param[in] maskControl The source Control to affect mask.
+ * @param[in] maskMode Defines pixel data type (alpha, luminance) used as the mask source.
+ * @param[in] maskPosition The Position of mask source.
+ * @param[in] maskScale The Scale of mask source.
+ *
+ * @SINCE_2_4.15
+ * @return A handle to a newly allocated Dali resource
+ */
+ static MaskEffect New(Toolkit::Control maskControl, MaskMode maskMode, Vector2 maskPosition, Vector2 maskScale);
+
+ /**
+ * @brief Creates an uninitialized mask effect.
+ * @SINCE_2_4.15
+ */
+ MaskEffect();
+
+ /**
+ * @brief Copy constructor.
+ * @SINCE_2_4.15
+ */
+ MaskEffect(const MaskEffect& handle);
+
+ /**
+ * @brief Destructor
+ * @SINCE_2_4.15
+ */
+ ~MaskEffect();
+
+public: // Not intended for use by Application developers
+ ///@cond internal
+ /**
+ * @brief Creates a handle using the Toolkit::Internal implementation.
+ * @SINCE_2_4.15
+ * @param[in] maskEffectImpl The mask effect internal implementation.
+ */
+ explicit DALI_INTERNAL MaskEffect(Internal::MaskEffectImpl* maskEffectImpl);
+ ///@endcond
+};
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_MASK_EFFECT_H
${public_api_src_dir}/controls/progress-bar/progress-bar.cpp
${public_api_src_dir}/controls/render-effects/render-effect.cpp
${public_api_src_dir}/controls/render-effects/background-blur-effect.cpp
+ ${public_api_src_dir}/controls/render-effects/mask-effect.cpp
${public_api_src_dir}/controls/scrollable/item-view/default-item-layout.cpp
${public_api_src_dir}/controls/scrollable/item-view/item-layout.cpp
${public_api_src_dir}/controls/scrollable/item-view/item-view.cpp
SET( public_api_render_effects_header_files
${public_api_src_dir}/controls/render-effects/render-effect.h
${public_api_src_dir}/controls/render-effects/background-blur-effect.h
+ ${public_api_src_dir}/controls/render-effects/mask-effect.h
)
SET( public_api_scrollable_header_files