From 99482f5e455ae1aa1b99de1e25c3c3b5e37833b4 Mon Sep 17 00:00:00 2001 From: zzvscx Date: Fri, 17 Nov 2023 15:12:36 +0800 Subject: [PATCH] Description: AddFRCSceneInfo Feature or Bugfix: Feature Binary Source: No Signed-off-by: zsw --- frameworks/core/common/window.h | 2 + .../core/components_ng/base/frame_node.cpp | 62 +++++++++++++++++-- .../core/components_ng/base/frame_node.h | 4 ++ .../core/components_ng/manager/BUILD.gn | 1 + .../manager/frame_rate/frame_rate_manager.cpp | 62 +++++++++++++++++++ .../manager/frame_rate/frame_rate_manager.h | 52 ++++++++++++++++ .../render/adapter/rosen_render_context.cpp | 8 ++- .../render/adapter/rosen_render_context.h | 2 +- .../render/adapter/rosen_window.cpp | 8 +++ .../render/adapter/rosen_window.h | 2 + .../components_ng/render/render_context.h | 5 +- .../core/pipeline_ng/pipeline_context.cpp | 11 ++++ .../core/pipeline_ng/pipeline_context.h | 9 +++ test/mock/core/render/mock_render_context.h | 1 - test/unittest/BUILD.gn | 1 + test/unittest/core/common/ace_engine/BUILD.gn | 1 + .../core/pattern/list/list_test_ng.cpp | 14 ----- .../core/pattern/refresh/refresh_test_ng.cpp | 4 -- test/unittest/core/pipeline/BUILD.gn | 1 + 19 files changed, 221 insertions(+), 29 deletions(-) create mode 100644 frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp create mode 100644 frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.h diff --git a/frameworks/core/common/window.h b/frameworks/core/common/window.h index caf7035c354..3d1cde8fc62 100644 --- a/frameworks/core/common/window.h +++ b/frameworks/core/common/window.h @@ -47,6 +47,8 @@ public: virtual void RequestFrame(); + virtual void FlushFrameRate(int32_t rate) {} + virtual void SetTaskExecutor(const RefPtr& taskExecutor) {} virtual void SetInstanceId(int32_t instanceId) {} diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index ec2b2929c4f..ce1877c7c8b 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -339,6 +339,10 @@ FrameNode::~FrameNode() dragManager->UnRegisterDragStatusListener(GetId()); #endif // ENABLE_DRAG_FRAMEWORK } + auto frameRateManager = pipeline->GetFrameRateManager(); + if (frameRateManager) { + frameRateManager->RemoveNodeRate(GetId()); + } } } @@ -2293,6 +2297,16 @@ std::vector> FrameNode::GetNodesById(const std::unordered_set< return nodes; } +int32_t FrameNode::GetNodeExpectedRate() +{ + if (sceneRateMap_.empty()) { + return 0; + } + auto iter = std::max_element( + sceneRateMap_.begin(), sceneRateMap_.end(), [](auto a, auto b) { return a.second < b.second; }); + return iter->second; +} + void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStatus status) { if (SystemProperties::GetDebugEnabled()) { @@ -2301,12 +2315,50 @@ void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStat scene.c_str(), speed, sceneStatusStrs[static_cast(status)].c_str()); } - if (status == SceneStatus::RUNNING) { - return; + auto renderContext = GetRenderContext(); + CHECK_NULL_VOID(renderContext); + auto pipelineContext = GetContext(); + CHECK_NULL_VOID(pipelineContext); + auto frameRateManager = pipelineContext->GetFrameRateManager(); + CHECK_NULL_VOID(frameRateManager); + + auto expectedRate = renderContext->CalcExpectedFrameRate(scene, speed); + auto nodeId = GetId(); + auto iter = sceneRateMap_.find(scene); + switch (status) { + case SceneStatus::START: { + if (iter == sceneRateMap_.end()) { + if (sceneRateMap_.empty()) { + frameRateManager->AddNodeRate(nodeId); + } + sceneRateMap_.emplace(scene, expectedRate); + frameRateManager->UpdateNodeRate(nodeId, GetNodeExpectedRate()); + } + return; + } + case SceneStatus::RUNNING: { + if (iter != sceneRateMap_.end() && iter->second != expectedRate) { + iter->second = expectedRate; + auto nodeExpectedRate = GetNodeExpectedRate(); + frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate); + } + return; + } + case SceneStatus::END: { + if (iter != sceneRateMap_.end()) { + sceneRateMap_.erase(iter); + if (sceneRateMap_.empty()) { + frameRateManager->RemoveNodeRate(nodeId); + } else { + auto nodeExpectedRate = GetNodeExpectedRate(); + frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate); + } + } + return; + } + default: + return; } - auto context = GetRenderContext(); - CHECK_NULL_VOID(context); - context->AddFRCSceneInfo(scene, speed); } void FrameNode::CheckSecurityComponentStatus(std::vector& rect) diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index bf1aca39b35..84aaebc61a6 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -672,6 +672,8 @@ private: void UpdateParentAbsoluteOffset(); void AddFrameNodeSnapshot(bool isHit, int32_t parentId); + int32_t GetNodeExpectedRate(); + // sort in ZIndex. std::multiset, ZIndexComparator> frameChildren_; RefPtr geometryNode_ = MakeRefPtr(); @@ -734,6 +736,8 @@ private: RefPtr overlayNode_; + std::unordered_map sceneRateMap_; + friend class RosenRenderContext; friend class RenderContext; friend class Pattern; diff --git a/frameworks/core/components_ng/manager/BUILD.gn b/frameworks/core/components_ng/manager/BUILD.gn index b45e62932f8..14a9c254058 100644 --- a/frameworks/core/components_ng/manager/BUILD.gn +++ b/frameworks/core/components_ng/manager/BUILD.gn @@ -18,6 +18,7 @@ build_component_ng("manager_ng") { sources = [ "drag_drop/drag_drop_manager.cpp", "drag_drop/drag_drop_proxy.cpp", + "frame_rate/frame_rate_manager.cpp", "full_screen/full_screen_manager.cpp", "safe_area/safe_area_manager.cpp", "select_overlay/select_overlay_client.cpp", diff --git a/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp b/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp new file mode 100644 index 00000000000..d9fed1173d4 --- /dev/null +++ b/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device 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. + */ +#include "frame_rate_manager.h" + +namespace OHOS::Ace::NG { +bool FrameRateManager::IsRateChanged() +{ + return isRateChanged_; +} + +void FrameRateManager::SetIsRateChanged(bool isChanged) +{ + isRateChanged_ = isChanged; +} + +void FrameRateManager::AddNodeRate(int32_t nodeId, int32_t rate) +{ + auto [iter, success] = nodeRateMap_.try_emplace(nodeId, rate); + if (success) { + isRateChanged_ = true; + } +} + +void FrameRateManager::RemoveNodeRate(int32_t nodeId) +{ + if (auto iter = nodeRateMap_.find(nodeId); iter != nodeRateMap_.end()) { + nodeRateMap_.erase(iter); + isRateChanged_ = true; + } +} + +void FrameRateManager::UpdateNodeRate(int32_t nodeId, int32_t rate) +{ + if (auto iter = nodeRateMap_.find(nodeId); iter != nodeRateMap_.end() && iter->second != rate) { + iter->second = rate; + isRateChanged_ = true; + } +} + +int32_t FrameRateManager::GetExpectedRate() +{ + int32_t expectedRate = 0; + if (!nodeRateMap_.empty()) { + auto maxIter = std::max_element( + nodeRateMap_.begin(), nodeRateMap_.end(), [](auto a, auto b) { return a.second < b.second; }); + expectedRate = maxIter->second; + } + return expectedRate; +} +} // namespace OHOS::Ace::NG \ No newline at end of file diff --git a/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.h b/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.h new file mode 100644 index 00000000000..165cfa508df --- /dev/null +++ b/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Huawei Device 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. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FRAME_RATE_FRAME_RATE_MANAGER_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FRAME_RATE_FRAME_RATE_MANAGER_H + +#include +#include + +#include "base/memory/ace_type.h" +#include "base/utils/noncopyable.h" + +namespace OHOS::Ace::NG { +class FrameRateManager : public virtual AceType { + DECLARE_ACE_TYPE(FrameRateManager, AceType); + +public: + FrameRateManager() = default; + ~FrameRateManager() override = default; + + bool IsRateChanged(); + + void SetIsRateChanged(bool isChanged); + + void AddNodeRate(int32_t nodeId, int32_t rate = 0); + + void RemoveNodeRate(int32_t nodeId); + + void UpdateNodeRate(int32_t nodeId, int32_t rate); + + int32_t GetExpectedRate(); + +private: + std::unordered_map nodeRateMap_; + bool isRateChanged_ = false; + + ACE_DISALLOW_COPY_AND_MOVE(FrameRateManager); +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FRAME_RATE_FRAME_RATE_MANAGER_H diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp b/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp index d4963ebd0a3..6d7d8c17366 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_render_context.cpp @@ -3411,10 +3411,12 @@ void RosenRenderContext::SetFrameGravity(OHOS::Rosen::Gravity gravity) rsNode_->SetFrameGravity(gravity); } -void RosenRenderContext::AddFRCSceneInfo(const std::string& scene, float speed) +int32_t RosenRenderContext::CalcExpectedFrameRate(const std::string& scene, float speed) { - CHECK_NULL_VOID(rsNode_); - rsNode_->AddFRCSceneInfo(scene, speed); + if (rsNode_ == nullptr) { + return 0; + } + return rsNode_->CalcExpectedFrameRate(scene, speed); } void RosenRenderContext::ClearDrawCommands() diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_context.h b/frameworks/core/components_ng/render/adapter/rosen_render_context.h index a8cd2d363bf..76e1d51510c 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_context.h +++ b/frameworks/core/components_ng/render/adapter/rosen_render_context.h @@ -284,7 +284,7 @@ public: void SetUsingContentRectForRenderFrame(bool value) override; void SetFrameGravity(OHOS::Rosen::Gravity gravity) override; - void AddFRCSceneInfo(const std::string& scene, float speed) override; + int32_t CalcExpectedFrameRate(const std::string& scene, float speed) override; private: void OnBackgroundImageUpdate(const ImageSourceInfo& src) override; diff --git a/frameworks/core/components_ng/render/adapter/rosen_window.cpp b/frameworks/core/components_ng/render/adapter/rosen_window.cpp index aa760886f79..e9259090d6a 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_window.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_window.cpp @@ -87,6 +87,14 @@ void RosenWindow::Init() } } +void RosenWindow::FlushFrameRate(int32_t rate) +{ + if (!rsWindow_ || rate < 0) { + return; + } + rsWindow_->FlushFrameRate(rate); +} + void RosenWindow::RequestFrame() { CHECK_NULL_VOID(onShow_); diff --git a/frameworks/core/components_ng/render/adapter/rosen_window.h b/frameworks/core/components_ng/render/adapter/rosen_window.h index 299eb8cc4a1..04e00bfb355 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_window.h +++ b/frameworks/core/components_ng/render/adapter/rosen_window.h @@ -53,6 +53,8 @@ public: void SetRootFrameNode(const RefPtr& root) override; + void FlushFrameRate(int32_t rate) override; + std::shared_ptr GetRSUIDirector() const override { return rsUIDirector_; diff --git a/frameworks/core/components_ng/render/render_context.h b/frameworks/core/components_ng/render/render_context.h index 04f8c25e9e1..8743cb5dfbe 100644 --- a/frameworks/core/components_ng/render/render_context.h +++ b/frameworks/core/components_ng/render/render_context.h @@ -488,7 +488,10 @@ public: } virtual void SetFrameGravity(OHOS::Rosen::Gravity gravity) {} - virtual void AddFRCSceneInfo(const std::string& scene, float speed) {} + virtual int32_t CalcExpectedFrameRate(const std::string& scene, float speed) + { + return 0; + } protected: RenderContext() = default; diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index a345d07bf9e..0962dfc0bb0 100755 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -416,6 +416,7 @@ void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount) if (hasAnimation) { RequestFrame(); } + FlushFrameRate(); FlushMessages(); if (dragCleanTask_) { dragCleanTask_(); @@ -581,6 +582,16 @@ void PipelineContext::FlushPipelineWithoutAnimation() FlushFocus(); } +void PipelineContext::FlushFrameRate() +{ + if (frameRateManager_->IsRateChanged()) { + auto rate = frameRateManager_->GetExpectedRate(); + ACE_SCOPED_TRACE("FlushFrameRate Expected frameRate = %d", rate); + window_->FlushFrameRate(rate); + frameRateManager_->SetIsRateChanged(false); + } +} + void PipelineContext::FlushBuild() { isRebuildFinished_ = false; diff --git a/frameworks/core/pipeline_ng/pipeline_context.h b/frameworks/core/pipeline_ng/pipeline_context.h index 9882d5e9b29..0e6d96fb8be 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.h +++ b/frameworks/core/pipeline_ng/pipeline_context.h @@ -31,6 +31,7 @@ #include "core/components_ng/base/frame_node.h" #include "core/components_ng/gestures/recognizers/gesture_recognizer.h" #include "core/components_ng/manager/drag_drop/drag_drop_manager.h" +#include "core/components_ng/manager/frame_rate/frame_rate_manager.h" #include "core/components_ng/manager/full_screen/full_screen_manager.h" #include "core/components_ng/manager/safe_area/safe_area_manager.h" #include "core/components_ng/manager/select_overlay/select_overlay_manager.h" @@ -249,6 +250,11 @@ public: const RefPtr& GetDragDropManager(); + const RefPtr& GetFrameRateManager() + { + return frameRateManager_; + } + void FlushBuild() override; void FlushPipelineImmediately() override; @@ -490,6 +496,8 @@ private: // only used for static form. void UpdateFormLinkInfos(); + + void FlushFrameRate(); template struct NodeCompare { @@ -559,6 +567,7 @@ private: RefPtr dragDropManager_; RefPtr sharedTransitionManager_; RefPtr safeAreaManager_ = MakeRefPtr(); + RefPtr frameRateManager_ = MakeRefPtr(); #ifdef WINDOW_SCENE_SUPPORTED RefPtr uiExtensionManager_ = MakeRefPtr(); #endif diff --git a/test/mock/core/render/mock_render_context.h b/test/mock/core/render/mock_render_context.h index 226fded4dfb..caf68b311e4 100644 --- a/test/mock/core/render/mock_render_context.h +++ b/test/mock/core/render/mock_render_context.h @@ -34,7 +34,6 @@ public: MOCK_METHOD1(AnimateHoverEffectScale, void(bool)); MOCK_METHOD1(SetVisible, void(bool)); MOCK_METHOD0(GetLocalTransformMatrix, Matrix4()); - MOCK_METHOD2(AddFRCSceneInfo, void(const std::string&, float)); void ResetBlendBgColor() override { diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index f266a0a77d6..3222bcf877a 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -212,6 +212,7 @@ ohos_source_set("ace_components_manager") { sources = [ "$ace_root/frameworks/core/components_ng/manager/drag_drop/drag_drop_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/drag_drop/drag_drop_proxy.cpp", + "$ace_root/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/full_screen/full_screen_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/safe_area/safe_area_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/select_overlay/select_overlay_client.cpp", diff --git a/test/unittest/core/common/ace_engine/BUILD.gn b/test/unittest/core/common/ace_engine/BUILD.gn index 9de877ac191..419f0391146 100644 --- a/test/unittest/core/common/ace_engine/BUILD.gn +++ b/test/unittest/core/common/ace_engine/BUILD.gn @@ -56,6 +56,7 @@ ohos_unittest("ace_engine_special_test") { "$ace_root/frameworks/core/components_ng/layout/layout_wrapper.cpp", "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_builder.cpp", "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_node.cpp", + "$ace_root/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/safe_area/safe_area_manager.cpp", "$ace_root/frameworks/core/components_ng/pattern/custom/custom_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp", diff --git a/test/unittest/core/pattern/list/list_test_ng.cpp b/test/unittest/core/pattern/list/list_test_ng.cpp index 48293c3cae2..504a4670420 100644 --- a/test/unittest/core/pattern/list/list_test_ng.cpp +++ b/test/unittest/core/pattern/list/list_test_ng.cpp @@ -6216,18 +6216,4 @@ HWTEST_F(ListTestNg, EdgeEffectOption004, TestSize.Level1) EXPECT_TRUE(pattern_->GetAlwaysEnabled()); EXPECT_TRUE(pattern_->scrollable_); } - -/** - * @tc.name: FRCCallback001 - * @tc.desc: Test FRC callback - * @tc.type: FUNC - */ -HWTEST_F(ListTestNg, FRCCallback001, TestSize.Level1) -{ - Create([](ListModelNG model) {}); - auto renderContext = AceType::MakeRefPtr(); - frameNode_->renderContext_ = renderContext; - EXPECT_CALL(*renderContext, AddFRCSceneInfo(_, _)).Times(1); - pattern_->NotifyFRCSceneInfo(0.0f, SceneStatus::START); -} } // namespace OHOS::Ace::NG diff --git a/test/unittest/core/pattern/refresh/refresh_test_ng.cpp b/test/unittest/core/pattern/refresh/refresh_test_ng.cpp index d85e4c8e8b2..233f6a56b74 100644 --- a/test/unittest/core/pattern/refresh/refresh_test_ng.cpp +++ b/test/unittest/core/pattern/refresh/refresh_test_ng.cpp @@ -52,7 +52,6 @@ constexpr float PERCENT = 0.01; // Percent constexpr Dimension TRIGGER_REFRESH_DISTANCE = 64.0_vp; constexpr float DEFAULT_SPEED = 10.0f; constexpr float DEFAULT_OFFSET = 20.0f; -constexpr int32_t CALL_TIMES = 2; } // namespace class RefreshTestNg : public testing::Test, public TestNG { public: @@ -845,9 +844,6 @@ HWTEST_F(RefreshTestNg, RefreshDragFrameRatio001, TestSize.Level1) EXPECT_TRUE(!!frameNode); auto refreshPattern = frameNode->GetPattern(); EXPECT_TRUE(!!refreshPattern); - auto renderContext = AceType::DynamicCast(frameNode->GetRenderContext()); - EXPECT_TRUE(!!renderContext); - EXPECT_CALL(*renderContext, AddFRCSceneInfo(_, _)).Times(CALL_TIMES); refreshPattern->HandleDragStart(true, DEFAULT_SPEED); refreshPattern->HandleDragUpdate(DEFAULT_OFFSET, DEFAULT_SPEED); refreshPattern->HandleDragUpdate(DEFAULT_OFFSET, DEFAULT_SPEED); diff --git a/test/unittest/core/pipeline/BUILD.gn b/test/unittest/core/pipeline/BUILD.gn index 044f15d9964..3ae9853d1e8 100644 --- a/test/unittest/core/pipeline/BUILD.gn +++ b/test/unittest/core/pipeline/BUILD.gn @@ -116,6 +116,7 @@ ohos_unittest("pipeline_context_test_ng") { "$ace_root/frameworks/core/components_ng/layout/layout_wrapper.cpp", "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_builder.cpp", "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_node.cpp", + "$ace_root/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/safe_area/safe_area_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/select_overlay/select_overlay_client.cpp", "$ace_root/frameworks/core/components_ng/manager/select_overlay/select_overlay_manager.cpp",