diff --git a/shell/common/animator.cc b/shell/common/animator.cc index a0704c7b8d26f09bd45098b246f4ae9255ade2c4..e5914f1a62a6c02f2dbfbb27e35d634b17996650 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -38,7 +38,7 @@ Animator::Animator(Delegate& delegate, task_runners.GetPlatformTaskRunner() == task_runners.GetRasterTaskRunner() ? 1 - : 2)), + : 4)), #endif // SHELL_ENABLE_METAL pending_frame_semaphore_(1), weak_factory_(this) { 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..1d4a193adb27f6bf81b8b8889dc9428cb52284fe 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/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets index be366b7cb7029b1208a0a17abb6f04a023cb8126..2f85b0bbd58407edc36a49ae6a1ec882a07e221f 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/cpp/types/libflutter/index.d.ets @@ -166,4 +166,6 @@ export const nativeUnicodeIsEmojiModifierBase: (code: number) => number; export const nativeUnicodeIsVariationSelector: (code: number) => number; -export const nativeUnicodeIsRegionalIndicatorSymbol: (code: number) => number; \ No newline at end of file +export const nativeUnicodeIsRegionalIndicatorSymbol: (code: number) => number; + +export const nativeSetDVsyncSwitch: (nativeShellHolderId: number, isEnable: boolean) => void; \ No newline at end of file diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets index cd3cd81923431aedd613734d5a7953624ec63f81..bb6b692fe663ce3eeb3b4f902082a86d9e8ea168 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterEngine.ets @@ -39,6 +39,7 @@ import LocalizationPlugin from '../../plugin/localization/LocalizationPlugin' import SettingsChannel from './systemchannels/SettingsChannel'; import PlatformViewsController from '../../plugin/platform/PlatformViewsController'; import { FlutterRenderer } from './renderer/FlutterRenderer'; +import NativeVsyncChannel from './systemchannels/NativeVsyncChannel'; const TAG = "FlutterEngine"; @@ -70,6 +71,7 @@ export default class FlutterEngine implements EngineLifecycleListener{ private localizationPlugin: LocalizationPlugin | null = null; private settingsChannel: SettingsChannel | null = null; private platformViewsController: PlatformViewsController; + private nativeVsyncChannel: NativeVsyncChannel | null = null; /** * 需要初始化的工作: @@ -125,6 +127,7 @@ export default class FlutterEngine implements EngineLifecycleListener{ this.accessibilityChannel = new AccessibilityChannel(this.dartExecutor, this.flutterNapi); this.flutterNapi.addEngineLifecycleListener(this); this.localizationPlugin = new LocalizationPlugin(context, this.localeChannel); + this.nativeVsyncChannel = new NativeVsyncChannel(this.dartExecutor, this.flutterNapi); // It should typically be a fresh, unattached NAPI. But on a spawned engine, the NAPI instance // is already attached to a native shell. In that case, the Java FlutterEngine is created around diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets index 7216db2888a77ce7e258fb93fd760700b3733c9f..3e6619e1048f3eb80b82b6aa8c850592b99a196c 100644 --- a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/FlutterNapi.ets @@ -542,6 +542,9 @@ export default class FlutterNapi { return Boolean(flutter.nativeUnicodeIsRegionalIndicatorSymbol(code)); } + SetDVsyncSwitch(isEnable: boolean): void { + flutter.nativeSetDVsyncSwitch(this.nativeShellHolderId!, isEnable); + } } export interface AccessibilityDelegate { diff --git a/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/NativeVsyncChannel.ets b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/NativeVsyncChannel.ets new file mode 100644 index 0000000000000000000000000000000000000000..0afc63c245da2a46efdf401037dc7fc0b50d3894 --- /dev/null +++ b/shell/platform/ohos/flutter_embedding/flutter/src/main/ets/embedding/engine/systemchannels/NativeVsyncChannel.ets @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2024 Hunan OpenValley Digital Industry Development 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. +*/ + +import Log from '../../../util/Log'; +import DartExecutor from '../dart/DartExecutor'; +import BasicMessageChannel, { MessageHandler, Reply} from '../../../plugin/common/BasicMessageChannel'; +import HashMap from '@ohos.util.HashMap'; +import StandardMessageCodec from '../../../plugin/common/StandardMessageCodec'; +import StringUtils from '../../../util/StringUtils'; +import Any from '../../../plugin/common/Any'; +import FlutterNapi from '../FlutterNapi'; + +/** +* nativeVsync功能channel +*/ +export default class NativeVsyncChannel implements MessageHandler { + private static TAG = "NativeVsyncChannel"; + private static CHANNEL_NAME = "flutter/nativevsync"; + private channel: BasicMessageChannel; + private flutterNapi: FlutterNapi; + + onMessage(message: object, reply: Reply): void { + let data: HashMap = message as HashMap; + let isEnable: boolean = data.get("isEnable"); + this.flutterNapi.setDVsyncSwitch(isEnable); + + Log.d(NativeVsyncChannel.TAG, `Received message: isEnable:$isEnable`); + reply.reply(StringUtils.stringToArrayBuffer("")); + } + + constructor(dartExecutor: DartExecutor, flutterNapi: FlutterNapi) { + Log.i(NativeVsyncChannel.TAG, "Channel entered"); + this.channel = new BasicMessageChannel( + dartExecutor, NativeVsyncChannel.CHANNEL_NAME, StandardMessageCodec.INSTANCE); + this.channel.setMessageHandler(this); + this.flutterNapi = flutterNapi; + } +} \ No newline at end of file diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp index ab9f2df807134c44bface863e2065f255af61cd3..856d3e19735f464d1145209c98933b4070bf047a 100644 --- a/shell/platform/ohos/library_loader.cpp +++ b/shell/platform/ohos/library_loader.cpp @@ -169,6 +169,9 @@ static napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_FUNCTION( "nativeUnicodeIsRegionalIndicatorSymbol", flutter::PlatformViewOHOSNapi::nativeUnicodeIsRegionalIndicatorSymbol), + DECLARE_NAPI_FUNCTION( + "nativeSetDVsyncSwitch", + flutter::PlatformViewOHOSNapi::nativeSetDVsyncSwitch), }; FML_DLOG(INFO) << "Init NAPI size=" << sizeof(desc) / sizeof(desc[0]); diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp index f6f23e803a185c6d26cd0c1f00e05eef512baf4c..61cd6a64691c52dc1e9396a0ff1c8242ebe964b2 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -33,6 +33,7 @@ #include "unicode/uchar.h" #include "flutter/shell/platform/ohos/ohos_xcomponent_adapter.h" #include "flutter/shell/platform/ohos/ohos_logging.h" +#include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" #define OHOS_SHELL_HOLDER (reinterpret_cast(shell_holder)) namespace flutter { @@ -2009,4 +2010,47 @@ napi_value PlatformViewOHOSNapi::nativeUnicodeIsRegionalIndicatorSymbol(napi_env napi_create_int32(env, (int)is_emoji, &result); return result; } + +napi_value PlatformViewOHOSNapi::nativeSetDVsyncSwitch(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value result; + napi_value args[2] = {nullptr}; + napi_status ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeSetDVsyncSwitch napi_get_cb_info error"); + napi_create_int32(env, -1, &result); + return result; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeSetDVsyncSwitch shell_holder " + "napi_get_value_int64 error"; + return nullptr; + } + + bool isEnable; + ret = napi_get_value_bool(env, args[1], &isEnable); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeSetDVsyncSwitch isEnable " + "napi_get_value_bool error"; + return nullptr; + } + + auto vsyncWaiter = std::shared_ptr(OHOS_SHELL_HOLDER->GetVsyncWaiter().lock()); + auto vsync_waiter_ohos = std::static_pointer_cast(vsyncWaiter); + + if (isEnable) { + LOGD("EnableDVsync"); + vsync_waiter_ohos->EnableDVsync(); + } else { + LOGD("DisableDVsync"); + vsync_waiter_ohos->DisableDVsync(); + } + + napi_create_int32(env, 0, &result); + return result; +} } // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h index 65f11e8776365cece1613c8f855a6e283cd76bd6..619bad9df70278b24f3b7badf9ed8970d69a8a57 100644 --- a/shell/platform/ohos/napi/platform_view_ohos_napi.h +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -244,6 +244,10 @@ class PlatformViewOHOSNapi { napi_env env, napi_callback_info info); + static napi_value nativeSetDVsyncSwitch( + napi_env env, + napi_callback_info info); + private: static napi_env env_; napi_ref ref_napi_obj_; diff --git a/shell/platform/ohos/ohos_shell_holder.h b/shell/platform/ohos/ohos_shell_holder.h index 4a87730862c4ded233a6f08ace2154ae3eba29cb..6fba882739c27999b0b0e596c8178e72ce9c99e3 100644 --- a/shell/platform/ohos/ohos_shell_holder.h +++ b/shell/platform/ohos/ohos_shell_holder.h @@ -68,6 +68,10 @@ 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/vsync_waiter_ohos.cpp b/shell/platform/ohos/vsync_waiter_ohos.cpp index 1330506a8a08223fee39ccb5f4b86da21e49a99c..0d40e434183d771b0f7172006869558969a2fa7e 100644 --- a/shell/platform/ohos/vsync_waiter_ohos.cpp +++ b/shell/platform/ohos/vsync_waiter_ohos.cpp @@ -69,10 +69,6 @@ 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 +92,17 @@ 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); + } +} + +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..b178455404df37b8b0d95fce4ff3acd2718a8ae3 100644 --- a/shell/platform/ohos/vsync_waiter_ohos.h +++ b/shell/platform/ohos/vsync_waiter_ohos.h @@ -16,6 +16,7 @@ #ifndef VSYNC_WAITER_OHOS_H #define VSYNC_WAITER_OHOS_H #include +#include #include #include "flutter/fml/macros.h" @@ -30,7 +31,11 @@ class VsyncWaiterOHOS final : public VsyncWaiter { ~VsyncWaiterOHOS() override; + void DisableDVsync() override; + void EnableDVsync() override; + private: + std::atomic dvsyncEnabled{false}; thread_local static bool firstCall; // |VsyncWaiter| void AwaitVSync() override;