From d222deb78b51f47181b52e02629f7030247c5471 Mon Sep 17 00:00:00 2001 From: jmm Date: Fri, 16 May 2025 13:24:03 +0900 Subject: [PATCH] Apply offscreen rendering to control's each visual Change-Id: Ib97cef454155a4ccfcdf169c411ae61691186b07 Signed-off-by: jmm --- .../src/dali-toolkit/utc-Dali-Control.cpp | 19 ++++ .../dali-toolkit/utc-Dali-RenderEffect.cpp | 4 - .../controls/control/control-data-impl.cpp | 29 +++++- .../controls/control/control-visual-data.cpp | 97 ++++++++++++++----- .../gaussian-blur-effect-impl.cpp | 21 +++- .../render-effects/mask-effect-impl.cpp | 5 +- .../offscreen-rendering-impl.cpp | 5 +- 7 files changed, 142 insertions(+), 38 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 181f32917c..9f5b4ee096 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -1538,6 +1538,10 @@ int UtcDaliControlOffScreenRendering(void) control.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + control.SetProperty(DevelControl::Property::BORDERLINE_WIDTH, 10.0f); + control.SetProperty(DevelControl::Property::BORDERLINE_COLOR, Color::RED); + control.SetProperty(DevelControl::Property::BORDERLINE_OFFSET, 10.0f); + application.GetScene().Add(control); control.SetBackgroundColor(Color::RED); @@ -1548,6 +1552,15 @@ int UtcDaliControlOffScreenRendering(void) DALI_TEST_EQUALS(control.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING).Get(), (int)DevelControl::OffScreenRenderingType::REFRESH_ALWAYS, TEST_LOCATION); tet_infoline("Set offscreen rendering : refresh always"); + const Property::Value SHADOW{ + {Visual::Property::TYPE, Visual::COLOR}, + {Visual::Property::MIX_COLOR, Vector4(0.0f, 0.0f, 0.0f, 0.5f)}, + {Visual::Property::TRANSFORM, + Property::Map{{Visual::Transform::Property::SIZE, Vector2(1.05f, 1.05f)}, + {Visual::Transform::Property::ORIGIN, Align::CENTER}, + {Visual::Transform::Property::ANCHOR_POINT, Align::CENTER}}}}; + control.SetProperty(DevelControl::Property::SHADOW, SHADOW); + 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"); @@ -1560,6 +1573,12 @@ int UtcDaliControlOffScreenRendering(void) application.SendNotification(); application.Render(); + control.Unparent(); + application.GetScene().Add(control); + + 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"); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-RenderEffect.cpp b/automated-tests/src/dali-toolkit/utc-Dali-RenderEffect.cpp index f5d56cd6ed..7fbfa666c2 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-RenderEffect.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-RenderEffect.cpp @@ -1043,15 +1043,11 @@ int UtcDaliRenderEffectBlurOnce(void) // Render effect activated. DALI_TEST_EQUALS(4u, taskList.GetTaskCount(), TEST_LOCATION); - tet_printf("order : %d\n", taskList.GetTask(taskList.GetTaskCount() - 1).GetOrderIndex()); - DALI_TEST_EQUALS(0u, taskList.GetTask(taskList.GetTaskCount() - 1).GetOrderIndex(), TEST_LOCATION); effect.SetBlurOnce(false); DALI_TEST_EQUALS(effect.GetBlurOnce(), false, TEST_LOCATION); DALI_TEST_EQUALS(4u, taskList.GetTaskCount(), TEST_LOCATION); - tet_printf("order : %d\n", taskList.GetTask(taskList.GetTaskCount() - 1).GetOrderIndex()); - DALI_TEST_EQUALS(0u, taskList.GetTask(taskList.GetTaskCount() - 1).GetOrderIndex(), TEST_LOCATION); } END_TEST; diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index 4e09bacf92..b10fe4af3d 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -1978,22 +1978,45 @@ void Control::Impl::SetOffScreenRendering(int32_t offScreenRenderingType) } DevelControl::OffScreenRenderingType newType = static_cast(offScreenRenderingType); + + Dali::Toolkit::Control handle(mControlImpl.GetOwner()); + if(newType == DevelControl::OffScreenRenderingType::NONE) { if(mOffScreenRenderingImpl) { auto tempOffscreenRenderingImpl = std::move(mOffScreenRenderingImpl); tempOffscreenRenderingImpl->ClearOwnerControl(); + + RegisteredVisualContainer& visuals = mVisualData->mVisuals; + for(auto it = visuals.begin(); it != visuals.end(); it++) + { + if((*it)->visual.GetDepthIndex() <= DepthIndex::BACKGROUND_EFFECT) + { + Renderer renderer = Toolkit::GetImplementation((*it)->visual).GetRenderer(); + handle.RemoveCacheRenderer(renderer); + handle.AddRenderer(renderer); + } + } } } else if(mOffScreenRenderingType == DevelControl::OffScreenRenderingType::NONE) { mOffScreenRenderingImpl = std::make_unique(newType); - - Dali::Toolkit::Control handle(mControlImpl.GetOwner()); mOffScreenRenderingImpl->SetOwnerControl(handle); + + RegisteredVisualContainer& visuals = mVisualData->mVisuals; + for(auto it = visuals.begin(); it != visuals.end(); it++) + { + if((*it)->visual.GetDepthIndex() <= DepthIndex::BACKGROUND_EFFECT) + { + Renderer renderer = Toolkit::GetImplementation((*it)->visual).GetRenderer(); + handle.RemoveRenderer(renderer); + handle.AddCacheRenderer(renderer); + } + } } - else + else if(mOffScreenRenderingType != newType) { mOffScreenRenderingImpl->SetType(newType); } diff --git a/dali-toolkit/internal/controls/control/control-visual-data.cpp b/dali-toolkit/internal/controls/control/control-visual-data.cpp index 2233900b23..73e8e6c85f 100644 --- a/dali-toolkit/internal/controls/control/control-visual-data.cpp +++ b/dali-toolkit/internal/controls/control/control-visual-data.cpp @@ -210,20 +210,69 @@ void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVis source.Erase(sourceIter); } +/** + * @brief Set visual on scene + * When offscreen rendering(using cache renderer) is on, it only includes control's context area. + * Swap the renderer's location to cache renderers for outer-drawn visuals. + * When depth index is lower than background effect(i.e. shadow visual), it is probably drawn out of control's context area. + * @param[in] visualImpl The visual + * @param[in] controlImpl Actor with renderers + * @note Changing depth index may not instantaneously update the visuals. (i.e. Turn offscreen rendering off and on again.) + */ +void SetVisualOnScene(Internal::Visual::Base& visualImpl, Internal::Control& controlImpl) +{ + Actor self = controlImpl.Self(); + visualImpl.SetOnScene(self); + + Toolkit::Control handle = Toolkit::Control(controlImpl.GetOwner()); + DevelControl::OffScreenRenderingType offscreenRenderingType = DevelControl::OffScreenRenderingType(handle.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING)); + if(offscreenRenderingType != DevelControl::OffScreenRenderingType::NONE) + { + if(visualImpl.GetDepthIndex() <= DepthIndex::BACKGROUND_EFFECT) + { + Renderer renderer = visualImpl.GetRenderer(); + self.RemoveRenderer(renderer); + self.AddCacheRenderer(renderer); + } + } +} + +/** + * @brief Remove visual's renderer from cache renderers(offscreen renderers) + * @param[in] visualImpl The visual + * @param[in] controlImpl Actor with renderers + */ +void SetVisualOffScene(Internal::Visual::Base& visualImpl, Internal::Control& controlImpl) +{ + Actor self = controlImpl.Self(); + visualImpl.SetOffScene(self); + + Toolkit::Control handle = Toolkit::Control(controlImpl.GetOwner()); + DevelControl::OffScreenRenderingType offscreenRenderingType = DevelControl::OffScreenRenderingType(handle.GetProperty(DevelControl::Property::OFFSCREEN_RENDERING)); + if(offscreenRenderingType != DevelControl::OffScreenRenderingType::NONE) + { + if(visualImpl.GetDepthIndex() <= DepthIndex::BACKGROUND_EFFECT) + { + Renderer renderer = visualImpl.GetRenderer(); + self.RemoveCacheRenderer(renderer); + } + } +} + /** * @brief Iterate through given container and setOffScene any visual found * * @param[in] container Container of visuals - * @param[in] parent Parent actor to remove visuals from + * @param[in] controlImpl Actor to remove visuals from */ -void SetVisualsOffScene(const RegisteredVisualContainer& container, Actor parent) +void SetVisualsOffScene(const RegisteredVisualContainer& container, Internal::Control& controlImpl) { for(auto iter = container.Begin(), end = container.End(); iter != end; iter++) { if((*iter)->visual) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index); - Toolkit::GetImplementation((*iter)->visual).SetOffScene(parent); + SetVisualOffScene(Toolkit::GetImplementation((*iter)->visual), controlImpl); } } } @@ -247,14 +296,14 @@ void Control::Impl::VisualData::ConnectScene(Actor parent) if((*iter)->visual && (*iter)->enabled) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::OnSceneConnection Setting visual(%d) on scene\n", (*iter)->index); - Toolkit::GetImplementation((*iter)->visual).SetOnScene(parent); + SetVisualOnScene(Toolkit::GetImplementation((*iter)->visual), mOuter.mControlImpl); } } } void Control::Impl::VisualData::ClearScene(Actor parent) { - SetVisualsOffScene(mVisuals, parent); + SetVisualsOffScene(mVisuals, mOuter.mControlImpl); if(!mRemoveVisuals.Empty()) { @@ -263,7 +312,7 @@ void Control::Impl::VisualData::ClearScene(Actor parent) while(!mRemoveVisuals.Empty()) { auto removalIter = mRemoveVisuals.End() - 1u; - Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(parent); + SetVisualOffScene(Toolkit::GetImplementation((*removalIter)->visual), mOuter.mControlImpl); // Discard removed visual. It will be destroyed at next Idle time. DiscardVisual(removalIter, mRemoveVisuals); @@ -281,8 +330,6 @@ void Control::Impl::VisualData::ResourceReady(Visual::Base& object) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::Impl::VisualData::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count()); - Actor self = mOuter.mControlImpl.Self(); - RegisteredVisualContainer::Iterator registeredIter; // A resource is ready, find resource in the registered visuals container and get its index @@ -301,7 +348,7 @@ void Control::Impl::VisualData::ResourceReady(Visual::Base& object) (*registeredIter)->pending = false; if(!((*visualToRemoveIter)->overideReadyTransition)) { - Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self); + SetVisualOffScene(Toolkit::GetImplementation((*visualToRemoveIter)->visual), mOuter.mControlImpl); } // Discard removed visual. It will be destroyed at next Idle time. @@ -454,7 +501,8 @@ void Control::Impl::VisualData::RegisterVisual(Property::Index index, Toolkit::V { // Visual with same index is already in removal container so current visual pending // Only the the last requested visual will be displayed so remove current visual which is staged but not ready. - Toolkit::GetImplementation(currentRegisteredVisual).SetOffScene(self); + SetVisualOffScene(Toolkit::GetImplementation(currentRegisteredVisual), mOuter.mControlImpl); + mVisuals.Erase(registeredVisualsiter); } else @@ -540,7 +588,7 @@ void Control::Impl::VisualData::RegisterVisual(Property::Index index, Toolkit::V // Put on stage if enabled and the control is already on the stage if((enabled == VisualState::ENABLED) && self.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { - visualImpl.SetOnScene(self); + SetVisualOnScene(visualImpl, mOuter.mControlImpl); } else if(enabled && visualImpl.IsResourceReady()) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already ) { @@ -561,16 +609,16 @@ void Control::Impl::VisualData::UnregisterVisual(Property::Index index) // stop observing visual StopObservingVisual((*iter)->visual); - Actor self(mOuter.mControlImpl.Self()); - Toolkit::GetImplementation((*iter)->visual).SetOffScene(self); + SetVisualOffScene(Toolkit::GetImplementation((*iter)->visual), mOuter.mControlImpl); + (*iter)->visual.Reset(); mVisuals.Erase(iter); } if(FindVisual(index, mRemoveVisuals, iter)) { - Actor self(mOuter.mControlImpl.Self()); - Toolkit::GetImplementation((*iter)->visual).SetOffScene(self); + SetVisualOffScene(Toolkit::GetImplementation((*iter)->visual), mOuter.mControlImpl); + (*iter)->pending = false; // Discard removed visual. It will be destroyed at next Idle time. @@ -611,19 +659,19 @@ void Control::Impl::VisualData::EnableVisual(Property::Index index, bool enable) return; } - (*iter)->enabled = enable; - Actor parentActor = mOuter.mControlImpl.Self(); + (*iter)->enabled = enable; if(mOuter.mControlImpl.Self().GetProperty(Actor::Property::CONNECTED_TO_SCENE)) // If control not on Scene then Visual will be added when SceneConnection is called. { if(enable) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index); - Toolkit::GetImplementation((*iter)->visual).SetOnScene(parentActor); + SetVisualOnScene(Toolkit::GetImplementation((*iter)->visual), mOuter.mControlImpl); } else { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index); - Toolkit::GetImplementation((*iter)->visual).SetOffScene(parentActor); // No need to call if control not staged. + + SetVisualOffScene(Toolkit::GetImplementation((*iter)->visual), mOuter.mControlImpl); // No need to call if control not staged. } } } @@ -688,8 +736,6 @@ bool Control::Impl::VisualData::IsVisualEnabled(Property::Index index) const void Control::Impl::VisualData::RemoveVisual(RegisteredVisualContainer& visuals, const std::string& visualName) { - Actor self(mOuter.mControlImpl.Self()); - for(RegisteredVisualContainer::Iterator visualIter = visuals.Begin(); visualIter != visuals.End(); ++visualIter) @@ -697,7 +743,8 @@ void Control::Impl::VisualData::RemoveVisual(RegisteredVisualContainer& visuals, Toolkit::Visual::Base visual = (*visualIter)->visual; if(visual && visual.GetName() == visualName) { - Toolkit::GetImplementation(visual).SetOffScene(self); + SetVisualOffScene(Toolkit::GetImplementation(visual), mOuter.mControlImpl); + (*visualIter)->visual.Reset(); visuals.Erase(visualIter); break; @@ -707,7 +754,6 @@ void Control::Impl::VisualData::RemoveVisual(RegisteredVisualContainer& visuals, void Control::Impl::VisualData::RemoveVisuals(RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals) { - Actor self(mOuter.mControlImpl.Self()); for(DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter) { const std::string visualName = *iter; @@ -726,7 +772,6 @@ void Control::Impl::VisualData::RecreateChangedVisuals(Dictionary const std::string& visualName = (*iter).key; const Property::Map& toMap = (*iter).entry; - Actor self = mOuter.mControlImpl.Self(); RegisteredVisualContainer::Iterator registeredVisualsiter; // Check if visual (visualName) is already registered, this is the current visual. if(FindVisual(visualName, mVisuals, registeredVisualsiter)) @@ -738,6 +783,7 @@ void Control::Impl::VisualData::RecreateChangedVisuals(Dictionary StopObservingVisual(visual); // If control staged then visuals will be swapped once ready + Actor self = mOuter.mControlImpl.Self(); if(self.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { // Check if visual is currently in the process of being replaced ( is in removal container ) @@ -746,7 +792,8 @@ void Control::Impl::VisualData::RecreateChangedVisuals(Dictionary { // Visual with same visual name is already in removal container so current visual pending // Only the the last requested visual will be displayed so remove current visual which is staged but not ready. - Toolkit::GetImplementation(visual).SetOffScene(self); + SetVisualOffScene(Toolkit::GetImplementation(visual), mOuter.mControlImpl); + (*registeredVisualsiter)->visual.Reset(); mVisuals.Erase(registeredVisualsiter); } diff --git a/dali-toolkit/internal/controls/render-effects/gaussian-blur-effect-impl.cpp b/dali-toolkit/internal/controls/render-effects/gaussian-blur-effect-impl.cpp index e62bae4e16..bc58f9eae0 100644 --- a/dali-toolkit/internal/controls/render-effects/gaussian-blur-effect-impl.cpp +++ b/dali-toolkit/internal/controls/render-effects/gaussian-blur-effect-impl.cpp @@ -106,6 +106,22 @@ OffScreenRenderable::Type GaussianBlurEffectImpl::GetOffScreenRenderableType() void GaussianBlurEffectImpl::GetOffScreenRenderTasks(std::vector& tasks, bool isForward) { + tasks.clear(); + if(isForward) + { + if(mSourceRenderTask) + { + tasks.push_back(mSourceRenderTask); + } + if(mHorizontalBlurTask) + { + tasks.push_back(mHorizontalBlurTask); + } + if(mVerticalBlurTask) + { + tasks.push_back(mVerticalBlurTask); + } + } } void GaussianBlurEffectImpl::SetBlurOnce(bool blurOnce) @@ -335,7 +351,7 @@ void GaussianBlurEffectImpl::OnActivate() // Inject blurred output to control Renderer renderer = GetTargetRenderer(); renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, Dali::Toolkit::DepthIndex::FOREGROUND_EFFECT); - ownerControl.GetImplementation().SetCacheRenderer(renderer); + ownerControl.AddCacheRenderer(renderer); ownerControl.GetImplementation().RegisterOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); SetRendererTexture(renderer, mBlurredOutputFrameBuffer); @@ -356,7 +372,8 @@ void GaussianBlurEffectImpl::OnDeactivate() auto ownerControl = GetOwnerControl(); if(DALI_LIKELY(ownerControl)) { - ownerControl.GetImplementation().RemoveCacheRenderer(); + Renderer renderer = GetTargetRenderer(); + ownerControl.RemoveCacheRenderer(renderer); ownerControl.GetImplementation().UnregisterOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); } DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[BlurEffect:%p] OnDeactivated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty(Actor::Property::ID) : -1); diff --git a/dali-toolkit/internal/controls/render-effects/mask-effect-impl.cpp b/dali-toolkit/internal/controls/render-effects/mask-effect-impl.cpp index 5387bd7d61..3b32f38ea0 100644 --- a/dali-toolkit/internal/controls/render-effects/mask-effect-impl.cpp +++ b/dali-toolkit/internal/controls/render-effects/mask-effect-impl.cpp @@ -141,7 +141,7 @@ void MaskEffectImpl::OnActivate() ownerControl.Add(mCamera); Renderer maskRenderer = GetTargetRenderer(); - ownerControl.GetImplementation().SetCacheRenderer(maskRenderer); + ownerControl.AddCacheRenderer(maskRenderer); ownerControl.GetImplementation().RegisterOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); Vector2 size = GetTargetSize(); @@ -169,7 +169,8 @@ void MaskEffectImpl::OnDeactivate() Toolkit::Control control = GetOwnerControl(); if(DALI_LIKELY(control)) { - control.GetImplementation().RemoveCacheRenderer(); + Renderer maskRenderer = GetTargetRenderer(); + control.RemoveCacheRenderer(maskRenderer); control.GetImplementation().UnregisterOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); } diff --git a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp index f9574743f2..0e64c5d429 100644 --- a/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp +++ b/dali-toolkit/internal/controls/render-effects/offscreen-rendering-impl.cpp @@ -93,7 +93,7 @@ void OffScreenRenderingImpl::OnActivate() SetRendererTexture(renderer, mFrameBuffer); Toolkit::Control control = GetOwnerControl(); - control.GetImplementation().SetCacheRenderer(renderer); + control.AddCacheRenderer(renderer); control.GetImplementation().RegisterOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); mRenderTask.SetScreenToFrameBufferMappingActor(control); } @@ -103,7 +103,8 @@ void OffScreenRenderingImpl::OnDeactivate() Toolkit::Control control = GetOwnerControl(); if(DALI_LIKELY(control)) { - control.GetImplementation().RemoveCacheRenderer(); + Renderer renderer = GetTargetRenderer(); + control.RemoveCacheRenderer(renderer); control.GetImplementation().UnregisterOffScreenRenderableType(OffScreenRenderable::Type::FORWARD); mCamera.Unparent(); -- 2.34.1