From: jmm Date: Mon, 6 Jan 2025 06:50:43 +0000 (+0900) Subject: Generalize RenderEffectImpl to OffScreenRendering X-Git-Tag: accepted/tizen/unified/20250115.005102~2^2~4^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bc53360695da2b00399945ba3ed50d67cffe4e6c;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git Generalize RenderEffectImpl to OffScreenRendering Change-Id: I3e4213b825edd9382d91e45293974f8def980385 Signed-off-by: jmm --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp index bfa78dfb31..a6b9c531b4 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp @@ -140,7 +140,6 @@ int UtcDaliInternalRenderEffectNewP(void) // Check that effect is not activate yet. Toolkit::Internal::TestRenderEffectImpl& impl = Toolkit::Internal::GetImplementation(testEffect); - DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION); DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION); DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); @@ -150,96 +149,84 @@ int UtcDaliInternalRenderEffectNewP(void) int UtcDaliInternalRenderEffectGetOwnerControl01(void) { tet_infoline("UtcDaliInternalRenderEffecGetOwnerControl01"); + ToolkitTestApplication application; Toolkit::TestRenderEffect testEffect = Toolkit::TestRenderEffect::New(); DALI_TEST_CHECK(testEffect); // Check that effect prototype is not activated. Toolkit::Internal::TestRenderEffectImpl& prototype = Toolkit::Internal::GetImplementation(testEffect); - DALI_TEST_EQUALS(prototype.IsActivated(), false, TEST_LOCATION); DALI_TEST_EQUALS(prototype.mOnActivated, false, TEST_LOCATION); DALI_TEST_EQUALS(prototype.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); - { - ToolkitTestApplication application; - - Integration::Scene scene = application.GetScene(); + Integration::Scene scene = application.GetScene(); - Control control = Control::New(); - control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - control.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f)); - scene.Add(control); + Control control = Control::New(); + control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f)); + scene.Add(control); - tet_printf("Test effect set, and activate due to control scene on.\n"); - control.SetRenderEffect(testEffect); + tet_printf("Test effect set, and activate due to control scene on.\n"); + control.SetRenderEffect(testEffect); - Toolkit::Internal::TestRenderEffectImplPtr impl = - dynamic_cast(control.GetRenderEffect().GetObjectPtr()); + Toolkit::Internal::TestRenderEffectImplPtr impl = + dynamic_cast(control.GetRenderEffect().GetObjectPtr()); - { // Check that effect prototype is not activated, - DALI_TEST_EQUALS(impl == &prototype, false, TEST_LOCATION); + { // Check that effect prototype is not activated, + DALI_TEST_EQUALS(impl == &prototype, false, TEST_LOCATION); - DALI_TEST_EQUALS(prototype.IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(prototype.mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(prototype.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); + DALI_TEST_EQUALS(prototype.mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(prototype.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); - // but the effect is set and activated. - DALI_TEST_EQUALS(impl->IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl->mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl->GetOwnerControl(), control, TEST_LOCATION); - } + // but the effect is set and activated. + DALI_TEST_EQUALS(impl->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl->GetOwnerControl(), control, TEST_LOCATION); + } - control.Unparent(); + control.Unparent(); - { - DALI_TEST_EQUALS(impl->IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->GetOwnerControl(), control, TEST_LOCATION); - } + { + DALI_TEST_EQUALS(impl->mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl->GetOwnerControl(), control, TEST_LOCATION); + } - scene.Add(control); + scene.Add(control); - { - DALI_TEST_EQUALS(impl->IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl->mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl->GetOwnerControl(), control, TEST_LOCATION); - } + { + DALI_TEST_EQUALS(impl->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl->GetOwnerControl(), control, TEST_LOCATION); + } - // Control released. - control.Unparent(); - control.Reset(); + // Control released. + control.Unparent(); + control.Reset(); - tet_printf("Test effect owner control is empty after control destructed.\n"); - DALI_TEST_CHECK(testEffect); + tet_printf("Test effect owner control is empty after control destructed.\n"); + DALI_TEST_CHECK(testEffect); - { - DALI_TEST_EQUALS(impl->IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); - } + { + DALI_TEST_EQUALS(impl->mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); + } - control = Control::New(); - control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - control.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f)); - scene.Add(control); + control = Control::New(); + control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + control.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f)); + scene.Add(control); - tet_printf("Test effect set again.\n"); - control.SetRenderEffect(testEffect); + tet_printf("Test effect set again.\n"); + control.SetRenderEffect(testEffect); - Toolkit::Internal::TestRenderEffectImplPtr impl2 = - dynamic_cast(control.GetRenderEffect().GetObjectPtr()); - { - DALI_TEST_EQUALS(impl == impl2, false, TEST_LOCATION); + Toolkit::Internal::TestRenderEffectImplPtr impl2 = + dynamic_cast(control.GetRenderEffect().GetObjectPtr()); + { + DALI_TEST_EQUALS(impl == impl2, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); // may be false? + DALI_TEST_EQUALS(impl->mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); // may be false? - DALI_TEST_EQUALS(impl2->IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl2->mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl2->GetOwnerControl(), control, TEST_LOCATION); - } - // Terminate application. + DALI_TEST_EQUALS(impl2->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl2->GetOwnerControl(), control, TEST_LOCATION); } END_TEST; @@ -267,68 +254,59 @@ int UtcDaliInternalRenderEffectGetOwnerControl02(void) // Check that effect is not activate yet. Toolkit::Internal::TestRenderEffectImpl& prototype = Toolkit::Internal::GetImplementation(testEffect); - DALI_TEST_EQUALS(prototype.IsActivated(), false, TEST_LOCATION); DALI_TEST_EQUALS(prototype.mOnActivated, false, TEST_LOCATION); DALI_TEST_EQUALS(prototype.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); tet_printf("Test effect set, and activate due to control scene on.\n"); control1.SetRenderEffect(testEffect); - Toolkit::Internal::TestRenderEffectImpl& impl1 = - *(dynamic_cast(control1.GetRenderEffect().GetObjectPtr())); + Toolkit::Internal::TestRenderEffectImplPtr impl1 = + dynamic_cast(control1.GetRenderEffect().GetObjectPtr()); - DALI_TEST_EQUALS(&prototype == &impl1, false, TEST_LOCATION); - DALI_TEST_EQUALS(prototype.IsActivated(), false, TEST_LOCATION); + DALI_TEST_EQUALS(&prototype == impl1, false, TEST_LOCATION); DALI_TEST_EQUALS(prototype.mOnActivated, false, TEST_LOCATION); DALI_TEST_EQUALS(prototype.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); - DALI_TEST_EQUALS(impl1.IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.GetOwnerControl(), control1, TEST_LOCATION); + DALI_TEST_EQUALS(impl1->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl1->GetOwnerControl(), control1, TEST_LOCATION); tet_printf("Test effect set to another control\n"); control2.SetRenderEffect(testEffect); - Toolkit::Internal::TestRenderEffectImpl& impl2 = - *(dynamic_cast(control2.GetRenderEffect().GetObjectPtr())); - DALI_TEST_EQUALS(&impl1 == &impl2, false, TEST_LOCATION); + Toolkit::Internal::TestRenderEffectImplPtr impl2 = + dynamic_cast(control2.GetRenderEffect().GetObjectPtr()); + DALI_TEST_EQUALS(impl1 == impl2, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.GetOwnerControl(), control2, TEST_LOCATION); + DALI_TEST_EQUALS(impl2->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl2->GetOwnerControl(), control2, TEST_LOCATION); tet_printf("Test control1 call ClearRenderEffect don't have any effort to control2's effect\n"); control1.ClearRenderEffect(); - DALI_TEST_EQUALS(impl1.IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); + DALI_TEST_EQUALS(impl1->mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl1->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); - DALI_TEST_EQUALS(impl2.IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.GetOwnerControl(), control2, TEST_LOCATION); + DALI_TEST_EQUALS(impl2->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl2->GetOwnerControl(), control2, TEST_LOCATION); tet_printf("Test control2 call ClearRenderEffect\n"); control2.ClearRenderEffect(); - DALI_TEST_EQUALS(impl2.IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl2.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); + DALI_TEST_EQUALS(impl2->mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl2->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); tet_printf("Reset control1 effect\n"); control1.SetRenderEffect(testEffect); - Toolkit::Internal::TestRenderEffectImpl& impl3 = - *(dynamic_cast(control1.GetRenderEffect().GetObjectPtr())); + Toolkit::Internal::TestRenderEffectImplPtr impl3 = + dynamic_cast(control1.GetRenderEffect().GetObjectPtr()); - DALI_TEST_EQUALS(&impl1 == &impl3, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.IsActivated(), false, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.mOnActivated, false, TEST_LOCATION); - DALI_TEST_EQUALS(impl1.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); + DALI_TEST_EQUALS(impl1 == impl3, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl1->mOnActivated, false, TEST_LOCATION); + DALI_TEST_EQUALS(impl1->GetOwnerControl(), Toolkit::Control(), TEST_LOCATION); - DALI_TEST_EQUALS(impl3.IsActivated(), true, TEST_LOCATION); - DALI_TEST_EQUALS(impl3.mOnActivated, true, TEST_LOCATION); - DALI_TEST_EQUALS(impl3.GetOwnerControl(), control1, TEST_LOCATION); + DALI_TEST_EQUALS(impl3->mOnActivated, true, TEST_LOCATION); + DALI_TEST_EQUALS(impl3->GetOwnerControl(), control1, TEST_LOCATION); tet_printf("Test control1 call SetRenderEffect with empty handle\n"); control1.SetRenderEffect(Toolkit::RenderEffect()); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 52c7e0fb26..5f4293346b 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Samsung Electronics Co., Ltd. + * 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. @@ -1500,20 +1500,27 @@ int UtcDaliControlOffScreenRendering(void) Control control = Control::New(); control.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + application.GetScene().Add(control); + control.SetBackgroundColor(Color::RED); DALI_TEST_EQUALS(control.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING).Get(), (int)DevelControl::OffScreenRenderingType::NONE, TEST_LOCATION); + tet_infoline("Control is ready"); control.SetProperty(DevelControl::Property::OFFSCREEN_RENDERING, DevelControl::OffScreenRenderingType::REFRESH_ALWAYS); DALI_TEST_EQUALS(control.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING).Get(), (int)DevelControl::OffScreenRenderingType::REFRESH_ALWAYS, TEST_LOCATION); + tet_infoline("Set offscreen rendering : refresh always"); + control.SetProperty(DevelControl::Property::OFFSCREEN_RENDERING, DevelControl::OffScreenRenderingType::REFRESH_ONCE); DALI_TEST_EQUALS(control.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING).Get(), (int)DevelControl::OffScreenRenderingType::REFRESH_ONCE, TEST_LOCATION); + tet_infoline("Set offscreen rendering : refresh once"); application.SendNotification(); application.Render(); control.SetProperty(DevelControl::Property::OFFSCREEN_RENDERING, DevelControl::OffScreenRenderingType::NONE); DALI_TEST_EQUALS(control.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING).Get(), (int)DevelControl::OffScreenRenderingType::NONE, TEST_LOCATION); + tet_infoline("Turn off offscreen rendering"); control.Unparent(); // Disconnect fron scene. application.GetScene().Add(control); diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index 326f90ea8a..89731c07b2 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Samsung Electronics Co., Ltd. + * 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. @@ -403,7 +403,7 @@ Control::Impl::Impl(Control& controlImpl) mPanGestureDetector(), mTapGestureDetector(), mLongPressGestureDetector(), - mOffScreenRenderingContext(nullptr), + mOffScreenRenderingImpl(nullptr), mOffScreenRenderingType(DevelControl::OffScreenRenderingType::NONE), mTooltip(NULL), mInputMethodContext(), @@ -537,9 +537,9 @@ void Control::Impl::OnSceneConnection() } } - if(mOffScreenRenderingContext) // mOffScreenRenderingType != NONE + if(mOffScreenRenderingImpl) // mOffScreenRenderingType != NONE { - mOffScreenRenderingContext->Enable(Toolkit::Control(mControlImpl.GetOwner()), mOffScreenRenderingType); + mOffScreenRenderingImpl->SetOwnerControl(Toolkit::Control(mControlImpl.GetOwner())); } } @@ -548,9 +548,9 @@ void Control::Impl::OnSceneDisconnection() Actor self = mControlImpl.Self(); mVisualData->ClearScene(self); - if(mOffScreenRenderingContext) + if(mOffScreenRenderingImpl) { - mOffScreenRenderingContext->Disable(Toolkit::Control(mControlImpl.GetOwner())); + mOffScreenRenderingImpl->ClearOwnerControl(); } } @@ -1557,31 +1557,22 @@ void Control::Impl::SetOffScreenRendering(int32_t offScreenRenderingType) } } - mOffScreenRenderingType = static_cast(offScreenRenderingType); - Dali::Toolkit::Control handle(mControlImpl.GetOwner()); - - // Disable - if(mOffScreenRenderingType == DevelControl::OffScreenRenderingType::NONE) - { - if(mOffScreenRenderingContext) - { - mOffScreenRenderingContext->Disable(handle); - mOffScreenRenderingContext.reset(); - } - } - // Enable - else + DevelControl::OffScreenRenderingType newType = static_cast(offScreenRenderingType); + if(newType != mOffScreenRenderingType) { - if(mOffScreenRenderingContext) - { - mOffScreenRenderingContext->Disable(handle); - } - else + // update type + mOffScreenRenderingType = newType; + + // update effect + if(mOffScreenRenderingImpl) { - Dali::Toolkit::Control handle(mControlImpl.GetOwner()); - mOffScreenRenderingContext = std::make_unique(); + mOffScreenRenderingImpl->ClearOwnerControl(); + mOffScreenRenderingImpl.reset(); } - mOffScreenRenderingContext->Enable(handle, mOffScreenRenderingType); + mOffScreenRenderingImpl = std::make_unique(mOffScreenRenderingType); + + Dali::Toolkit::Control handle(mControlImpl.GetOwner()); + mOffScreenRenderingImpl->SetOwnerControl(handle); } } diff --git a/dali-toolkit/internal/controls/control/control-data-impl.h b/dali-toolkit/internal/controls/control/control-data-impl.h index 8248a5cd3d..4232a82727 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_CONTROL_DATA_IMPL_H /* - * Copyright (c) 2024 Samsung Electronics Co., Ltd. + * 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. @@ -27,7 +27,7 @@ // INTERNAL INCLUDES #include -#include +#include #include #include #include @@ -496,8 +496,8 @@ public: LongPressGestureDetector mLongPressGestureDetector; // Off screen rendering context - std::unique_ptr mOffScreenRenderingContext; - DevelControl::OffScreenRenderingType mOffScreenRenderingType; + std::unique_ptr mOffScreenRenderingImpl; + DevelControl::OffScreenRenderingType mOffScreenRenderingType; // Tooltip TooltipPtr mTooltip; diff --git a/dali-toolkit/internal/controls/render-effects/blur-effect-impl.cpp b/dali-toolkit/internal/controls/render-effects/blur-effect-impl.cpp index b7ea03f201..c39aec040f 100644 --- a/dali-toolkit/internal/controls/render-effects/blur-effect-impl.cpp +++ b/dali-toolkit/internal/controls/render-effects/blur-effect-impl.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include #include @@ -30,7 +29,6 @@ // INTERNAL INCLUDES #include -#include #include #include #include @@ -186,13 +184,6 @@ void BlurEffectImpl::OnInitialize() // 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); @@ -265,35 +256,21 @@ void BlurEffectImpl::OnActivate() DALI_ASSERT_ALWAYS(ownerControl && "Set the owner of RenderEffect before you activate."); // Get size - Vector2 size = GetTargetSizeForValidTexture(); + Vector2 size = GetTargetSize(); DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[BlurEffect:%p] OnActivated! [ID:%d][size:%fx%f]\n", this, ownerControl ? ownerControl.GetProperty(Actor::Property::ID) : -1, size.x, size.y); - if(size == Vector2::ZERO) - { - return; - } uint32_t downsampledWidth = std::max(static_cast(size.width * mDownscaleFactor), 1u); uint32_t downsampledHeight = std::max(static_cast(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 weak 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; - } - mPlacementSceneHolder = sceneHolder; - // Set blur CreateFrameBuffers(size, ImageDimensions(downsampledWidth, downsampledHeight)); - CreateRenderTasks(sceneHolder, ownerControl); + CreateRenderTasks(GetSceneHolder(), ownerControl); SetShaderConstants(downsampledWidth, downsampledHeight); // Inject blurred output to control @@ -337,14 +314,13 @@ void BlurEffectImpl::OnDeactivate() mTemporaryFrameBuffer.Reset(); mSourceFrameBuffer.Reset(); - auto sceneHolder = mPlacementSceneHolder.GetHandle(); + auto sceneHolder = GetSceneHolder(); if(DALI_LIKELY(sceneHolder)) { RenderTaskList taskList = sceneHolder.GetRenderTaskList(); taskList.RemoveTask(mHorizontalBlurTask); taskList.RemoveTask(mVerticalBlurTask); taskList.RemoveTask(mSourceRenderTask); - mPlacementSceneHolder.Reset(); } mHorizontalBlurTask.Reset(); @@ -379,7 +355,7 @@ void BlurEffectImpl::CreateRenderTasks(Integration::SceneHolder sceneHolder, con // draw input texture mSourceRenderTask = taskList.CreateTask(); - mSourceRenderTask.SetCameraActor(mRenderFullSizeCamera); + mSourceRenderTask.SetCameraActor(GetCameraActor()); mSourceRenderTask.SetFrameBuffer(mInputBackgroundFrameBuffer); mSourceRenderTask.SetInputEnabled(false); @@ -448,29 +424,6 @@ void BlurEffectImpl::ApplyRenderTaskSourceActor(RenderTask sourceRenderTask, con sourceRenderTask.RenderUntil(stopperActor); } -Vector2 BlurEffectImpl::GetTargetSizeForValidTexture() const -{ - Vector2 size = GetTargetSize(); - if(size == Vector2::ZERO) - { - size = GetOwnerControl().GetNaturalSize(); - } - - if(size == Vector2::ZERO || size.x < 0.0f || size.y < 0.0f) - { - return Vector2::ZERO; - } - - const uint32_t maxTextureSize = Dali::GetMaxTextureSize(); - if(uint32_t(size.x) > maxTextureSize || uint32_t(size.y) > maxTextureSize) - { - uint32_t denominator = std::max(size.x, size.y); - size.x = (size.x * maxTextureSize / denominator); - size.y = (size.y * maxTextureSize / denominator); - } - return size; -} - void BlurEffectImpl::SetShaderConstants(uint32_t downsampledWidth, uint32_t downsampledHeight) { const uint32_t sampleCount = mPixelRadius >> 1; // compression @@ -514,12 +467,6 @@ void BlurEffectImpl::SetShaderConstants(uint32_t downsampledWidth, uint32_t down mVerticalBlurActor.RegisterProperty(GetSampleOffsetsPropertyName(i), Vector2(0.0f, uvOffsets[i] / downsampledHeight)); mVerticalBlurActor.RegisterProperty(GetSampleWeightsPropertyName(i), weights[i]); } - - // Apply background properties - if(mIsBackground) - { - SynchronizeBackgroundCornerRadius(); - } } std::string BlurEffectImpl::GetSampleOffsetsPropertyName(unsigned int index) const @@ -536,29 +483,6 @@ std::string BlurEffectImpl::GetSampleWeightsPropertyName(unsigned int index) con return oss.str(); } -void BlurEffectImpl::SynchronizeBackgroundCornerRadius() -{ - DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Verbose, "[BlurEffect:%p] Synchronize background corner radius\n", this); - - DALI_ASSERT_ALWAYS(GetOwnerControl() && "You should first SetRenderEffect(), then set its background property map"); - - Property::Map map = GetOwnerControl().GetProperty(Toolkit::Control::Property::BACKGROUND); - - Vector4 radius = Vector4::ZERO; - map[Toolkit::DevelVisual::Property::CORNER_RADIUS].Get(radius); - - Vector4 squareness = Vector4::ZERO; - map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS].Get(squareness); - - Visual::Transform::Policy::Type policy{Visual::Transform::Policy::ABSOLUTE}; - map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY].Get(policy); - - Renderer renderer = GetTargetRenderer(); - renderer.RegisterProperty("uCornerRadius", radius); - renderer.RegisterProperty("uCornerSquareness", squareness); - renderer.RegisterProperty("uCornerRadiusPolicy", static_cast(policy)); -} - } // namespace Internal } // namespace Toolkit } // namespace Dali diff --git a/dali-toolkit/internal/controls/render-effects/blur-effect-impl.h b/dali-toolkit/internal/controls/render-effects/blur-effect-impl.h index e24f352176..c60ce241ac 100644 --- a/dali-toolkit/internal/controls/render-effects/blur-effect-impl.h +++ b/dali-toolkit/internal/controls/render-effects/blur-effect-impl.h @@ -142,14 +142,6 @@ private: */ void ApplyRenderTaskSourceActor(RenderTask sourceRenderTask, 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). - * @return A valid version of mTargetSize, Vector2::ZERO otherwise. - * @note The return value is a copy, not mTargetSize itself. - */ - Vector2 GetTargetSizeForValidTexture() const; - /** * @brief Sets shader constants, gaussian kernel weights and pixel offsets. * @param[in] downsampledWidth Downsized width of input texture. @@ -171,11 +163,6 @@ private: */ std::string GetSampleWeightsPropertyName(unsigned int index) const; - /** - * @brief Synchronize mOwnerControl's background corner radius to the blurred output. - */ - void SynchronizeBackgroundCornerRadius(); - BlurEffectImpl(const BlurEffectImpl&) = delete; BlurEffectImpl(BlurEffectImpl&&) = delete; BlurEffectImpl& operator=(BlurEffectImpl&&) = delete; // no move() @@ -183,14 +170,11 @@ private: private: // Camera actors - CameraActor mRenderFullSizeCamera; CameraActor mRenderDownsampledCamera; // Resource FrameBuffer mInputBackgroundFrameBuffer; // Input. Background. What to blur. - WeakHandle mPlacementSceneHolder; - Actor mInternalRoot; Actor mHorizontalBlurActor; RenderTask mHorizontalBlurTask; diff --git a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-context.cpp b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-context.cpp deleted file mode 100644 index a057addfc7..0000000000 --- a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-context.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2024 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 - -// INTERNAL INCLUDES -#include -#include - -// EXTERNAL INCLUDES -#include - -namespace Dali -{ -namespace Toolkit -{ -namespace Internal -{ -bool OffScreenRenderingContext::IsEnabled() -{ - return mCamera && mRenderer; -} - -void OffScreenRenderingContext::Enable(Toolkit::Control control, DevelControl::OffScreenRenderingType type) -{ - if(type == DevelControl::OffScreenRenderingType::NONE) - { - return; - } - - // Create resources - if(!IsEnabled()) - { - Integration::SceneHolder sceneHolder = Integration::SceneHolder::Get(control); - if(DALI_UNLIKELY(!sceneHolder)) - { - DALI_LOG_ERROR("Could not enable offscreen rendering. The control is not connected to a scene.\n"); - return; - } - mSceneHolder = sceneHolder; - - const Size size = control.GetProperty(Actor::Property::SIZE); - - mCamera = CameraActor::New(size); - mCamera.SetInvertYAxis(true); - mCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - mCamera.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); - mCamera.SetType(Camera::FREE_LOOK); - mCamera.SetPerspectiveProjection(size); - control.Add(mCamera); - - mFrameBuffer = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL); - Texture texture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height); - mFrameBuffer.AttachColorTexture(texture); - - RenderTaskList taskList = sceneHolder.GetRenderTaskList(); - mRenderTask = taskList.CreateTask(); - mRenderTask.SetSourceActor(control); - mRenderTask.SetCameraActor(mCamera); - mRenderTask.SetExclusive(true); - mRenderTask.SetInputEnabled(false); - mRenderTask.SetFrameBuffer(mFrameBuffer); - mRenderTask.SetClearEnabled(true); - mRenderTask.SetClearColor(sceneHolder.GetBackgroundColor()); - - mRenderer = CreateRenderer(SHADER_CONTROL_RENDERERS_VERT, SHADER_CONTROL_RENDERERS_FRAG); - SetRendererTexture(mRenderer, mFrameBuffer); - - control.GetImplementation().SetCacheRenderer(mRenderer); - control.GetImplementation().SetOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); - } - - // Set refresh rate - if(type == DevelControl::OffScreenRenderingType::REFRESH_ALWAYS) - { - mRenderTask.SetRefreshRate(RenderTask::REFRESH_ALWAYS); - } - else if(type == DevelControl::OffScreenRenderingType::REFRESH_ONCE) - { - mRenderTask.SetRefreshRate(RenderTask::REFRESH_ONCE); - } -} - -void OffScreenRenderingContext::Disable(Toolkit::Control control) -{ - if(IsEnabled()) - { - if(DALI_LIKELY(control)) - { - control.GetImplementation().RemoveCacheRenderer(); - - mCamera.Unparent(); - control.GetImplementation().SetOffScreenRenderableType(OffScreenRenderable::Type::NONE); - } - - auto sceneHolder = mSceneHolder.GetHandle(); - if(DALI_LIKELY(sceneHolder)) - { - RenderTaskList taskList = sceneHolder.GetRenderTaskList(); - taskList.RemoveTask(mRenderTask); - } - mSceneHolder.Reset(); - - mFrameBuffer.Reset(); - mRenderTask.Reset(); - mCamera.Reset(); - mRenderer.Reset(); - } -} - -} // namespace Internal -} // namespace Toolkit -} // namespace Dali diff --git a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-context.h b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-context.h deleted file mode 100644 index 6299d12fcb..0000000000 --- a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-context.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef DALI_TOOLKIT_INTERNAL_OFFSCREEN_RENDERING_CONTEXT -#define DALI_TOOLKIT_INTERNAL_OFFSCREEN_RENDERING_CONTEXT - -/* - * Copyright (c) 2024 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 -#include -#include -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ -namespace Toolkit -{ -namespace Internal -{ -class OffScreenRenderingContext -{ -public: - OffScreenRenderingContext() = default; - void Enable(Toolkit::Control control, DevelControl::OffScreenRenderingType type); - void Disable(Toolkit::Control control); - -private: - bool IsEnabled(); - -private: - RenderTask mRenderTask; - CameraActor mCamera; - FrameBuffer mFrameBuffer; - Renderer mRenderer; - - WeakHandle mSceneHolder; -}; -} // namespace Internal -} // namespace Toolkit -} // namespace Dali -#endif //DALI_TOOLKIT_INTERNAL_OFFSCREEN_RENDERING_CONTEXT diff --git a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp new file mode 100644 index 0000000000..58b12c07e3 --- /dev/null +++ b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp @@ -0,0 +1,124 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +OffScreenRenderingImpl::OffScreenRenderingImpl(DevelControl::OffScreenRenderingType type) +: mType(type) +{ + Initialize(); +} + +RenderEffectImplPtr OffScreenRenderingImpl::Clone() const +{ + DALI_LOG_ERROR("Cloning offscreen rendering is not allowed.\n"); + return RenderEffectImplPtr(); +} + +OffScreenRenderable::Type OffScreenRenderingImpl::GetOffScreenRenderableType() +{ + return OffScreenRenderable::Type::FORWARD; +} + +void OffScreenRenderingImpl::GetOffScreenRenderTasks(std::vector& tasks, bool isForward) +{ +} + +void OffScreenRenderingImpl::OnInitialize() +{ +} + +void OffScreenRenderingImpl::OnActivate() +{ + if(mType == DevelControl::OffScreenRenderingType::NONE) + { + return; + } + + // Create resources + Toolkit::Control control = GetOwnerControl(); + const Size size = GetTargetSize(); + + mFrameBuffer = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL); + Texture texture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height); + mFrameBuffer.AttachColorTexture(texture); + + Integration::SceneHolder sceneHolder = GetSceneHolder(); + RenderTaskList taskList = sceneHolder.GetRenderTaskList(); + mRenderTask = taskList.CreateTask(); + mRenderTask.SetSourceActor(control); + mRenderTask.SetCameraActor(GetCameraActor()); + mRenderTask.SetExclusive(true); + mRenderTask.SetInputEnabled(false); + mRenderTask.SetFrameBuffer(mFrameBuffer); + mRenderTask.SetClearEnabled(true); + mRenderTask.SetClearColor(sceneHolder.GetBackgroundColor()); + + Renderer renderer = GetTargetRenderer(); + SetRendererTexture(renderer, mFrameBuffer); + + control.GetImplementation().SetCacheRenderer(renderer); + control.GetImplementation().SetOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); + + // Set refresh rate + if(mType == DevelControl::OffScreenRenderingType::REFRESH_ALWAYS) + { + mRenderTask.SetRefreshRate(RenderTask::REFRESH_ALWAYS); + } + else if(mType == DevelControl::OffScreenRenderingType::REFRESH_ONCE) + { + mRenderTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + } +} + +void OffScreenRenderingImpl::OnDeactivate() +{ + Toolkit::Control control = GetOwnerControl(); + if(DALI_LIKELY(control)) + { + control.GetImplementation().RemoveCacheRenderer(); + control.GetImplementation().SetOffScreenRenderableType(OffScreenRenderable::Type::NONE); + } + + auto sceneHolder = GetSceneHolder(); + if(DALI_LIKELY(sceneHolder)) + { + RenderTaskList taskList = sceneHolder.GetRenderTaskList(); + taskList.RemoveTask(mRenderTask); + } + + mFrameBuffer.Reset(); + mRenderTask.Reset(); +} + +} // namespace Internal +} // namespace Toolkit +} // namespace Dali diff --git a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.h b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.h new file mode 100644 index 0000000000..16034d7611 --- /dev/null +++ b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.h @@ -0,0 +1,64 @@ +#ifndef DALI_TOOLKIT_INTERNAL_OFFSCREEN_RENDERING_IMPL +#define DALI_TOOLKIT_INTERNAL_OFFSCREEN_RENDERING_IMPL + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +class OffScreenRenderingImpl : public RenderEffectImpl +{ +public: + OffScreenRenderingImpl(DevelControl::OffScreenRenderingType type); + RenderEffectImplPtr Clone() const override; + OffScreenRenderable::Type GetOffScreenRenderableType() override; + void GetOffScreenRenderTasks(std::vector& tasks, bool isForward) override; + +protected: + void OnInitialize() override; + void OnActivate() override; + void OnDeactivate() override; + +private: + RenderTask mRenderTask; + FrameBuffer mFrameBuffer; + DevelControl::OffScreenRenderingType mType; +}; +} // namespace Internal +} // namespace Toolkit +} // namespace Dali +#endif //DALI_TOOLKIT_INTERNAL_OFFSCREEN_RENDERING_IMPL diff --git a/dali-toolkit/internal/controls/render-effects/render-effect-impl.cpp b/dali-toolkit/internal/controls/render-effects/render-effect-impl.cpp index 633ce3fba7..3533062e4b 100644 --- a/dali-toolkit/internal/controls/render-effects/render-effect-impl.cpp +++ b/dali-toolkit/internal/controls/render-effects/render-effect-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Samsung Electronics Co., Ltd. + * 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. @@ -19,10 +19,12 @@ #include // EXTERNAL INCLUDES +#include #include #include // INTERNAL INCLUDES +#include #include #include @@ -44,6 +46,7 @@ Debug::Filter* gRenderEffectLogFilter = Debug::Filter::New(Debug::NoLogging, fal RenderEffectImpl::RenderEffectImpl() : mRenderer(), + mCamera(), mOwnerControl(), mSizeNotification(), mTargetSize(Vector2::ZERO), @@ -58,6 +61,9 @@ RenderEffectImpl::~RenderEffectImpl() // Reset weak handle first. (Since it might not valid during destruction.) mOwnerControl.Reset(); + mPlacementSceneHolder.Reset(); + + mSizeNotification.Reset(); // Don't call Deactivate here, since we cannot call virtual function during destruction. // Deactivate already be called at Control's destructor, and InheritVisibilityChanged signal. @@ -77,17 +83,7 @@ void RenderEffectImpl::SetOwnerControl(Dali::Toolkit::Control control) if(ownerControl) { - mTargetSize = ownerControl.GetProperty(Actor::Property::SIZE); - if(!mRenderer) - { - mRenderer = CreateRenderer(SHADER_RENDER_EFFECT_VERT, SHADER_RENDER_EFFECT_FRAG); - mRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha - - Shader shader = mRenderer.GetShader(); - shader.RegisterProperty("uCornerRadius", Vector4::ZERO); - shader.RegisterProperty("uCornerSquareness", Vector4::ZERO); - shader.RegisterProperty("uCornerRadiusPolicy", static_cast(1.0f)); - } + UpdateTargetSize(); ownerControl.InheritedVisibilityChangedSignal().Connect(this, &RenderEffectImpl::OnControlInheritedVisibilityChanged); @@ -114,6 +110,7 @@ void RenderEffectImpl::ClearOwnerControl() auto previousOwnerControl = ownerControl; mOwnerControl.Reset(); + mPlacementSceneHolder.Reset(); // Make previous owner don't have render effect, after make we don't have owner control now. previousOwnerControl.ClearRenderEffect(); @@ -127,6 +124,12 @@ bool RenderEffectImpl::IsActivated() const void RenderEffectImpl::Initialize() { + mCamera = CameraActor::New(); + mCamera.SetInvertYAxis(true); + mCamera.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + mCamera.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + mCamera.SetType(Dali::Camera::FREE_LOOK); + OnInitialize(); } @@ -135,6 +138,11 @@ Toolkit::Control RenderEffectImpl::GetOwnerControl() const return mOwnerControl.GetHandle(); } +Integration::SceneHolder RenderEffectImpl::GetSceneHolder() const +{ + return mPlacementSceneHolder.GetHandle(); +} + Renderer RenderEffectImpl::GetTargetRenderer() const { return mRenderer; @@ -145,16 +153,51 @@ Vector2 RenderEffectImpl::GetTargetSize() const return mTargetSize; } +CameraActor RenderEffectImpl::GetCameraActor() const +{ + return mCamera; +} + void RenderEffectImpl::Activate() { if(!IsActivated() && IsActivateValid()) { + mIsActivated = true; + Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle(); DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] Activated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty(Actor::Property::ID) : -1); - mIsActivated = true; - // Activate logic for subclass. - OnActivate(); + // Keep sceneHolder as weak handle. + Integration::SceneHolder sceneHolder = Integration::SceneHolder::Get(ownerControl); + if(DALI_UNLIKELY(!sceneHolder)) + { + DALI_LOG_ERROR("RenderEffect Could not be activated due to ownerControl's SceneHolder is not exist\n"); + return; + } + mPlacementSceneHolder = sceneHolder; + + if(!mRenderer) + { + mRenderer = CreateRenderer(SHADER_RENDER_EFFECT_VERT, SHADER_RENDER_EFFECT_FRAG); + mRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true); // Always use pre-multiply alpha + + Shader shader = mRenderer.GetShader(); + shader.RegisterProperty("uCornerRadius", Vector4::ZERO); + shader.RegisterProperty("uCornerSquareness", Vector4::ZERO); + shader.RegisterProperty("uCornerRadiusPolicy", static_cast(1.0f)); + } + + Vector2 size = GetTargetSize(); + if(size != Vector2::ZERO) + { + mCamera.SetPerspectiveProjection(size); + ownerControl.Add(mCamera); + + // Activate logic for subclass. + OnActivate(); + + SynchronizeBackgroundCornerRadius(); + } } } @@ -162,12 +205,15 @@ void RenderEffectImpl::Deactivate() { if(IsActivated() || !IsActivateValid()) { + mIsActivated = false; + Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle(); DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] Deactivated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty(Actor::Property::ID) : -1); - mIsActivated = false; // Deactivate logic for subclass. OnDeactivate(); + + mCamera.Unparent(); } } @@ -209,6 +255,29 @@ bool RenderEffectImpl::IsActivateValid() const return ret; } +void RenderEffectImpl::UpdateTargetSize() +{ + Vector2 size = GetOwnerControl().GetProperty(Actor::Property::SIZE); + if(size == Vector2::ZERO) + { + size = GetOwnerControl().GetNaturalSize(); + } + + if(size == Vector2::ZERO || size.x < 0.0f || size.y < 0.0f) + { + mTargetSize = Vector2::ZERO; + } + + const uint32_t maxTextureSize = Dali::GetMaxTextureSize(); + if(uint32_t(size.x) > maxTextureSize || uint32_t(size.y) > maxTextureSize) + { + uint32_t denominator = std::max(size.x, size.y); + size.x = (size.x * maxTextureSize / denominator); + size.y = (size.y * maxTextureSize / denominator); + } + mTargetSize = size; +} + void RenderEffectImpl::OnSizeSet(PropertyNotification& source) { Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle(); @@ -217,7 +286,7 @@ void RenderEffectImpl::OnSizeSet(PropertyNotification& source) const auto targetSize = ownerControl.GetCurrentProperty(Actor::Property::SIZE); if(mTargetSize != targetSize && IsActivated()) { - mTargetSize = targetSize; + UpdateTargetSize(); Deactivate(); Activate(); } @@ -238,6 +307,29 @@ void RenderEffectImpl::OnControlInheritedVisibilityChanged(Actor actor, bool vis } } +void RenderEffectImpl::SynchronizeBackgroundCornerRadius() +{ + DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Verbose, "[BlurEffect:%p] Synchronize background corner radius\n", this); + + DALI_ASSERT_ALWAYS(GetOwnerControl() && "You should first SetRenderEffect(), then set its background property map"); + + Property::Map map = GetOwnerControl().GetProperty(Toolkit::Control::Property::BACKGROUND); + + Vector4 radius = Vector4::ZERO; + map[Toolkit::DevelVisual::Property::CORNER_RADIUS].Get(radius); + + Vector4 squareness = Vector4::ZERO; + map[Toolkit::DevelVisual::Property::CORNER_SQUARENESS].Get(squareness); + + Visual::Transform::Policy::Type policy{Visual::Transform::Policy::ABSOLUTE}; + map[Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY].Get(policy); + + Renderer renderer = GetTargetRenderer(); + renderer.RegisterProperty("uCornerRadius", radius); + renderer.RegisterProperty("uCornerSquareness", squareness); + renderer.RegisterProperty("uCornerRadiusPolicy", static_cast(policy)); +} + } // namespace Internal } // namespace Toolkit } // namespace Dali diff --git a/dali-toolkit/internal/controls/render-effects/render-effect-impl.h b/dali-toolkit/internal/controls/render-effects/render-effect-impl.h index 07e805544e..67f72070d2 100644 --- a/dali-toolkit/internal/controls/render-effects/render-effect-impl.h +++ b/dali-toolkit/internal/controls/render-effects/render-effect-impl.h @@ -19,6 +19,8 @@ */ // EXTERNAL INCLUDE +#include +#include #include #include #include @@ -54,12 +56,6 @@ public: */ void ClearOwnerControl(); - /** - * @brief Get whether this effect activated or not. - * @return True if effect is activated. False otherwise. - */ - bool IsActivated() const; - /** * @brief Clones current instance. * @return Clone implementation @@ -123,12 +119,24 @@ protected: */ Vector2 GetTargetSize() const; + /** + * @brief Get camera that captures full size texture of mOwnerControl + * @return mCamera + */ + CameraActor GetCameraActor() const; + /** * @brief Get Owner control. It could be return empty handle if owner control is not set, or destroyed. * @return mOwnerControl */ Toolkit::Control GetOwnerControl() const; + /** + * @brief Get scene holder of owner control. + * @return mPlacementSceneHolder + */ + Integration::SceneHolder GetSceneHolder() const; + /// For sub classes protected: /** @@ -164,7 +172,19 @@ private: */ bool IsActivateValid() const; + /** + * @brief Get whether this effect activated or not. + * @return True if effect is activated. False otherwise. + */ + bool IsActivated() const; + private: + /** + * @brief Calculates a valid target size for texture. + * Invalid cases include: zero vector, minus numbers or large numbers(larger than the maximum). + */ + void UpdateTargetSize(); + /** * @brief Callback when the size changes. */ @@ -177,10 +197,17 @@ private: */ void OnControlInheritedVisibilityChanged(Actor actor, bool visible); + /** + * @brief Synchronize mOwnerControl's background corner radius to the output. + */ + void SynchronizeBackgroundCornerRadius(); + private: Dali::Renderer mRenderer; // An additional renderer for mOwnerControl + CameraActor mCamera; // A camera that captures full size texture of mOwnerControl - Dali::WeakHandle mOwnerControl; ///< Weakhandle of owner control. + Dali::WeakHandle mOwnerControl; ///< Weakhandle of owner control. + WeakHandle mPlacementSceneHolder; ///< Weakhandle of scene PropertyNotification mSizeNotification; // Resize/Relayout signal. Vector2 mTargetSize; // The final size of mOwnerControl diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 12d902d031..6cc4e5f5c6 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -71,7 +71,7 @@ SET( toolkit_src_files ${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/offscreen-rendering-context.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 ${toolkit_src_dir}/controls/bubble-effect/bubble-renderer.cpp diff --git a/dali-toolkit/public-api/controls/render-effects/render-effect.h b/dali-toolkit/public-api/controls/render-effects/render-effect.h index cce2877451..8cf3cbc230 100644 --- a/dali-toolkit/public-api/controls/render-effects/render-effect.h +++ b/dali-toolkit/public-api/controls/render-effects/render-effect.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_RENDER_EFFECT_H /* - * Copyright (c) 2024 Samsung Electronics Co., Ltd. + * 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. @@ -21,7 +21,6 @@ // EXTERNAL INCLUDES #include #include -#include // std::shared_ptr // INTERNAL INCLUDES #include