diff --git a/shell/common/animator.cc b/shell/common/animator.cc index a0704c7b8d26f09bd45098b246f4ae9255ade2c4..d785b6f5bc9700a66f9cb6ffdc6c6a5ae570f3b7 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -90,6 +90,9 @@ void Animator::BeginFrame( // full because the consumer is being too slow. Try again at the next // frame interval. TRACE_EVENT0("flutter", "PipelineFull"); +#if defined(FML_OS_OHOS) + waiter_->DisableDVSync(); +#endif RequestFrame(); return; } @@ -124,6 +127,9 @@ void Animator::BeginFrame( TRACE_EVENT0("flutter", "BeginFrame idle callback"); self->delegate_.OnAnimatorNotifyIdle( now + fml::TimeDelta::FromMilliseconds(100)); +#if defined(FML_OS_OHOS) + self->waiter_->DisableDVSync(); +#endif } }, kNotifyIdleTaskWaitTime); diff --git a/shell/common/vsync_waiter.cc b/shell/common/vsync_waiter.cc index a23904f2d4f2713b8ed291f4ddd181d30470611b..1fc436ca3ce6481b21ed68d03fd96c0d7329f92e 100644 --- a/shell/common/vsync_waiter.cc +++ b/shell/common/vsync_waiter.cc @@ -87,8 +87,9 @@ void VsyncWaiter::ScheduleSecondaryCallback(uintptr_t id, void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time, fml::TimePoint frame_target_time, bool pause_secondary_tasks) { +#if !defined(FML_OS_OHOS) FML_DCHECK(fml::TimePoint::Now() >= frame_start_time); - +#endif Callback callback; std::vector secondary_callbacks; diff --git a/shell/common/vsync_waiter.h b/shell/common/vsync_waiter.h index cfce4524df4d7a59c90ff8a1fb3ce459b61ca9c9..58286e35dd712c84c2ad385e738fd2eae037dd56 100644 --- a/shell/common/vsync_waiter.h +++ b/shell/common/vsync_waiter.h @@ -31,7 +31,9 @@ class VsyncWaiter : public std::enable_shared_from_this { /// See also |PointerDataDispatcher::ScheduleSecondaryVsyncCallback| and /// |Animator::ScheduleMaybeClearTraceFlowIds|. void ScheduleSecondaryCallback(uintptr_t id, const fml::closure& callback); - + // For DVSync control + virtual void DisableDVSync() {} + virtual void EnableDVSync() {} protected: // On some backends, the |FireCallback| needs to be made from a static C // method. diff --git a/shell/platform/ohos/ohos_shell_holder.h b/shell/platform/ohos/ohos_shell_holder.h index 4a87730862c4ded233a6f08ace2154ae3eba29cb..2f0bc2f0e2f7cbdfe15a367b87cf78faa22af7b8 100644 --- a/shell/platform/ohos/ohos_shell_holder.h +++ b/shell/platform/ohos/ohos_shell_holder.h @@ -68,6 +68,9 @@ class OHOSShellHolder { return shell_->GetPlatformMessageHandler(); } + const std::weak_ptr GetVsyncWaiter() const { + return shell_->GetVsyncWaiter(); + } private: std::optional BuildRunConfiguration( const std::string& entrypoint, diff --git a/shell/platform/ohos/ohos_touch_processor.cpp b/shell/platform/ohos/ohos_touch_processor.cpp index 2e0af9081903b8bdb9c67f2fbe91c2af5647f1e5..792531d148641ddf91d5b62770ddcbbd2b0f85d0 100644 --- a/shell/platform/ohos/ohos_touch_processor.cpp +++ b/shell/platform/ohos/ohos_touch_processor.cpp @@ -148,6 +148,15 @@ void OhosTouchProcessor::HandleTouchEvent( int64_t shell_holderID, OH_NativeXComponent* component, OH_NativeXComponent_TouchEvent* touchEvent) { + + // There has touch event, update hasTouchEvent for DVSync. + auto ohos_shell_holder = reinterpret_cast(shell_holderID); + auto vsync_waiter = std::shared_ptr(ohos_shell_holder->GetVsyncWaiter().lock()); + auto vsync_waiter_ohos = std::static_pointer_cast(vsync_waiter); + if (!(vsync_waiter_ohos->hasTouchEvent.load())) { + vsync_waiter_ohos->hasTouchEvent.store(true); + } + if (touchEvent == nullptr) { return; } diff --git a/shell/platform/ohos/vsync_waiter_ohos.cpp b/shell/platform/ohos/vsync_waiter_ohos.cpp index 1330506a8a08223fee39ccb5f4b86da21e49a99c..4860d025f8aba802f1fd6209d4ead24f1b2fadd5 100644 --- a/shell/platform/ohos/vsync_waiter_ohos.cpp +++ b/shell/platform/ohos/vsync_waiter_ohos.cpp @@ -46,6 +46,14 @@ void VsyncWaiterOHOS::AwaitVSync() { auto* weak_this = new std::weak_ptr(shared_from_this()); OH_NativeVSync* handle = vsyncHandle; + // If it has touch event in the previous vsync period, mark disable DVSync; + // If there is no touch event, enable DVSync to get better performace. + if (hasTouchEvent.load()) { + DisableDVSync(); + } else { + EnableDVSync(); + } + fml::TaskRunner::RunNowOrPostTask( task_runners_.GetUITaskRunner(), [weak_this, handle]() { int32_t ret = 0; @@ -69,10 +77,7 @@ void VsyncWaiterOHOS::OnVsyncFromOHOS(long long timestamp, void* data) { int64_t frame_nanos = static_cast(timestamp); auto frame_time = fml::TimePoint::FromEpochDelta( fml::TimeDelta::FromNanoseconds(frame_nanos)); - auto now = fml::TimePoint::Now(); - if (frame_time > now) { - frame_time = now; - } + auto target_time = frame_time + fml::TimeDelta::FromNanoseconds( 1000000000.0 / g_refresh_rate_); auto* weak_this = reinterpret_cast*>(data); @@ -96,4 +101,19 @@ void VsyncWaiterOHOS::OnUpdateRefreshRate(long long refresh_rate) { g_refresh_rate_ = static_cast(refresh_rate); } +void VsyncWaiterOHOS::DisableDVSync() { + if (dvsyncEnabled.load()) { + OH_NativeVSync_DVSyncSwitch(vsyncHandle, false); + dvsyncEnabled.store(false); + } + // reset to false, if in the next vsync period hasTouchEvent is not marked, we can do DVSync. + hasTouchEvent.store(false); +} + +void VsyncWaiterOHOS::EnableDVSync() { + if (!dvsyncEnabled.load()) { + OH_NativeVSync_DVSyncSwitch(vsyncHandle, true); + dvsyncEnabled.store(true); + } +} } // namespace flutter diff --git a/shell/platform/ohos/vsync_waiter_ohos.h b/shell/platform/ohos/vsync_waiter_ohos.h index e9aac66c852b888b7495c27d0843fe777e3af169..9d5ce2b83f0732bf32467dea2598519a23ccc2c3 100644 --- a/shell/platform/ohos/vsync_waiter_ohos.h +++ b/shell/platform/ohos/vsync_waiter_ohos.h @@ -16,7 +16,7 @@ #ifndef VSYNC_WAITER_OHOS_H #define VSYNC_WAITER_OHOS_H #include - +#include #include #include "flutter/fml/macros.h" #include "flutter/shell/common/vsync_waiter.h" @@ -29,8 +29,12 @@ class VsyncWaiterOHOS final : public VsyncWaiter { static void OnUpdateRefreshRate(long long refresh_rate); ~VsyncWaiterOHOS() override; - + void DisableDVSync() override; + void EnableDVSync() override; + std::atomic hasTouchEvent{true}; private: + std::atomic dvsyncEnabled{false}; + thread_local static bool firstCall; // |VsyncWaiter| void AwaitVSync() override;