diff --git a/BUILD.gn b/BUILD.gn index acd070c7f87bd500fea227e6f4dea535f72e68a6..107f3da944c0daad128b99111f5d10c9a10da02c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -32,7 +32,7 @@ config("export_dynamic_symbols") { # -exported_symbols_list is the macOS linker syntax. The different flags # accept files formatted differently, so we have exported_symbols.sym for GNU # linker syntax, and exported_symbols_mac.sym for the macOS linker syntax. - if (is_linux || is_fuchsia) { + if (is_ohos|| is_linux || is_fuchsia) { inputs = [ "//flutter/common/exported_symbols.sym" ] ldflags = [ "-Wl,--dynamic-list=" + rebase_path(inputs[0], root_build_dir) ] } else if (is_mac) { diff --git a/OAT.xml b/OAT.xml new file mode 100644 index 0000000000000000000000000000000000000000..af9f8562b5e0d50df12cdb4839ed2669ee325dd6 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.OpenSource b/README.OpenSource new file mode 100644 index 0000000000000000000000000000000000000000..4302db9e1a841b6fff69a97551d3b5fe2468a6ba --- /dev/null +++ b/README.OpenSource @@ -0,0 +1,11 @@ +[ + { + "Name": "engine", + "License": "BSD 3-Clause License", + "License File": "LICENSE", + "Version Number": "3.7.12", + "Owner": "aibin@openvalley.net", + "Upstream URL": "https://flutter.dev/", + "Description": "The Flutter Engine is a portable runtime for hosting Flutter applications. It implements Flutter's core libraries, including animation and graphics, file and network I/O, accessibility support, plugin architecture, and a Dart runtime and compile toolchain. Most developers will interact with Flutter via the Flutter Framework, which provides a modern, reactive framework, and a rich set of platform, layout and foundation widgets." + } +] \ No newline at end of file diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..9b9ebdfa6cd7582597f44fe60bf1070ad3095966 --- /dev/null +++ b/README.en.md @@ -0,0 +1,37 @@ +Flutter Engine +=============== + +Source of original warehouse: https://github.com/flutter/engine + +## Warehouse description: +This repository is based on the extension of flutter's official engine repository, which can build flutter engine programs that support running on OpenHarmony devices. + +## Build instructions: + +* Build environment: +1. Currently only supports building under linux; + +2. Please ensure that the current build environment can access the allowed_hosts list configured in DEPS. + +* Build steps: +1. Refer to https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment to configure the build environment under linux; + +2. Obtain the source code, create an empty folder engine, create a new .gclient file in the engine, and edit the file: +``` +solutions = [ + { + "managed": False, + "name": "src/flutter", + "url": "git@gitee.com:openharmony-sig/flutter_engine.git", + "custom_deps": {}, + "deps_file": "DEPS", + "safesync_url": "", + }, +] +``` + +3. In the engine directory, execute 'gclient sync' command; here, the engine source code, the official packages warehouse, and the ohos_setup task will be executed; + +4. From the daily build at http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist, download ohos-sdk-full, create a new folder 'ndk/4.0' in the engine root directory, and decompress 'ohos-sdk-all' files in the 'native' folder in the full sdk are transferred to the 'ndk/4.0' folder; + +5. In the engine directory, execute 'make' command to start building the flutter engine that supports ohos devices. \ No newline at end of file diff --git a/README.md b/README.md index 0f2caad12a80448b06abb62f26de74b8d98b25c5..fd6857e32a687133548ce7d8e0c7da3c37af388d 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,38 @@ Flutter Engine ============== -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/flutter/engine/badge)](https://api.securityscorecards.dev/projects/github.com/flutter/engine) - -Flutter is Google's SDK for crafting beautiful, fast user experiences for -mobile, web, and desktop from a single codebase. Flutter works with existing -code, is used by developers and organizations around the world, and is free -and open source. - -The Flutter Engine is a portable runtime for hosting -[Flutter](https://flutter.dev) applications. It implements Flutter's core -libraries, including animation and graphics, file and network I/O, -accessibility support, plugin architecture, and a Dart runtime and compile -toolchain. Most developers will interact with Flutter via the [Flutter -Framework](https://github.com/flutter/flutter), which provides a modern, -reactive framework, and a rich set of platform, layout and foundation widgets. - -If you want to run/contribute to Flutter Web engine, more tooling can be -found at [felt](https://github.com/flutter/engine/tree/main/lib/web_ui#using-felt). -This is a tool written to make web engine development experience easy. - -If you are new to Flutter, then you will find more general information -on the Flutter project, including tutorials and samples, on our Web -site at [Flutter.dev](https://flutter.dev). For specific information -about Flutter's APIs, consider our API reference which can be found at -the [docs.flutter.dev](https://docs.flutter.dev/). - -Flutter is a fully open source project, and we welcome contributions. -Information on how to get started can be found at our -[contributor guide](CONTRIBUTING.md). - -[Build Status - Cirrus]: https://api.cirrus-ci.com/github/flutter/engine.svg?branch=main - -[Build status]: https://cirrus-ci.com/github/flutter/engine +原始仓来源:https://github.com/flutter/engine + +## 仓库说明: +本仓库是基于flutter官方engine仓库拓展,可构建支持在OpenHarmony设备上运行的flutter engine程序。 + +## 构建说明: + +* 构建环境: +1. 目前仅支持linux下构建; + +2. 请确保当前构建环境,可以访问DEPS中配置的allowed_hosts列表。 + +* 构建步骤: +1. 参照https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment 说明,配置好linux下构建环境; + +2. 获取源码,创建空文件夹engine,engine内新建.gclient文件,编辑文件: +``` +solutions = [ + { + "managed": False, + "name": "src/flutter", + "url": "git@gitee.com:openharmony-sig/flutter_engine.git", + "custom_deps": {}, + "deps_file": "DEPS", + "safesync_url": "", + }, +] +``` + +3. 在engine目录,执行gclient sync;这里会同步engine源码、官方packages仓,还有执行ohos_setup任务; + +4. 从 http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist 每日构建中,下载ohos-sdk-full,在engine根目录下,新建文件夹 ndk/4.0 ,解压ohos-sdk-full sdk中的native文件夹内所有文件到 ndk/4.0文件夹中; + +5. engine目录,执行make,既可以开始构建支持ohos设备的flutter engine。 diff --git a/fml/BUILD.gn b/fml/BUILD.gn index 0b25ea59f8df063b8c6442d89296477f7294bde0..ddcb7cb64b195e140aa02c5fd69c6cd95fce8966 100644 --- a/fml/BUILD.gn +++ b/fml/BUILD.gn @@ -97,8 +97,13 @@ source_set("fml") { "wakeable.h", ] - if (is_mac || is_linux || is_win || (is_ios && is_debug)) { - sources += [ "backtrace.cc" ] + if( is_ohos){ + sources += [ "backtrace_stub.cc" ] + }else if ( is_linux){ + sources += [ "backtrace_stub.cc" ] + }else if (is_mac || is_linux || is_win || (is_ios && is_debug)) { + #sources += [ "backtrace.cc" ] + sources += [ "backtrace_stub.cc" ] } else { sources += [ "backtrace_stub.cc" ] } @@ -183,7 +188,23 @@ source_set("fml") { ] } - if (is_linux) { + if (is_ohos) { + sources += [ + "platform/ohos/message_loop_ohos.cc", + "platform/ohos/message_loop_ohos.h", + "platform/ohos/paths_ohos.cc", + "platform/ohos/paths_ohos.h", + "platform/ohos/timerfd.cc", + "platform/ohos/timerfd.h", + #"platform/ohos/message_loop_ohos_test.cc", + #"platform/ohos/message_loop_ohos_test.h", + "platform/ohos/napi_util.h", + "platform/ohos/napi_util.cc", + ] + libs += [ "hilog_ndk.z" ] + libs += [ "ace_napi.z" ] + libs += [ "uv" ] + }else if (is_linux) { sources += [ "platform/linux/message_loop_linux.cc", "platform/linux/message_loop_linux.h", diff --git a/fml/backtrace.cc b/fml/backtrace.cc index 264fa7d0bcda5099689a42f5d4f5831d18b3a0b9..3a3be765a6e63b33b2c11ae6c92e940f7164ca88 100644 --- a/fml/backtrace.cc +++ b/fml/backtrace.cc @@ -17,7 +17,7 @@ #include #include #else // FML_OS_WIN -#include +//#include #endif // FML_OS_WIN namespace fml { diff --git a/fml/build_config.h b/fml/build_config.h index 3c7ebc9528d7942066b3176e98a9e683537d0ee2..a43431f1a03266454a84b06d2e7639b78d5b6dfe 100644 --- a/fml/build_config.h +++ b/fml/build_config.h @@ -29,6 +29,16 @@ #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #define FML_OS_IOS 1 #endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE + +#elif defined(__OHOS_FAMILY__) +#define FML_OS_OHOS 1 +// include a system header to pull in features.h for glibc/uclibc macros. +#include +#if defined(__GLIBC__) && !defined(__UCLIBC__) +// we really are using glibc, not uClibc pretending to be glibc +#define LIBC_GLIBC 1 +#endif + #elif defined(__linux__) #define FML_OS_LINUX 1 // include a system header to pull in features.h for glibc/uclibc macros. @@ -37,6 +47,8 @@ // we really are using glibc, not uClibc pretending to be glibc #define LIBC_GLIBC 1 #endif + + #elif defined(_WIN32) #define FML_OS_WIN 1 #elif defined(__FreeBSD__) diff --git a/fml/log_level.h b/fml/log_level.h index 2c9a85305b53d591bfa9dde5b76cadcca3fbd1dd..79316f86b657a66114aab8ff2a926335912f97f7 100644 --- a/fml/log_level.h +++ b/fml/log_level.h @@ -15,6 +15,7 @@ constexpr LogSeverity LOG_WARNING = 1; constexpr LogSeverity LOG_ERROR = 2; constexpr LogSeverity LOG_FATAL = 3; constexpr LogSeverity LOG_NUM_SEVERITIES = 4; +constexpr LogSeverity LOG_DEBUG= 4; // One of the Windows headers defines ERROR to 0. This makes the token // concatenation in FML_LOG(ERROR) to resolve to LOG_0. We define this back to diff --git a/fml/logging.cc b/fml/logging.cc index 5a0280e0f0c25904988199ffc6233c733f345a79..88c537dab0ad43bed282cb50c509d9e9dba6889f 100644 --- a/fml/logging.cc +++ b/fml/logging.cc @@ -18,6 +18,32 @@ #include #endif +#ifdef FML_OS_OHOS +#include + +extern "C"{ +#define OHOS_LOG_TYPE_APP 0 +#define HILOG_LOG_DOMAIN 0 +#define HILOG_LOG_TAG "XComFlutterEngine" + typedef enum { + /** Debug level to be used by {@link OH_LOG_DEBUG} */ + HILOG_LOG_DEBUG = 3, + /** Informational level to be used by {@link OH_LOG_INFO} */ + HILOG_LOG_INFO = 4, + /** Warning level to be used by {@link OH_LOG_WARN} */ + HILOG_LOG_WARN = 5, + /** Error level to be used by {@link OH_LOG_ERROR} */ + HILOG_LOG_ERROR = 6, + /** Fatal level to be used by {@link OH_LOG_FATAL} */ + HILOG_LOG_FATAL = 7, +} HiLog_LogLevel; +int OH_LOG_Print(int type, HiLog_LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) ; +#define HILOG_LOG(level,...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, (level), HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__)) +#define HILOG_DEBUG(...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, HILOG_LOG_DEBUG, HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__)) +#define HILOG_ERROR(...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, HILOG_LOG_ERROR, HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__)) +#define HILOG_INFO(...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, HILOG_LOG_INFO, HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__)) +} +#endif namespace fml { namespace { @@ -122,6 +148,30 @@ LogMessage::~LogMessage() { } fx_logger_log_with_source(fx_log_get_logger(), fx_severity, nullptr, file_, line_, stream_.str().c_str()); +#elif defined(FML_OS_OHOS) + HiLog_LogLevel fx_severity; + + switch (severity_) { + case LOG_INFO: + fx_severity= HILOG_LOG_INFO; + break; + case LOG_WARNING: + fx_severity = HILOG_LOG_WARN; + break; + case LOG_ERROR: + fx_severity = HILOG_LOG_ERROR; + break; + case LOG_FATAL: + fx_severity = HILOG_LOG_FATAL; + break; + default: + fx_severity = HILOG_LOG_INFO; + //fx_severity = HILOG_LOG_DEBUG; + }//end switch + HILOG_LOG(fx_severity,"Thread:%{public}lu %{public}s",pthread_self(),stream_.str().c_str() ); + + std::cerr << stream_.str(); + std::cerr.flush(); #else std::cerr << stream_.str(); std::cerr.flush(); @@ -141,7 +191,11 @@ bool ShouldCreateLogMessage(LogSeverity severity) { } void KillProcess() { - abort(); +#ifdef FML_OS_OHOS + HILOG_ERROR("FML KILL PROCESS"); +#else + abort(); +#endif } } // namespace fml diff --git a/fml/logging.h b/fml/logging.h index 0b732ee818a0aefef7bc988d8adab86e9805e422..cd07846805dc1ab889320adcfafc785c06f64930 100644 --- a/fml/logging.h +++ b/fml/logging.h @@ -43,7 +43,8 @@ int GetVlogVerbosity(); // LOG_FATAL and above is always true. bool ShouldCreateLogMessage(LogSeverity severity); -[[noreturn]] void KillProcess(); +//[[noreturn]] void KillProcess(); + void KillProcess(); } // namespace fml diff --git a/fml/message_loop.cc b/fml/message_loop.cc index c1043e664ae0a5b7c2cc33bda9907875edb77571..615165b2f919538081b6fc9ddc08aa857d56635d 100644 --- a/fml/message_loop.cc +++ b/fml/message_loop.cc @@ -29,15 +29,23 @@ void MessageLoop::EnsureInitializedForCurrentThread() { // Already initialized. return; } - tls_message_loop.reset(new MessageLoop()); + tls_message_loop.reset(new MessageLoop(nullptr)); +} + +void MessageLoop::EnsureInitializedForCurrentThread(void* platform_loop) { + if (tls_message_loop.get() != nullptr) { + // Already initialized. + return; + } + tls_message_loop.reset(new MessageLoop(platform_loop)); } bool MessageLoop::IsInitializedForCurrentThread() { return tls_message_loop.get() != nullptr; } -MessageLoop::MessageLoop() - : loop_(MessageLoopImpl::Create()), +MessageLoop::MessageLoop(void* platform_loop) + : loop_(MessageLoopImpl::Create(platform_loop)), task_runner_(fml::MakeRefCounted(loop_)) { FML_CHECK(loop_); FML_CHECK(task_runner_); diff --git a/fml/message_loop.h b/fml/message_loop.h index ccc1f70b93b8df4ffe4cb3a382fd9530627e80ae..b33449a4610922c5e1e46ac6cbd54348d6dc6710 100644 --- a/fml/message_loop.h +++ b/fml/message_loop.h @@ -46,6 +46,8 @@ class MessageLoop { static void EnsureInitializedForCurrentThread(); + static void EnsureInitializedForCurrentThread(void* platform_loop); + /// Returns true if \p EnsureInitializedForCurrentThread has been called on /// this thread already. static bool IsInitializedForCurrentThread(); @@ -64,7 +66,7 @@ class MessageLoop { fml::RefPtr loop_; fml::RefPtr task_runner_; - MessageLoop(); + MessageLoop(void* platform_loop); fml::RefPtr GetLoopImpl() const; diff --git a/fml/message_loop_impl.cc b/fml/message_loop_impl.cc index 01f4d58d769f487f6326649b97d7c4b829bfdf21..8562284afbc7393ea9adb0a5c2dcf5b29d756472 100644 --- a/fml/message_loop_impl.cc +++ b/fml/message_loop_impl.cc @@ -18,6 +18,8 @@ #include "flutter/fml/platform/android/message_loop_android.h" #elif OS_FUCHSIA #include "flutter/fml/platform/fuchsia/message_loop_fuchsia.h" +#elif FML_OS_OHOS +#include "flutter/fml/platform/ohos/message_loop_ohos.h" #elif FML_OS_LINUX #include "flutter/fml/platform/linux/message_loop_linux.h" #elif FML_OS_WIN @@ -26,13 +28,15 @@ namespace fml { -fml::RefPtr MessageLoopImpl::Create() { +fml::RefPtr MessageLoopImpl::Create(void* platform_loop) { #if FML_OS_MACOSX return fml::MakeRefCounted(); #elif FML_OS_ANDROID return fml::MakeRefCounted(); #elif OS_FUCHSIA return fml::MakeRefCounted(); +#elif FML_OS_OHOS +return fml::MakeRefCounted(platform_loop); #elif FML_OS_LINUX return fml::MakeRefCounted(); #elif FML_OS_WIN diff --git a/fml/message_loop_impl.h b/fml/message_loop_impl.h index 270cc3c86a9ade6627e79df23dcb91c502e42bbb..865ffb43ebe3e1667e268faeb830ea5ea0d122ca 100644 --- a/fml/message_loop_impl.h +++ b/fml/message_loop_impl.h @@ -31,7 +31,7 @@ namespace fml { class MessageLoopImpl : public Wakeable, public fml::RefCountedThreadSafe { public: - static fml::RefPtr Create(); + static fml::RefPtr Create(void* platform_loop); virtual ~MessageLoopImpl(); diff --git a/fml/platform/ohos/message_loop_ohos.cc b/fml/platform/ohos/message_loop_ohos.cc new file mode 100644 index 0000000000000000000000000000000000000000..9a0f7b52bf4c7918a5e5863ae654df691bbf0fab --- /dev/null +++ b/fml/platform/ohos/message_loop_ohos.cc @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/fml/platform/ohos/message_loop_ohos.h" + +#include +#include + +#include "flutter/fml/eintr_wrapper.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/platform/ohos/timerfd.h" + +namespace fml { + +static constexpr int kClockType = CLOCK_MONOTONIC; + +void MessageLoopOhos::OnPollCallback(uv_poll_t* handle, + int status, + int events) { + if (status < 0) { + FML_DLOG(ERROR) << "Poll error:" << uv_strerror(status); + return; + } + + if (events & UV_READABLE) { + reinterpret_cast(handle->data)->OnEventFired(); + } +} + +MessageLoopOhos::MessageLoopOhos(void* platform_loop) + : timer_fd_(::timerfd_create(kClockType, TFD_NONBLOCK | TFD_CLOEXEC)), + running_(false) { + if (platform_loop != nullptr) { + uv_loop_t* loop = reinterpret_cast(platform_loop); + uv_poll_init(loop, &poll_handle_, timer_fd_.get()); + } else { + uv_loop_init(&loop_); + uv_poll_init(&loop_, &poll_handle_, timer_fd_.get()); + } + poll_handle_.data = this; + uv_poll_start(&poll_handle_, UV_READABLE, OnPollCallback); + FML_CHECK(timer_fd_.is_valid()); +} + +MessageLoopOhos::~MessageLoopOhos() { + uv_poll_stop(&poll_handle_); + if (uv_loop_alive(&loop_)) { + uv_loop_close(&loop_); + } +} + +// |fml::MessageLoopImpl| +void MessageLoopOhos::Run() { + running_ = true; + uv_run(&loop_, UV_RUN_DEFAULT); +} + +// |fml::MessageLoopImpl| +void MessageLoopOhos::Terminate() { + running_ = false; + WakeUp(fml::TimePoint::Now()); +} + +// |fml::MessageLoopImpl| +void MessageLoopOhos::WakeUp(fml::TimePoint time_point) { + bool result = TimerRearm(timer_fd_.get(), time_point); + (void)result; + FML_DCHECK(result); +} + +void MessageLoopOhos::OnEventFired() { + if (TimerDrain(timer_fd_.get())) { + RunExpiredTasksNow(); + } +} + +} // namespace fml diff --git a/fml/platform/ohos/message_loop_ohos.h b/fml/platform/ohos/message_loop_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..448a2bf67990d3e7974e4e9e2c10ace7010c7317 --- /dev/null +++ b/fml/platform/ohos/message_loop_ohos.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_FML_PLATFORM_OHOS_MESSAGE_LOOP_OHOS_H_ +#define FLUTTER_FML_PLATFORM_OHOS_MESSAGE_LOOP_OHOS_H_ + +#include + +#include +#include "flutter/fml/macros.h" +#include "flutter/fml/message_loop_impl.h" +#include "flutter/fml/unique_fd.h" + +namespace fml { + +class MessageLoopOhos : public MessageLoopImpl { + private: + uv_poll_t poll_handle_; + uv_loop_t loop_; + fml::UniqueFD timer_fd_; + bool running_; + + MessageLoopOhos(void* platform_loop); + + ~MessageLoopOhos() override; + + // |fml::MessageLoopImpl| + void Run() override; + + // |fml::MessageLoopImpl| + void Terminate() override; + + // |fml::MessageLoopImpl| + void WakeUp(fml::TimePoint time_point) override; + + void OnEventFired(); + + FML_FRIEND_MAKE_REF_COUNTED(MessageLoopOhos); + FML_FRIEND_REF_COUNTED_THREAD_SAFE(MessageLoopOhos); + FML_DISALLOW_COPY_AND_ASSIGN(MessageLoopOhos); + + public: + static void OnPollCallback(uv_poll_t* handle, int status, int events); +}; + +} // namespace fml + +#endif // FLUTTER_FML_PLATFORM_OHOS_MESSAGE_LOOP_OHOS_H_ diff --git a/fml/platform/ohos/message_loop_ohos_test.cc b/fml/platform/ohos/message_loop_ohos_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..1aa1db255e040ed052207884bf55782ec751987a --- /dev/null +++ b/fml/platform/ohos/message_loop_ohos_test.cc @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/fml/message_loop.h" + +#include +#include + +#include "flutter/fml/build_config.h" +#include "flutter/fml/concurrent_message_loop.h" +#include "flutter/fml/synchronization/count_down_latch.h" +#include "flutter/fml/synchronization/waitable_event.h" +#include "flutter/fml/task_runner.h" +#include "flutter/fml/time/chrono_timestamp_provider.h" +#include "gtest/gtest.h" + +namespace fml { +namespace message_loop_test { + +#define PLATFORM_SPECIFIC_CAPTURE(...) [__VA_ARGS__] + +/** + * breif: 注册异步任务 + * + */ +void MessageLoopTestPostTask(void) { + bool started = false; + bool terminated = false; + std::thread thread([&started, &terminated]() { + fml::MessageLoop::EnsureInitializedForCurrentThread(); + auto& loop = fml::MessageLoop::GetCurrent(); + ASSERT_TRUE(loop.GetTaskRunner()); + loop.GetTaskRunner()->PostTask([&terminated]() { + std::cout << "MessageLoopTestPostTask running ..." << std::endl; + fml::MessageLoop::GetCurrent().Terminate(); + terminated = true; + }); + loop.Run(); + started = true; + }); + thread.join(); + ASSERT_TRUE(started); + ASSERT_TRUE(terminated); +} + +/** + * breif: + * 进行观察者测试,注册25个任务后,添加观察者,在回调中增加观察者回调打印 + * + */ +void MessageLoopTestObserverFire(void) { + bool started = false; + bool terminated = false; + std::thread thread([&started, &terminated]() { + fml::MessageLoop::EnsureInitializedForCurrentThread(); + const size_t count = 25; + auto& loop = fml::MessageLoop::GetCurrent(); + size_t task_count = 0; + size_t obs_count = 0; + auto obs = PLATFORM_SPECIFIC_CAPTURE(&obs_count)() { + obs_count++; + std::cout << "MessageLoopTestObserverFire obs_count" << obs_count + << std::endl; + }; + for (size_t i = 0; i < count; i++) { + loop.GetTaskRunner()->PostTask( + PLATFORM_SPECIFIC_CAPTURE(&terminated, i, &task_count)() { + ASSERT_EQ(task_count, i); + task_count++; + if (count == i + 1) { + fml::MessageLoop::GetCurrent().Terminate(); + terminated = true; + } + }); + } + loop.AddTaskObserver(0, obs); + loop.Run(); + ASSERT_EQ(task_count, count); + ASSERT_EQ(obs_count, count); + started = true; + }); + thread.join(); + ASSERT_TRUE(started); + ASSERT_TRUE(terminated); +} + +} // namespace message_loop_test +} // namespace fml \ No newline at end of file diff --git a/fml/platform/ohos/message_loop_ohos_test.h b/fml/platform/ohos/message_loop_ohos_test.h new file mode 100644 index 0000000000000000000000000000000000000000..f0e74721e39d4d9bc2b0dd634c175256363b1681 --- /dev/null +++ b/fml/platform/ohos/message_loop_ohos_test.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_FML_PLATFORM_OHOS_LOOP_TEST_H_ +#define FLUTTER_FML_PLATFORM_OHOS_LOOP_TEST_H_ + +namespace fml { +namespace message_loop_test { + +void MessageLoopTestPostTask(void); +void MessageLoopTestObserverFire(void); + +} // namespace message_loop_test +} // namespace fml + +#endif // FLUTTER_FML_PLATFORM_OHOS_LOOP_TEST_H_ diff --git a/fml/platform/ohos/napi_util.cc b/fml/platform/ohos/napi_util.cc new file mode 100644 index 0000000000000000000000000000000000000000..87a32b2554dba578e431091e6aa6e6cb13dff9d4 --- /dev/null +++ b/fml/platform/ohos/napi_util.cc @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/fml/platform/ohos/napi_util.h" +#include +#include +#include + +namespace fml { +namespace napi { + +bool NapiIsNull(napi_env env, napi_value value) { + return value == nullptr || NapiIsType(env, value, napi_null); +} +bool NapiIsNotType(napi_env env, napi_value value, napi_valuetype type) { + return !NapiIsType(env, value, type); +} +std::string NapiGetLastError(napi_env env, napi_status status) { + std::string ret("Napi Error:"); + ret += status; + + const napi_extended_error_info* error_info; + napi_get_last_error_info(env, &error_info); + ret += error_info->error_message; + return ret; +} +bool NapiIsType(napi_env env, napi_value value, napi_valuetype type) { + napi_status status; + napi_valuetype argType; + status = napi_typeof(env, value, &argType); + return status == napi_ok && type == argType; +} +bool NapiIsAnyType(napi_env env, napi_value value, ...) { + napi_status status; + napi_valuetype argType; + status = napi_typeof(env, value, &argType); + + if (status != napi_ok) { + return false; + } + + bool matched = false; + { + va_list types; + va_start(types, value); + napi_valuetype cur; + while (!matched) { + cur = va_arg(types, napi_valuetype); + matched = (cur == argType); + } + va_end(types); + } + return matched; +} +void NapiPrintValueTypes(napi_env env, int argc, napi_value* args) { + FML_DLOG(INFO) << "argc: " << argc; + for (int i = 0; i < argc; i++) { + napi_value cur = args[i]; + FML_DLOG(INFO) << "arg: " << i << ",null?" << (cur == nullptr); + if (cur != nullptr) { + NapiPrintValueType(env, cur); + } + } +} + +bool IsArrayBuffer(napi_env env, napi_value value) { + napi_status status; + bool result; + + // Check if the value is an ArrayBuffer + status = napi_is_arraybuffer(env, value, &result); + if (status != napi_ok) { + FML_DLOG(INFO) << "napi_is_arraybuffer: failed:" << status; + return false; + } + + // If it's not an ArrayBuffer, check if it's an Array + if (!result) { + status = napi_is_array(env, value, &result); + if (status != napi_ok) { + FML_DLOG(INFO) << "napi_is_array: failed:" + << NapiGetLastError(env, status); + return false; + } + } + return true; +} + +void NapiPrintValueType(napi_env env, napi_value cur) { + napi_status status; + napi_valuetype argType; + int i = 0; + status = napi_typeof(env, cur, &argType); + if (status != napi_ok) { + FML_DLOG(INFO) << "args,gettype: failed:" << status; + return; + } + if (argType == napi_number) { + FML_DLOG(INFO) << "args,type: " << argType << " number"; + } else if (argType == napi_string) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_string"; + } else if (argType == napi_boolean) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_boolean "; + } else if (argType == napi_object) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_object"; + } else if (argType == napi_function) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_function"; + } else if (argType == napi_null) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_null "; + } else if (argType == napi_symbol) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_symbol"; + } else if (argType == napi_external) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_external"; + } else if (argType == napi_bigint) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_bigint"; + } else { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " number"; + } + bool ok = false; + napi_is_array(env, cur, &ok); + if (ok) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " is_array "; + } + //(env,cur,&ok); + if (IsArrayBuffer(env, cur)) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType + << " is_arraybuffer "; + } + napi_is_typedarray(env, cur, &ok); + if (ok) { + FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " is_typearray"; + } +} + +int32_t GetString(napi_env env, napi_value arg, std::string& strValue) { + napi_status status; + + if (NapiIsType(env, arg, napi_null)) { + FML_DLOG(INFO) << "napi_null"; + strValue = ""; + return SUCCESS; + } + if (!NapiIsType(env, arg, napi_string)) { + FML_DLOG(ERROR) << "Invalid type:"; + return ERROR_TYPE; + } + + std::vector buff(STRING_MAX_LENGTH); + size_t copy_lenth; + status = napi_get_value_string_utf8(env, arg, static_cast(buff.data()), + STRING_MAX_LENGTH, ©_lenth); + if (status != napi_ok) { + FML_DLOG(ERROR) << "Error get string:" << status; + FML_DLOG(ERROR) << "result size:" << copy_lenth; + return status; + } + strValue.assign(buff.data(), copy_lenth); + return SUCCESS; +} + +int32_t GetArrayString(napi_env env, + napi_value arg, + std::vector& arrayString) { + uint32_t arrayLenth; + napi_status status = napi_get_array_length(env, arg, &arrayLenth); + if (status != napi_ok) { + FML_DLOG(ERROR) << "Failed to napi_get_array_length:" << status; + return status; + } + FML_DLOG(INFO) << "GetArrayString length:" << arrayLenth; + for (uint32_t i = 0; i < arrayLenth; i++) { + napi_value element; + napi_get_element(env, arg, i, &element); + std::string str; + GetString(env, element, str); + arrayString.push_back(str); + } + return SUCCESS; +} +int32_t GetArrayBuffer(napi_env env, + napi_value arg, + void** message, + size_t* lenth) { + napi_status status; + // bool ok = false ; + if (NapiIsType(env, arg, napi_null)) { + FML_DLOG(ERROR) << "GetArrayBuffer value is null :"; + return ERROR_NULL; + } + + // if( napi_ok != (status = napi_is_arraybuffer(env,arg,& ok )) ){ + if (!IsArrayBuffer(env, arg)) { + // FML_DLOG(ERROR)<<"GetArrayBuffer valueType is Not arraybuffer + // status:"< +#include +#include +#include +#include "flutter/fml/logging.h" +#include "napi/native_api.h" + +namespace fml { +namespace napi { +enum { + SUCCESS = 0, + ERROR_TYPE = -100, + ERROR_NULL, +}; +const int32_t STRING_MAX_LENGTH = 512; +int32_t GetString(napi_env env, napi_value arg, std::string& strValue); +int32_t GetArrayString(napi_env env, + napi_value arg, + std::vector& arrayString); +int32_t GetArrayBuffer(napi_env env, + napi_value arg, + void** message, + size_t* lenth); + +/** + * 打印napi_value @args 的类型信息 + */ +void NapiPrintValueTypes(napi_env env, int argc, napi_value* argv); +/** + * 打印napi_value @cur 的类型信息 + */ +void NapiPrintValueType(napi_env env, napi_value cur); + +/** + * 判断napi value 类型 + */ +bool NapiIsType(napi_env env, napi_value value, napi_valuetype type); +bool NapiIsNotType(napi_env env, napi_value value, napi_valuetype type); +/** + * 判断napi value类型是否是其中的一种 + */ +bool NapiIsAnyType(napi_env env, napi_value value, ...); +/** + * 判断值是否为空 + */ +bool NapiIsNull(napi_env env, napi_value value); + +/** + * 创建ArrayBuffer + */ +napi_value CreateArrayBuffer(napi_env env, void* inputData, size_t dataSize); + +/** + * 回调JS方法 + */ +napi_status InvokeJsMethod(napi_env env_, + napi_ref ref_napi_obj_, + const char* methodName, + size_t argc, + const napi_value* argv); +} // namespace napi +} // namespace fml +#endif diff --git a/fml/platform/ohos/paths_ohos.cc b/fml/platform/ohos/paths_ohos.cc new file mode 100644 index 0000000000000000000000000000000000000000..056bdd3770dc917d8aaf0025fc1b548eccd9d9a2 --- /dev/null +++ b/fml/platform/ohos/paths_ohos.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/fml/platform/ohos/paths_ohos.h" + +#include "flutter/fml/file.h" + +namespace fml { +namespace paths { + +std::pair GetExecutablePath() { + return {false, ""}; +} + +static std::string gCachesPath; + +void InitializeOhosCachesPath(std::string caches_path) { + gCachesPath = std::move(caches_path); +} + +fml::UniqueFD GetCachesDirectory() { + // If the caches path is not initialized, the FD will be invalid and caching + // will be disabled throughout the system. + return OpenDirectory(gCachesPath.c_str(), false, fml::FilePermission::kRead); +} + +} // namespace paths +} // namespace fml diff --git a/fml/platform/ohos/paths_ohos.h b/fml/platform/ohos/paths_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..494d1516a128955d749d18317ee627b872d33f02 --- /dev/null +++ b/fml/platform/ohos/paths_ohos.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_FML_PLATFORM_OHOS_PATHS_OHOS_H_ +#define FLUTTER_FML_PLATFORM_OHOS_PATHS_OHOS_H_ + +#include "flutter/fml/macros.h" +#include "flutter/fml/paths.h" + +namespace fml { +namespace paths { + +void InitializeOhosCachesPath(std::string caches_path); + +} // namespace paths +} // namespace fml + +#endif // FLUTTER_FML_PLATFORM_OHOS_PATHS_OHOS_H_ diff --git a/fml/platform/ohos/timerfd.cc b/fml/platform/ohos/timerfd.cc new file mode 100644 index 0000000000000000000000000000000000000000..c15e4eaa991a1604c1e142ee26d6545ca1b9a9bc --- /dev/null +++ b/fml/platform/ohos/timerfd.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/fml/platform/ohos/timerfd.h" + +#include +#include +#include + +#include "flutter/fml/eintr_wrapper.h" +#include "flutter/fml/logging.h" + +#if FML_TIMERFD_AVAILABLE == 0 + +#include +#include + +int timerfd_create(int clockid, int flags) { + return syscall(__NR_timerfd_create, clockid, flags); +} + +int timerfd_settime(int ufc, + int flags, + const struct itimerspec* utmr, + struct itimerspec* otmr) { + return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr); +} + +#endif // FML_TIMERFD_AVAILABLE == 0 + +namespace fml { + +#ifndef NSEC_PER_SEC +#define NSEC_PER_SEC 1000000000 +#endif + +bool TimerRearm(int fd, fml::TimePoint time_point) { + uint64_t nano_secs = time_point.ToEpochDelta().ToNanoseconds(); + + // "0" will disarm the timer, desired behavior is to immediately + // trigger the timer. + if (nano_secs < 1) { + nano_secs = 1; + } + + struct itimerspec spec = {}; + spec.it_value.tv_sec = static_cast(nano_secs / NSEC_PER_SEC); + spec.it_value.tv_nsec = nano_secs % NSEC_PER_SEC; + spec.it_interval = spec.it_value; // single expiry. + + int result = ::timerfd_settime(fd, TFD_TIMER_ABSTIME, &spec, nullptr); + if (result != 0) { + FML_DLOG(ERROR) << "timerfd_settime err:" << strerror(errno); + } + return result == 0; +} + +bool TimerDrain(int fd) { + // 8 bytes must be read from a signaled timer file descriptor when signaled. + uint64_t fire_count = 0; + ssize_t size = FML_HANDLE_EINTR(::read(fd, &fire_count, sizeof(uint64_t))); + if (size != sizeof(uint64_t)) { + return false; + } + return fire_count > 0; +} + +} // namespace fml diff --git a/fml/platform/ohos/timerfd.h b/fml/platform/ohos/timerfd.h new file mode 100644 index 0000000000000000000000000000000000000000..b2715d83f63faf46136f2abc506dcf046e5b8467 --- /dev/null +++ b/fml/platform/ohos/timerfd.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_FML_PLATFORM_OHOS_TIMER_FD_H_ +#define FLUTTER_FML_PLATFORM_OHOS_TIMER_FD_H_ + +#include "flutter/fml/time/time_point.h" + +// clang-format off +#if __has_include() && \ + (!defined(__ANDROID_API__) || __ANDROID_API__ >= 19) + // sys/timerfd.h is always present in Android NDK due to unified headers, + // but timerfd functions are only available on API 19 or later. +// clang-format on + +#include + +#define FML_TIMERFD_AVAILABLE 1 + +#else // __has_include() + +#define FML_TIMERFD_AVAILABLE 0 + +#include +// Must come after sys/types +#include + +#define TFD_TIMER_ABSTIME (1 << 0) +#define TFD_TIMER_CANCEL_ON_SET (1 << 1) + +#define TFD_CLOEXEC O_CLOEXEC +#define TFD_NONBLOCK O_NONBLOCK + +int timerfd_create(int clockid, int flags); + +int timerfd_settime(int ufc, + int flags, + const struct itimerspec* utmr, + struct itimerspec* otmr); + +#endif // __has_include() + +namespace fml { + +/// Rearms the timer to expire at the given time point. +bool TimerRearm(int fd, fml::TimePoint time_point); + +/// Drains the timer FD and returns true if it has expired. This may be false in +/// case the timer read is non-blocking and this routine was called before the +/// timer expiry. +bool TimerDrain(int fd); + +} // namespace fml + +#endif // FLUTTER_FML_PLATFORM_OHOS_TIMER_FD_H_ diff --git a/fml/thread.cc b/fml/thread.cc index a905fd071eaa9a86935e7c854c4bf035d5a30a46..e74e8ab5b41f88bb2f1d2658f6bcc60e0698ac33 100644 --- a/fml/thread.cc +++ b/fml/thread.cc @@ -13,6 +13,7 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/message_loop.h" #include "flutter/fml/synchronization/waitable_event.h" +#include "flutter/fml/logging.h" #if defined(FML_OS_WIN) #include @@ -42,8 +43,9 @@ void SetThreadName(const std::string& name) { } #if defined(FML_OS_MACOSX) pthread_setname_np(name.c_str()); -#elif defined(FML_OS_LINUX) || defined(FML_OS_ANDROID) +#elif defined(FML_OS_LINUX) || defined(FML_OS_ANDROID) || defined(FML_OS_OHOS) pthread_setname_np(pthread_self(), name.c_str()); + FML_DLOG(INFO) << "set the thread name to '" << name; #elif defined(FML_OS_WIN) THREADNAME_INFO info; info.dwType = 0x1000; diff --git a/fml/thread_local.h b/fml/thread_local.h index 010c0ff643dd33a7516bee5c52c55cb3d8894f39..a5f3ba08e2d31ca357ee76e21979bca092cdc723 100644 --- a/fml/thread_local.h +++ b/fml/thread_local.h @@ -11,7 +11,7 @@ #include "flutter/fml/macros.h" #define FML_THREAD_LOCAL_PTHREADS \ - FML_OS_MACOSX || FML_OS_LINUX || FML_OS_ANDROID + FML_OS_MACOSX || FML_OS_LINUX || FML_OS_ANDROID || FML_OS_OHOS #if FML_THREAD_LOCAL_PTHREADS #include diff --git a/fml/thread_unittests.cc b/fml/thread_unittests.cc index 65479762823fc1d325b75849bcd58db827005311..095fc2dad42537ef5798495dbb4235a98081f1e6 100644 --- a/fml/thread_unittests.cc +++ b/fml/thread_unittests.cc @@ -4,7 +4,7 @@ #include "flutter/fml/thread.h" -#if defined(FML_OS_MACOSX) || defined(FML_OS_LINUX) || defined(FML_OS_ANDROID) +#if defined(FML_OS_MACOSX) || defined(FML_OS_LINUX) || defined(FML_OS_ANDROID) || defined(FML_OS_OHOS) #define FLUTTER_PTHREAD_SUPPORTED 1 #else #define FLUTTER_PTHREAD_SUPPORTED 0 diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 687d19f4012b576059e9b41a8c36ece4fee61a45..3215629734e60a3726d56fe2e0de3e04aa5d6516 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -341,6 +341,8 @@ std::optional BlendFilterContents::RenderFilter( foreground_color_, GetAbsorbOpacity()); } FML_UNREACHABLE(); + std::optional ret; + return ret; } } // namespace impeller diff --git a/impeller/entity/contents/filters/inputs/filter_input.cc b/impeller/entity/contents/filters/inputs/filter_input.cc index 4f61ba49fa9d5d4edb3e2b1a32227e06e1f762d5..b19ac60bbb4c6c2feabf3112b17679e4f1f8ca12 100644 --- a/impeller/entity/contents/filters/inputs/filter_input.cc +++ b/impeller/entity/contents/filters/inputs/filter_input.cc @@ -33,6 +33,7 @@ FilterInput::Ref FilterInput::Make(Variant input) { } FML_UNREACHABLE(); + return std::shared_ptr(); } FilterInput::Ref FilterInput::Make(std::shared_ptr texture, diff --git a/impeller/entity/entity_pass_delegate.cc b/impeller/entity/entity_pass_delegate.cc index 529c8698f68bd31f3126dda56e72823a0aef9aa5..8455f1adf0f25f5f324bd03bb171c2f8a81103a2 100644 --- a/impeller/entity/entity_pass_delegate.cc +++ b/impeller/entity/entity_pass_delegate.cc @@ -31,7 +31,9 @@ class DefaultEntityPassDelegate final : public EntityPassDelegate { std::shared_ptr target, const Matrix& effect_transform) override { // Not possible since this pass always collapses into its parent. + std::shared_ptr ret; FML_UNREACHABLE(); + return ret; } private: diff --git a/impeller/toolkit/egl/display.h b/impeller/toolkit/egl/display.h index 07f5d251291894e01980f035edf6b7b40ded9f63..420d143697b0157fd36f7b47c798ebb83d94e51a 100644 --- a/impeller/toolkit/egl/display.h +++ b/impeller/toolkit/egl/display.h @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#pragma once +#ifndef EGL_DISPLAY_H +#define EGL_DISPLAY_H #include #include @@ -45,3 +46,5 @@ class Display { } // namespace egl } // namespace impeller + +#endif diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni index e6e71edfbeae63aed315fe5266701a90c5bd3af8..2badbbff65bb32ef21d102be5582d5efaef9e653 100644 --- a/impeller/tools/impeller.gni +++ b/impeller/tools/impeller.gni @@ -14,10 +14,11 @@ declare_args() { impeller_enable_metal = is_mac || is_ios # Whether the OpenGLES backend is enabled. - impeller_enable_opengles = is_mac || is_linux || is_win || is_android + impeller_enable_opengles = is_mac || is_linux || is_win || is_android ||is_ohos # Whether the Vulkan backend is enabled. - impeller_enable_vulkan = is_linux || is_android + #impeller_enable_vulkan = is_mac || is_linux || is_win || is_android + impeller_enable_vulkan = is_mac || is_win || is_android # Whether to use a prebuilt impellerc. # If this is the empty string, impellerc will be built. diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index 733b8a2903e7132197f6365c36528465ca44664a..9cd15cd4ead378eea37465e7bf7e8fa83b62b9af 100644 --- a/lib/ui/painting/canvas.cc +++ b/lib/ui/painting/canvas.cc @@ -25,6 +25,8 @@ #include "third_party/tonic/dart_binding_macros.h" #include "third_party/tonic/dart_library_natives.h" +#include "flutter/fml/logging.h" + using tonic::ToDart; namespace flutter { @@ -249,7 +251,7 @@ void Canvas::drawLine(double x1, void Canvas::drawPaint(Dart_Handle paint_objects, Dart_Handle paint_data) { Paint paint(paint_objects, paint_data); - + FML_DLOG(INFO)<<"drawPaint:" <<(int64_t)paint_objects ; FML_DCHECK(paint.isNotNull()); if (display_list_recorder_) { paint.sync_to(builder(), kDrawPaintFlags); diff --git a/lib/ui/painting/paint.cc b/lib/ui/painting/paint.cc index 2849526ca00a4c639a8e0b2fdb720c3c06365531..e7daf2a3375e035e255992090c67eec5ff3fcc13 100644 --- a/lib/ui/painting/paint.cc +++ b/lib/ui/painting/paint.cc @@ -74,7 +74,7 @@ const SkPaint* Paint::paint(SkPaint& paint) const { return nullptr; } FML_DCHECK(paint == SkPaint()); - + FML_DLOG(INFO) << " Paint::paint " ; tonic::DartByteData byte_data(paint_data_); FML_CHECK(byte_data.length_in_bytes() == kDataByteCount); @@ -336,6 +336,7 @@ void Paint::toDlPaint(DlPaint& paint) const { return; } FML_DCHECK(paint == DlPaint()); + FML_DLOG(INFO) << " Paint::toDlPaint" ; tonic::DartByteData byte_data(paint_data_); FML_CHECK(byte_data.length_in_bytes() == kDataByteCount); diff --git a/lib/ui/platform_dispatcher.dart b/lib/ui/platform_dispatcher.dart index 20349ded2fe43785f7d1ac1d3c936cc1fc5d7867..03bcc662c3026f0b81593e0a06075d7c4913f66a 100644 --- a/lib/ui/platform_dispatcher.dart +++ b/lib/ui/platform_dispatcher.dart @@ -335,6 +335,7 @@ class PlatformDispatcher { // Called from the engine, via hooks.dart void _drawFrame() { + print("platform_dispatcher::drawFrame..${_onDrawFrame}") ; _invoke(onDrawFrame, _onDrawFrameZone); } diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index d3d56c13f1029d0ceb59ff07d98a020d1f954df6..d4333231d468b28e8cf140f89519dc287940ed4f 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -143,6 +143,10 @@ void PlatformConfiguration::DispatchPlatformMessage( std::unique_ptr message) { std::shared_ptr dart_state = dispatch_platform_message_.dart_state().lock(); + + FML_DLOG(INFO) + << "DispatchPlatformMessage channel: " + << message->channel(); if (!dart_state) { FML_DLOG(WARNING) << "Dropping platform message for lack of DartState on channel: " @@ -176,6 +180,9 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id, fml::MallocMapping args) { std::shared_ptr dart_state = dispatch_semantics_action_.dart_state().lock(); + FML_DLOG(INFO) + << "DispatchSemanticsAction : " + << id ; if (!dart_state) { return; } @@ -350,6 +357,7 @@ Dart_Handle PlatformConfigurationNativeApi::SendPortPlatformMessage( void PlatformConfigurationNativeApi::RespondToPlatformMessage( int response_id, const tonic::DartByteData& data) { + FML_DLOG(INFO)<<"PlatformConfigurationNativeApi::RespondToPlatformMessage:" << response_id; if (Dart_IsNull(data.dart_handle())) { UIDartState::Current() ->platform_configuration() diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 0f819ef9981c11e5d9515702f184eed4d4245e19..56c6ed15bbbf1721fe805ac08c5db68a858b9ffc 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -805,8 +805,10 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( settings.observatory_host, // server IP address settings.observatory_port, // server observatory port tonic::DartState::HandleLibraryTag, // embedder library tag handler - false, // disable websocket origin check - settings.disable_service_auth_codes, // disable VM service auth codes + true, + //false, // disable websocket origin check + true, // disable VM service auth codes + //settings.disable_service_auth_codes, // disable VM service auth codes settings.enable_service_port_fallback, // enable fallback to port 0 // when bind fails. error // error (out) diff --git a/runtime/dart_service_isolate.cc b/runtime/dart_service_isolate.cc index 18b51a32a6f1a33fa538a14bd39c74b7aa80ea71..17fa47d1baa3f67e1e7d6569890cc217b248f7ba 100644 --- a/runtime/dart_service_isolate.cc +++ b/runtime/dart_service_isolate.cc @@ -180,11 +180,13 @@ bool DartServiceIsolate::Startup(const std::string& server_ip, SHUTDOWN_ON_ERROR(result); result = Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"), - Dart_NewBoolean(disable_origin_check)); + Dart_NewBoolean(true)); + //Dart_NewBoolean(disable_origin_check)); SHUTDOWN_ON_ERROR(result); result = Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"), - Dart_NewBoolean(disable_service_auth_codes)); + Dart_NewBoolean(true)); + //Dart_NewBoolean(disable_service_auth_codes)); SHUTDOWN_ON_ERROR(result); result = Dart_SetField( library, Dart_NewStringFromCString("_enableServicePortFallback"), diff --git a/runtime/dart_snapshot.cc b/runtime/dart_snapshot.cc index 5943524aa9f8066ae8738b028f1c42c595bb6200..cb92670b8997b59ec6ab77cd2bda3413e07ed5cb 100644 --- a/runtime/dart_snapshot.cc +++ b/runtime/dart_snapshot.cc @@ -9,6 +9,7 @@ #include "flutter/fml/native_library.h" #include "flutter/fml/paths.h" #include "flutter/fml/trace_event.h" +#include "flutter/fml/logging.h" #include "flutter/lib/snapshot/snapshot.h" #include "flutter/runtime/dart_vm.h" #include "third_party/dart/runtime/include/dart_api.h" @@ -56,6 +57,7 @@ static std::shared_ptr SearchMapping( const std::vector& native_library_path, const char* native_library_symbol_name, bool is_executable) { + FML_LOG(INFO)<<"SearchMapping file:"< SearchMapping( static std::shared_ptr ResolveVMData( const Settings& settings) { #if DART_SNAPSHOT_STATIC_LINK + FML_LOG(ERROR)<<"ResolveVMData: NonOwnedMapping" ; return std::make_unique(kDartVmSnapshotData, 0, // size nullptr, // release_func diff --git a/shell/common/animator.cc b/shell/common/animator.cc index b396b0a4e2da08093ff3ccf74a716a0808d7da3d..07963bf190de9d0a801faa7c366eb447ba75c693 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -8,6 +8,7 @@ #include "flutter/fml/time/time_point.h" #include "flutter/fml/trace_event.h" #include "third_party/dart/runtime/include/dart_tools_api.h" +#include "flutter/fml/logging.h" namespace flutter { @@ -111,6 +112,7 @@ void Animator::BeginFrame( // time to start doing GC work. task_runners_.GetUITaskRunner()->PostDelayedTask( [self = weak_factory_.GetWeakPtr()]() { + if (!self) { return; } diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 7d2a63d57cad2ae43ab0295cc2cdbdd71fdae77f..bbdf61cac7194f7b779497f4e7d85ee76d0a8b14 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -443,15 +443,24 @@ void Engine::ScheduleFrame(bool regenerate_layer_tree) { void Engine::Render(std::shared_ptr layer_tree) { if (!layer_tree) { + FML_DLOG(ERROR) << "Render layer_tree IS NULL"; return; } + if (layer_tree->frame_size().isEmpty()){ + FML_DLOG(INFO) << "engin Render frame_size is empty"; + } + + if (layer_tree->device_pixel_ratio() <= 0.0f){ + FML_DLOG(INFO) << "engin Render device_pixel_ratio <= 0"; + } + // Ensure frame dimensions are sane. if (layer_tree->frame_size().isEmpty() || layer_tree->device_pixel_ratio() <= 0.0f) { + FML_DLOG(INFO) << "engin layer_tree isEmpty"; return; } - animator_->Render(std::move(layer_tree)); } diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index ce2b22009f8211cc230da3f49b42eb7324e9428f..03523f5682a26398b99ca4c660939274a96d57dc 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -14,7 +14,9 @@ namespace flutter { PlatformView::PlatformView(Delegate& delegate, const TaskRunners& task_runners) - : delegate_(delegate), task_runners_(task_runners), weak_factory_(this) {} + : delegate_(delegate), task_runners_(task_runners), weak_factory_(this) { + FML_LOG(INFO)<<"PlatformView"; + } PlatformView::~PlatformView() = default; diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 479988440a6cc91b5b87c92b25958f7dff7ec320..78a42915e1244d08a09060700aa505bfe6a6e9c9 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -22,6 +22,8 @@ #include "third_party/skia/include/core/SkSurfaceCharacterization.h" #include "third_party/skia/include/utils/SkBase64.h" +#include "flutter/fml/logging.h" + namespace flutter { // The rasterizer will tell Skia to purge cached resources that have not been @@ -158,6 +160,7 @@ flutter::LayerTree* Rasterizer::GetLastLayerTree() { void Rasterizer::DrawLastLayerTree( std::unique_ptr frame_timings_recorder) { if (!last_layer_tree_ || !surface_) { + FML_DLOG(ERROR)<<"DrawLastLayerTree last_layer_tree_ or surface_ is nullptr " ; return; } RasterStatus raster_status = @@ -490,7 +493,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree) { FML_DCHECK(surface_); - + compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); @@ -603,8 +606,11 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( } compositor_context_->raster_cache().EndFrame(); + frame_timings_recorder.RecordRasterEnd( &compositor_context_->raster_cache()); + + FireNextFrameCallbackIfPresent(); if (surface_->GetContext()) { diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 693d36a14336690323ee8b2cfa87cf77f2b249c2..b0bf51ae5d5cc87e53aeb2f9544b01fc6a8e5bd0 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #define RAPIDJSON_HAS_STDSTRING 1 #include "flutter/shell/common/shell.h" @@ -76,13 +77,12 @@ std::unique_ptr CreateEngine( // that cause shell initialization failures will still lead to some of their // settings being applied. void PerformInitializationTasks(Settings& settings) { - { +/* { fml::LogSettings log_settings; log_settings.min_log_level = settings.verbose_logging ? fml::LOG_INFO : fml::LOG_ERROR; fml::SetLogSettings(log_settings); - } - + } */ static std::once_flag gShellSettingsInitialization = {}; std::call_once(gShellSettingsInitialization, [&settings] { tonic::SetLogHandler( @@ -98,8 +98,6 @@ void PerformInitializationTasks(Settings& settings) { if (!settings.skia_deterministic_rendering_on_cpu) { SkGraphics::Init(); - } else { - FML_DLOG(INFO) << "Skia deterministic rendering is enabled."; } if (settings.icu_initialization_required) { @@ -112,7 +110,6 @@ void PerformInitializationTasks(Settings& settings) { } } }); - PersistentCache::SetCacheSkSL(settings.cache_sksl); } @@ -301,6 +298,7 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( shell->volatile_path_tracker_)); })); + if (!shell->Setup(std::move(platform_view), // engine_future.get(), // rasterizer_future.get(), // @@ -336,7 +334,6 @@ std::unique_ptr Shell::CreateWithSnapshot( if (!task_runners.IsValid() || !callbacks_valid) { return nullptr; } - fml::AutoResetWaitableEvent latch; std::unique_ptr shell; auto platform_task_runner = task_runners.GetPlatformTaskRunner(); @@ -521,6 +518,7 @@ std::unique_ptr Shell::Spawn( fml::SyncSwitch::Handlers() .SetIfFalse([&is_gpu_disabled] { is_gpu_disabled = false; }) .SetIfTrue([&is_gpu_disabled] { is_gpu_disabled = true; })); + std::unique_ptr result = CreateWithSnapshot( PlatformData{}, task_runners_, rasterizer_->GetRasterThreadMerger(), io_manager_, resource_cache_limit_calculator_, GetSettings(), vm_, @@ -536,6 +534,7 @@ std::unique_ptr Shell::Spawn( const fml::RefPtr& unref_queue, fml::TaskRunnerAffineWeakPtr snapshot_delegate, const std::shared_ptr& volatile_path_tracker) { + return engine->Spawn( /*delegate=*/delegate, /*dispatcher_maker=*/dispatcher_maker, @@ -585,7 +584,9 @@ void Shell::RunEngine( return; } platform_runner->PostTask( - [result_callback, run_result]() { result_callback(run_result); }); + [result_callback, run_result]() { + result_callback(run_result); + }); }; FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); @@ -746,7 +747,6 @@ DartVM* Shell::GetDartVM() { // |PlatformView::Delegate| void Shell::OnPlatformViewCreated(std::unique_ptr surface) { - TRACE_EVENT0("flutter", "Shell::OnPlatformViewCreated"); FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); diff --git a/shell/common/snapshot_controller_impeller.cc b/shell/common/snapshot_controller_impeller.cc index 5e7317805812d11e90ad57bc0c7d060f4df28cf7..b115b06c0f03e1ac34a4f5158e9c131d81f20dcc 100644 --- a/shell/common/snapshot_controller_impeller.cc +++ b/shell/common/snapshot_controller_impeller.cc @@ -75,6 +75,8 @@ sk_sp SnapshotControllerImpeller::DoMakeRasterSnapshot( sk_sp SnapshotControllerImpeller::ConvertToRasterImage( sk_sp image) { FML_UNREACHABLE(); + sk_sp result; + return result; } } // namespace flutter diff --git a/shell/common/switches.cc b/shell/common/switches.cc index 1d518824aa8199f4e67b8cc6b95efff7cde1b066..0cb341d0d6577ba05ee0141752b83d0fa688d9af 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -76,7 +76,7 @@ static const std::string kAllowedDartFlags[] = { // Define symbols for the ICU data that is linked into the Flutter library on // Android. This is a workaround for crashes seen when doing dynamic lookups // of the engine's own symbols on some older versions of Android. -#if FML_OS_ANDROID +#if FML_OS_ANDROID extern uint8_t _binary_icudtl_dat_start[]; extern uint8_t _binary_icudtl_dat_end[]; @@ -406,7 +406,7 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { command_line.GetOptionValue(FlagForSwitch(Switch::ICUNativeLibPath), &native_lib_path); -#if FML_OS_ANDROID +#if FML_OS_ANDROID settings.icu_mapper = GetICUStaticMapping; #else settings.icu_mapper = [icu_symbol_prefix, native_lib_path] { diff --git a/shell/common/vsync_waiter.h b/shell/common/vsync_waiter.h index df70342c399e49af8bdd7454a9f05750524232fa..cfce4524df4d7a59c90ff8a1fb3ce459b61ca9c9 100644 --- a/shell/common/vsync_waiter.h +++ b/shell/common/vsync_waiter.h @@ -37,6 +37,7 @@ class VsyncWaiter : public std::enable_shared_from_this { // method. friend class VsyncWaiterAndroid; friend class VsyncWaiterEmbedder; + friend class VsyncWaiterOHOS; const TaskRunners task_runners_; diff --git a/shell/gpu/gpu_surface_software.cc b/shell/gpu/gpu_surface_software.cc index 862cb7d3e96946ff6af8c7f29ea28ad9e231c73e..78b28e0545ffa74f62cb7b5bb1077f6fb86869dd 100644 --- a/shell/gpu/gpu_surface_software.cc +++ b/shell/gpu/gpu_surface_software.cc @@ -28,6 +28,7 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame( SurfaceFrame::FramebufferInfo framebuffer_info; framebuffer_info.supports_readback = true; + FML_DLOG(INFO) <<"AcquireFrame" ; // TODO(38466): Refactor GPU surface APIs take into account the fact that an // external view embedder may want to render to the root surface. if (!render_to_surface_) { @@ -47,11 +48,14 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame( sk_sp backing_store = delegate_->AcquireBackingStore(size); +FML_DLOG(INFO) << "AcquireFrame"; if (backing_store == nullptr) { + FML_DLOG(INFO) <<"AcquireFrame ... backing_store is null" ; return nullptr; } if (size != SkISize::Make(backing_store->width(), backing_store->height())) { + FML_DLOG(INFO) <<"AcquireFrame ... backing_store size not matched" ; return nullptr; } @@ -61,19 +65,26 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame( SkCanvas* canvas = backing_store->getCanvas(); canvas->resetMatrix(); +FML_DLOG(INFO) << "resetMatrix end"; SurfaceFrame::SubmitCallback on_submit = [self = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame, SkCanvas* canvas) -> bool { + FML_DLOG(INFO) << "on_submit start"; // If the surface itself went away, there is nothing more to do. + FML_DLOG(INFO) <<"AcquireFrame ... on_submit ..." ; if (!self || !self->IsValid() || canvas == nullptr) { + FML_DLOG(INFO) << "on_submit return false"; return false; } + FML_DLOG(INFO) <<"AcquireFrame ... on_submit canvas->flush " ; canvas->flush(); + FML_DLOG(INFO) <<"AcquireFrame ... delegate_-->PresentBackingStore" ; return self->delegate_->PresentBackingStore(surface_frame.SkiaSurface()); }; +FML_DLOG(INFO) << "return SurfaceFrame"; return std::make_unique(backing_store, framebuffer_info, on_submit, logical_size); } diff --git a/shell/platform/BUILD.gn b/shell/platform/BUILD.gn index 66baf0e887fe1d71a73ecd7d6c765062607ad9d4..8af1e768590fd9303dcc0cbc83ac7c0bfc1fb619 100644 --- a/shell/platform/BUILD.gn +++ b/shell/platform/BUILD.gn @@ -10,6 +10,8 @@ group("platform") { deps = [ "darwin" ] } else if (is_android) { deps = [ "android" ] + }else if ( is_ohos){ + deps = [ "ohos" ] } else if (is_linux) { deps = [] if (enable_desktop_embeddings) { diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index 83d62c610d1cb872ba32e5d3c49463b15a1cb616..56335f45afd715add78c6f571d03c3d1239f4886 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -115,6 +115,9 @@ template("embedder_source_set") { "//third_party/dart/runtime/bin:elf_loader", "//third_party/skia", ] + if( is_ohos ){ + #libs +=["hilog_ndk.z"] + } if (embedder_enable_metal) { sources += [ @@ -381,7 +384,7 @@ shared_library("flutter_engine_library") { if (is_mac && !embedder_for_target) { ldflags += [ "-Wl,-install_name,@rpath/FlutterEmbedder.framework/$_framework_binary_subpath" ] } - if (is_linux) { + if (is_ohos || is_linux) { ldflags += [ "-Wl,--version-script=" + rebase_path("embedder_exports.lst") ] } diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 6240bc9efcf808a3c0dce551c2957c85d4a3dc1f..2161b4a8b8ae3e2297dd5f42162f3d98f2a87fd3 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -68,6 +68,24 @@ extern const intptr_t kPlatformStrongDillSize; #include "flutter/shell/platform/embedder/embedder_surface_metal.h" #endif +#ifdef FML_OS_OHOS +extern "C"{ + typedef enum { + /** Debug level to be used by {@link OH_LOG_DEBUG} */ + HILOG_LOG_DEBUG = 3, + /** Informational level to be used by {@link OH_LOG_INFO} */ + HILOG_LOG_INFO = 4, + /** Warning level to be used by {@link OH_LOG_WARN} */ + HILOG_LOG_WARN = 5, + /** Error level to be used by {@link OH_LOG_ERROR} */ + HILOG_LOG_ERROR = 6, + /** Fatal level to be used by {@link OH_LOG_FATAL} */ + HILOG_LOG_FATAL = 7, +} HiLog_LogLevel; +int OH_LOG_Print(int type, HiLog_LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) ; +} +#endif + const int32_t kFlutterSemanticsNodeIdBatchEnd = -1; const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1; @@ -111,6 +129,15 @@ static FlutterEngineResult LogEmbedderError(FlutterEngineResult code, "%s (%d): '%s' returned '%s'. %s", file_base, line, function, code_name, reason); std::cerr << error << std::endl; + + +#if defined(FML_OS_OHOS) +#define OHOS_LOG_TYPE_APP 0 +#define HILOG_LOG_DOMAIN 0 +#define HILOG_LOG_TAG "XcomFlutterEmbedder" + HiLog_LogLevel fx_severity = HILOG_LOG_ERROR; + (void ) OH_LOG_Print(0,fx_severity,HILOG_LOG_DOMAIN, HILOG_LOG_TAG,"%s",error ); +#endif return code; } diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..8c65f55f4ab5927416d7ea07d0edc2cf003e423b --- /dev/null +++ b/shell/platform/ohos/BUILD.gn @@ -0,0 +1,266 @@ +# Copyright (c) 2023 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. + +assert(is_ohos) + +import("//flutter/build/zip_bundle.gni") +import("//flutter/shell/platform/glfw/config.gni") +import("//flutter/testing/testing.gni") +import("//build/config/ohos/pkg_config.gni") +import("//flutter/shell/gpu/gpu.gni") + +group("ohos") { + deps = [ + ":flutter", + #":publish_headers_ohos", + ] +} +shell_gpu_configuration("ohos_gpu_configuration") { + enable_software = true + enable_gl = true + enable_vulkan = false + enable_metal = false +} +# Temporary workaround for the issue describe in +# https://github.com/flutter/flutter/issues/14509 and +# https://github.com/flutter/flutter/issues/14438 +# Remove once the build infrastructure moves to Ubuntu 18.04 or newer, where +# the underlying issue is fixed. +config("disable_fatal_link_warnings") { + visibility = [ ":*" ] + ldflags = [ "-Wl,--no-fatal-warnings" ] +} + +_public_headers = [ + #"public/flutter_ohos/fl_view.h", + # "napi_common.h", + #"platform_view_ohos.h", +] + +config("relative_flutter_ohos_headers") { + include_dirs = [ "public", + + ] +} + +source_set("flutter_ohos_sources") { + public = _public_headers + [ + "napi_common.h", + "ohos_xcomponent_adapter.h", + "./napi/platform_view_ohos_napi.h", + "ohos_shell_holder.h", + "platform_view_ohos.h", + "platform_message_response_ohos.h", + "platform_message_handler_ohos.h", + "vsync_waiter_ohos.h", + "ohos_logger.h" , + "ohos_display.h", + "ohos_surface_software.h", + "./context/ohos_context.h", + "./surface/ohos_native_window.h", + "./surface/ohos_surface.h", + "ohos_touch_processor.h", + "ohos_context_gl_skia.h", + "ohos_egl_surface.h", + "ohos_environment_gl.h", + "ohos_surface_gl_skia.h", + ] + + #configs += [ "//flutter/shell/platform/ohos/config:gtk" ] + + sources = [ + "library_loader.cpp" , + "ohos_xcomponent_adapter.cpp", + "./napi/platform_view_ohos_napi.cpp", + "ohos_shell_holder.cpp", + "platform_view_ohos.cpp", + "ohos_display.cpp", + "ohos_surface_software.cpp", + "platform_message_handler_ohos.cpp", + "platform_message_response_ohos.cpp", + "vsync_waiter_ohos.cpp", + "./surface/ohos_native_window.cpp", + "./surface/ohos_surface.cpp", + "./context/ohos_context.cpp", + "ohos_asset_provider.cpp", + "ohos_touch_processor.cpp", + "ohos_main.cpp" , + "ohos_logger.c" , + "ohos_context_gl_impeller.cpp", + "ohos_surface_gl_impeller.cpp", + # "//flutter/impeller/toolkit/egl/display.cc", + "ohos_context_gl_skia.cpp" , + "ohos_egl_surface.cpp" , + "ohos_environment_gl.cpp", + "ohos_surface_gl_skia.cpp", + "ohos_image_generator.cpp", + "ohos_external_texture_gl.cpp", + "./surface/ohos_snapshot_surface_producer.cpp", + ] + + # Set flag to stop headers being directly included (library users should not do this) + defines = [ + "FLUTTER_LINUX_COMPILATION", + "FLUTTER_ENGINE_NO_PROTOTYPES", + "OHOS_PLATFORM" , + "__MUSL__", + ] + + deps = [ + "//flutter/shell/platform/common:common_cpp_input", + "//flutter/shell/platform/common:common_cpp_switches", + "//flutter/shell/platform/embedder:embedder_headers", + "//third_party/rapidjson", + ] + + public_deps = [ + ":ohos_gpu_configuration", + "//flutter/assets", + "//flutter/common", + "//flutter/common/graphics", + "//flutter/flow", + "//flutter/fml", + "//flutter/impeller", + "//flutter/impeller/toolkit/egl", + "//flutter/lib/ui", + "//flutter/runtime", + "//flutter/runtime:libdart", + "//flutter/shell/common", + #"//flutter/vulkan", + "//third_party/skia", + "//flutter/shell/gpu:gpu_surface_gl", + + + ] + +} + +source_set("flutter_ohos_src") { + configs += [ + #"//flutter/shell/platform/ohos/config:gtk", + #"//flutter/shell/platform/ohos/config:epoxy", + ] + + defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ] + + public_deps = [ ":flutter_ohos_sources"] + + deps = [ "//flutter/shell/platform/embedder:embedder_as_internal_library" ] +} + +test_fixtures("flutter_ohos_fixtures") { + fixtures = [] +} + + +executable("flutter_ohos_unittests") { + testonly = true + + sources = [ + #"testing/mock_texture_registrar.cc", + ] + + public_configs = [ "//flutter:config" ] + + + defines = [ + "FLUTTER_ENGINE_NO_PROTOTYPES", + + # Set flag to allow public headers to be directly included + # (library users should not do this) + "FLUTTER_LINUX_COMPILATION", + ] + + deps = [ + ":flutter_ohos_fixtures", + ":flutter_ohos_sources", + "//flutter/runtime:libdart", + "//flutter/shell/platform/embedder:embedder_headers", + "//flutter/shell/platform/embedder:embedder_test_utils", + "//flutter/testing", + ] +} + +shared_library("flutter") { + deps = [ ":flutter_ohos_src" ] + + ldflags = ["--rtlib=compiler-rt", + "-fuse-ld=lld", + "-static-libstdc++", +# "-Wl", "--build-id=sha1", +# "-Wl,","--warn-shared-textrel", +# "-Wl,","--fatal-warnings -lunwind", +# "-Wl,","--no-undefined -Qunused-arguments", +# "-Wl,","-z,noexecstack" + ] + + #ldflags = [ "-Wl,-rpath,\$ORIGIN" ] + #ldflags += ["-L{$OHOS_NDK_LIB}","-lnative_window"] + ldflags += ["-lnative_window"] + ldflags += ["-lnative_vsync"] + ldflags += ["-lace_napi.z"] + ldflags += ["-lace_ndk.z"] + ldflags += ["-lhilog_ndk.z"] + ldflags += ["-luv"] + ldflags += ["-lrawfile.z"] + ldflags += ["-lEGL"] + ldflags += ["-lGLESv3"] + + ldflags += ["-lc++_shared"] + ldflags += ["-lm"] + ldflags += ["-lpthread"] + ldflags += ["-lpixelmap_ndk.z"] + + + public_configs = [ "//flutter:config" ] +} + +#copy("publish_headers_ohos") { +# sources = _public_headers +# outputs = [ "$root_out_dir/flutter_ohos/{{source_file_part}}" ] +#} + +#zip_bundle("flutter_gtk") { +# prefix = "$full_target_platform_name/" +# if (flutter_runtime_mode != "debug" || +# (flutter_runtime_mode == "debug" && target_cpu != "x64")) { +# prefix = "$full_target_platform_name-$flutter_runtime_mode/" +# } +# output = "${prefix}${full_target_platform_name}-flutter-gtk.zip" +# deps = [ +# ":flutter_ohos_gtk", +# ":publish_headers_ohos", +# "//third_party/dart/runtime/bin:gen_snapshot", +# ] +# sources = get_target_outputs(":publish_headers_ohos") +# tmp_files = [] +# foreach(source, sources) { +# tmp_files += [ +# { +# source = source +# destination = rebase_path(source, "$root_build_dir") +# }, +# ] +# } +# tmp_files += [ +# { +# source = "$root_build_dir/libflutter_${host_os}_gtk.so" +# destination = "libflutter_${host_os}_gtk.so" +# }, +# { +# source = "$root_build_dir/gen_snapshot" +# destination = "gen_snapshot" +# }, +# ] +# files = tmp_files +#} diff --git a/shell/platform/ohos/config/BUILD.gn b/shell/platform/ohos/config/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d8a2dd87c9a984b7392d1658c1fb80b0df9b6c68 --- /dev/null +++ b/shell/platform/ohos/config/BUILD.gn @@ -0,0 +1,15 @@ +# Copyright (c) 2023 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("//build/config/linux/pkg_config.gni") +import("//flutter/shell/platform/glfw/config.gni") diff --git a/shell/platform/ohos/context/ohos_context.cpp b/shell/platform/ohos/context/ohos_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e436459390a0f9e7a2af97d33822c1026cd5f056 --- /dev/null +++ b/shell/platform/ohos/context/ohos_context.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/context/ohos_context.h" + +namespace flutter { + +OHOSContext::OHOSContext(OHOSRenderingAPI rendering_api) + : rendering_api_(rendering_api) {} + +OHOSContext::~OHOSContext() { + if (main_context_) { + main_context_->releaseResourcesAndAbandonContext(); + } +} + +OHOSRenderingAPI OHOSContext::RenderingApi() const { + return rendering_api_; +} + +bool OHOSContext::IsValid() const { + return true; +} + +void OHOSContext::SetMainSkiaContext( + const sk_sp& main_context) { + main_context_ = main_context; +} + +sk_sp OHOSContext::GetMainSkiaContext() const { + return main_context_; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/context/ohos_context.h b/shell/platform/ohos/context/ohos_context.h new file mode 100644 index 0000000000000000000000000000000000000000..84cdeb5820f055aab74deaaf36f7981878110468 --- /dev/null +++ b/shell/platform/ohos/context/ohos_context.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_CONTEXT_H +#define OHOS_CONTEXT_H + +#include "flutter/fml/macros.h" +#include "flutter/fml/task_runner.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" + +namespace flutter { + +enum class OHOSRenderingAPI { + kSoftware, + kOpenGLES, +}; + +class OHOSContext { + public: + explicit OHOSContext(OHOSRenderingAPI rendering_api); + + virtual ~OHOSContext(); + + OHOSRenderingAPI RenderingApi() const; + + virtual bool IsValid() const; + + void SetMainSkiaContext(const sk_sp& main_context); + + sk_sp GetMainSkiaContext() const; + + private: + const OHOSRenderingAPI rendering_api_; + + // This is the Skia context used for on-screen rendering. + sk_sp main_context_; + + FML_DISALLOW_COPY_AND_ASSIGN(OHOSContext); +}; + +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef39c7ca82fc970e14ee3802ddd42d4a3de3674a --- /dev/null +++ b/shell/platform/ohos/library_loader.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +#include "flutter/shell/platform/ohos/ohos_main.h" +#include "napi/native_api.h" +#include "napi_common.h" +#include "ohos_xcomponent_adapter.h" + +// namespace flutter { + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) { + FML_DLOG(INFO) << "Flutter Init NAPI"; + napi_property_descriptor desc[] = { + // TODO:1 ArcTS import so库的时候应该先初始化shell + // Holder,然后再初始化XComponent + DECLARE_NAPI_FUNCTION("nativeInit", flutter::OhosMain::NativeInit), + DECLARE_NAPI_FUNCTION( + "nativeImageDecodeCallback", + flutter::OHOSImageGenerator::NativeImageDecodeCallback), + DECLARE_NAPI_FUNCTION( + "nativeUpdateRefreshRate", + flutter::PlatformViewOHOSNapi::nativeUpdateRefreshRate), + DECLARE_NAPI_FUNCTION( + "nativeRunBundleAndSnapshotFromLibrary", + flutter::PlatformViewOHOSNapi::nativeRunBundleAndSnapshotFromLibrary), + DECLARE_NAPI_FUNCTION( + "nativePrefetchDefaultFontManager", + flutter::PlatformViewOHOSNapi::nativePrefetchDefaultFontManager), + DECLARE_NAPI_FUNCTION( + "nativeGetIsSoftwareRenderingEnabled", + flutter::PlatformViewOHOSNapi::nativeGetIsSoftwareRenderingEnabled), + DECLARE_NAPI_FUNCTION("nativeAttach", + flutter::PlatformViewOHOSNapi::nativeAttach), + DECLARE_NAPI_FUNCTION("nativeSpawn", + flutter::PlatformViewOHOSNapi::nativeSpawn), + DECLARE_NAPI_FUNCTION("nativeDestroy", + flutter::PlatformViewOHOSNapi::nativeDestroy), + DECLARE_NAPI_FUNCTION( + "nativeSetViewportMetrics", + flutter::PlatformViewOHOSNapi::nativeSetViewportMetrics), + DECLARE_NAPI_FUNCTION( + "nativeSetAccessibilityFeatures", + flutter::PlatformViewOHOSNapi::nativeSetAccessibilityFeatures), + DECLARE_NAPI_FUNCTION( + "nativeCleanupMessageData", + flutter::PlatformViewOHOSNapi::nativeCleanupMessageData), + DECLARE_NAPI_FUNCTION( + "nativeDispatchEmptyPlatformMessage", + flutter::PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage), + DECLARE_NAPI_FUNCTION( + "nativeDispatchPlatformMessage", + flutter::PlatformViewOHOSNapi::nativeDispatchPlatformMessage), + DECLARE_NAPI_FUNCTION( + "nativeInvokePlatformMessageEmptyResponseCallback", + flutter::PlatformViewOHOSNapi:: + nativeInvokePlatformMessageEmptyResponseCallback), + DECLARE_NAPI_FUNCTION("nativeInvokePlatformMessageResponseCallback", + flutter::PlatformViewOHOSNapi:: + nativeInvokePlatformMessageResponseCallback), + DECLARE_NAPI_FUNCTION( + "nativeLoadDartDeferredLibrary", + flutter::PlatformViewOHOSNapi::nativeLoadDartDeferredLibrary), + DECLARE_NAPI_FUNCTION( + "nativeUpdateOhosAssetManager", + flutter::PlatformViewOHOSNapi::nativeUpdateOhosAssetManager), + DECLARE_NAPI_FUNCTION( + "nativeDeferredComponentInstallFailure", + flutter::PlatformViewOHOSNapi::nativeDeferredComponentInstallFailure), + DECLARE_NAPI_FUNCTION("nativeGetPixelMap", + flutter::PlatformViewOHOSNapi::nativeGetPixelMap), + DECLARE_NAPI_FUNCTION( + "nativeNotifyLowMemoryWarning", + flutter::PlatformViewOHOSNapi::nativeNotifyLowMemoryWarning), + DECLARE_NAPI_FUNCTION( + "nativeFlutterTextUtilsIsEmoji", + flutter::PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmoji), + DECLARE_NAPI_FUNCTION( + "nativeFlutterTextUtilsIsEmojiModifier", + flutter::PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifier), + DECLARE_NAPI_FUNCTION("nativeFlutterTextUtilsIsEmojiModifierBase", + flutter::PlatformViewOHOSNapi:: + nativeFlutterTextUtilsIsEmojiModifierBase), + DECLARE_NAPI_FUNCTION("nativeFlutterTextUtilsIsVariationSelector", + flutter::PlatformViewOHOSNapi:: + nativeFlutterTextUtilsIsVariationSelector), + DECLARE_NAPI_FUNCTION("nativeFlutterTextUtilsIsRegionalIndicator", + flutter::PlatformViewOHOSNapi:: + nativeFlutterTextUtilsIsRegionalIndicator), + DECLARE_NAPI_FUNCTION( + "nativeGetSystemLanguages", + flutter::PlatformViewOHOSNapi::nativeGetSystemLanguages), + + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + bool ret = flutter::XComponentAdapter::GetInstance()->Export(env, exports); + if (!ret) { + FML_DLOG(INFO) << "Flutter Init Failed"; + } + return exports; +} +EXTERN_C_END + +static napi_module flutterModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "flutter", + .nm_priv = ((void*)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { + napi_module_register(&flutterModule); +} + +//} diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6eec795900517d524e82fb5e92a25d2e223f72fd --- /dev/null +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp @@ -0,0 +1,1398 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "platform_view_ohos_napi.h" +#include +#include +#include +#include +#include +#include "flutter/fml/make_copyable.h" +#include "flutter/fml/platform/ohos/napi_util.h" +#include "flutter/shell/platform/ohos/ohos_main.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" +#include "unicode/uchar.h" + +#define OHOS_SHELL_HOLDER (reinterpret_cast(shell_holder)) +namespace flutter { + +int64_t PlatformViewOHOSNapi::shell_holder; +napi_env PlatformViewOHOSNapi::env_; +napi_ref PlatformViewOHOSNapi::ref_napi_obj_; +std::vector PlatformViewOHOSNapi::system_languages; + +/** + * @brief send empty PlatformMessage + * @note + * @param nativeShellHolderId: number,channel: string,responseId: number + * @return void + */ +napi_value PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage( + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage"; + napi_status ret; + size_t argc = 3; + napi_value args[3] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + int64_t shell_holder, responseId; + std::string channel; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeDispatchEmptyPlatformMessage napi get shell_holder error"); + return nullptr; + } + fml::napi::GetString(env, args[1], channel); + FML_DLOG(INFO) << "nativeDispatchEmptyPlatformMessage channel:" << channel; + ret = napi_get_value_int64(env, args[2], &responseId); + if (ret != napi_ok) { + LOGE("nativeDispatchEmptyPlatformMessage napi get responseId error"); + return nullptr; + } + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage " + "DispatchEmptyPlatformMessage"; + OHOS_SHELL_HOLDER->GetPlatformView()->DispatchEmptyPlatformMessage( + channel, responseId); + return nullptr; +} + +/** + * @brief send PlatformMessage + * @note + * @param nativeShellHolderId: number,channel: string,message: + * ArrayBuffer,position: number,responseId: number + * @return void + */ +napi_value PlatformViewOHOSNapi::nativeDispatchPlatformMessage( + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeDispatchPlatformMessage"; + napi_status ret; + napi_value thisArg; + size_t argc = 5; + napi_value args[5] = {nullptr}; + int64_t shell_holder, responseId, position; + std::string channel; + void* message = nullptr; + size_t message_lenth = 0; + + int32_t status; + + // flutter.nativeDispatchPlatformMessage(this.nativeShellHolderId, channel, + // message, position, responseId); + // + ret = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr); + if (argc < 5 || ret != napi_ok) { + FML_DLOG(ERROR) << "nativeDispatchPlatformMessage napi get argc ,argc=" + << argc << "<5,error:" << ret; + napi_throw_type_error(env, nullptr, "Wrong number of arguments"); + return nullptr; + } + // #ifndef NDEBUG + fml::napi::NapiPrintValueTypes(env, argc, args); + // #endif + + napi_value napiShellHolder = args[0]; + napi_value napiChannel = args[1]; + napi_value napiMessage = args[2]; + napi_value napiPos = args[3]; + napi_value napiResponseId = args[4]; + + ret = napi_get_value_int64(env, napiShellHolder, &shell_holder); + if (ret != napi_ok) { + LOGE("nativeDispatchPlatformMessage napi get shell_holder error"); + return nullptr; + } + FML_DLOG(INFO) << "nativeDispatchPlatformMessage:shell_holder:" + << shell_holder; + + if (0 != (status = fml::napi::GetString(env, napiChannel, channel))) { + FML_DLOG(ERROR) << "nativeDispatchPlatformMessage napi get channel error:" + << status; + return nullptr; + } + FML_DLOG(INFO) << "nativeDispatchEmptyPlatformMessage channel:" << channel; + + if (0 != (status = fml::napi::GetArrayBuffer(env, napiMessage, &message, + &message_lenth))) { + FML_DLOG(ERROR) << "nativeDispatchPlatformMessage napi get message error:" + << status; + return nullptr; + } + if (message == nullptr) { + FML_LOG(ERROR) + << "nativeInvokePlatformMessageResponseCallback message null"; + return nullptr; + } + ret = napi_get_value_int64(env, napiPos, &position); + if (ret != napi_ok) { + LOGE("nativeDispatchPlatformMessage napi get position error"); + return nullptr; + } + ret = napi_get_value_int64(env, napiResponseId, &responseId); + if (ret != napi_ok) { + LOGE("nativeDispatchPlatformMessage napi get responseId error"); + return nullptr; + } + FML_DLOG(INFO) << "DispatchPlatformMessage,channel:" << channel + << ",message:" << message << ",position:" << position + << ",responseId:" << responseId; + + OHOS_SHELL_HOLDER->GetPlatformView()->DispatchPlatformMessage( + channel, message, position, responseId); + return nullptr; +} +/** + * @brief + * @note + * @param nativeShellHolderId: number,responseId: number + * @return void + */ +napi_value +PlatformViewOHOSNapi::nativeInvokePlatformMessageEmptyResponseCallback( + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "nativeInvokePlatformMessageEmptyResponseCallback"; + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + int64_t shell_holder, responseId; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE( + "nativeInvokePlatformMessageEmptyResponseCallback napi get " + "shell_holder error"); + return nullptr; + } + ret = napi_get_value_int64(env, args[1], &responseId); + if (ret != napi_ok) { + LOGE(" napi get responseId error"); + return nullptr; + } + FML_DLOG(INFO) << "InvokePlatformMessageEmptyResponseCallback"; + OHOS_SHELL_HOLDER->GetPlatformMessageHandler() + ->InvokePlatformMessageEmptyResponseCallback(responseId); + return nullptr; +} +/** + * @brief + * @note + * @param nativeShellHolderId: number, responseId: number, message: + * ArrayBuffer,position: number + * @return void + */ +napi_value PlatformViewOHOSNapi::nativeInvokePlatformMessageResponseCallback( + napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "nativeInvokePlatformMessageResponseCallback"; + napi_status ret; + size_t argc = 4; + napi_value args[4] = {nullptr}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + int64_t shell_holder, responseId, position; + void* message = nullptr; + size_t message_lenth = 0; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE(" napi get shell_holdererror"); + return nullptr; + } + ret = napi_get_value_int64(env, args[1], &responseId); + if (ret != napi_ok) { + LOGE(" napi get responseId error"); + return nullptr; + } + int32_t result = + fml::napi::GetArrayBuffer(env, args[2], &message, &message_lenth); + if (result != 0) { + FML_DLOG(ERROR) + << "nativeInvokePlatformMessageResponseCallback GetArrayBuffer error " + << result; + } + if (message == nullptr) { + FML_LOG(ERROR) + << "nativeInvokePlatformMessageResponseCallback message null"; + return nullptr; + } + ret = napi_get_value_int64(env, args[3], &position); + if (ret != napi_ok) { + LOGE("nativeInvokePlatformMessageResponseCallback napi get position error"); + return nullptr; + } + + uint8_t* response_data = static_cast(message); + FML_DCHECK(response_data != nullptr); + auto mapping = std::make_unique( + fml::MallocMapping::Copy(response_data, response_data + position)); + FML_DLOG(INFO) << "InvokePlatformMessageResponseCallback"; + OHOS_SHELL_HOLDER->GetPlatformMessageHandler() + ->InvokePlatformMessageResponseCallback(responseId, std::move(mapping)); + return nullptr; +} + +/* void PlatformViewOHOSNapi::FlutterViewHandlePlatformMessageResponse( + int responseId, + std::unique_ptr data) { + +} + */ +PlatformViewOHOSNapi::PlatformViewOHOSNapi(napi_env env) {} + +void PlatformViewOHOSNapi::FlutterViewHandlePlatformMessageResponse( + int reponse_id, + std::unique_ptr data) { + FML_DLOG(INFO) << "FlutterViewHandlePlatformMessageResponse"; + napi_status status; + napi_value callbackParam[2]; + status = napi_create_int64(env_, reponse_id, callbackParam); + if (status != napi_ok) { + FML_DLOG(ERROR) << "napi_create_int64 reponse_id fail"; + } + + if (data == nullptr) { + callbackParam[1] = NULL; + } else { + callbackParam[1] = fml::napi::CreateArrayBuffer( + env_, (void*)data->GetMapping(), data->GetSize()); + } + + status = fml::napi::InvokeJsMethod( + env_, ref_napi_obj_, "handlePlatformMessageResponse", 2, callbackParam); + if (status != napi_ok) { + FML_DLOG(ERROR) << "InvokeJsMethod fail "; + } +} + +void PlatformViewOHOSNapi::FlutterViewHandlePlatformMessage( + int reponse_id, + std::unique_ptr message) { + FML_DLOG(INFO) << "FlutterViewHandlePlatformMessage message channal " + << message->channel().c_str(); + + napi_value callbackParam[4]; + napi_status status; + + status = napi_create_string_utf8(env_, message->channel().c_str(), + message->channel().size(), callbackParam); + if (status != napi_ok) { + FML_DLOG(ERROR) << "napi_create_string_utf8 err " << status; + return; + } + + if (message->data().GetSize() > 0) { + callbackParam[1] = fml::napi::CreateArrayBuffer( + env_, (void*)message->data().GetMapping(), message->data().GetSize()); + + status = napi_create_int64(env_, reponse_id, &callbackParam[2]); + if (status != napi_ok) { + FML_DLOG(ERROR) << "napi_create_int64 err " << status; + return; + } + + fml::MallocMapping mapping = message->releaseData(); + char* mapData = (char*)mapping.Release(); + status = napi_create_string_utf8(env_, mapData, strlen(mapData), + &callbackParam[3]); + if (status != napi_ok) { + FML_DLOG(ERROR) << "napi_create_string_utf8 err " << status; + return; + } + + if (mapData) { + delete mapData; + } + + status = fml::napi::InvokeJsMethod( + env_, ref_napi_obj_, "handlePlatformMessage", 4, callbackParam); + if (status != napi_ok) { + FML_DLOG(ERROR) << "InvokeJsMethod fail "; + } + } +} + +void PlatformViewOHOSNapi::FlutterViewOnFirstFrame() { + FML_DLOG(INFO) << "FlutterViewOnFirstFrame"; + napi_status status = fml::napi::InvokeJsMethod(env_, ref_napi_obj_, + "onFirstFrame", 0, nullptr); + if (status != napi_ok) { + FML_DLOG(ERROR) << "InvokeJsMethod onFirstFrame fail "; + } +} + +void PlatformViewOHOSNapi::FlutterViewOnPreEngineRestart() { + FML_DLOG(INFO) << "FlutterViewOnPreEngineRestart"; + napi_status status = fml::napi::InvokeJsMethod( + env_, ref_napi_obj_, "onPreEngineRestart", 0, nullptr); + if (status != napi_ok) { + FML_DLOG(ERROR) << "InvokeJsMethod onPreEngineRestart fail "; + } +} + +std::vector splitString(const std::string& input, char delimiter) { + std::vector result; + std::stringstream ss(input); + std::string token; + + while (std::getline(ss, token, delimiter)) { + result.push_back(token); + } + + return result; +} +flutter::locale PlatformViewOHOSNapi::resolveNativeLocale( + std::vector supportedLocales) { + if (supportedLocales.empty()) { + flutter::locale default_locale; + default_locale.language = "zh"; + default_locale.script = "Hans"; + default_locale.region = "CN"; + return default_locale; + } + char delimiter = '-'; + if (PlatformViewOHOSNapi::system_languages.empty()) { + PlatformViewOHOSNapi::system_languages.push_back("zh-Hans"); + } + for (size_t i = 0; i < PlatformViewOHOSNapi::system_languages.size(); i++) { + std::string language = PlatformViewOHOSNapi::system_languages + [i]; // 格式language-script-region,例如en-Latn-US + for (const locale& localeInfo : supportedLocales) { + if (language == localeInfo.language + "-" + localeInfo.script + "-" + + localeInfo.region) { + return localeInfo; + } + std::vector element = splitString(language, delimiter); + if (element[0] + "-" + element[1] == + localeInfo.language + "-" + localeInfo.region) { + return localeInfo; + } + if (element[0] == localeInfo.language) { + return localeInfo; + } + } + } + return supportedLocales[0]; +} + +std::unique_ptr> +PlatformViewOHOSNapi::FlutterViewComputePlatformResolvedLocales( + const std::vector& support_locale_data) { + std::vector supportedLocales; + std::vector result; + const int localeDataLength = 3; + flutter::locale mlocale; + for (size_t i = 0; i < support_locale_data.size(); i += localeDataLength) { + mlocale.language = support_locale_data[i + 0]; + mlocale.region = support_locale_data[i + 1]; + mlocale.script = support_locale_data[i + 2]; + supportedLocales.push_back(mlocale); + } + mlocale = resolveNativeLocale(supportedLocales); + result.push_back(mlocale.language); + result.push_back(mlocale.region); + result.push_back(mlocale.script); + FML_DLOG(INFO) << "resolveNativeLocale result to flutter language: " + << result[0] << " region: " << result[1] + << " script: " << result[2]; + return std::make_unique>(std::move(result)); +} + +void PlatformViewOHOSNapi::DecodeImage(int64_t imageGeneratorAddress, + void* inputData, + size_t dataSize) { + FML_DLOG(INFO) << "start decodeImage"; + platform_task_runner_->PostTask(fml::MakeCopyable( + [imageGeneratorAddress_ = imageGeneratorAddress, + inputData_ = std::move(inputData), dataSize_ = dataSize]() mutable { + napi_value callbackParam[2]; + + callbackParam[0] = + fml::napi::CreateArrayBuffer(env_, inputData_, dataSize_); + napi_status status = + napi_create_int64(env_, imageGeneratorAddress_, &callbackParam[1]); + if (status != napi_ok) { + FML_DLOG(ERROR) << "napi_create_int64 decodeImage fail "; + } + status = fml::napi::InvokeJsMethod(env_, ref_napi_obj_, "decodeImage", + 2, callbackParam); + if (status != napi_ok) { + FML_DLOG(ERROR) << "InvokeJsMethod decodeImage fail "; + } + })); +} + +/** + * attach flutterNapi实例给到 native + * engine,这个支持rkts到flutter平台的无关引擎之间的通信 attach只需要执行一次 + */ +napi_value PlatformViewOHOSNapi::nativeAttach(napi_env env, + napi_callback_info info) { + FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeAttach"; + + napi_status status; + // 获取传入的参数 + size_t argc = 1; + napi_value argv[1]; + status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (status != napi_ok) { + FML_DLOG(ERROR) << "nativeAttach Failed to get napiObjec info"; + } + napi_create_reference(env, argv[0], 1, &ref_napi_obj_); + + std::shared_ptr napi_facade = + std::make_shared(env); + + uv_loop_t* platform_loop = nullptr; + status = napi_get_uv_event_loop(env, &platform_loop); + if (status != napi_ok) { + FML_DLOG(ERROR) << "nativeAttach napi_get_uv_event_loop fail"; + } + + auto shell_holder = std::make_unique( + OhosMain::Get().GetSettings(), napi_facade, platform_loop); + if (shell_holder->IsValid()) { + PlatformViewOHOSNapi::shell_holder = + reinterpret_cast(shell_holder.get()); + FML_DLOG(INFO) << "PlatformViewOHOSNapi shell_holder:" + << PlatformViewOHOSNapi::shell_holder; + napi_value id; + napi_create_int64(env, reinterpret_cast(shell_holder.release()), + &id); + return id; + } else { + FML_DLOG(ERROR) << "shell holder inValid"; + napi_value id; + napi_create_int64(env, 0, &id); + return id; + } +} + +/** + * 加载dart工程构建产物 + */ +napi_value PlatformViewOHOSNapi::nativeRunBundleAndSnapshotFromLibrary( + napi_env env, + napi_callback_info info) { + napi_status ret; + size_t argc = 6; + napi_value args[6] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeRunBundleAndSnapshotFromLibrary napi_get_cb_info error"); + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeRunBundleAndSnapshotFromLibrary napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeRunBundleAndSnapshotFromLibrary::shell_holder : %{public}ld", + shell_holder); + + std::string bundlePath; + if (fml::napi::SUCCESS != fml::napi::GetString(env, args[1], bundlePath)) { + LOGE(" napi_get_value_string_utf8 error"); + return nullptr; + } + LOGD("nativeRunBundleAndSnapshotFromLibrary: bundlePath: %{public}s", + bundlePath.c_str()); + + std::string entrypointFunctionName; + if (fml::napi::SUCCESS != + fml::napi::GetString(env, args[2], entrypointFunctionName)) { + LOGE(" napi_get_value_string_utf8 error"); + return nullptr; + } + LOGD("entrypointFunctionName: %{public}s", entrypointFunctionName.c_str()); + + std::string pathToEntrypointFunction; + if (fml::napi::SUCCESS != + fml::napi::GetString(env, args[3], pathToEntrypointFunction)) { + LOGE(" napi_get_value_string_utf8 error"); + return nullptr; + } + LOGD(" pathToEntrypointFunction: %{public}s", + pathToEntrypointFunction.c_str()); + + NativeResourceManager* ResourceManager = + OH_ResourceManager_InitNativeResourceManager(env, args[4]); + + std::vector entrypointArgs; + if (fml::napi::SUCCESS != + fml::napi::GetArrayString(env, args[5], entrypointArgs)) { + LOGE("nativeRunBundleAndSnapshotFromLibrary GetArrayString error"); + return nullptr; + } + + auto ohos_asset_provider = std::make_unique( + static_cast(ResourceManager)); + OHOS_SHELL_HOLDER->Launch(std::move(ohos_asset_provider), + entrypointFunctionName, pathToEntrypointFunction, + entrypointArgs); + + env_ = env; + return nullptr; +} + +/** + * 设置ResourceManager和assetBundlePath到engine + */ +napi_value PlatformViewOHOSNapi::nativeUpdateOhosAssetManager( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeUpdateOhosAssetManager"); + + // TODO: + return nullptr; +} + +/** + * 从engine获取当前绘制pixelMap + */ +napi_value PlatformViewOHOSNapi::nativeGetPixelMap(napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeGetPixelMap"); + + // TODO: + return nullptr; +} + +/** + * 从当前的flutterNapi复制一个新的实例 + */ +napi_value PlatformViewOHOSNapi::nativeSpawn(napi_env env, + napi_callback_info info) { + // TODO: + return nullptr; +} + +static void LoadLoadingUnitFailure(intptr_t loading_unit_id, + const std::string& message, + bool transient) { + // TODO(garyq): Implement + LOGD("LoadLoadingUnitFailure: message %s transient %d", message.c_str(), + transient); +} + +/** + * load一个合法的.so文件到dart vm + */ +napi_value PlatformViewOHOSNapi::nativeLoadDartDeferredLibrary( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeLoadDartDeferredLibrary"); + + napi_status ret; + size_t argc = 3; + napi_value args[3] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeLoadDartDeferredLibrary napi_get_cb_info error"); + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeLoadDartDeferredLibrary napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeLoadDartDeferredLibrary::shell_holder : %{public}ld", + shell_holder); + + int64_t loadingUnitId; + ret = napi_get_value_int64(env, args[1], &loadingUnitId); + if (ret != napi_ok) { + LOGE("nativeLoadDartDeferredLibrary napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeLoadDartDeferredLibrary::loadingUnitId : %{public}ld", + loadingUnitId); + + std::vector search_paths; + if (fml::napi::SUCCESS != + fml::napi::GetArrayString(env, args[2], search_paths)) { + LOGE("nativeLoadDartDeferredLibrary GetArrayString error"); + return nullptr; + } + + LOGD("nativeLoadDartDeferredLibrary::search_paths"); + for (const std::string& path : search_paths) { + LOGD("%{public}s", path.c_str()); + } + + intptr_t loading_unit_id = static_cast(loadingUnitId); + // Use dlopen here to directly check if handle is nullptr before creating a + // NativeLibrary. + void* handle = nullptr; + while (handle == nullptr && !search_paths.empty()) { + std::string path = search_paths.back(); + handle = ::dlopen(path.c_str(), RTLD_NOW); + search_paths.pop_back(); + } + if (handle == nullptr) { + LoadLoadingUnitFailure(loading_unit_id, + "No lib .so found for provided search paths.", true); + return nullptr; + } + fml::RefPtr native_lib = + fml::NativeLibrary::CreateWithHandle(handle, false); + + // Resolve symbols. + std::unique_ptr data_mapping = + std::make_unique( + native_lib, DartSnapshot::kIsolateDataSymbol); + std::unique_ptr instructions_mapping = + std::make_unique( + native_lib, DartSnapshot::kIsolateInstructionsSymbol); + + OHOS_SHELL_HOLDER->GetPlatformView()->LoadDartDeferredLibrary( + loading_unit_id, std::move(data_mapping), + std::move(instructions_mapping)); + + return nullptr; +} + +/** + * 把物理屏幕参数通知到native + */ +napi_value PlatformViewOHOSNapi::nativeSetViewportMetrics( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeSetViewportMetrics"); + + napi_status ret; + size_t argc = 20; + napi_value args[20] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_cb_info error"); + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::shell_holder : %{public}ld", shell_holder); + + int64_t devicePixelRatio; + ret = napi_get_value_int64(env, args[1], &devicePixelRatio); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::devicePixelRatio : %{public}ld", + devicePixelRatio); + + int64_t physicalWidth; + ret = napi_get_value_int64(env, args[2], &physicalWidth); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalWidth : %{public}ld", physicalWidth); + + int64_t physicalHeight; + ret = napi_get_value_int64(env, args[3], &physicalHeight); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalHeight : %{public}ld", + physicalHeight); + + int64_t physicalPaddingTop; + ret = napi_get_value_int64(env, args[4], &physicalPaddingTop); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalPaddingTop : %{public}ld", + physicalPaddingTop); + + int64_t physicalPaddingRight; + ret = napi_get_value_int64(env, args[5], &physicalPaddingRight); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalPaddingRight : %{public}ld", + physicalPaddingRight); + + int64_t physicalPaddingBottom; + ret = napi_get_value_int64(env, args[6], &physicalPaddingBottom); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalPaddingBottom : %{public}ld", + physicalPaddingBottom); + + int64_t physicalPaddingLeft; + ret = napi_get_value_int64(env, args[7], &physicalPaddingLeft); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalPaddingLeft : %{public}ld", + physicalPaddingLeft); + + int64_t physicalViewInsetTop; + ret = napi_get_value_int64(env, args[8], &physicalViewInsetTop); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalViewInsetTop : %{public}ld", + physicalViewInsetTop); + + int64_t physicalViewInsetRight; + ret = napi_get_value_int64(env, args[9], &physicalViewInsetRight); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalViewInsetRight : %{public}ld", + physicalViewInsetRight); + + int64_t physicalViewInsetBottom; + ret = napi_get_value_int64(env, args[10], &physicalViewInsetBottom); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalViewInsetBottom : %{public}ld", + physicalViewInsetBottom); + + int64_t physicalViewInsetLeft; + ret = napi_get_value_int64(env, args[11], &physicalViewInsetLeft); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalViewInsetLeft : %{public}ld", + physicalViewInsetLeft); + int64_t systemGestureInsetTop; + ret = napi_get_value_int64(env, args[12], &systemGestureInsetTop); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::systemGestureInsetTop : %{public}ld", + systemGestureInsetTop); + int64_t systemGestureInsetRight; + ret = napi_get_value_int64(env, args[13], &systemGestureInsetRight); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::systemGestureInsetRight : %{public}ld", + systemGestureInsetRight); + + int64_t systemGestureInsetBottom; + ret = napi_get_value_int64(env, args[14], &systemGestureInsetBottom); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::systemGestureInsetBottom : %{public}ld", + systemGestureInsetBottom); + int64_t systemGestureInsetLeft; + ret = napi_get_value_int64(env, args[15], &systemGestureInsetLeft); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::systemGestureInsetLeft : %{public}ld", + systemGestureInsetLeft); + + int64_t physicalTouchSlop; + ret = napi_get_value_int64(env, args[16], &physicalTouchSlop); + if (ret != napi_ok) { + LOGE("nativeSetViewportMetrics napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetViewportMetrics::physicalTouchSlop : %{public}ld", + physicalTouchSlop); + + std::vector displayFeaturesBounds; + napi_value array = args[17]; + uint32_t length; + napi_get_array_length(env, array, &length); + displayFeaturesBounds.resize(length); + for (uint32_t i = 0; i < length; ++i) { + napi_value element; + napi_get_element(env, array, i, &element); + napi_get_value_double(env, element, &(displayFeaturesBounds[i])); + } + + LOGD("nativeSetViewportMetrics::displayFeaturesBounds"); + for (const uint64_t& bounds : displayFeaturesBounds) { + LOGD(" %{public}ld", bounds); + } + + std::vector displayFeaturesType; + array = args[18]; + napi_get_array_length(env, array, &length); + displayFeaturesType.resize(length); + for (uint32_t i = 0; i < length; ++i) { + napi_value element; + napi_get_element(env, array, i, &element); + napi_get_value_int64(env, element, &(displayFeaturesType[i])); + } + + LOGD("nativeSetViewportMetrics::displayFeaturesType"); + for (const uint64_t& featuresType : displayFeaturesType) { + LOGD(" %{public}ld", featuresType); + } + + std::vector displayFeaturesState; + array = args[19]; + napi_get_array_length(env, array, &length); + displayFeaturesState.resize(length); + for (uint32_t i = 0; i < length; ++i) { + napi_value element; + napi_get_element(env, array, i, &element); + napi_get_value_int64(env, element, &(displayFeaturesState[i])); + } + + LOGD("nativeSetViewportMetrics::displayFeaturesState"); + for (const uint64_t& featurestate : displayFeaturesState) { + LOGD(" %{public}ld", featurestate); + } + + const flutter::ViewportMetrics metrics{ + static_cast(devicePixelRatio), + static_cast(physicalWidth), + static_cast(physicalHeight), + static_cast(physicalPaddingTop), + static_cast(physicalPaddingRight), + static_cast(physicalPaddingBottom), + static_cast(physicalPaddingLeft), + static_cast(physicalViewInsetTop), + static_cast(physicalViewInsetRight), + static_cast(physicalViewInsetBottom), + static_cast(physicalViewInsetLeft), + static_cast(systemGestureInsetTop), + static_cast(systemGestureInsetRight), + static_cast(systemGestureInsetBottom), + static_cast(systemGestureInsetLeft), + static_cast(physicalTouchSlop), + displayFeaturesBounds, + std::vector(displayFeaturesType.begin(), displayFeaturesType.end()), + std::vector(displayFeaturesState.begin(), + displayFeaturesState.end()), + }; + + OHOS_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(metrics); + + return nullptr; +} + +/** + * 清除某个messageData + */ +napi_value PlatformViewOHOSNapi::nativeCleanupMessageData( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeCleanupMessageData"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeUpdateRefreshRate napi_get_cb_info error"); + return nullptr; + } + + int64_t messageData; + ret = napi_get_value_int64(env, args[0], &messageData); + if (ret != napi_ok) { + LOGE("nativeUpdateRefreshRate napi_get_value_int64 error"); + return nullptr; + } + + LOGD("nativeCleanupMessageData messageData: %{public}ld", messageData); + free(reinterpret_cast(messageData)); + return nullptr; +} + +/** + * 设置刷新率 + */ +napi_value PlatformViewOHOSNapi::nativeUpdateRefreshRate( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeUpdateRefreshRate"); + + int64_t refreshRate; + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeUpdateRefreshRate napi_get_cb_info error"); + return nullptr; + } + + ret = napi_get_value_int64(env, args[0], &refreshRate); + if (ret != napi_ok) { + LOGE("nativeUpdateRefreshRate napi_get_value_int64 error"); + return nullptr; + } + + LOGD("PlatformViewOHOSNapi::nativeUpdateRefreshRate: %{public}ld", + refreshRate); + FML_DCHECK(refreshRate > 0); + VsyncWaiterOHOS::OnUpdateRefreshRate(refreshRate); + return nullptr; +} + +/** + * 初始化SkFontMgr::RefDefault(),skia引擎文字管理初始化 + */ +napi_value PlatformViewOHOSNapi::nativePrefetchDefaultFontManager( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativePrefetchDefaultFontManager"); + + SkFontMgr::RefDefault(); + return nullptr; +} + +/** + * 返回是否支持软件绘制 + */ +napi_value PlatformViewOHOSNapi::nativeGetIsSoftwareRenderingEnabled( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeGetIsSoftwareRenderingEnabled"); + napi_value result = nullptr; + // TODO: 需要 FlutterMain 初始化 + napi_status ret = napi_get_boolean( + env, OhosMain::Get().GetSettings().enable_software_rendering, &result); + if (ret != napi_ok) { + LOGE("nativeGetIsSoftwareRenderingEnabled napi_get_boolean error"); + return nullptr; + } + + return result; +} + +/** + * Detaches flutterNapi和engine之间的关联 + */ +napi_value PlatformViewOHOSNapi::nativeDestroy(napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeDestroy"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeDestroy napi_get_cb_info error"); + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeDestroy napi_get_value_int64 error"); + return nullptr; + } + + LOGD("nativeDestroy shell_holder: %{public}ld", shell_holder); + + delete OHOS_SHELL_HOLDER; + return nullptr; +} + +/** + * 设置能力参数 + */ +napi_value PlatformViewOHOSNapi::nativeSetAccessibilityFeatures( + napi_env env, + napi_callback_info info) { + LOGD("nativeSetAccessibilityFeatures"); + + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeSetAccessibilityFeatures napi_get_cb_info error"); + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeDestroy napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeSetAccessibilityFeatures shell_holder: %{public}ld", + shell_holder); + int64_t flags; + ret = napi_get_value_int64(env, args[1], &flags); + if (ret != napi_ok) { + LOGE("nativeSetAccessibilityFeatures napi_get_value_int64 error"); + return nullptr; + } + LOGD( + "PlatformViewOHOSNapi::nativeSetAccessibilityFeatures flags: %{public}ld", + flags); + OHOS_SHELL_HOLDER->GetPlatformView()->SetAccessibilityFeatures(flags); + return nullptr; +} + +/** + * 加载动态库,或者dart库失败时的通知 + */ +napi_value PlatformViewOHOSNapi::nativeDeferredComponentInstallFailure( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeDeferredComponentInstallFailure"); + + napi_status ret; + size_t argc = 3; + napi_value args[3] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeDeferredComponentInstallFailure napi_get_cb_info error"); + return nullptr; + } + + int64_t loadingUnitId; + ret = napi_get_value_int64(env, args[0], &loadingUnitId); + if (ret != napi_ok) { + LOGE("nativeDeferredComponentInstallFailure napi_get_value_int64 error"); + return nullptr; + } + LOGD( + "PlatformViewOHOSNapi::nativeSetAccessibilityFeatures loadingUnitId: " + "%{public}ld", + loadingUnitId); + std::string error; + if (fml::napi::SUCCESS != fml::napi::GetString(env, args[1], error)) { + LOGE( + "nativeDeferredComponentInstallFailure napi_get_value_string_utf8 " + "error"); + return nullptr; + } + LOGD("nativeSetAccessibilityFeatures loadingUnitId: %s", error.c_str()); + + bool isTransient; + ret = napi_get_value_bool(env, args[2], &isTransient); + if (ret != napi_ok) { + LOGE("nativeDeferredComponentInstallFailure napi_get_value_bool error"); + return nullptr; + } + LOGD("nativeSetAccessibilityFeatures loadingUnitId: %{public}d", isTransient); + + LoadLoadingUnitFailure(static_cast(loadingUnitId), + std::string(error), static_cast(isTransient)); + + return nullptr; +} + +/** + * 应用低内存警告 + */ +napi_value PlatformViewOHOSNapi::nativeNotifyLowMemoryWarning( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeNotifyLowMemoryWarning"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeNotifyLowMemoryWarning napi_get_cb_info error"); + return nullptr; + } + + int64_t shell_holder; + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + LOGE("nativeNotifyLowMemoryWarning napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeNotifyLowMemoryWarning shell_holder: %{public}ld", shell_holder); + OHOS_SHELL_HOLDER->NotifyLowMemoryWarning(); + + return nullptr; +} + +// 下面的方法,从键盘输入中判断当前字符是否是emoji + +/** + * + */ +napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmoji( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmoji"); + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmoji napi_get_cb_info error"); + return nullptr; + } + + int64_t codePoint; + ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmoji napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeFlutterTextUtilsIsEmoji codePoint: %{public}ld ", codePoint); + + bool value = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI); + napi_value result = nullptr; + ret = napi_get_boolean(env, value, &result); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmoji napi_get_boolean error"); + return nullptr; + } + + return result; +} + +/** + * + */ +napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifier( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifier"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmojiModifier napi_get_cb_info error"); + return nullptr; + } + + int64_t codePoint; + ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmojiModifier napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeFlutterTextUtilsIsEmojiModifier codePoint: %{public}ld ", + codePoint); + + bool value = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER); + napi_value result = nullptr; + ret = napi_get_boolean(env, value, &result); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmojiModifier napi_get_boolean error"); + return nullptr; + } + + return result; +} + +/** + * + */ +napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifierBase( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifierBase"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmojiModifierBase napi_get_cb_info error"); + return nullptr; + } + + int64_t codePoint; + ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + LOGE( + "nativeFlutterTextUtilsIsEmojiModifierBase napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeFlutterTextUtilsIsEmojiModifierBase codePoint: %{public}ld ", + codePoint); + + bool value = + u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER_BASE); + napi_value result = nullptr; + ret = napi_get_boolean(env, value, &result); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsEmojiModifierBase napi_get_boolean error"); + return nullptr; + } + + return result; +} + +/** + * + */ +napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsVariationSelector( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsVariationSelector"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsVariationSelector napi_get_cb_info error"); + return nullptr; + } + + int64_t codePoint; + ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + LOGE( + "nativeFlutterTextUtilsIsVariationSelector napi_get_value_int64 error"); + return nullptr; + } + LOGD("nativeFlutterTextUtilsIsVariationSelector codePoint: %{public}ld ", + codePoint); + + bool value = + u_hasBinaryProperty(codePoint, UProperty::UCHAR_VARIATION_SELECTOR); + napi_value result = nullptr; + ret = napi_get_boolean(env, value, &result); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsVariationSelector napi_get_boolean error"); + return nullptr; + } + + return result; +} + +/** + * + */ +napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsRegionalIndicator( + napi_env env, + napi_callback_info info) { + LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsRegionalIndicator"); + + napi_status ret; + size_t argc = 1; + napi_value args[1] = {nullptr}; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsRegionalIndicator napi_get_cb_info error"); + return nullptr; + } + + int64_t codePoint; + ret = napi_get_value_int64(env, args[0], &codePoint); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsRegionalIndicator napi_get_value_int64 fail"); + return nullptr; + } + LOGD("nativeFlutterTextUtilsIsRegionalIndicator codePoint: %{public}ld ", + codePoint); + + bool value = + u_hasBinaryProperty(codePoint, UProperty::UCHAR_REGIONAL_INDICATOR); + napi_value result = nullptr; + ret = napi_get_boolean(env, value, &result); + if (ret != napi_ok) { + LOGE("nativeFlutterTextUtilsIsRegionalIndicator napi_get_boolean error"); + return nullptr; + } + + return result; +} + +/** + * @brief ArkTS下发系统语言设置列表 + * @note + * @param nativeShellHolderId: number + * @param systemLanguages: Array + * @return void + */ +napi_value PlatformViewOHOSNapi::nativeGetSystemLanguages( + napi_env env, + napi_callback_info info) { + napi_status ret; + size_t argc = 2; + napi_value args[2] = {nullptr}; + int64_t shell_holder; + std::vector local_languages; + ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeGetSystemLanguages napi_get_cb_info error:" + << ret; + return nullptr; + } + ret = napi_get_value_int64(env, args[0], &shell_holder); + if (ret != napi_ok) { + FML_DLOG(ERROR) << "nativeGetSystemLanguages napi_get_value_int64 error"; + return nullptr; + } + if (fml::napi::SUCCESS != + fml::napi::GetArrayString(env, args[1], local_languages)) { + FML_DLOG(ERROR) << "nativeGetSystemLanguages GetArrayString error"; + return nullptr; + } + system_languages = local_languages; + return nullptr; +} + +int64_t PlatformViewOHOSNapi::GetShellHolder() { + return PlatformViewOHOSNapi::shell_holder; +} + +void PlatformViewOHOSNapi::SurfaceCreated(int64_t shell_holder, void* window) { + auto native_window = fml::MakeRefCounted( + static_cast(window)); + OHOS_SHELL_HOLDER->GetPlatformView()->NotifyCreate(std::move(native_window)); +} + +void PlatformViewOHOSNapi::SurfaceChanged(int64_t shell_holder, + int32_t width, + int32_t height) { + OHOS_SHELL_HOLDER->GetPlatformView()->NotifyChanged( + SkISize::Make(width, height)); +} + +void PlatformViewOHOSNapi::SurfaceDestroyed(int64_t shell_holder) { + OHOS_SHELL_HOLDER->GetPlatformView()->NotifyDestroyed(); +} + +void PlatformViewOHOSNapi::SetPlatformTaskRunner( + fml::RefPtr platform_task_runner) { + platform_task_runner_ = platform_task_runner; +} + +} // namespace flutter diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h new file mode 100644 index 0000000000000000000000000000000000000000..8e698dc6e57f70335e85e85e5e3409f7b0338d9a --- /dev/null +++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef PLATFORM_VIEW_OHOS_NAPI_H +#define PLATFORM_VIEW_OHOS_NAPI_H +#include +#include "../napi_common.h" +#include "flutter/assets/directory_asset_bundle.h" +#include "flutter/common/settings.h" +#include "flutter/fml/file.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/mapping.h" +#include "flutter/fml/native_library.h" +#include "flutter/fml/size.h" +#include "flutter/lib/ui/plugins/callback_cache.h" +#include "flutter/runtime/dart_service_isolate.h" +#include "flutter/shell/common/run_configuration.h" +#include "napi/native_api.h" +// class for all c++ to call js function +namespace flutter { + +struct locale { + std::string language; + std::string script; + std::string region; +}; + +class PlatformViewOHOSNapi { + public: + static napi_value nativeDispatchEmptyPlatformMessage( + napi_env env, + napi_callback_info info); // 发送一个空的PlatformMessage + static napi_value nativeDispatchPlatformMessage( + napi_env env, + napi_callback_info info); // 发送一个PlatformMessage + static napi_value nativeInvokePlatformMessageEmptyResponseCallback( + napi_env env, + napi_callback_info info); // 空的PlatformMessage响应回调 + static napi_value nativeInvokePlatformMessageResponseCallback( + napi_env env, + napi_callback_info info); + + explicit PlatformViewOHOSNapi(napi_env env); + void SetPlatformTaskRunner(fml::RefPtr platform_task_runner); + void FlutterViewHandlePlatformMessageResponse( + int reponse_id, + std::unique_ptr data); + void FlutterViewHandlePlatformMessage( + int reponse_id, + std::unique_ptr message); + + void FlutterViewOnFirstFrame(); + void FlutterViewOnPreEngineRestart(); + flutter::locale resolveNativeLocale( + std::vector supportedLocales); + std::unique_ptr> + FlutterViewComputePlatformResolvedLocales( + const std::vector& support_locale_data); + void DecodeImage(int64_t imageGeneratorAddress, + void* inputData, + size_t dataSize); + + static napi_value nativeUpdateRefreshRate( + napi_env env, + napi_callback_info info); // 设置刷新率 + static napi_value nativeRunBundleAndSnapshotFromLibrary( + napi_env env, + napi_callback_info info); // 加载dart工程构建产物 + static napi_value nativePrefetchDefaultFontManager( + napi_env env, + napi_callback_info + info); // 初始化SkFontMgr::RefDefault(),skia引擎文字管理初始化 + static napi_value nativeGetIsSoftwareRenderingEnabled( + napi_env env, + napi_callback_info info); // 返回是否支持软件绘制 + + static napi_value nativeAttach( + napi_env env, + napi_callback_info + info); // attach flutterNapi实例给到 native + // engine,这个支持rkts到flutter平台的无关引擎之间的通信 + // attach只需要执行一次 + static napi_value nativeSpawn( + napi_env env, + napi_callback_info info); // 从当前的flutterNapi复制一个新的实例 + static napi_value nativeDestroy( + napi_env env, + napi_callback_info info); // Detaches flutterNapi和engine之间的关联 + static napi_value nativeSetViewportMetrics( + napi_env env, + napi_callback_info info); // 把物理屏幕参数通知到native + static napi_value nativeSetAccessibilityFeatures( + napi_env env, + napi_callback_info info); // 设置能力参数 + + static napi_value nativeCleanupMessageData( + napi_env env, + napi_callback_info info); // 清除某个messageData + static napi_value nativeLoadDartDeferredLibrary( + napi_env env, + napi_callback_info info); // load一个合法的.so文件到dart vm + static napi_value nativeUpdateOhosAssetManager( + napi_env env, + napi_callback_info info); // 设置ResourceManager和assetBundlePath到engine + static napi_value nativeDeferredComponentInstallFailure( + napi_env env, + napi_callback_info info); // 加载动态库,或者dart库失败时的通知 + static napi_value nativeGetPixelMap( + napi_env env, + napi_callback_info info); // 从engine获取当前绘制pixelMap + static napi_value nativeNotifyLowMemoryWarning( + napi_env env, + napi_callback_info info); // 应用低内存警告 + + // 下面的方法,从键盘输入中判断当前字符是否是emoji,实现优先级低 + static napi_value nativeFlutterTextUtilsIsEmoji(napi_env env, + napi_callback_info info); + static napi_value nativeFlutterTextUtilsIsEmojiModifier( + napi_env env, + napi_callback_info info); + static napi_value nativeFlutterTextUtilsIsEmojiModifierBase( + napi_env env, + napi_callback_info info); + static napi_value nativeFlutterTextUtilsIsVariationSelector( + napi_env env, + napi_callback_info info); + static napi_value nativeFlutterTextUtilsIsRegionalIndicator( + napi_env env, + napi_callback_info info); + static napi_value nativeGetSystemLanguages( + napi_env env, + napi_callback_info info); // 应用下发系统语言设置 + + // Surface相关,XComponent调用 + static void SurfaceCreated(int64_t shell_holder, void* window); + static void SurfaceChanged(int64_t shell_holder, + int32_t width, + int32_t height); + static void SurfaceDestroyed(int64_t shell_holder); + static int64_t GetShellHolder(); + + private: + static napi_env env_; + static napi_ref ref_napi_obj_; + static int64_t shell_holder; + static std::vector system_languages; + fml::RefPtr platform_task_runner_; +}; + +} // namespace flutter +#endif diff --git a/shell/platform/ohos/napi_common.h b/shell/platform/ohos/napi_common.h new file mode 100644 index 0000000000000000000000000000000000000000..1783f071818ed634ea98f148a14dbf68a47209ea --- /dev/null +++ b/shell/platform/ohos/napi_common.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 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. + */ + +// +// Created on 2023/6/17. +// +// Node APIs are not fully supported. To solve the compilation error of the +// interface cannot be found, please include "napi/native_api.h". + +#ifndef XComponentDemo_native_common_H +#define XComponentDemo_native_common_H + +#include +#define APP_LOG_DOMAIN 0x0000 +#define APP_LOG_TAG "XComFlutterOHOS_Native" +#define LOGI(...) \ + ((void)OH_LOG_Print(LOG_APP, LOG_INFO, APP_LOG_DOMAIN, APP_LOG_TAG, \ + __VA_ARGS__)) +// #define LOGD(...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, APP_LOG_DOMAIN, +// APP_LOG_TAG, __VA_ARGS__)) +#define LOGD(...) \ + ((void)OH_LOG_Print(LOG_APP, LOG_INFO, APP_LOG_DOMAIN, APP_LOG_TAG, \ + __VA_ARGS__)) +#define LOGW(...) \ + ((void)OH_LOG_Print(LOG_APP, LOG_WARN, APP_LOG_DOMAIN, APP_LOG_TAG, \ + __VA_ARGS__)) +#define LOGE(...) \ + ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, APP_LOG_DOMAIN, APP_LOG_TAG, \ + __VA_ARGS__)) + +#define NAPI_RETVAL_NOTHING + +#define GET_AND_THROW_LAST_ERROR(env) \ + do { \ + const napi_extended_error_info* errorInfo = nullptr; \ + napi_get_last_error_info((env), &errorInfo); \ + bool isPending = false; \ + napi_is_exception_pending((env), &isPending); \ + if (!isPending && errorInfo != nullptr) { \ + const char* errorMessage = errorInfo->error_message != nullptr \ + ? errorInfo->error_message \ + : "empty error message"; \ + napi_throw_error((env), nullptr, errorMessage); \ + } \ + } while (0) + +#define NAPI_ASSERT_BASE(env, assertion, message, retVal) \ + do { \ + if (!(assertion)) { \ + napi_throw_error((env), nullptr, \ + "assertion (" #assertion ") failed: " message); \ + return retVal; \ + } \ + } while (0) + +#define NAPI_ASSERT(env, assertion, message) \ + NAPI_ASSERT_BASE(env, assertion, message, nullptr) + +#define NAPI_ASSERT_RETURN_VOID(env, assertion, message) \ + NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING) + +#define NAPI_CALL_BASE(env, theCall, retVal) \ + do { \ + if ((theCall) != napi_ok) { \ + GET_AND_THROW_LAST_ERROR((env)); \ + return retVal; \ + } \ + } while (0) + +#define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr) + +#define NAPI_CALL_RETURN_VOID(env, theCall) \ + NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING) + +#define DECLARE_NAPI_PROPERTY(name, val) \ + { (name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr } + +#define DECLARE_NAPI_STATIC_PROPERTY(name, val) \ + { (name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr } + +#define DECLARE_NAPI_FUNCTION(name, func) \ + { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr } + +#define DECLARE_NAPI_FUNCTION_WITH_DATA(name, func, data) \ + { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, data } + +#define DECLARE_NAPI_STATIC_FUNCTION(name, func) \ + { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr } + +#define DECLARE_NAPI_GETTER(name, getter) \ + { \ + (name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, \ + nullptr \ + } + +#define DECLARE_NAPI_SETTER(name, setter) \ + { \ + (name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, \ + nullptr \ + } + +#define DECLARE_NAPI_GETTER_SETTER(name, getter, setter) \ + { \ + (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, \ + nullptr \ + } + +#endif // XComponentDemo_native_common_H diff --git a/shell/platform/ohos/ohos_asset_provider.cpp b/shell/platform/ohos/ohos_asset_provider.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8cabce185ea2bd5b0ca89114493b473a11160a06 --- /dev/null +++ b/shell/platform/ohos/ohos_asset_provider.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_asset_provider.h" +#include +#include +#include "napi_common.h" + +namespace flutter { + +class FileDescriptionMapping : public fml::Mapping { + public: + explicit FileDescriptionMapping(RawFile* fileHandle) + : fileHandle_(fileHandle), filebuf(nullptr), _read_from_file(false) { + LOGD("FileDescriptionMapping :%{public}p", fileHandle_); + int ret = 0; + if (0 > (ret = ReadFile())) { + LOGD("FileDescriptionMapping :%{public}d", ret); + } + } + void* GetBuffer() { + // TODO 考虑线程安全 + + if (filebuf != nullptr) + return filebuf; + + size_t bufLenth = GetSize(); + + if (fileHandle_ != nullptr && bufLenth > 0) { + LOGD("FileDescriptionMapping buflenth = %{public}ld", bufLenth); + filebuf = malloc(bufLenth + 1); + memset(filebuf, 0, bufLenth + 1); + } + return filebuf; + } + + ~FileDescriptionMapping() override { + if (fileHandle_ != nullptr) { + OH_ResourceManager_CloseRawFile(fileHandle_); + } + if (filebuf != nullptr) { + free(filebuf); + filebuf = nullptr; + } + } + + size_t GetSize() const override { + if (fileHandle_ == nullptr) + return 0; + + size_t ret = OH_ResourceManager_GetRawFileSize(fileHandle_); + LOGD("GetSize():%{public}zu", ret); + return ret; + } + + int ReadFile() { + if (fileHandle_ == nullptr) { + LOGE("GetMapping failed. fileHandle_:%{public}p,filebuf:%{public}p", + fileHandle_, filebuf); + return -1; + } + + size_t len = GetSize(); + void* buf = GetBuffer(); + int ret = 0; + + if (buf != nullptr) { + ret = OH_ResourceManager_ReadRawFile(fileHandle_, buf, len); + _read_from_file = true; + } + LOGD("GetMapping ... total:%{public}zu, ret:%{public}d,buf:%{public}p", len, + ret, buf); + return ret; + } + const uint8_t* GetMapping() const override { + return reinterpret_cast(filebuf); + } + + bool IsDontNeedSafe() const override { + // thread unsafe + return false; + } + + private: + RawFile* fileHandle_; + void* filebuf; + bool _read_from_file; + FML_DISALLOW_COPY_AND_ASSIGN(FileDescriptionMapping); +}; + +OHOSAssetProvider::OHOSAssetProvider(void* assetHandle, const std::string& dir) + : assetHandle_(assetHandle), dir_(dir) { + LOGD("assets dir:%{public}s", dir.c_str()); +} + +bool OHOSAssetProvider::IsValid() const { + return (assetHandle_ != nullptr); +} + +bool OHOSAssetProvider::IsValidAfterAssetManagerChange() const { + return true; +} + +AssetResolver::AssetResolverType OHOSAssetProvider::GetType() const { + return AssetResolver::AssetResolverType::kApkAssetProvider; +} + +std::unique_ptr OHOSAssetProvider::GetAsMapping( + const std::string& asset_name) const { + NativeResourceManager* nativeResMgr = + reinterpret_cast(assetHandle_); + if (assetHandle_ == nullptr || nativeResMgr == nullptr) { + LOGE("nativeResMgr is null:%{public}p or nativeResMgr is null:%{public}p ", + assetHandle_, nativeResMgr); + } + std::string relativePath = dir_ + "/" + asset_name; + + LOGE("GetAsMapping=%{public}s->%{public}s", asset_name.c_str(), + relativePath.c_str()); + + RawFile* fileHandle = + OH_ResourceManager_OpenRawFile(nativeResMgr, relativePath.c_str()); + LOGE("GetAsMapping=%{public}s->%{public}p", relativePath.c_str(), fileHandle); + + if (fileHandle == nullptr) { + fileHandle = + OH_ResourceManager_OpenRawFile(nativeResMgr, asset_name.c_str()); + LOGE("GetAsMapping2 ..fallback:%{public}s->%{public}p", asset_name.c_str(), + fileHandle); + } + LOGE("GetAsMappingend:%{public}p", fileHandle); + return fileHandle == nullptr + ? nullptr + : (std::make_unique(fileHandle)); +} + +std::unique_ptr OHOSAssetProvider::Clone() const { + return std::make_unique(assetHandle_); +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_asset_provider.h b/shell/platform/ohos/ohos_asset_provider.h new file mode 100755 index 0000000000000000000000000000000000000000..666aeb69b66cedb6e7859821efeb6c9fec59965a --- /dev/null +++ b/shell/platform/ohos/ohos_asset_provider.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_ASSET_PROVIDER_H +#define OHOS_ASSET_PROVIDER_H + +#include "flutter/assets/asset_resolver.h" +#include "flutter/fml/memory/ref_counted.h" + +namespace flutter { + +// ohos平台的文件管理 ,必须通过NativeResourceManager* 指针对它进行初始化 +class OHOSAssetProvider final : public AssetResolver { + public: + explicit OHOSAssetProvider(void* assetHandle, + const std::string& dir = "flutter_assets"); + ~OHOSAssetProvider() = default; + + std::unique_ptr Clone() const; + + private: + void* assetHandle_; + std::string dir_; + + bool IsValid() const override; + + bool IsValidAfterAssetManagerChange() const override; + + AssetResolver::AssetResolverType GetType() const override; + + std::unique_ptr GetAsMapping( + const std::string& asset_name) const override; +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_context_gl_impeller.cpp b/shell/platform/ohos/ohos_context_gl_impeller.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1610073bb8364a0d9f55134dd5be5de8a85770d7 --- /dev/null +++ b/shell/platform/ohos/ohos_context_gl_impeller.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_context_gl_impeller.h" + +namespace flutter { + +OHOSContextGLImpeller::OHOSContextGLImpeller() + : OHOSContext(OHOSRenderingAPI::kOpenGLES) {} + +OHOSContextGLImpeller::~OHOSContextGLImpeller() {} + +bool OHOSContextGLImpeller::IsValid() const { + return true; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_context_gl_impeller.h b/shell/platform/ohos/ohos_context_gl_impeller.h new file mode 100755 index 0000000000000000000000000000000000000000..3947b457d1452d90ac8ae87b100f91e4dc92047e --- /dev/null +++ b/shell/platform/ohos/ohos_context_gl_impeller.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_CONTEXT_GL_IMPELLER_H +#define OHOS_CONTEXT_GL_IMPELLER_H +#include "context/ohos_context.h" +#include "flutter/fml/macros.h" + +namespace flutter { +class OHOSContextGLImpeller : public OHOSContext { + public: + OHOSContextGLImpeller(); + + ~OHOSContextGLImpeller(); + + bool IsValid() const override; + + private: + FML_DISALLOW_COPY_AND_ASSIGN(OHOSContextGLImpeller); +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_context_gl_skia.cpp b/shell/platform/ohos/ohos_context_gl_skia.cpp new file mode 100755 index 0000000000000000000000000000000000000000..2dbd1a971833dc6f5d6d5bbd3ab90b921c1dfe96 --- /dev/null +++ b/shell/platform/ohos/ohos_context_gl_skia.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h" + +#include + +#include "flutter/fml/trace_event.h" +#include "flutter/shell/platform/ohos/ohos_egl_surface.h" + +namespace flutter { + +template +using EGLResult = std::pair; + +static EGLResult CreateContext(EGLDisplay display, + EGLConfig config, + EGLContext share = EGL_NO_CONTEXT) { + EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + + EGLContext context = eglCreateContext(display, config, share, attributes); + + return {context != EGL_NO_CONTEXT, context}; +} + +static EGLResult ChooseEGLConfiguration(EGLDisplay display, + uint8_t msaa_samples) { + EGLint sample_buffers = msaa_samples > 1 ? 1 : 0; + EGLint attributes[] = { + // clang-format off + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 0, + EGL_STENCIL_SIZE, 0, + EGL_SAMPLES, static_cast(msaa_samples), + EGL_SAMPLE_BUFFERS, sample_buffers, + EGL_NONE, // termination sentinel + // clang-format on + }; + + EGLint config_count = 0; + EGLConfig egl_config = nullptr; + + if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) != + EGL_TRUE) { + return {false, nullptr}; + } + + bool success = config_count > 0 && egl_config != nullptr; + + return {success, success ? egl_config : nullptr}; +} + +static bool TeardownContext(EGLDisplay display, EGLContext context) { + if (context != EGL_NO_CONTEXT) { + return eglDestroyContext(display, context) == EGL_TRUE; + } + + return true; +} + +OhosContextGLSkia::OhosContextGLSkia(OHOSRenderingAPI rendering_api, + fml::RefPtr environment, + const TaskRunners& task_runners, + uint8_t msaa_samples) + : OHOSContext(OHOSRenderingAPI::kOpenGLES), + environment_(std::move(environment)), + config_(nullptr), + task_runners_(task_runners) { + if (!environment_->IsValid()) { + FML_LOG(ERROR) << "Could not create an Ohos GL environment."; + return; + } + + bool success = false; + + // Choose a valid configuration. + std::tie(success, config_) = + ChooseEGLConfiguration(environment_->Display(), msaa_samples); + if (!success) { + FML_LOG(ERROR) << "Could not choose an EGL configuration."; + LogLastEGLError(); + return; + } + + // Create a context for the configuration. + std::tie(success, context_) = + CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT); + if (!success) { + FML_LOG(ERROR) << "Could not create an EGL context"; + LogLastEGLError(); + return; + } + + std::tie(success, resource_context_) = + CreateContext(environment_->Display(), config_, context_); + if (!success) { + FML_LOG(ERROR) << "Could not create an EGL resource context"; + LogLastEGLError(); + return; + } + + // All done! + valid_ = true; +} + +OhosContextGLSkia::~OhosContextGLSkia() { + FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); + sk_sp main_context = GetMainSkiaContext(); + SetMainSkiaContext(nullptr); + fml::AutoResetWaitableEvent latch; + // This context needs to be deallocated from the raster thread in order to + // keep a coherent usage of egl from a single thread. + fml::TaskRunner::RunNowOrPostTask(task_runners_.GetRasterTaskRunner(), [&] { + if (main_context) { + std::unique_ptr pbuffer_surface = CreatePbufferSurface(); + auto status = pbuffer_surface->MakeCurrent(); + if (status != OhosEGLSurfaceMakeCurrentStatus::kFailure) { + main_context->releaseResourcesAndAbandonContext(); + main_context.reset(); + ClearCurrent(); + } + } + latch.Signal(); + }); + latch.Wait(); + + if (!TeardownContext(environment_->Display(), context_)) { + FML_LOG(ERROR) + << "Could not tear down the EGL context. Possible resource leak."; + LogLastEGLError(); + } + + if (!TeardownContext(environment_->Display(), resource_context_)) { + FML_LOG(ERROR) << "Could not tear down the EGL resource context. Possible " + "resource leak."; + LogLastEGLError(); + } +} + +std::unique_ptr OhosContextGLSkia::CreateOnscreenSurface( + const fml::RefPtr& window) const { + if (window->IsFakeWindow()) { + return CreatePbufferSurface(); + } else { + EGLDisplay display = environment_->Display(); + + const EGLint attribs[] = {EGL_NONE}; + + EGLSurface surface = eglCreateWindowSurface( + display, config_, + reinterpret_cast(window->handle()), attribs); + return std::make_unique(surface, display, context_); + } +} + +std::unique_ptr OhosContextGLSkia::CreateOffscreenSurface() + const { + // We only ever create pbuffer surfaces for background resource loading + // contexts. We never bind the pbuffer to anything. + FML_LOG(INFO) << "CreateOffscreenSurface 1"; + if (environment_) { + FML_LOG(INFO) << "CreateOffscreenSurface environment_ "; + } else { + FML_LOG(INFO) << "CreateOffscreenSurface environment_ nullptr"; + } + + EGLDisplay display = environment_->Display(); + + const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; + FML_LOG(INFO) << "CreateOffscreenSurface 2"; + EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs); + FML_LOG(INFO) << "CreateOffscreenSurface 3"; + return std::make_unique(surface, display, resource_context_); +} + +std::unique_ptr OhosContextGLSkia::CreatePbufferSurface() + const { + EGLDisplay display = environment_->Display(); + + const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; + + EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs); + return std::make_unique(surface, display, context_); +} + +fml::RefPtr OhosContextGLSkia::Environment() const { + return environment_; +} + +bool OhosContextGLSkia::IsValid() const { + return valid_; +} + +bool OhosContextGLSkia::ClearCurrent() const { + if (eglGetCurrentContext() != context_) { + return true; + } + if (eglMakeCurrent(environment_->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT) != EGL_TRUE) { + FML_LOG(ERROR) << "Could not clear the current context"; + LogLastEGLError(); + return false; + } + return true; +} + +EGLContext OhosContextGLSkia::CreateNewContext() const { + bool success; + EGLContext context; + std::tie(success, context) = + CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT); + return success ? context : EGL_NO_CONTEXT; +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_context_gl_skia.h b/shell/platform/ohos/ohos_context_gl_skia.h new file mode 100755 index 0000000000000000000000000000000000000000..c30a24da87310f8b2e02f62c53de08875e1152d6 --- /dev/null +++ b/shell/platform/ohos/ohos_context_gl_skia.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_ +#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_ + +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/ref_counted.h" +#include "flutter/fml/memory/ref_ptr.h" +#include "flutter/shell/common/platform_view.h" +#include "flutter/shell/platform/ohos/context/ohos_context.h" +#include "flutter/shell/platform/ohos/ohos_environment_gl.h" +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace flutter { + +class OhosEGLSurface; + +//------------------------------------------------------------------------------ +/// The Ohos context is used by `OhosSurfaceGL` to create and manage +/// EGL surfaces. +/// +/// This context binds `EGLContext` to the current rendering thread and to the +/// draw and read `EGLSurface`s. +/// +class OhosContextGLSkia : public OHOSContext { + public: + OhosContextGLSkia(OHOSRenderingAPI rendering_api, + fml::RefPtr environment, + const TaskRunners& taskRunners, + uint8_t msaa_samples); + + ~OhosContextGLSkia(); + + //---------------------------------------------------------------------------- + /// @brief Allocates an new EGL window surface that is used for on-screen + /// pixels. + /// + /// @return The window surface. + /// + std::unique_ptr CreateOnscreenSurface( + const fml::RefPtr& window) const; + + //---------------------------------------------------------------------------- + /// @brief Allocates an 1x1 pbuffer surface that is used for making the + /// offscreen current for texture uploads. + /// + /// @return The pbuffer surface. + /// + std::unique_ptr CreateOffscreenSurface() const; + + //---------------------------------------------------------------------------- + /// @brief Allocates an 1x1 pbuffer surface that is used for making the + /// onscreen context current for snapshotting. + /// + /// @return The pbuffer surface. + /// + std::unique_ptr CreatePbufferSurface() const; + + //---------------------------------------------------------------------------- + /// @return The Ohos environment that contains a reference to the + /// display. + /// + fml::RefPtr Environment() const; + + //---------------------------------------------------------------------------- + /// @return Whether the current context is valid. That is, if the EGL + /// contexts were successfully created. + /// + bool IsValid() const override; + + //---------------------------------------------------------------------------- + /// @return Whether the current context was successfully clear. + /// + bool ClearCurrent() const; + + //---------------------------------------------------------------------------- + /// @brief Create a new EGLContext using the same EGLConfig. + /// + /// @return The EGLContext. + /// + EGLContext CreateNewContext() const; + + //---------------------------------------------------------------------------- + /// @brief The EGLConfig for this context. + /// + EGLConfig Config() const { return config_; } + + private: + fml::RefPtr environment_; + EGLConfig config_; + EGLContext context_; + EGLContext resource_context_; + bool valid_ = false; + TaskRunners task_runners_; + + FML_DISALLOW_COPY_AND_ASSIGN(OhosContextGLSkia); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_ diff --git a/shell/platform/ohos/ohos_display.cpp b/shell/platform/ohos/ohos_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32feddb2c3ad863179afd0be83d663c35a49b18e --- /dev/null +++ b/shell/platform/ohos/ohos_display.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_display.h" + +namespace flutter { + +const double defaultFPS = 60; + +OHOSDisplay::OHOSDisplay(std::shared_ptr napi_facade) + : Display(60), napi_facade_(std::move(napi_facade)) {} + +double OHOSDisplay::GetRefreshRate() const { + return defaultFPS; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_display.h b/shell/platform/ohos/ohos_display.h new file mode 100644 index 0000000000000000000000000000000000000000..873f2cff90e15467199eda7890a68b7c66229b62 --- /dev/null +++ b/shell/platform/ohos/ohos_display.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_DISPLAY_H +#define OHOS_DISPLAY_H + +#include + +#include "flutter/fml/macros.h" +#include "flutter/shell/common/display.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +namespace flutter { + +class OHOSDisplay : public Display { + public: + explicit OHOSDisplay(std::shared_ptr napi_facade_); + ~OHOSDisplay() = default; + + double GetRefreshRate() const override; + + private: + std::shared_ptr napi_facade_; + FML_DISALLOW_COPY_AND_ASSIGN(OHOSDisplay); +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_egl_surface.cpp b/shell/platform/ohos/ohos_egl_surface.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b416d1269fec3993de31982af9e70c868477c55c --- /dev/null +++ b/shell/platform/ohos/ohos_egl_surface.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_egl_surface.h" + +#include + +#include +#include + +#include "flutter/fml/trace_event.h" + +namespace flutter { + +void LogLastEGLError() { + struct EGLNameErrorPair { + const char* name; + EGLint code; + }; + +#define _EGL_ERROR_DESC(a) \ + { #a, a } + + const EGLNameErrorPair pairs[] = { + _EGL_ERROR_DESC(EGL_SUCCESS), + _EGL_ERROR_DESC(EGL_NOT_INITIALIZED), + _EGL_ERROR_DESC(EGL_BAD_ACCESS), + _EGL_ERROR_DESC(EGL_BAD_ALLOC), + _EGL_ERROR_DESC(EGL_BAD_ATTRIBUTE), + _EGL_ERROR_DESC(EGL_BAD_CONTEXT), + _EGL_ERROR_DESC(EGL_BAD_CONFIG), + _EGL_ERROR_DESC(EGL_BAD_CURRENT_SURFACE), + _EGL_ERROR_DESC(EGL_BAD_DISPLAY), + _EGL_ERROR_DESC(EGL_BAD_SURFACE), + _EGL_ERROR_DESC(EGL_BAD_MATCH), + _EGL_ERROR_DESC(EGL_BAD_PARAMETER), + _EGL_ERROR_DESC(EGL_BAD_NATIVE_PIXMAP), + _EGL_ERROR_DESC(EGL_BAD_NATIVE_WINDOW), + _EGL_ERROR_DESC(EGL_CONTEXT_LOST), + }; + +#undef _EGL_ERROR_DESC + + const auto count = sizeof(pairs) / sizeof(EGLNameErrorPair); + + EGLint last_error = eglGetError(); + + for (size_t i = 0; i < count; i++) { + if (last_error == pairs[i].code) { + FML_LOG(ERROR) << "EGL Error: " << pairs[i].name << " (" << pairs[i].code + << ")"; + return; + } + } + + FML_LOG(ERROR) << "Unknown EGL Error"; +} + +namespace { + +static bool HasExtension(const char* extensions, const char* name) { + const char* r = strstr(extensions, name); + auto len = strlen(name); + // check that the extension name is terminated by space or null terminator + return r != nullptr && (r[len] == ' ' || r[len] == 0); +} + +} // namespace + +class OhosEGLSurfaceDamage { + public: + void init(EGLDisplay display, EGLContext context) { + const char* extensions = eglQueryString(display, EGL_EXTENSIONS); + if (HasExtension(extensions, "EGL_KHR_partial_update")) { + set_damage_region_ = reinterpret_cast( + eglGetProcAddress("eglSetDamageRegionKHR")); + } + + if (HasExtension(extensions, "EGL_EXT_swap_buffers_with_damage")) { + swap_buffers_with_damage_ = + reinterpret_cast( + eglGetProcAddress("eglSwapBuffersWithDamageEXT")); + } else if (HasExtension(extensions, "EGL_KHR_swap_buffers_with_damage")) { + swap_buffers_with_damage_ = + reinterpret_cast( + eglGetProcAddress("eglSwapBuffersWithDamageKHR")); + } + + partial_redraw_supported_ = + set_damage_region_ != nullptr && swap_buffers_with_damage_ != nullptr; + } + + void SetDamageRegion(EGLDisplay display, + EGLSurface surface, + const std::optional& region) { + if (set_damage_region_ && region) { + auto rects = RectToInts(display, surface, *region); + set_damage_region_(display, surface, rects.data(), 1); + } + } + + // Maximum damage history - for triple buffering we need to store damage for + // last two frames; Some Ohos devices (Pixel 4) use quad buffering. + static const int kMaxHistorySize = 10; + + bool SupportsPartialRepaint() const { return partial_redraw_supported_; } + + std::optional InitialDamage(EGLDisplay display, EGLSurface surface) { + if (!partial_redraw_supported_) { + return std::nullopt; + } + + EGLint age; + eglQuerySurface(display, surface, EGL_BUFFER_AGE_EXT, &age); + + if (age == 0) { // full repaint + return std::nullopt; + } else { + // join up to (age - 1) last rects from damage history + --age; + auto res = SkIRect::MakeEmpty(); + for (auto i = damage_history_.rbegin(); + i != damage_history_.rend() && age > 0; ++i, --age) { + res.join(*i); + } + return res; + } + } + + bool SwapBuffersWithDamage(EGLDisplay display, + EGLSurface surface, + const std::optional& damage) { + if (swap_buffers_with_damage_ && damage) { + damage_history_.push_back(*damage); + if (damage_history_.size() > kMaxHistorySize) { + damage_history_.pop_front(); + } + auto rects = RectToInts(display, surface, *damage); + return swap_buffers_with_damage_(display, surface, rects.data(), 1); + } else { + return eglSwapBuffers(display, surface); + } + } + + private: + std::array static RectToInts(EGLDisplay display, + EGLSurface surface, + const SkIRect& rect) { + EGLint height; + eglQuerySurface(display, surface, EGL_HEIGHT, &height); + + std::array res{rect.left(), height - rect.bottom(), rect.width(), + rect.height()}; + return res; + } + + PFNEGLSETDAMAGEREGIONKHRPROC set_damage_region_ = nullptr; + PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage_ = nullptr; + + bool partial_redraw_supported_; + + std::list damage_history_; +}; + +OhosEGLSurface::OhosEGLSurface(EGLSurface surface, + EGLDisplay display, + EGLContext context) + : surface_(surface), + display_(display), + context_(context), + damage_(std::make_unique()), + presentation_time_proc_(nullptr) { + FML_LOG(INFO) << "OhosEGLSurface start"; + damage_->init(display_, context); + FML_LOG(INFO) << "OhosEGLSurface end"; +} + +OhosEGLSurface::~OhosEGLSurface() { + [[maybe_unused]] auto result = eglDestroySurface(display_, surface_); + FML_DCHECK(result == EGL_TRUE); +} + +bool OhosEGLSurface::IsValid() const { + return surface_ != EGL_NO_SURFACE; +} + +bool OhosEGLSurface::IsContextCurrent() const { + EGLContext current_egl_context = eglGetCurrentContext(); + if (context_ != current_egl_context) { + return false; + } + + EGLDisplay current_egl_display = eglGetCurrentDisplay(); + if (display_ != current_egl_display) { + return false; + } + + EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW); + if (draw_surface != surface_) { + return false; + } + + EGLSurface read_surface = eglGetCurrentSurface(EGL_READ); + if (read_surface != surface_) { + return false; + } + + return true; +} + +OhosEGLSurfaceMakeCurrentStatus OhosEGLSurface::MakeCurrent() const { + if (IsContextCurrent()) { + return OhosEGLSurfaceMakeCurrentStatus::kSuccessAlreadyCurrent; + } + if (eglMakeCurrent(display_, surface_, surface_, context_) != EGL_TRUE) { + FML_LOG(ERROR) << "Could not make the context current"; + LogLastEGLError(); + return OhosEGLSurfaceMakeCurrentStatus::kFailure; + } + return OhosEGLSurfaceMakeCurrentStatus::kSuccessMadeCurrent; +} + +void OhosEGLSurface::SetDamageRegion( + const std::optional& buffer_damage) { + damage_->SetDamageRegion(display_, surface_, buffer_damage); +} + +bool OhosEGLSurface::SetPresentationTime( + const fml::TimePoint& presentation_time) { + if (presentation_time_proc_) { + const auto time_ns = presentation_time.ToEpochDelta().ToNanoseconds(); + return presentation_time_proc_(display_, surface_, time_ns); + } else { + return false; + } +} + +bool OhosEGLSurface::SwapBuffers(const std::optional& surface_damage) { + TRACE_EVENT0("flutter", "OhosContextGL::SwapBuffers"); + return damage_->SwapBuffersWithDamage(display_, surface_, surface_damage); +} + +bool OhosEGLSurface::SupportsPartialRepaint() const { + return damage_->SupportsPartialRepaint(); +} + +std::optional OhosEGLSurface::InitialDamage() { + return damage_->InitialDamage(display_, surface_); +} + +SkISize OhosEGLSurface::GetSize() const { + EGLint width = 0; + EGLint height = 0; + + if (!eglQuerySurface(display_, surface_, EGL_WIDTH, &width) || + !eglQuerySurface(display_, surface_, EGL_HEIGHT, &height)) { + FML_LOG(ERROR) << "Unable to query EGL surface size"; + LogLastEGLError(); + return SkISize::Make(0, 0); + } + return SkISize::Make(width, height); +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_egl_surface.h b/shell/platform/ohos/ohos_egl_surface.h new file mode 100755 index 0000000000000000000000000000000000000000..a2f98f90a40b295fe836e065c890a491e4b1df6f --- /dev/null +++ b/shell/platform/ohos/ohos_egl_surface.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_SHELL_PLATFORM_OHOS_EGL_SURFACE_H_ +#define FLUTTER_SHELL_PLATFORM_OHOS_EGL_SURFACE_H_ + +#include +#include +#include +#include + +#include "flutter/fml/macros.h" +#include "flutter/fml/time/time_point.h" +#include "flutter/shell/platform/ohos/ohos_environment_gl.h" +#include "third_party/skia/include/core/SkRect.h" + +namespace flutter { + +//------------------------------------------------------------------------------ +/// Holds an `EGLSurface` reference. +/// +/// +/// This can be used in conjunction to unique_ptr to provide better guarantees +/// about the lifespan of the `EGLSurface` object. +/// +class OhosEGLSurfaceDamage; + +/// Result of calling MakeCurrent on OhosEGLSurface. +enum class OhosEGLSurfaceMakeCurrentStatus { + /// Success, the egl context for the surface was already current. + kSuccessAlreadyCurrent, + /// Success, the egl context for the surface made current. + kSuccessMadeCurrent, + /// Failed to make the egl context for the surface current. + kFailure, +}; + +void LogLastEGLError(); + +class OhosEGLSurface { + public: + OhosEGLSurface(EGLSurface surface, EGLDisplay display, EGLContext context); + + ~OhosEGLSurface(); + + //---------------------------------------------------------------------------- + /// @return Whether the current `EGLSurface` reference is valid. That is, + /// if + /// the surface doesn't point to `EGL_NO_SURFACE`. + /// + bool IsValid() const; + + //---------------------------------------------------------------------------- + /// @brief Binds the EGLContext context to the current rendering thread + /// and to the draw and read surface. + /// + /// @return Whether the surface was made current. + /// + OhosEGLSurfaceMakeCurrentStatus MakeCurrent() const; + + //---------------------------------------------------------------------------- + /// + /// @return Whether target surface supports partial repaint. + /// + bool SupportsPartialRepaint() const; + + //---------------------------------------------------------------------------- + /// @brief This is the minimal area that needs to be repainted to get + /// correct result. + /// + /// With double or triple buffering this buffer content may lag behind + /// current front buffer and the rect accounts for accumulated damage. + /// + /// @return The area of current surface where it is behind front buffer. + /// + std::optional InitialDamage(); + + //---------------------------------------------------------------------------- + /// @brief Sets the damage region for current surface. Corresponds to + // eglSetDamageRegionKHR + void SetDamageRegion(const std::optional& buffer_damage); + + //---------------------------------------------------------------------------- + /// @brief Sets the presentation time for the current surface. This + // corresponds to calling eglPresentationTimeOhos when + // available. + bool SetPresentationTime(const fml::TimePoint& presentation_time); + + //---------------------------------------------------------------------------- + /// @brief This only applies to on-screen surfaces such as those created + /// by `OhosContextGL::CreateOnscreenSurface`. + /// + /// @return Whether the EGL surface color buffer was swapped. + /// + bool SwapBuffers(const std::optional& surface_damage); + + //---------------------------------------------------------------------------- + /// @return The size of an `EGLSurface`. + /// + SkISize GetSize() const; + + private: + /// Returns true if the EGLContext held is current for the display and surface + bool IsContextCurrent() const; + + const EGLSurface surface_; + const EGLDisplay display_; + const EGLContext context_; + std::unique_ptr damage_; + PFNEGLPRESENTATIONTIMEANDROIDPROC presentation_time_proc_; +}; + +} // namespace flutter + +#endif diff --git a/shell/platform/ohos/ohos_environment_gl.cpp b/shell/platform/ohos/ohos_environment_gl.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b179e6a05aa5c15d4585c610c4db40cb1ae9f819 --- /dev/null +++ b/shell/platform/ohos/ohos_environment_gl.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_environment_gl.h" + +namespace flutter { + +OhosEnvironmentGL::OhosEnvironmentGL() + : display_(EGL_NO_DISPLAY), valid_(false) { + // Get the display. + display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + if (display_ == EGL_NO_DISPLAY) { + return; + } + + // Initialize the display connection. + if (eglInitialize(display_, nullptr, nullptr) != EGL_TRUE) { + return; + } + + valid_ = true; +} + +OhosEnvironmentGL::~OhosEnvironmentGL() { + // Disconnect the display if valid. + if (display_ != EGL_NO_DISPLAY) { + eglTerminate(display_); + } +} + +bool OhosEnvironmentGL::IsValid() const { + return valid_; +} + +EGLDisplay OhosEnvironmentGL::Display() const { + return display_; +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_environment_gl.h b/shell/platform/ohos/ohos_environment_gl.h new file mode 100755 index 0000000000000000000000000000000000000000..a2e925f61284b27471b703a6c903558758ac4c30 --- /dev/null +++ b/shell/platform/ohos/ohos_environment_gl.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_SHELL_PLATFORM_OHOS_ENVIRONMENT_GL_H_ +#define FLUTTER_SHELL_PLATFORM_OHOS_ENVIRONMENT_GL_H_ + +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/ref_counted.h" + +#include + +namespace flutter { + +class OhosEnvironmentGL : public fml::RefCountedThreadSafe { + private: + // MakeRefCounted + OhosEnvironmentGL(); + + // MakeRefCounted + ~OhosEnvironmentGL(); + + public: + bool IsValid() const; + + EGLDisplay Display() const; + + private: + EGLDisplay display_; + bool valid_; + + FML_FRIEND_MAKE_REF_COUNTED(OhosEnvironmentGL); + FML_FRIEND_REF_COUNTED_THREAD_SAFE(OhosEnvironmentGL); + FML_DISALLOW_COPY_AND_ASSIGN(OhosEnvironmentGL); +}; + +} // namespace flutter + +#endif diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8c5c6a68260abcef0f49c15799cc9b299a8bece3 --- /dev/null +++ b/shell/platform/ohos/ohos_external_texture_gl.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_external_texture_gl.h" +#include + +#include + +#include "third_party/skia/include/core/SkAlphaType.h" +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/core/SkColorType.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" + +namespace flutter { + +OHOSExternalTextureGL::OHOSExternalTextureGL(int id) + : Texture(id), transform(SkMatrix::I()) {} + +OHOSExternalTextureGL::~OHOSExternalTextureGL() { + if (state_ == AttachmentState::attached) { + // glDeleteTextures(1, &texture_name_); + } +} + +void OHOSExternalTextureGL::Paint(PaintContext& context, + const SkRect& bounds, + bool freeze, + const SkSamplingOptions& sampling) { + if (state_ == AttachmentState::detached) { + return; + } + if (state_ == AttachmentState::uninitialized) { + // glGenTextures(1, &texture_name_); + Attach(static_cast(texture_name_)); + state_ = AttachmentState::attached; + } + if (!freeze && new_frame_ready_) { + Update(); + new_frame_ready_ = false; + } + GrGLTextureInfo textureInfo = {0, texture_name_, GL_RGBA8_OES}; + GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo); + sk_sp image = SkImage::MakeFromTexture( + context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr); + if (image) { + SkAutoCanvasRestore autoRestore(context.canvas, true); + + // The incoming texture is vertically flipped, so we flip it + // back. OpenGL's coordinate system has Positive Y equivalent to up, while + // Skia's coordinate system has Negative Y equvalent to up. + context.canvas->translate(bounds.x(), bounds.y() + bounds.height()); + context.canvas->scale(bounds.width(), -bounds.height()); + + if (!transform.isIdentity()) { + sk_sp shader = image->makeShader( + SkTileMode::kRepeat, SkTileMode::kRepeat, sampling, transform); + + SkPaint paintWithShader; + if (context.sk_paint) { + paintWithShader = *context.sk_paint; + } + paintWithShader.setShader(shader); + context.canvas->drawRect(SkRect::MakeWH(1, 1), paintWithShader); + } else { + context.canvas->drawImage(image, 0, 0, sampling, context.sk_paint); + } + } +} + +void OHOSExternalTextureGL::OnGrContextCreated() { + state_ = AttachmentState::uninitialized; +} + +void OHOSExternalTextureGL::OnGrContextDestroyed() { + if (state_ == AttachmentState::attached) { + Detach(); + // glDeleteTextures(1, &texture_name_); + } + state_ = AttachmentState::detached; +} + +void OHOSExternalTextureGL::MarkNewFrameAvailable() { + new_frame_ready_ = true; +} + +void OHOSExternalTextureGL::OnTextureUnregistered() { + // do nothing +} + +void OHOSExternalTextureGL::Attach(int textureName) { + // do nothing +} + +void OHOSExternalTextureGL::Update() { + UpdateTransform(); +} + +void OHOSExternalTextureGL::Detach() { + // do nothing +} + +void OHOSExternalTextureGL::UpdateTransform() { + SkMatrix inverted; + if (!transform.invert(&inverted)) { + FML_LOG(FATAL) << "Invalid SurfaceTexture transformation matrix"; + } + transform = inverted; +} +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h new file mode 100755 index 0000000000000000000000000000000000000000..aa08880048c15b286713289593a7fb8073d7cb29 --- /dev/null +++ b/shell/platform/ohos/ohos_external_texture_gl.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_EXTERNAL_TEXTURE_GL_H +#define OHOS_EXTERNAL_TEXTURE_GL_H +#include + +#include "flutter/common/graphics/texture.h" +#include "napi/platform_view_ohos_napi.h" + +// maybe now unused +namespace flutter { + +class OHOSExternalTextureGL : public flutter::Texture { + public: + explicit OHOSExternalTextureGL(int id); + + ~OHOSExternalTextureGL() override; + + void Paint(PaintContext& context, + const SkRect& bounds, + bool freeze, + const SkSamplingOptions& sampling) override; + + void OnGrContextCreated() override; + + void OnGrContextDestroyed() override; + + void MarkNewFrameAvailable() override; + + void OnTextureUnregistered() override; + + private: + void Attach(int textureName); + + void Update(); + + void Detach(); + + void UpdateTransform(); + + enum class AttachmentState { uninitialized, attached, detached }; + + AttachmentState state_ = AttachmentState::uninitialized; + + bool new_frame_ready_ = false; + + GLuint texture_name_ = 0; + + SkMatrix transform; + + FML_DISALLOW_COPY_AND_ASSIGN(OHOSExternalTextureGL); +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_image_generator.cpp b/shell/platform/ohos/ohos_image_generator.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0e0e525f60bb746cb2dec7bf77ab98a1858e6881 --- /dev/null +++ b/shell/platform/ohos/ohos_image_generator.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_image_generator.h" + +#include +#include + +#include +#include "third_party/skia/include/codec/SkCodecAnimation.h" + +namespace flutter { + +OHOSImageGenerator::OHOSImageGenerator( + sk_sp buffer, + std::shared_ptr napi_facade) + : data_(std::move(buffer)), image_info_(SkImageInfo::MakeUnknown(-1, -1)) { + napi_facade_ = napi_facade; +} + +napi_env OHOSImageGenerator::g_env = nullptr; + +napi_value OHOSImageGenerator::ImageNativeInit(napi_env env, + napi_callback_info info) { + g_env = env; + + return nullptr; +} + +OHOSImageGenerator::~OHOSImageGenerator() = default; + +// |ImageGenerator| +const SkImageInfo& OHOSImageGenerator::GetInfo() { + header_decoded_latch_.Wait(); + return image_info_; +} + +// |ImageGenerator| +unsigned int OHOSImageGenerator::GetFrameCount() const { + return 1; +} + +// |ImageGenerator| +unsigned int OHOSImageGenerator::GetPlayCount() const { + return 1; +} + +// |ImageGenerator| +const ImageGenerator::FrameInfo OHOSImageGenerator::GetFrameInfo( + unsigned int frame_index) const { + return {.required_frame = std::nullopt, + .duration = 0, + .disposal_method = SkCodecAnimation::DisposalMethod::kKeep}; +} + +// |ImageGenerator| +SkISize OHOSImageGenerator::GetScaledDimensions(float desired_scale) { + return GetInfo().dimensions(); +} + +// |ImageGenerator| +bool OHOSImageGenerator::GetPixels(const SkImageInfo& info, + void* pixels, + size_t row_bytes, + unsigned int frame_index, + std::optional prior_frame) { + fully_decoded_latch_.Wait(); + if (!software_decoded_data_) { + return false; + } + + if (kRGBA_8888_SkColorType != info.colorType()) { + return false; + } + + switch (info.alphaType()) { + case kOpaque_SkAlphaType: + if (kOpaque_SkAlphaType != GetInfo().alphaType()) { + return false; + } + break; + case kPremul_SkAlphaType: + break; + default: + return false; + } + + // TODO(bdero): Override `GetImage()` to use `SkImage::FromAHardwareBuffer` on + // API level 30+ once it's updated to do symbol lookups and not get + // preprocessed out in Skia. This will allow for avoiding this copy in + // cases where the result image doesn't need to be resized. + memcpy(pixels, software_decoded_data_->data(), + software_decoded_data_->size()); + return true; +} + +void OHOSImageGenerator::DecodeImage() { + DoDecodeImage(); + + header_decoded_latch_.Signal(); + fully_decoded_latch_.Signal(); +} + +std::shared_ptr OHOSImageGenerator::MakeFromData( + sk_sp data, + const fml::RefPtr& task_runner, + std::shared_ptr napi_facade) { + // contructer is private, + std::shared_ptr generator( + new OHOSImageGenerator(std::move(data), napi_facade)); + + fml::TaskRunner::RunNowOrPostTask( + task_runner, [generator]() { generator->DecodeImage(); }); + + if (generator->IsValidImageData()) { + return generator; + } + return nullptr; +} + +void OHOSImageGenerator::DoDecodeImage() { + napi_facade_->DecodeImage((int64_t)this, (void*)data_->data(), data_->size()); + native_callback_latch_.Wait(); +} + +bool OHOSImageGenerator::IsValidImageData() { + // The generator kicks off an IO task to decode everything, and calls to + // "GetInfo()" block until either the header has been decoded or decoding has + // failed, whichever is sooner. The decoder is initialized with a width and + // height of -1 and will update the dimensions if the image is able to be + // decoded. + return GetInfo().height() != -1; +} + +napi_value OHOSImageGenerator::NativeImageDecodeCallback( + napi_env env, + napi_callback_info info) { + // to get this + + size_t argc = 4; + + // width, height, OHOSImageGenerator this, pixmap; + napi_value args[4] = {nullptr}; + + napi_status status = + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (status != napi_ok) { + LOGE("NativeImageDecodeCallback napi_get_cb_info error"); + return nullptr; + } + + if (argc != 4) { + FML_LOG(ERROR) << "argc is error"; + return nullptr; + } + + // unwarp object + int64_t width = 0; + int64_t height = 0; + OHOSImageGenerator* generator = nullptr; + + status = napi_get_value_int64(env, args[0], &width); + if (status != napi_ok) { + FML_LOG(ERROR) << "napi_get_value_int32 width error"; + } + + status = napi_get_value_int64(env, args[1], &height); + if (status != napi_ok) { + FML_LOG(ERROR) << "napi_get_value_int32 height error"; + } + + status = napi_get_value_int64(env, args[2], (int64_t*)&generator); + if (status != napi_ok) { + FML_LOG(ERROR) << "napi_get_value_int64 this error"; + } + + // call object native func to set image_info + + generator->image_info_ = SkImageInfo::Make( + width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType); + + generator->header_decoded_latch_.Signal(); + + void* pixel_lock; + + int ret = OHOS::Media::OH_AccessPixels(g_env, args[3], (void**)&pixel_lock); + if (ret != 0) { + FML_DLOG(ERROR) << "Failed to lock pixels, error=" << ret; + return nullptr; + } + // pixel_lock, g_env_ =g_env , resultout + + struct ReleaseCtx { + napi_env env_; + napi_ref ref = nullptr; + char* buf; + }; + + ReleaseCtx* ctx = new ReleaseCtx(); + ctx->env_ = env; + ctx->buf = (char*)pixel_lock; + napi_create_reference(env, args[3], 1, &(ctx->ref)); + + SkData::ReleaseProc on_release = [](const void* ptr, void* context) -> void { + ReleaseCtx* ctx = reinterpret_cast(context); + napi_value res = nullptr; + napi_get_reference_value(ctx->env_, ctx->ref, &res); + OHOS::Media::OH_UnAccessPixels(ctx->env_, res); + napi_delete_reference(ctx->env_, ctx->ref); + return; + }; + + // get software_decode_data by call back, bitmap buffer will unlock in + // callback + + generator->software_decoded_data_ = SkData::MakeWithProc( + pixel_lock, width * height * sizeof(uint32_t), on_release, ctx); + + // notify dodecode + generator->native_callback_latch_.Signal(); + return nullptr; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_image_generator.h b/shell/platform/ohos/ohos_image_generator.h new file mode 100755 index 0000000000000000000000000000000000000000..d2762a74e80319ba419ff1807bf2e3952a67dd06 --- /dev/null +++ b/shell/platform/ohos/ohos_image_generator.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef FLUTTER_IMAGE_GENERATOR_H +#define FLUTTER_IMAGE_GENERATOR_H + +#include "flutter/fml/memory/ref_ptr.h" +#include "flutter/fml/synchronization/waitable_event.h" +#include "flutter/fml/task_runner.h" +#include "flutter/lib/ui/painting/image_generator.h" + +#include "napi/native_api.h" +#include "napi/platform_view_ohos_napi.h" +#include "napi_common.h" + +namespace flutter { + +class OHOSImageGenerator : public ImageGenerator { + private: + explicit OHOSImageGenerator( + sk_sp buffer, + std::shared_ptr napi_facade); + + static napi_env g_env; + + public: + static napi_value ImageNativeInit(napi_env env, napi_callback_info info); + + static napi_value NativeImageDecodeCallback(napi_env env, + napi_callback_info info); + + ~OHOSImageGenerator(); + + // |ImageGenerator| + const SkImageInfo& GetInfo() override; + + // |ImageGenerator| + unsigned int GetFrameCount() const override; + + // |ImageGenerator| + unsigned int GetPlayCount() const override; + + // |ImageGenerator| + const ImageGenerator::FrameInfo GetFrameInfo( + unsigned int frame_index) const override; + + // |ImageGenerator| + SkISize GetScaledDimensions(float desired_scale) override; + + // |ImageGenerator| + bool GetPixels(const SkImageInfo& info, + void* pixels, + size_t row_bytes, + unsigned int frame_index, + std::optional prior_frame) override; + + void DecodeImage(); + + static std::shared_ptr MakeFromData( + sk_sp data, + const fml::RefPtr& task_runner, + std::shared_ptr napi_facade); + + private: + sk_sp data_; + sk_sp software_decoded_data_; + + SkImageInfo image_info_; + + std::shared_ptr napi_facade_; + + /// Blocks until the header of the image has been decoded and the image + /// dimensions have been determined. + fml::ManualResetWaitableEvent header_decoded_latch_; + + /// Blocks until the image has been fully decoded. + fml::ManualResetWaitableEvent fully_decoded_latch_; + + // block this unconstruct until nativeCallback called + fml::ManualResetWaitableEvent native_callback_latch_; + + void DoDecodeImage(); + + bool IsValidImageData(); + + FML_DISALLOW_COPY_ASSIGN_AND_MOVE(OHOSImageGenerator); +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_logger.c b/shell/platform/ohos/ohos_logger.c new file mode 100644 index 0000000000000000000000000000000000000000..95d0446d0e580112fe366cd8e87741d933539f30 --- /dev/null +++ b/shell/platform/ohos/ohos_logger.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_logger.h" + +#define OHOS_TAG "XComFlutterOHOS" + +int ohos_log(OhosLogLevel level, const char* fmt, ...) { + char buffer[1024]; + int len = 0; + { + va_list args; + va_start(args, fmt); + len = vsnprintf(buffer, sizeof(buffer) - 1, fmt, args); + va_end(args); + } + if (len <= 0) { + return len; + } + buffer[len] = '\0'; + // int OH_LOG_Print(LogType type, LogLevel level, unsigned int domain, const + // char *tag, const char *fmt, ...) + OH_LOG_Print(LOG_APP, (LogLevel)level, LOG_DOMAIN, OHOS_TAG, + "Thread:%{public}lu %{public}s", (unsigned long)pthread_self(), + buffer); + return len; +} diff --git a/shell/platform/ohos/ohos_logger.h b/shell/platform/ohos/ohos_logger.h new file mode 100644 index 0000000000000000000000000000000000000000..da4bd255817d551bd9db9c74962a7a0d5195d803 --- /dev/null +++ b/shell/platform/ohos/ohos_logger.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef __OHOS__LOGGER_H +#define __OHOS__LOGGER_H +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + /** Debug level to be used by {@link OH_LOG_DEBUG} */ + OHOS_LOG_DEBUG = 3, + /** Informational level to be used by {@link OH_LOG_INFO} */ + OHOS_LOG_INFO = 4, + /** Warning level to be used by {@link OH_LOG_WARN} */ + OHOS_LOG_WARN = 5, + /** Error level to be used by {@link OH_LOG_ERROR} */ + OHOS_LOG_ERROR = 6, + /** Fatal level to be used by {@link OH_LOG_FATAL} */ + OHOS_LOG_FATAL = 7, +} OhosLogLevel; + +extern int ohos_log(OhosLogLevel level, const char* fmt, ...); + +#ifdef __cplusplus +} // end extern +#endif + +#endif diff --git a/shell/platform/ohos/ohos_main.cpp b/shell/platform/ohos/ohos_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..041de2e1803178e48372fe4c57e45fc5bb940ec2 --- /dev/null +++ b/shell/platform/ohos/ohos_main.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_main.h" + +#include "flutter/fml/command_line.h" +#include "flutter/fml/file.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/message_loop.h" +#include "flutter/fml/native_library.h" +#include "flutter/fml/paths.h" +#include "flutter/fml/platform/ohos/napi_util.h" +#include "flutter/fml/platform/ohos/paths_ohos.h" +#include "flutter/fml/size.h" +#include "flutter/lib/ui/plugins/callback_cache.h" +#include "flutter/runtime/dart_vm.h" +#include "flutter/shell/common/shell.h" +#include "flutter/shell/common/switches.h" +#include "third_party/dart/runtime/include/dart_tools_api.h" +#include "third_party/skia/include/core/SkFontMgr.h" + +namespace flutter { + +std::vector StringArrayToVector(napi_env env, + napi_value arrayValue) { + napi_status status; + uint32_t arrayLength = 0; + status = napi_get_array_length(env, arrayValue, &arrayLength); + LOGE("StringArrayToVector get array length %{pubilc}d", arrayLength); + if (status != napi_ok) { + LOGE("StringArrayToVector napi_get_array_length error "); + } + std::vector stringArray; + for (uint32_t i = 0; i < arrayLength; i++) { + napi_value elementValue; + status = napi_get_element(env, arrayValue, i, &elementValue); + if (status != napi_ok) { + LOGE("StringArrayToVector napi_get_element error"); + } + size_t stringLength; + status = napi_get_value_string_utf8(env, elementValue, nullptr, 0, + &stringLength); + if (status != napi_ok) { + LOGE("StringArrayToVector napi_get_value_string_utf8 error"); + } + + std::string stringValue(stringLength, '\0'); + status = napi_get_value_string_utf8(env, elementValue, &stringValue[0], + stringLength + 1, nullptr); + if (status != napi_ok) { + LOGE("StringArrayToVector napi_get_value_string_utf8 error"); + } + stringArray.push_back(stringValue); + } + return stringArray; +} + +OhosMain::OhosMain(const flutter::Settings& settings) + : settings_(settings), observatory_uri_callback_() {} + +OhosMain::~OhosMain() = default; + +static std::unique_ptr g_flutter_main; + +OhosMain& OhosMain::Get() { + FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already " + "been called."; + return *g_flutter_main; +} + +const flutter::Settings& OhosMain::GetSettings() const { + return settings_; +} + +/** + * @brief + * @note + * @param context: common.Context, args: Array, bundlePath: string, + * appStoragePath: string, engineCachesPath: string, initTimeMillis: number + * @return void + */ +void OhosMain::Init(napi_env env, napi_callback_info info) { + size_t argc = 6; + napi_value param[6]; + // char kernelPath[512], appStoragePath[512], engineCachesPath[512]; + std::string kernelPath, appStoragePath, engineCachesPath; + int64_t initTimeMillis; + napi_get_cb_info(env, info, &argc, param, nullptr, nullptr); + napi_get_value_int64(env, param[5], &initTimeMillis); + fml::napi::GetString(env, param[2], kernelPath); + fml::napi::GetString(env, param[3], appStoragePath); + fml::napi::GetString(env, param[4], engineCachesPath); + FML_DLOG(INFO) << "INIT kernelPath:" << kernelPath; + FML_DLOG(INFO) << "appStoragePath:" << appStoragePath; + FML_DLOG(INFO) << "engineCachesPath:" << engineCachesPath; + FML_DLOG(INFO) << "initTimeMillis:" << initTimeMillis; + std::vector args; + args.push_back("flutter"); + fml::napi::GetArrayString(env, param[1], args); + for (std::vector::iterator it = args.begin(); it != args.end(); + ++it) { + FML_DLOG(INFO) << *it; + } + auto command_line = fml::CommandLineFromIterators(args.begin(), args.end()); + auto settings = SettingsFromCommandLine(command_line); + flutter::DartCallbackCache::SetCachePath(appStoragePath); + fml::paths::InitializeOhosCachesPath(std::string(engineCachesPath)); + flutter::DartCallbackCache::LoadCacheFromDisk(); + // TODO 使用CPU + // settings.skia_deterministic_rendering_on_cpu = true; + + if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath[0]) { + auto application_kernel_path = kernelPath; + if (fml::IsFile(application_kernel_path)) { + FML_DLOG(INFO) << "application_kernel_path exist"; + settings.application_kernel_asset = application_kernel_path; + } + } + + settings.task_observer_add = [](intptr_t key, const fml::closure& callback) { + FML_DLOG(INFO) << "task_observer_add:" << (int64_t)key; + fml::MessageLoop::GetCurrent().AddTaskObserver(key, callback); + }; + settings.task_observer_remove = [](intptr_t key) { + FML_DLOG(INFO) << "task_observer_remove:" << (int64_t)key; + fml::MessageLoop::GetCurrent().RemoveTaskObserver(key); + }; + settings.log_message_callback = [](const std::string& tag, + const std::string& message) { + // TODO: Hilog print + FML_DLOG(INFO) << tag << " " << message; + }; + + g_flutter_main.reset(new OhosMain(settings)); + // TODO : g_flutter_main->SetupObservatoryUriCallback(env); +} + +napi_value OhosMain::NativeInit(napi_env env, napi_callback_info info) { + OhosMain::Init(env, info); + OHOSImageGenerator::ImageNativeInit(env, info); + return nullptr; +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_main.h b/shell/platform/ohos/ohos_main.h new file mode 100644 index 0000000000000000000000000000000000000000..22c2abaef735713d44bae552902db911fb7cf47a --- /dev/null +++ b/shell/platform/ohos/ohos_main.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef __OHOS__MAIN__H +#define __OHOS__MAIN__H +#define FML_USED_ON_EMBEDDER +#include "flutter/common/settings.h" +#include "flutter/fml/macros.h" +#include "flutter/runtime/dart_service_isolate.h" +#include "napi/native_api.h" +#include "napi_common.h" +#include "ohos_image_generator.h" + +namespace flutter { +class OhosMain { + public: + ~OhosMain(); + static OhosMain& Get(); + const flutter::Settings& GetSettings() const; + static napi_value NativeInit(napi_env env, napi_callback_info info); + + private: + const flutter::Settings settings_; + DartServiceIsolate::CallbackHandle observatory_uri_callback_; + + explicit OhosMain(const flutter::Settings& settings); + + static void Init(napi_env env, napi_callback_info info); + + void SetupObservatoryUriCallback(napi_env env, napi_callback_info info); + FML_DISALLOW_COPY_AND_ASSIGN(OhosMain); +}; +} // namespace flutter +#endif diff --git a/shell/platform/ohos/ohos_shell_holder.cpp b/shell/platform/ohos/ohos_shell_holder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7024a36a260b338ab63b679f377f40b34bdc6328 --- /dev/null +++ b/shell/platform/ohos/ohos_shell_holder.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" +#include "flutter/fml/native_library.h" +#include "flutter/shell/common/rasterizer.h" +#include "flutter/shell/common/run_configuration.h" +#include "flutter/shell/common/thread_host.h" +#include "flutter/shell/platform/ohos/ohos_display.h" + +#include "flutter/fml/logging.h" + +#include +#include + +namespace flutter { + +static void OHOSPlatformThreadConfigSetter( + const fml::Thread::ThreadConfig& config) { + fml::Thread::SetCurrentThreadName(config); + // set thread priority + switch (config.priority) { + case fml::Thread::ThreadPriority::BACKGROUND: { + if (::setpriority(PRIO_PROCESS, 0, 10) != 0) { + FML_DLOG(ERROR) << "Failed to set IO task runner priority"; + } + break; + } + case fml::Thread::ThreadPriority::DISPLAY: { + if (::setpriority(PRIO_PROCESS, 0, -1) != 0) { + FML_DLOG(ERROR) << "Failed to set UI task runner priority"; + } + break; + } + case fml::Thread::ThreadPriority::RASTER: { + // Android describes -8 as "most important display threads, for + // compositing the screen and retrieving input events". Conservatively + // set the raster thread to slightly lower priority than it. + if (::setpriority(PRIO_PROCESS, 0, -5) != 0) { + // Defensive fallback. Depending on the OEM, it may not be possible + // to set priority to -5. + if (::setpriority(PRIO_PROCESS, 0, -2) != 0) { + FML_DLOG(ERROR) << "Failed to set raster task runner priority"; + } + } + break; + } + default: + if (::setpriority(PRIO_PROCESS, 0, 0) != 0) { + FML_DLOG(ERROR) << "Failed to set priority"; + } + } +} + +static PlatformData GetDefaultPlatformData() { + FML_DLOG(INFO) << "GetDefaultPlatformData"; + PlatformData platform_data; + platform_data.lifecycle_state = "AppLifecycleState.detached"; + return platform_data; +} + +OHOSShellHolder::OHOSShellHolder( + const flutter::Settings& settings, + std::shared_ptr napi_facade, + void* platform_loop) + : settings_(settings), napi_facade_(napi_facade) { + FML_DLOG(INFO) << " ohos shell holder constructor"; + static size_t thread_host_count = 1; + auto thread_label = std::to_string(thread_host_count++); + + auto mask = + ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO; + + flutter::ThreadHost::ThreadHostConfig host_config( + thread_label, mask, OHOSPlatformThreadConfigSetter); + host_config.ui_config = fml::Thread::ThreadConfig( + flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::UI, thread_label), + fml::Thread::ThreadPriority::DISPLAY); + host_config.raster_config = fml::Thread::ThreadConfig( + flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::RASTER, thread_label), + fml::Thread::ThreadPriority::RASTER); + host_config.io_config = fml::Thread::ThreadConfig( + flutter::ThreadHost::ThreadHostConfig::MakeThreadName( + flutter::ThreadHost::Type::IO, thread_label), + fml::Thread::ThreadPriority::NORMAL); + + thread_host_ = std::make_shared(host_config); + FML_DLOG(INFO) << "thred host config finish"; + fml::WeakPtr weak_platform_view; + + Shell::CreateCallback on_create_platform_view = + [&napi_facade, &weak_platform_view](Shell& shell) { + FML_DLOG(INFO) << "on_create_platform_view"; + std::unique_ptr platform_view_OHOS; + platform_view_OHOS = std::make_unique( + shell, // delegate + shell.GetTaskRunners(), // task runners + napi_facade, // napi interop + shell.GetSettings() + .enable_software_rendering, // use software rendering + shell.GetSettings().msaa_samples // msaa sample count + ); + LOGI("on_create_platform_view LOGI"); + FML_LOG(INFO) << "on_create_platform_view end"; + weak_platform_view = platform_view_OHOS->GetWeakPtr(); + LOGI("on_create_platform_view LOGI2"); + FML_LOG(INFO) << "on_create_platform_view end1"; + std::vector> displays; + displays.push_back(std::make_unique(napi_facade)); + FML_DLOG(INFO) << "on_create_platform_view LOGI3"; + FML_LOG(INFO) << "on_create_platform_view end3"; + shell.OnDisplayUpdates(DisplayUpdateType::kStartup, + std::move(displays)); + LOGI("on_create_platform_view LOGI4"); + FML_LOG(INFO) << "on_create_platform_view end3"; + return platform_view_OHOS; + }; + + Shell::CreateCallback on_create_rasterizer = [](Shell& shell) { + FML_DLOG(INFO) << "Create Rasterizer Callback"; + return std::make_unique(shell); + }; + + // The current thread will be used as the platform thread. Ensure that the + // message loop is initialized. + fml::MessageLoop::EnsureInitializedForCurrentThread(platform_loop); + fml::RefPtr raster_runner; + fml::RefPtr ui_runner; + fml::RefPtr io_runner; + fml::RefPtr platform_runner = + fml::MessageLoop::GetCurrent().GetTaskRunner(); + raster_runner = thread_host_->raster_thread->GetTaskRunner(); + ui_runner = thread_host_->ui_thread->GetTaskRunner(); + io_runner = thread_host_->io_thread->GetTaskRunner(); + + flutter::TaskRunners task_runners(thread_label, // label + platform_runner, // platform + raster_runner, // raster + ui_runner, // ui + io_runner // io + ); + + napi_facade_->SetPlatformTaskRunner(platform_runner); + FML_DLOG(INFO) << "before shell create"; + shell_ = + Shell::Create(GetDefaultPlatformData(), // window data + task_runners, // task runners + settings_, // settings + on_create_platform_view, // platform view create callback + on_create_rasterizer // rasterizer create callback + ); + FML_DLOG(INFO) << "shell create end"; + if (shell_) { + shell_->GetDartVM()->GetConcurrentMessageLoop()->PostTaskToAllWorkers([]() { + if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) { + FML_DLOG(ERROR) << "Failed to set Workers task runner priority"; + } + }); + + LOGI("shell_ end"); + shell_->RegisterImageDecoder( + [runner = task_runners.GetIOTaskRunner(), + napi_facade = napi_facade_](sk_sp buffer) { + return OHOSImageGenerator::MakeFromData(std::move(buffer), runner, + napi_facade); + }, + -1); + + FML_DLOG(INFO) << "Registered Android SDK image decoder (API level 28+)"; + } + + platform_view_ = weak_platform_view; + FML_DCHECK(platform_view_); + is_valid_ = shell_ != nullptr; +} + +bool OHOSShellHolder::IsValid() const { + return is_valid_; +} + +const flutter::Settings& OHOSShellHolder::GetSettings() const { + return settings_; +} + +fml::WeakPtr OHOSShellHolder::GetPlatformView() { + FML_DCHECK(platform_view_); + return platform_view_; +} + +void OHOSShellHolder::NotifyLowMemoryWarning() { + FML_DCHECK(shell_); + shell_->NotifyLowMemoryWarning(); +} + +void OHOSShellHolder::Launch( + std::unique_ptr apk_asset_provider, + const std::string& entrypoint, + const std::string& libraryUrl, + const std::vector& entrypoint_args) { + FML_DLOG(INFO) << "Launch ...entrypoint<<" << entrypoint + << ",libraryUrl:" << libraryUrl; + if (!IsValid()) { + FML_DLOG(ERROR) << "Is Not Valid"; + return; + } + + assetProvider_ = std::move(apk_asset_provider); + auto config = BuildRunConfiguration(entrypoint, libraryUrl, entrypoint_args); + if (!config) { + return; + } + FML_LOG(INFO) << "start RunEngine"; + shell_->RunEngine(std::move(config.value())); + FML_LOG(INFO) << "end Launch"; +} + +std::optional OHOSShellHolder::BuildRunConfiguration( + const std::string& entrypoint, + const std::string& libraryUrl, + const std::vector& entrypoint_args) const { + std::unique_ptr isolate_configuration; + FML_DLOG(INFO) << "entrypoint." << entrypoint.c_str(); + FML_DLOG(INFO) << "libraryUrl." << libraryUrl.c_str(); + if (flutter::DartVM::IsRunningPrecompiledCode()) { + FML_LOG(INFO) << "isolate_configuration."; + isolate_configuration = IsolateConfiguration::CreateForAppSnapshot(); + } else { + std::unique_ptr kernel_blob = + fml::FileMapping::CreateReadOnly( + GetSettings().application_kernel_asset); + if (!kernel_blob) { + FML_DLOG(ERROR) << "Unable to load the kernel blob asset."; + return std::nullopt; + } + FML_LOG(INFO) << "CreateForKernel."; + isolate_configuration = + IsolateConfiguration::CreateForKernel(std::move(kernel_blob)); + } + + RunConfiguration config(std::move(isolate_configuration)); + config.AddAssetResolver(assetProvider_->Clone()); + + { + if (!entrypoint.empty() && !libraryUrl.empty()) { + FML_LOG(INFO) << "SetEntrypointAndLibrary."; + config.SetEntrypointAndLibrary(entrypoint, libraryUrl); + } else if (!entrypoint.empty()) { + FML_LOG(INFO) << "SetEntrypoint."; + config.SetEntrypoint(entrypoint); + } + if (!entrypoint_args.empty()) { + FML_LOG(INFO) << "SetEntrypointArgs."; + config.SetEntrypointArgs(entrypoint_args); + } + } + return config; +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_shell_holder.h b/shell/platform/ohos/ohos_shell_holder.h new file mode 100644 index 0000000000000000000000000000000000000000..7d5fb0d64a5b5605e5223f310cd9431a72baa74d --- /dev/null +++ b/shell/platform/ohos/ohos_shell_holder.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SHELL_HOLDER_H +#define OHOS_SHELL_HOLDER_H +#define FML_USED_ON_EMBEDDER +#include "flutter/assets/asset_manager.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/unique_fd.h" +#include "flutter/lib/ui/window/viewport_metrics.h" +#include "flutter/runtime/platform_data.h" +#include "flutter/shell/common/run_configuration.h" +#include "flutter/shell/common/shell.h" +#include "flutter/shell/common/thread_host.h" + +#include "flutter/assets/asset_resolver.h" +#include "flutter/common/settings.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +#include "flutter/shell/platform/ohos/platform_view_ohos.h" + +#include "napi_common.h" +#include "ohos_asset_provider.h" +#include "ohos_image_generator.h" + +namespace flutter { + +class OHOSShellHolder { + public: + OHOSShellHolder(const flutter::Settings& settings, + std::shared_ptr napi_facade, + void* plateform_loop); + + bool IsValid() const; + + const flutter::Settings& GetSettings() const; + + fml::WeakPtr GetPlatformView(); + + // Rasterizer::Screenshot Screenshot(Rasterizer::ScreenshotType type, + // bool base64_encode); + + void NotifyLowMemoryWarning(); + + void Launch(std::unique_ptr apk_asset_provider, + const std::string& entrypoint, + const std::string& libraryUrl, + const std::vector& entrypoint_args); + + const std::shared_ptr& GetPlatformMessageHandler() + const { + LOGI("GetPlatformMessageHandler LOGI"); + return shell_->GetPlatformMessageHandler(); + } + + private: + std::optional BuildRunConfiguration( + const std::string& entrypoint, + const std::string& libraryUrl, + const std::vector& entrypoint_args) const; + + const flutter::Settings settings_; + fml::WeakPtr platform_view_; + std::shared_ptr thread_host_; + std::unique_ptr shell_; + bool is_valid_ = false; + uint64_t next_pointer_flow_id_ = 0; + + std::unique_ptr assetProvider_; + + std::shared_ptr napi_facade_; + + static void ThreadDestructCallback(void* value); + + FML_DISALLOW_COPY_AND_ASSIGN(OHOSShellHolder); +}; +} // namespace flutter + +#endif diff --git a/shell/platform/ohos/ohos_surface_gl_impeller.cpp b/shell/platform/ohos/ohos_surface_gl_impeller.cpp new file mode 100755 index 0000000000000000000000000000000000000000..6579e8f1fecdaa5235a12d5ddca97f5a38f49e0a --- /dev/null +++ b/shell/platform/ohos/ohos_surface_gl_impeller.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_surface_gl_impeller.h" + +#include "flutter/fml/logging.h" +#include "flutter/impeller/entity/gles/entity_shaders_gles.h" +#include "flutter/impeller/renderer/backend/gles/context_gles.h" +#include "flutter/impeller/renderer/backend/gles/proc_table_gles.h" +#include "flutter/impeller/toolkit/egl/context.h" +#include "flutter/impeller/toolkit/egl/surface.h" +#include "flutter/shell/gpu/gpu_surface_gl_impeller.h" + +namespace flutter { + +class OHOSSurfaceGLImpeller::ReactorWorker final + : public impeller::ReactorGLES::Worker { + public: + ReactorWorker() = default; + + // |impeller::ReactorGLES::Worker| + ~ReactorWorker() override = default; + + // |impeller::ReactorGLES::Worker| + bool CanReactorReactOnCurrentThreadNow( + const impeller::ReactorGLES& reactor) const override { + impeller::ReaderLock lock(mutex_); + auto found = reactions_allowed_.find(std::this_thread::get_id()); + if (found == reactions_allowed_.end()) { + return false; + } + return found->second; + } + + void SetReactionsAllowedOnCurrentThread(bool allowed) { + impeller::WriterLock lock(mutex_); + reactions_allowed_[std::this_thread::get_id()] = allowed; + } + + private: + mutable impeller::RWMutex mutex_; + std::map reactions_allowed_ IPLR_GUARDED_BY(mutex_); + + FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); +}; + +// for init use +static std::shared_ptr CreateImpellerContext( + const std::shared_ptr& worker) { + auto proc_table = std::make_unique( + impeller::egl::CreateProcAddressResolver()); + + if (!proc_table->IsValid()) { + FML_LOG(ERROR) << "Could not create OpenGL proc table."; + return nullptr; + } + + std::vector> shader_mappings = { + std::make_shared( + impeller_entity_shaders_gles_data, + impeller_entity_shaders_gles_length), + }; + + auto context = + impeller::ContextGLES::Create(std::move(proc_table), shader_mappings); + if (!context) { + FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; + return nullptr; + } + + if (!context->AddReactorWorker(worker).has_value()) { + FML_LOG(ERROR) << "Could not add reactor worker."; + return nullptr; + } + FML_LOG(ERROR) << "Using the Impeller rendering backend."; + + return context; +} + +OHOSSurfaceGLImpeller::OHOSSurfaceGLImpeller( + const std::shared_ptr& ohos_context) + : OHOSSurface(ohos_context), + reactor_worker_(std::shared_ptr(new ReactorWorker())) { + auto display = std::make_unique(); + if (!display->IsValid()) { + FML_DLOG(ERROR) << "Could not create EGL display."; + return; + } + + impeller::egl::ConfigDescriptor desc; + desc.api = impeller::egl::API::kOpenGLES2; + desc.color_format = impeller::egl::ColorFormat::kRGBA8888; + desc.depth_bits = impeller::egl::DepthBits::kZero; + desc.stencil_bits = impeller::egl::StencilBits::kEight; + desc.samples = impeller::egl::Samples::kFour; + + desc.surface_type = impeller::egl::SurfaceType::kWindow; + auto onscreen_config = display->ChooseConfig(desc); + if (!onscreen_config) { + FML_DLOG(ERROR) << "Could not choose onscreen config."; + return; + } + + desc.surface_type = impeller::egl::SurfaceType::kPBuffer; + auto offscreen_config = display->ChooseConfig(desc); + if (!offscreen_config) { + FML_DLOG(ERROR) << "Could not choose offscreen config."; + return; + } + + auto onscreen_context = display->CreateContext(*onscreen_config, nullptr); + if (!onscreen_context) { + FML_DLOG(ERROR) << "Could not create onscreen context."; + return; + } + + auto offscreen_context = + display->CreateContext(*offscreen_config, onscreen_context.get()); + if (!offscreen_context) { + FML_DLOG(ERROR) << "Could not create offscreen context."; + return; + } + + auto offscreen_surface = + display->CreatePixelBufferSurface(*offscreen_config, 1u, 1u); + if (!offscreen_surface) { + FML_DLOG(ERROR) << "Could not create offscreen surface."; + return; + } + + if (!offscreen_context->MakeCurrent(*offscreen_surface)) { + FML_DLOG(ERROR) << "Could not make offscreen context current."; + return; + } + + auto impeller_context = CreateImpellerContext(reactor_worker_); + + if (!impeller_context) { + FML_DLOG(ERROR) << "Could not create Impeller context."; + return; + } + + if (!offscreen_context->ClearCurrent()) { + FML_DLOG(ERROR) << "Could not clear offscreen context."; + return; + } + + // Setup context listeners. + impeller::egl::Context::LifecycleListener listener = + [worker = + reactor_worker_](impeller::egl ::Context::LifecycleEvent event) { + switch (event) { + case impeller::egl::Context::LifecycleEvent::kDidMakeCurrent: + worker->SetReactionsAllowedOnCurrentThread(true); + break; + case impeller::egl::Context::LifecycleEvent::kWillClearCurrent: + worker->SetReactionsAllowedOnCurrentThread(false); + break; + } + }; + if (!onscreen_context->AddLifecycleListener(listener).has_value() || + !offscreen_context->AddLifecycleListener(listener).has_value()) { + FML_DLOG(ERROR) << "Could not add lifecycle listeners"; + } + + display_ = std::move(display); + onscreen_config_ = std::move(onscreen_config); + offscreen_config_ = std::move(offscreen_config); + offscreen_surface_ = std::move(offscreen_surface); + onscreen_context_ = std::move(onscreen_context); + offscreen_context_ = std::move(offscreen_context); + impeller_context_ = std::move(impeller_context); + + // The onscreen surface will be acquired once the native window is set. + + is_valid_ = true; +} + +OHOSSurfaceGLImpeller::~OHOSSurfaceGLImpeller() = default; + +// OHOSSurface +bool OHOSSurfaceGLImpeller::IsValid() const { + return is_valid_; +} + +// OHOSSurface +std::unique_ptr OHOSSurfaceGLImpeller::CreateGPUSurface( + GrDirectContext* gr_context) { + auto surface = + std::make_unique(this, // delegate + impeller_context_ // context + ); + if (!surface->IsValid()) { + return nullptr; + } + return surface; +} + +// OHOSSurface +void OHOSSurfaceGLImpeller::TeardownOnScreenContext() { + GLContextClearCurrent(); + onscreen_surface_.reset(); +} + +// OHOSSurface +bool OHOSSurfaceGLImpeller::OnScreenSurfaceResize(const SkISize& size) { + // unused function + return RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent(); +} + +// OHOSSurface +bool OHOSSurfaceGLImpeller::ResourceContextMakeCurrent() { + if (!offscreen_context_ || !offscreen_surface_) { + return false; + } + + return offscreen_context_->MakeCurrent(*offscreen_surface_); +} + +// OHOSSurface +bool OHOSSurfaceGLImpeller::ResourceContextClearCurrent() { + if (!offscreen_context_ || !offscreen_surface_) { + return false; + } + + return offscreen_context_->ClearCurrent(); +} + +// OHOSSurface +bool OHOSSurfaceGLImpeller::SetNativeWindow( + fml::RefPtr window) { + native_window_ = std::move(window); + return RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent(); +} + +// OHOSSurface +std::unique_ptr OHOSSurfaceGLImpeller::CreateSnapshotSurface() { + // unreachable func + FML_UNREACHABLE(); + + return nullptr; +} + +// OHOSSurface +std::shared_ptr OHOSSurfaceGLImpeller::GetImpellerContext() { + return impeller_context_; +} + +// |GPUSurfaceGLDelegate| +std::unique_ptr OHOSSurfaceGLImpeller::GLContextMakeCurrent() { + return std::make_unique(OnGLContextMakeCurrent()); +} + +// |GPUSurfaceGLDelegate| +bool OHOSSurfaceGLImpeller::GLContextClearCurrent() { + if (!onscreen_surface_ || !onscreen_context_) { + return false; + } + + return onscreen_context_->ClearCurrent(); +} + +// |GPUSurfaceGLDelegate| +SurfaceFrame::FramebufferInfo OHOSSurfaceGLImpeller::GLContextFramebufferInfo() + const { + auto info = SurfaceFrame::FramebufferInfo{}; + info.supports_readback = true; + info.supports_partial_repaint = false; + return info; +} + +// |GPUSurfaceGLDelegate| +void OHOSSurfaceGLImpeller::GLContextSetDamageRegion( + const std::optional& region) { + // 不支持 +} + +// |GPUSurfaceGLDelegate| +bool OHOSSurfaceGLImpeller::GLContextPresent( + const GLPresentInfo& present_info) { + if (!onscreen_surface_) { + return false; + } + + return onscreen_surface_->Present(); +} + +// |GPUSurfaceGLDelegate| +GLFBOInfo OHOSSurfaceGLImpeller::GLContextFBO(GLFrameInfo frame_info) const { + // FBO0 is the default window bound framebuffer in EGL environments. + return GLFBOInfo{ + .fbo_id = 0, + }; +} + +// |GPUSurfaceGLDelegate| +sk_sp OHOSSurfaceGLImpeller::GetGLInterface() const { + return nullptr; +} + +bool OHOSSurfaceGLImpeller::OnGLContextMakeCurrent() { + if (!onscreen_surface_ || !onscreen_context_) { + return false; + } + + return onscreen_context_->MakeCurrent(*onscreen_surface_); +} + +bool OHOSSurfaceGLImpeller:: + RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent() { + GLContextClearCurrent(); + if (!native_window_) { + return false; + } + onscreen_surface_.reset(); + auto onscreen_surface = display_->CreateWindowSurface( + *onscreen_config_, (EGLNativeWindowType)native_window_->Gethandle()); + if (!onscreen_surface) { + FML_DLOG(ERROR) << "Could not create onscreen surface."; + return false; + } + onscreen_surface_ = std::move(onscreen_surface); + return OnGLContextMakeCurrent(); +} + +} // namespace flutter + +// todo //flutter/impeller/toolkit/egl/display.cc +// 中的该方法一直链接不上,其他方法都可以,无奈之举 +namespace impeller { +namespace egl { +std::unique_ptr Display::CreateWindowSurface( + const Config& config, + EGLNativeWindowType window) { + const EGLint attribs[] = {EGL_NONE}; + auto surface = ::eglCreateWindowSurface(display_, // display + config.GetHandle(), // config + window, // window + attribs // attrib_list + ); + if (surface == EGL_NO_SURFACE) { + IMPELLER_LOG_EGL_ERROR; + return nullptr; + } + return std::make_unique(display_, surface); +} + +} // namespace egl +} // namespace impeller diff --git a/shell/platform/ohos/ohos_surface_gl_impeller.h b/shell/platform/ohos/ohos_surface_gl_impeller.h new file mode 100755 index 0000000000000000000000000000000000000000..dfd1ee7ac37f844aa1c66d1fed34e1b7a15d09dd --- /dev/null +++ b/shell/platform/ohos/ohos_surface_gl_impeller.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SURFACE_GL_IMPELLER_H +#define OHOS_SURFACE_GL_IMPELLER_H + +#include "flutter/fml/macros.h" +#include "flutter/impeller/renderer/context.h" +#include "flutter/impeller/toolkit/egl/display.h" +#include "flutter/shell/gpu/gpu_surface_gl_delegate.h" +#include "surface/ohos_native_window.h" +#include "surface/ohos_surface.h" + +namespace flutter { + +class OHOSSurfaceGLImpeller final : public GPUSurfaceGLDelegate, + public OHOSSurface { + public: + OHOSSurfaceGLImpeller(const std::shared_ptr& ohos_context); + + ~OHOSSurfaceGLImpeller() override; + + // OHOSSurface + bool IsValid() const override; + + // OHOSSurface + std::unique_ptr CreateGPUSurface( + GrDirectContext* gr_context) override; + + // OHOSSurface + void TeardownOnScreenContext() override; + + // OHOSSurface + bool OnScreenSurfaceResize(const SkISize& size) override; + + // OHOSSurface + bool ResourceContextMakeCurrent() override; + + // OHOSSurface + bool ResourceContextClearCurrent() override; + + // OHOSSurface + bool SetNativeWindow(fml::RefPtr window) override; + + // OHOSSurface + std::unique_ptr CreateSnapshotSurface() override; + + // OHOSSurface + virtual std::shared_ptr GetImpellerContext() override; + + // |GPUSurfaceGLDelegate| + std::unique_ptr GLContextMakeCurrent() override; + + // |GPUSurfaceGLDelegate| + bool GLContextClearCurrent() override; + + // |GPUSurfaceGLDelegate| + SurfaceFrame::FramebufferInfo GLContextFramebufferInfo() const override; + + // |GPUSurfaceGLDelegate| + void GLContextSetDamageRegion(const std::optional& region) override; + + // |GPUSurfaceGLDelegate| + bool GLContextPresent(const GLPresentInfo& present_info) override; + + // |GPUSurfaceGLDelegate| + GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override; + + // |GPUSurfaceGLDelegate| + sk_sp GetGLInterface() const override; + + private: + class ReactorWorker; + std::shared_ptr reactor_worker_; + std::unique_ptr display_; + std::unique_ptr onscreen_config_; + std::unique_ptr offscreen_config_; + std::unique_ptr onscreen_surface_; + std::unique_ptr offscreen_surface_; + std::unique_ptr onscreen_context_; + std::unique_ptr offscreen_context_; + std::shared_ptr impeller_context_; + fml::RefPtr native_window_; + + bool is_valid_ = false; + + bool OnGLContextMakeCurrent(); + + bool RecreateOnscreenSurfaceAndMakeOnscreenContextCurrent(); + + FML_DISALLOW_COPY_AND_ASSIGN(OHOSSurfaceGLImpeller); +}; + +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_surface_gl_skia.cpp b/shell/platform/ohos/ohos_surface_gl_skia.cpp new file mode 100755 index 0000000000000000000000000000000000000000..bcc08639aadde79761013bab7431ece44275f19d --- /dev/null +++ b/shell/platform/ohos/ohos_surface_gl_skia.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_surface_gl_skia.h" + +#include +#include + +#include "flutter/fml/logging.h" +#include "flutter/fml/memory/ref_ptr.h" +#include "flutter/shell/platform/ohos/ohos_egl_surface.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" + +namespace flutter { + +namespace { +// GL renderer string prefix used by the Ohos emulator GLES implementation. +constexpr char kEmulatorRendererPrefix[] = "Mali-G78"; +} // anonymous namespace + +OhosSurfaceGLSkia::OhosSurfaceGLSkia( + const std::shared_ptr& ohos_context) + : OHOSSurface(ohos_context), + native_window_(nullptr), + onscreen_surface_(nullptr), + offscreen_surface_(nullptr) { + // Acquire the offscreen surface. + FML_LOG(INFO) << "OhosSurfaceGLSkia constructor"; + offscreen_surface_ = GLContextPtr()->CreateOffscreenSurface(); + if (!offscreen_surface_->IsValid()) { + FML_LOG(ERROR) << "OhosSurfaceGLSkia offscreen_surface_->IsValid() FAIL"; + offscreen_surface_ = nullptr; + } + FML_LOG(INFO) << "OhosSurfaceGLSkia constructor end"; +} + +OhosSurfaceGLSkia::~OhosSurfaceGLSkia() = default; + +void OhosSurfaceGLSkia::TeardownOnScreenContext() { + // When the onscreen surface is destroyed, the context and the surface + // instance should be deleted. Issue: + // https://github.com/flutter/flutter/issues/64414 + GLContextPtr()->ClearCurrent(); + onscreen_surface_ = nullptr; +} + +bool OhosSurfaceGLSkia::IsValid() const { + return offscreen_surface_ && GLContextPtr()->IsValid(); +} + +std::unique_ptr OhosSurfaceGLSkia::CreateGPUSurface( + GrDirectContext* gr_context) { + if (gr_context) { + FML_LOG(INFO) << "gr_context NO null"; + return std::make_unique(sk_ref_sp(gr_context), this, + true); + } else { + sk_sp main_skia_context = + GLContextPtr()->GetMainSkiaContext(); + if (!main_skia_context) { + main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this); + FML_LOG(ERROR) << "Could not make main_skia_context"; + GLContextPtr()->SetMainSkiaContext(main_skia_context); + } + return std::make_unique(main_skia_context, this, true); + } +} + +bool OhosSurfaceGLSkia::OnScreenSurfaceResize(const SkISize& size) { + FML_DCHECK(IsValid()); + FML_DCHECK(onscreen_surface_); + FML_DCHECK(native_window_); + + if (size == onscreen_surface_->GetSize()) { + return true; + } + + GLContextPtr()->ClearCurrent(); + + // Ensure the destructor is called since it destroys the `EGLSurface` before + // creating a new onscreen surface. + onscreen_surface_ = nullptr; + onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(native_window_); + if (!onscreen_surface_->IsValid()) { + FML_LOG(ERROR) << "Unable to create EGL window surface on resize."; + return false; + } + onscreen_surface_->MakeCurrent(); + return true; +} + +bool OhosSurfaceGLSkia::ResourceContextMakeCurrent() { + FML_DCHECK(IsValid()); + auto status = offscreen_surface_->MakeCurrent(); + return status != OhosEGLSurfaceMakeCurrentStatus::kFailure; +} + +bool OhosSurfaceGLSkia::ResourceContextClearCurrent() { + FML_DCHECK(IsValid()); + EGLBoolean result = eglMakeCurrent(eglGetCurrentDisplay(), EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); + return result == EGL_TRUE; +} + +bool OhosSurfaceGLSkia::SetNativeWindow(fml::RefPtr window) { + FML_DCHECK(IsValid()); + FML_DCHECK(window); + native_window_ = window; + // Ensure the destructor is called since it destroys the `EGLSurface` before + // creating a new onscreen surface. + onscreen_surface_ = nullptr; + // Create the onscreen surface. + onscreen_surface_ = GLContextPtr()->CreateOnscreenSurface(window); + if (!onscreen_surface_->IsValid()) { + return false; + } + return true; +} + +std::unique_ptr OhosSurfaceGLSkia::GLContextMakeCurrent() { + FML_DCHECK(IsValid()); + FML_DCHECK(onscreen_surface_); + auto status = onscreen_surface_->MakeCurrent(); + auto default_context_result = std::make_unique( + status != OhosEGLSurfaceMakeCurrentStatus::kFailure); + return std::move(default_context_result); +} + +bool OhosSurfaceGLSkia::GLContextClearCurrent() { + FML_DCHECK(IsValid()); + return GLContextPtr()->ClearCurrent(); +} + +SurfaceFrame::FramebufferInfo OhosSurfaceGLSkia::GLContextFramebufferInfo() + const { + FML_DCHECK(IsValid()); + SurfaceFrame::FramebufferInfo res; + res.supports_readback = true; + res.supports_partial_repaint = onscreen_surface_->SupportsPartialRepaint(); + res.existing_damage = onscreen_surface_->InitialDamage(); + // Some devices (Pixel2 XL) needs EGL_KHR_partial_update rect aligned to 4, + // otherwise there are glitches + // (https://github.com/flutter/flutter/issues/97482#) + // Larger alignment might also be beneficial for tile base renderers. + res.horizontal_clip_alignment = 32; + res.vertical_clip_alignment = 32; + + return res; +} + +void OhosSurfaceGLSkia::GLContextSetDamageRegion( + const std::optional& region) { + FML_DCHECK(IsValid()); + onscreen_surface_->SetDamageRegion(region); +} + +bool OhosSurfaceGLSkia::GLContextPresent(const GLPresentInfo& present_info) { + FML_DCHECK(IsValid()); + FML_DCHECK(onscreen_surface_); + if (present_info.presentation_time) { + onscreen_surface_->SetPresentationTime(*present_info.presentation_time); + } + return onscreen_surface_->SwapBuffers(present_info.frame_damage); +} + +GLFBOInfo OhosSurfaceGLSkia::GLContextFBO(GLFrameInfo frame_info) const { + FML_DCHECK(IsValid()); + // The default window bound framebuffer on Ohos. + return GLFBOInfo{ + .fbo_id = 0, + .partial_repaint_enabled = onscreen_surface_->SupportsPartialRepaint(), + .existing_damage = onscreen_surface_->InitialDamage(), + }; +} + +// |GPUSurfaceGLDelegate| +sk_sp OhosSurfaceGLSkia::GetGLInterface() const { + // This is a workaround for a bug in the Ohos emulator EGL/GLES + // implementation. Some versions of the emulator will not update the + // GL version string when the process switches to a new EGL context + // unless the EGL context is being made current for the first time. + // The inaccurate version string will be rejected by Skia when it + // tries to build the GrGLInterface. Flutter can work around this + // by creating a new context, making it current to force an update + // of the version, and then reverting to the previous context. + const char* gl_renderer = + reinterpret_cast(glGetString(GL_RENDERER)); + + FML_DLOG(INFO) << "OhosSurfaceGLSkia::GetGLInterface 1"; + if (gl_renderer && strncmp(gl_renderer, kEmulatorRendererPrefix, + strlen(kEmulatorRendererPrefix)) == 0) { + FML_DLOG(INFO) << "OhosSurfaceGLSkia::GetGLInterface 2"; + EGLContext new_context = GLContextPtr()->CreateNewContext(); + if (new_context != EGL_NO_CONTEXT) { + FML_DLOG(INFO) << "OhosSurfaceGLSkia::GetGLInterface 3"; + EGLContext old_context = eglGetCurrentContext(); + EGLDisplay display = eglGetCurrentDisplay(); + EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW); + EGLSurface read_surface = eglGetCurrentSurface(EGL_READ); + [[maybe_unused]] EGLBoolean result = + eglMakeCurrent(display, draw_surface, read_surface, new_context); + FML_DCHECK(result == EGL_TRUE); + result = eglMakeCurrent(display, draw_surface, read_surface, old_context); + FML_DCHECK(result == EGL_TRUE); + result = eglDestroyContext(display, new_context); + FML_DCHECK(result == EGL_TRUE); + } + } + + FML_DLOG(INFO) << "OhosSurfaceGLSkia::GetGLInterface 4"; + return GPUSurfaceGLDelegate::GetGLInterface(); +} + +OhosContextGLSkia* OhosSurfaceGLSkia::GLContextPtr() const { + return reinterpret_cast(ohos_context_.get()); +} + +std::unique_ptr OhosSurfaceGLSkia::CreateSnapshotSurface() { + if (!onscreen_surface_ || !onscreen_surface_->IsValid()) { + onscreen_surface_ = GLContextPtr()->CreatePbufferSurface(); + } + sk_sp main_skia_context = + GLContextPtr()->GetMainSkiaContext(); + if (!main_skia_context) { + main_skia_context = GPUSurfaceGLSkia::MakeGLContext(this); + GLContextPtr()->SetMainSkiaContext(main_skia_context); + } + + return std::make_unique(main_skia_context, this, true); +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_surface_gl_skia.h b/shell/platform/ohos/ohos_surface_gl_skia.h new file mode 100755 index 0000000000000000000000000000000000000000..4a99529433248f7f0a6677120d5e5b61cb896c66 --- /dev/null +++ b/shell/platform/ohos/ohos_surface_gl_skia.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SURFACE_GL_SKIA_H +#define OHOS_SURFACE_GL_SKIA_H + +#include + +#include "flutter/fml/macros.h" +#include "flutter/shell/gpu/gpu_surface_gl_skia.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h" +#include "flutter/shell/platform/ohos/ohos_environment_gl.h" +#include "flutter/shell/platform/ohos/surface/ohos_surface.h" + +namespace flutter { + +class OhosSurfaceGLSkia final : public GPUSurfaceGLDelegate, + public OHOSSurface { + public: + OhosSurfaceGLSkia(const std::shared_ptr& ohos_context); + + ~OhosSurfaceGLSkia() override; + + // |OhosSurface| + bool IsValid() const override; + + // |OhosSurface| + std::unique_ptr CreateGPUSurface( + GrDirectContext* gr_context) override; + + // |OhosSurface| + void TeardownOnScreenContext() override; + + // |OhosSurface| + bool OnScreenSurfaceResize(const SkISize& size) override; + + // |OhosSurface| + bool ResourceContextMakeCurrent() override; + + // |OhosSurface| + bool ResourceContextClearCurrent() override; + + // |OhosSurface| + bool SetNativeWindow(fml::RefPtr window) override; + + // |OhosSurface| + virtual std::unique_ptr CreateSnapshotSurface() override; + + // |GPUSurfaceGLDelegate| + std::unique_ptr GLContextMakeCurrent() override; + + // |GPUSurfaceGLDelegate| + bool GLContextClearCurrent() override; + + // |GPUSurfaceGLDelegate| + SurfaceFrame::FramebufferInfo GLContextFramebufferInfo() const override; + + // |GPUSurfaceGLDelegate| + void GLContextSetDamageRegion(const std::optional& region) override; + + // |GPUSurfaceGLDelegate| + bool GLContextPresent(const GLPresentInfo& present_info) override; + + // |GPUSurfaceGLDelegate| + GLFBOInfo GLContextFBO(GLFrameInfo frame_info) const override; + + // |GPUSurfaceGLDelegate| + sk_sp GetGLInterface() const override; + + // Obtain a raw pointer to the on-screen OhosEGLSurface. + // + // This method is intended for use in tests. Callers must not + // delete the returned pointer. + OhosEGLSurface* GetOnscreenSurface() const { return onscreen_surface_.get(); } + + private: + fml::RefPtr native_window_; + std::unique_ptr onscreen_surface_; + std::unique_ptr offscreen_surface_; + + //---------------------------------------------------------------------------- + /// @brief Takes the super class OhosSurface's OhosContext and + /// return a raw pointer to an OhosContextGL. + /// + OhosContextGLSkia* GLContextPtr() const; + + FML_DISALLOW_COPY_AND_ASSIGN(OhosSurfaceGLSkia); +}; + +} // namespace flutter + +#endif diff --git a/shell/platform/ohos/ohos_surface_software.cpp b/shell/platform/ohos/ohos_surface_software.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cebb31fd1e0d38829b5e404dbc172f497ecdb716 --- /dev/null +++ b/shell/platform/ohos/ohos_surface_software.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_surface_software.h" +#include +#include +#include "flutter/fml/logging.h" +#include "napi_common.h" +#include "third_party/skia/include/core/SkImage.h" + +namespace flutter { + +bool GetSkColorType(int32_t buffer_format, + SkColorType* color_type, + SkAlphaType* alpha_type) { + switch (buffer_format) { + case 12: // PIXEL_FMT_RGBA_8888 + *color_type = kRGBA_8888_SkColorType; + *alpha_type = kPremul_SkAlphaType; + return true; + default: + return false; + } +} + +OHOSSurfaceSoftware::OHOSSurfaceSoftware( + const std::shared_ptr& ohos_context) + : OHOSSurface(ohos_context) { + GetSkColorType(12, &target_color_type_, &target_alpha_type_); +} + +OHOSSurfaceSoftware::~OHOSSurfaceSoftware() {} + +bool OHOSSurfaceSoftware::IsValid() const { + return true; +} + +// |OHOSSurface| +bool OHOSSurfaceSoftware::ResourceContextMakeCurrent() { + return false; +} + +// |OHOSSurface| +bool OHOSSurfaceSoftware::ResourceContextClearCurrent() { + return false; +} + +// |OHOSSurface| +std::unique_ptr OHOSSurfaceSoftware::CreateGPUSurface( + GrDirectContext* gr_context) { + LOGD("CreateGPUSurface start"); + if (!IsValid()) { + return nullptr; + } + + FML_DLOG(INFO) << "CreateGPUSurface"; + + auto surface = + std::make_unique(this, true /* render to surface */); + + if (!surface->IsValid()) { + FML_DLOG(INFO) << "CreateGPUSurface failed."; + return nullptr; + } + LOGD("CreateGPUSurface end"); + return surface; +} + +// |OHOSSurface| +void OHOSSurfaceSoftware::TeardownOnScreenContext() { + FML_DLOG(INFO) << "TeardownOnScreenContext"; +} + +// |OHOSSurface| +bool OHOSSurfaceSoftware::OnScreenSurfaceResize(const SkISize& size) { + FML_DLOG(INFO) << "OnScreenSurfaceResize"; + return true; +} + +// |OHOSSurface| +bool OHOSSurfaceSoftware::SetNativeWindow( + fml::RefPtr window) { + FML_DLOG(INFO) << "SetNativeWindow"; + native_window_ = std::move(window); + if (!(native_window_ && native_window_->IsValid())) { + FML_DLOG(INFO) << "SetNativeWindow failed."; + return false; + } + + LOGD("SetNativeWindow true"); + return true; +} + +// |GPUSurfaceSoftwareDelegate| +sk_sp OHOSSurfaceSoftware::AcquireBackingStore(const SkISize& size) { + FML_DLOG(INFO) << "AcquireBackingStore..."; + if (!IsValid()) { + LOGE("AcquireBackingStore the surface is Invalid"); + return nullptr; + } + + if (sk_surface_ != nullptr && + SkISize::Make(sk_surface_->width(), sk_surface_->height()) == size) { + // The old and new surface sizes are the same. Nothing to do here. + return sk_surface_; + } + + LOGE("SkImageInfofWidth=%{public}d, fHeight=%{public}d", size.fWidth, + size.fHeight); + SkImageInfo image_info = + SkImageInfo::Make(size.fWidth, size.fHeight, target_color_type_, + target_alpha_type_, SkColorSpace::MakeSRGB()); + + FML_DLOG(INFO) << "AcquireBackingStore...MakeRaster "; + sk_surface_ = SkSurface::MakeRaster(image_info); + + LOGD("AcquireBackingStore end"); + return sk_surface_; +} + +// |GPUSurfaceSoftwareDelegate| +/*将 backing_store 画布中的数据 绘制到 native_window 构筑的画布中 */ +bool OHOSSurfaceSoftware::PresentBackingStore(sk_sp backing_store) { + FML_DLOG(INFO) << "PresentBackingStore...MakeRaster "; + if (!IsValid() || backing_store == nullptr) { + LOGE("PresentBackingStore backing_store is inValid"); + return false; + } + + SkPixmap pixmap; + LOGE("PresentBackingStore peekPixels ...."); + + if (!backing_store->peekPixels(&pixmap)) { + LOGE("PresentBackingStore peekPixels failed"); + return false; + } + + OHNativeWindowBuffer* buffer = nullptr; + int fenceFd = -1; + FML_DLOG(INFO) << "PresentBackingStore Requestbuffer ..." + << (int64_t)native_window_.get()->Gethandle(); + if (native_window_.get() == nullptr || !native_window_.get()->IsValid()) { + FML_DLOG(ERROR) + << "PresentBackingStore Requestbuffer ...native_window is invalid " + << (int64_t)native_window_.get()->Gethandle(); + return false; + } + + int32_t ret = OH_NativeWindow_NativeWindowRequestBuffer( + native_window_.get()->Gethandle(), &buffer, &fenceFd); + if (ret != 0) { + LOGE( + "PresentBackingStore OH_NativeWindow_NativeWindowRequestBuffer failed " + ":%{public}d", + ret); + return false; + } + + BufferHandle* bufferHandle = + OH_NativeWindow_GetBufferHandleFromNative(buffer); + + if (bufferHandle == nullptr) { + FML_DLOG(ERROR) << "PresentBackingStore " + "OH_NativeWindow_GetBufferHandleFromNative failed ."; + OH_NativeWindow_DestroyNativeWindowBuffer(buffer); + return false; + } + LOGI( + "BufferHandle.fd:%{public}d,w:%{public}d,h:%{public}d,stride:%{public}d," + "format:%{public}d,usage:%{public}ld,virAddr:%{public}p,phyAddr:%{public}" + "ld,key:%{public}d", + bufferHandle->fd, bufferHandle->width, bufferHandle->height, + bufferHandle->stride, bufferHandle->format, bufferHandle->usage, + bufferHandle->virAddr, bufferHandle->phyAddr, bufferHandle->key); + void* virAddr = mmap(nullptr, bufferHandle->size, PROT_READ | PROT_WRITE, + MAP_SHARED, bufferHandle->fd, 0); + if (virAddr == MAP_FAILED) { + FML_DLOG(ERROR) << "mmap BufferHandle.virAddr failed "; + OH_NativeWindow_DestroyNativeWindowBuffer(buffer); + return false; + } + + { + SkColorType color_type; + SkAlphaType alpha_type; + FML_DLOG(INFO) << "GetSkColorType..."; + if (GetSkColorType(bufferHandle->format, &color_type, &alpha_type)) { + SkImageInfo native_image_info = SkImageInfo::Make( + bufferHandle->width, bufferHandle->height, color_type, alpha_type); + FML_DLOG(INFO) << "native_image_info.w:" << native_image_info.width() + << ",h:" << native_image_info.height(); + int bytesPerPixel = 1; // SkColorTypeBytesPerPixel(color_type); + FML_DLOG(INFO) << "MakeRasterDirect,bytesPerPixel:" << bytesPerPixel; + + std::unique_ptr canvas = SkCanvas::MakeRasterDirect( + native_image_info, virAddr, bufferHandle->stride * bytesPerPixel); + FML_DLOG(INFO) << "MakeRasterDirect,created canvas:" + << (int64_t)canvas.get(); + + if (canvas) { + SkBitmap bitmap; + if (bitmap.installPixels(pixmap)) { + FML_DLOG(INFO) << "MakeRasterDirect,canvasdrawImageRect.width:" + << bufferHandle->width << ",height" + << bufferHandle->height; + canvas->drawImageRect( + bitmap.asImage(), + SkRect::MakeIWH(bufferHandle->width, bufferHandle->height), + SkSamplingOptions()); + + } else { + FML_DLOG(INFO) << "bitmap.installPixels failed ."; + } + + } else { + FML_DLOG(INFO) << "MakeRasterDirect Failed."; + } + } else { + FML_DLOG(INFO) << "GetSkColorType Failed."; + } + } + + Region region{nullptr, 0}; + if (virAddr != nullptr) { + munmap(virAddr, bufferHandle->size); + } + LOGI("OH_NativeWindow_NativeWindowFlushBuffer ...."); + ret = OH_NativeWindow_NativeWindowFlushBuffer( + native_window_.get()->Gethandle(), buffer, fenceFd, region); + LOGI("PresentBackingStore flush Buffer :%{public}d", ret); + OH_NativeWindow_DestroyNativeWindowBuffer(buffer); + return ret == 0; +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_surface_software.h b/shell/platform/ohos/ohos_surface_software.h new file mode 100644 index 0000000000000000000000000000000000000000..a0dfd8ae0044bac6d03d3b523453a3c91beae9aa --- /dev/null +++ b/shell/platform/ohos/ohos_surface_software.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SURFACE_SOFTWARE_H +#define OHOS_SURFACE_SOFTWARE_H + +#include "flutter/fml/macros.h" +#include "flutter/shell/gpu/gpu_surface_software.h" +#include "flutter/shell/platform/ohos/surface/ohos_surface.h" + +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" + +namespace flutter { + +class OHOSSurfaceSoftware final : public OHOSSurface, + public GPUSurfaceSoftwareDelegate { + public: + OHOSSurfaceSoftware(const std::shared_ptr& ohos_context); + ~OHOSSurfaceSoftware() override; + + bool IsValid() const override; + + // |OHOSSurface| + bool ResourceContextMakeCurrent() override; + + // |OHOSSurface| + bool ResourceContextClearCurrent() override; + + // |OHOSSurface| + std::unique_ptr CreateGPUSurface( + GrDirectContext* gr_context) override; + + // |OHOSSurface| + void TeardownOnScreenContext() override; + + // |OHOSSurface| + bool OnScreenSurfaceResize(const SkISize& size) override; + + // |OHOSSurface| + bool SetNativeWindow(fml::RefPtr window) override; + + // |GPUSurfaceSoftwareDelegate| + sk_sp AcquireBackingStore(const SkISize& size) override; + + // |GPUSurfaceSoftwareDelegate| + bool PresentBackingStore(sk_sp backing_store) override; + + private: + sk_sp sk_surface_; + fml::RefPtr native_window_; + SkColorType target_color_type_; + SkAlphaType target_alpha_type_; + + FML_DISALLOW_COPY_AND_ASSIGN(OHOSSurfaceSoftware); +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_surface_vulkan_impeller.cpp b/shell/platform/ohos/ohos_surface_vulkan_impeller.cpp new file mode 100755 index 0000000000000000000000000000000000000000..3e6a3937fc39c33d7ec8526253fb0b7dc7883f1e --- /dev/null +++ b/shell/platform/ohos/ohos_surface_vulkan_impeller.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_surface_vulkan_impeller.h" + +#include +#include + +#include "flutter/fml/concurrent_message_loop.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/memory/ref_ptr.h" +#include "flutter/impeller/renderer/backend/vulkan/context_vk.h" +#include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h" +#include "flutter/vulkan/vulkan_native_surface_android.h" +#include "impeller/entity/vk/entity_shaders_vk.h" +#include "impeller/entity/vk/modern_shaders_vk.h" + +namespace flutter { + +std::shared_ptr CreateImpellerContext( + const fml::RefPtr& proc_table, + const std::shared_ptr& concurrent_loop) { + std::vector> shader_mappings = { + std::make_shared(impeller_entity_shaders_vk_data, + impeller_entity_shaders_vk_length), + std::make_shared(impeller_modern_shaders_vk_data, + impeller_modern_shaders_vk_length), + }; + + PFN_vkGetInstanceProcAddr instance_proc_addr = + proc_table->NativeGetInstanceProcAddr(); + + auto context = + impeller::ContextVK::Create(instance_proc_addr, // + shader_mappings, // + nullptr, // + concurrent_loop->GetTaskRunner(), // + "Android Impeller Vulkan Lib" // + ); + + return context; +} + +OHOSSurfaceVulkanImpeller::OHOSSurfaceVulkanImpeller( + const std::shared_ptr& ohos_context) + : OHOSSurface(ohos_context), + proc_table_(fml::MakeRefCounted()), + workers_(fml::ConcurrentMessageLoop::Create()) { + impeller_context_ = CreateImpellerContext(proc_table_, workers_); + is_valid_ = + proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context_; +} + +OHOSSurfaceVulkanImpeller::~OHOSSurfaceVulkanImpeller() {} + +// |OHOSSurface| +bool OHOSSurfaceVulkanImpeller::IsValid() const { + return is_valid_; +} + +// |OHOSSurface| +std::unique_ptr OHOSSurfaceVulkanImpeller::CreateGPUSurface( + GrDirectContext* gr_context) { + if (!IsValid()) { + return nullptr; + } + + if (!native_window_ || !native_window_->IsValid()) { + return nullptr; + } + + std::unique_ptr gpu_surface = + std::make_unique(impeller_context_); + + if (!gpu_surface->IsValid()) { + return nullptr; + } + + return gpu_surface; +} + +// |OHOSSurface| +void OHOSSurfaceVulkanImpeller::TeardownOnScreenContext() { + // do nothing +} + +// |OHOSSurface| +bool OHOSSurfaceVulkanImpeller::OnScreenSurfaceResize(const SkISize& size) { + return true; +} + +// |OHOSSurface| +bool OHOSSurfaceVulkanImpeller::ResourceContextMakeCurrent() { + // not support + return false; +} + +// |OHOSSurface| +bool OHOSSurfaceVulkanImpeller::ResourceContextClearCurrent() { + // not support + return false; +} + +// |OHOSSurface| +std::shared_ptr +OHOSSurfaceVulkanImpeller::GetImpellerContext() { + return impeller_context_; +} + +// |OHOSSurface| +bool OHOSSurfaceVulkanImpeller::SetNativeWindow( + fml::RefPtr window) { + bool success = native_window_ && native_window_->IsValid(); + + if (success) { + auto& context_vk = impeller::ContextVK::Cast(*impeller_context_); + auto surface = context_vk.CreateAndroidSurface(native_window_->Gethandle()); + + if (!surface) { + FML_LOG(ERROR) << "Could not create a vulkan surface."; + return false; + } + + context_vk.SetupSwapchain(std::move(surface)); + return true; + } + + native_window_ = nullptr; + return false; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_surface_vulkan_impeller.h b/shell/platform/ohos/ohos_surface_vulkan_impeller.h new file mode 100755 index 0000000000000000000000000000000000000000..b5bbb42e7a123c0804503a450906210f26edfdee --- /dev/null +++ b/shell/platform/ohos/ohos_surface_vulkan_impeller.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SURFACE_VULKAN_IMPELLER_H +#define OHOS_SURFACE_VULKAN_IMPELLER_H + +#include "flutter/fml/concurrent_message_loop.h" +#include "flutter/fml/macros.h" +#include "flutter/impeller/renderer/context.h" +#include "flutter/vulkan/procs/vulkan_proc_table.h" + +#include "surface/ohos_native_window.h" +#include "surface/ohos_surface.h" + +namespace flutter { + +class OHOSSurfaceVulkanImpeller : public OHOSSurface { + public: + OHOSSurfaceVulkanImpeller(const std::shared_ptr& ohos_context); + + ~OHOSSurfaceVulkanImpeller() override; + + // |OHOSSurface| + bool IsValid() const override; + + // |OHOSSurface| + std::unique_ptr CreateGPUSurface( + GrDirectContext* gr_context) override; + + // |OHOSSurface| + void TeardownOnScreenContext() override; + + // |OHOSSurface| + bool OnScreenSurfaceResize(const SkISize& size) override; + + // |OHOSSurface| + bool ResourceContextMakeCurrent() override; + + // |OHOSSurface| + bool ResourceContextClearCurrent() override; + + // |OHOSSurface| + std::shared_ptr GetImpellerContext() override; + + // |OHOSSurface| + bool SetNativeWindow(fml::RefPtr window) override; + + private: + fml::RefPtr proc_table_; + fml::RefPtr native_window_; + std::shared_ptr workers_; + std::shared_ptr impeller_context_; + bool is_valid_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(OHOSSurfaceVulkanImpeller); +}; +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/ohos_touch_processor.cpp b/shell/platform/ohos/ohos_touch_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45938c990ac8d8bcc892ae3ef17ed8f9a875a5d5 --- /dev/null +++ b/shell/platform/ohos/ohos_touch_processor.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/ohos_touch_processor.h" +#include "flutter/lib/ui/window/pointer_data_packet.h" +#include "flutter/shell/platform/ohos/ohos_shell_holder.h" + +namespace flutter { +PointerData::Change OhosTouchProcessor::getPointerChangeForAction( + int maskedAction) { + switch (maskedAction) { + case OH_NATIVEXCOMPONENT_DOWN: + return PointerData::Change::kDown; + case OH_NATIVEXCOMPONENT_UP: + return PointerData::Change::kUp; + case OH_NATIVEXCOMPONENT_CANCEL: + return PointerData::Change::kCancel; + case OH_NATIVEXCOMPONENT_MOVE: + return PointerData::Change::kMove; + } + return PointerData::Change::kCancel; +} + +PointerData::DeviceKind OhosTouchProcessor::getPointerDeviceTypeForToolType( + int toolType) { + switch (toolType) { + case OH_NATIVEXCOMPONENT_TOOL_TYPE_FINGER: + return PointerData::DeviceKind::kTouch; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_PEN: + return PointerData::DeviceKind::kStylus; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_RUBBER: + return PointerData::DeviceKind::kInvertedStylus; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_BRUSH: + return PointerData::DeviceKind::kStylus; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_PENCIL: + return PointerData::DeviceKind::kStylus; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_AIRBRUSH: + return PointerData::DeviceKind::kStylus; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_MOUSE: + return PointerData::DeviceKind::kMouse; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS: + return PointerData::DeviceKind::kTouch; + case OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN: + return PointerData::DeviceKind::kTouch; + } + return PointerData::DeviceKind::kTouch; +} + +void OhosTouchProcessor::HandleTouchEvent( + int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent) { + if (touchEvent == nullptr) { + LOGE("touchEvent Invalid"); + return; + } + auto packet = + std::make_unique(touchEvent->numPoints); + for (size_t index = 0; index < touchEvent->numPoints; ++index) { + PointerData pointerData; + pointerData.Clear(); + pointerData.embedder_id = touchEvent->id; + pointerData.time_stamp = touchEvent->touchPoints[index].timeStamp / 1000; + pointerData.change = + getPointerChangeForAction(touchEvent->touchPoints[index].type); + pointerData.physical_y = touchEvent->touchPoints[index].screenY; + pointerData.physical_x = touchEvent->touchPoints[index].screenX; + // Delta will be generated in pointer_data_packet_converter.cc. + pointerData.physical_delta_x = 0.0; + pointerData.physical_delta_y = 0.0; + pointerData.device = touchEvent->touchPoints[index].id; + // Pointer identifier will be generated in pointer_data_packet_converter.cc. + pointerData.pointer_identifier = 0; + // XComponent not support Scroll + pointerData.signal_kind = PointerData::SignalKind::kNone; + pointerData.scroll_delta_x = 0.0; + pointerData.scroll_delta_y = 0.0; + pointerData.pressure = touchEvent->touchPoints[index].force; + pointerData.pressure_max = 1.0; + pointerData.pressure_min = 0.0; + OH_NativeXComponent_TouchPointToolType toolType; + OH_NativeXComponent_GetTouchPointToolType(component, index, &toolType); + pointerData.kind = getPointerDeviceTypeForToolType(toolType); + if (pointerData.kind == PointerData::DeviceKind::kTouch) { + if (pointerData.change == PointerData::Change::kDown || + pointerData.change == PointerData::Change::kMove) { + pointerData.buttons = kPointerButtonTouchContact; + } + } else if (pointerData.kind == PointerData::DeviceKind::kMouse) { + // TODO:button获取鼠标EventButton + } + pointerData.pan_x = 0.0; + pointerData.pan_y = 0.0; + // Delta will be generated in pointer_data_packet_converter.cc. + pointerData.pan_delta_x = 0.0; + pointerData.pan_delta_y = 0.0; + // The contact area between the fingerpad and the screen + pointerData.size = touchEvent->touchPoints[index].size; + pointerData.scale = 1.0; + pointerData.rotation = 0.0; + LOGD( + "Touch Info:dots[%{public}d] id %{public}d x = %{public}f, y = " + "%{public}f type %{public}d", + static_cast(index), touchEvent->touchPoints[index].id, + touchEvent->touchPoints[index].x, touchEvent->touchPoints[index].y, + touchEvent->touchPoints[index].type); + LOGD("Touch Info : screenx = %{public}f, screeny = %{public}f", + touchEvent->touchPoints[index].screenX, + touchEvent->touchPoints[index].screenY); + LOGD( + "vtimeStamp = %{public}ld, isPressed = %{public}d toolType = " + "%{public}d", + touchEvent->touchPoints[index].timeStamp, + touchEvent->touchPoints[index].isPressed, toolType); + + packet->SetPointerData(index, pointerData); + } + auto ohos_shell_holder = reinterpret_cast(shell_holderID); + ohos_shell_holder->GetPlatformView()->DispatchPointerDataPacket( + std::move(packet)); +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/ohos_touch_processor.h b/shell/platform/ohos/ohos_touch_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..68873848fd417a47be9cf048feb04a5633174a5a --- /dev/null +++ b/shell/platform/ohos/ohos_touch_processor.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_TOUCH_PROCESSOR_H +#define OHOS_TOUCH_PROCESSOR_H +#include +#include +#include "flutter/lib/ui/window/pointer_data.h" +#include "napi_common.h" + +namespace flutter { + +class OhosTouchProcessor { + public: + void HandleTouchEvent(int64_t shell_holderID, + OH_NativeXComponent* component, + OH_NativeXComponent_TouchEvent* touchEvent); + flutter::PointerData::Change getPointerChangeForAction(int maskedAction); + flutter::PointerData::DeviceKind getPointerDeviceTypeForToolType( + int toolType); + + public: + OH_NativeXComponent_TouchPointToolType touchType_; + + private: +}; +} // namespace flutter +#endif // XComponent_OhosTouchProcessor_H \ No newline at end of file diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.cpp b/shell/platform/ohos/ohos_xcomponent_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b55625845fd459a82a7e17e0be3cb41b5ae88a3b --- /dev/null +++ b/shell/platform/ohos/ohos_xcomponent_adapter.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "ohos_xcomponent_adapter.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +namespace flutter { + +enum ContextType { + APP_LIFECYCLE = 0, + JS_PAGE_LIFECYCLE, +}; + +XComponentAdapter XComponentAdapter::mXComponentAdapter; +OH_NativeXComponent_Callback XComponentAdapter::callback_; + +void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window) { + XComponentAdapter::GetInstance()->OnSurfaceCreated(component, window); +} + +void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window) { + XComponentAdapter::GetInstance()->OnSurfaceChanged(component, window); +} + +void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window) { + XComponentAdapter::GetInstance()->OnSurfaceDestroyed(component, window); +} + +void DispatchTouchEventCB(OH_NativeXComponent* component, void* window) { + XComponentAdapter::GetInstance()->DispatchTouchEvent(component, window); +} + +XComponentAdapter::XComponentAdapter(/* args */) {} + +XComponentAdapter::~XComponentAdapter() {} + +XComponentAdapter* XComponentAdapter::GetInstance() { + return &XComponentAdapter::mXComponentAdapter; +} + +bool XComponentAdapter::Export(napi_env env, napi_value exports) { + napi_status status; + napi_value exportInstance = nullptr; + OH_NativeXComponent* nativeXComponent = nullptr; + int32_t ret; + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + + status = napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, + &exportInstance); + LOGD("napi_get_named_property,status = %{public}d", status); + if (status != napi_ok) { + return false; + } + + status = napi_unwrap(env, exportInstance, + reinterpret_cast(&nativeXComponent)); + LOGD("napi_unwrap,status = %{public}d", status); + if (status != napi_ok) { + return false; + } + + ret = OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize); + LOGD("NativeXComponent id:%{public}s", idStr); + if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + return false; + } + std::string id(idStr); + auto context = XComponentAdapter::GetInstance(); + if (context) { + XComponentAdapter::shell_holder = PlatformViewOHOSNapi::GetShellHolder(); + context->SetNativeXComponent(id, nativeXComponent); + return true; + } + + return false; +} + +void XComponentAdapter::SetNativeXComponent( + std::string& id, + OH_NativeXComponent* nativeXComponent) { + nativeXComponent_ = nativeXComponent; + BindXComponentCallback(); + OH_NativeXComponent_RegisterCallback(nativeXComponent_, + &XComponentAdapter::callback_); +} + +OH_NativeXComponent* XComponentAdapter::GetNativeXComponent(std::string& id) { + return nativeXComponent_; +} + +#include +using OHOS_SurfaceBufferUsage = enum { + BUFFER_USAGE_CPU_READ = (1ULL << 0), /**< CPU read buffer */ + BUFFER_USAGE_CPU_WRITE = (1ULL << 1), /**< CPU write memory */ + BUFFER_USAGE_MEM_MMZ = (1ULL << 2), /**< Media memory zone (MMZ) */ + BUFFER_USAGE_MEM_DMA = (1ULL << 3), /**< Direct memory access (DMA) buffer */ + BUFFER_USAGE_MEM_SHARE = (1ULL << 4), /**< Shared memory buffer*/ + BUFFER_USAGE_MEM_MMZ_CACHE = (1ULL << 5), /**< MMZ with cache*/ + BUFFER_USAGE_MEM_FB = (1ULL << 6), /**< Framebuffer */ + BUFFER_USAGE_ASSIGN_SIZE = (1ULL << 7), /**< Memory assigned */ + BUFFER_USAGE_HW_RENDER = (1ULL << 8), /**< For GPU write case */ + BUFFER_USAGE_HW_TEXTURE = (1ULL << 9), /**< For GPU read case */ + BUFFER_USAGE_HW_COMPOSER = (1ULL << 10), /**< For hardware composer */ + BUFFER_USAGE_PROTECTED = + (1ULL << 11), /**< For safe buffer case, such as DRM */ + BUFFER_USAGE_CAMERA_READ = (1ULL << 12), /**< For camera read case */ + BUFFER_USAGE_CAMERA_WRITE = (1ULL << 13), /**< For camera write case */ + BUFFER_USAGE_VIDEO_ENCODER = (1ULL << 14), /**< For encode case */ + BUFFER_USAGE_VIDEO_DECODER = (1ULL << 15), /**< For decode case */ + BUFFER_USAGE_VENDOR_PRI0 = (1ULL << 44), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI1 = (1ULL << 45), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI2 = (1ULL << 46), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI3 = (1ULL << 47), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI4 = (1ULL << 48), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI5 = (1ULL << 49), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI6 = (1ULL << 50), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI7 = (1ULL << 51), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI8 = (1ULL << 52), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI9 = (1ULL << 53), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI10 = (1ULL << 54), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI11 = (1ULL << 55), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI12 = (1ULL << 56), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI13 = (1ULL << 57), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI14 = (1ULL << 58), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI15 = (1ULL << 59), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI16 = (1ULL << 60), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI17 = (1ULL << 61), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI18 = (1ULL << 62), /**< Reserverd for vendor */ + BUFFER_USAGE_VENDOR_PRI19 = (1ULL << 63), /**< Reserverd for vendor */ +}; +static int32_t SetNativeWindowOpt(OHNativeWindow* nativeWindow, + int32_t width, + int height) { + // Set the read and write scenarios of the native window buffer. + int code = SET_USAGE; + int32_t usage = + BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA; + int32_t ret = + OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, usage); + if (ret) { + LOGE( + "Set NativeWindow Usage Failed :window:%{public}p ,w:%{public}d x " + "%{public}d:%{public}d", + nativeWindow, width, height, ret); + } + // Set the width and height of the native window buffer. + code = SET_BUFFER_GEOMETRY; + ret = + OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height); + if (ret) { + LOGE( + "Set NativeWindow GEOMETRY Failed :window:%{public}p ,w:%{public}d x " + "%{public}d:%{public}d", + nativeWindow, width, height, ret); + } + // Set the step of the native window buffer. + code = SET_STRIDE; + int32_t stride = 0x8; + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, stride); + if (ret) { + LOGE( + "Set NativeWindow stride Failed :window:%{public}p ,w:%{public}d x " + "%{public}d:%{public}d", + nativeWindow, width, height, ret); + } + // Set the format of the native window buffer. + code = SET_FORMAT; +#ifndef PIXEL_FMT_RGBA_8888 +// foundation/graphic/graphic_2d/interfaces/inner_api/surface/surface_type.h +// GRAPHIC_PIXEL_FMT_RGBA_8888, +#define PIXEL_FMT_RGBA_8888 12 +#endif + int32_t format = PIXEL_FMT_RGBA_8888; + + ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, format); + if (ret) { + LOGE( + "Set NativeWindow PIXEL_FMT_RGBA_8888 Failed :window:%{public}p " + ",w:%{public}d x %{public}d:%{public}d", + nativeWindow, width, height, ret); + } + return ret; +} +void XComponentAdapter::OnSurfaceCreated(OH_NativeXComponent* component, + void* window) { + LOGD( + "XComponentManger::OnSurfaceCreated window = %{public}p component = " + "%{public}p", + window, component); + int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, + &width_, &height_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + LOGD("XComponent Current width:%{public}d,height:%{public}d", + static_cast(width_), static_cast(height_)); + // mXComponentRender.XComponentRenderInit(window, width_, height_); + // mXComponentRender.Draw(); + } else { + LOGE("GetXComponentSize result:%{public}d", ret); + } + + LOGD("OnSurfaceCreated,window.size:%{public}d,%{public}d", (int)width_, + (int)height_); + ret = SetNativeWindowOpt((OHNativeWindow*)window, width_, height_); + if (ret) { + LOGD("SetNativeWindowOpt failed:%{public}d", ret); + } + PlatformViewOHOSNapi::SurfaceCreated(shell_holder, window); +} + +void XComponentAdapter::OnSurfaceChanged(OH_NativeXComponent* component, + void* window) { + LOGD("XComponentManger::OnSurfaceChanged "); + int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, + &width_, &height_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + LOGD("XComponent Current width:%{public}d,height:%{public}d", + static_cast(width_), static_cast(height_)); + } + PlatformViewOHOSNapi::SurfaceChanged(shell_holder, width_, height_); +} + +void XComponentAdapter::OnSurfaceDestroyed(OH_NativeXComponent* component, + void* window) { + LOGD("XComponentManger::OnSurfaceDestroyed"); + PlatformViewOHOSNapi::SurfaceDestroyed(shell_holder); +} + +void XComponentAdapter::DispatchTouchEvent(OH_NativeXComponent* component, + void* window) { + LOGD("XComponentManger::DispatchTouchEvent"); + int32_t ret = + OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_); + if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + ohosTouchProcessor_.HandleTouchEvent(shell_holder, component, &touchEvent_); + } +} + +OH_NativeXComponent_Callback* XComponentAdapter::GetNXComponentCallback() { + return &XComponentAdapter::callback_; +} + +void XComponentAdapter::BindXComponentCallback() { + auto renderCallback = XComponentAdapter::GetNXComponentCallback(); + renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB; + renderCallback->OnSurfaceChanged = OnSurfaceChangedCB; + renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB; + renderCallback->DispatchTouchEvent = DispatchTouchEventCB; +} + +} // namespace flutter diff --git a/shell/platform/ohos/ohos_xcomponent_adapter.h b/shell/platform/ohos/ohos_xcomponent_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..009d3f5e4aef9588ed5565b96dbaf2241939f075 --- /dev/null +++ b/shell/platform/ohos/ohos_xcomponent_adapter.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_XCOMPONENT_ADAPTER_H +#define OHOS_XCOMPONENT_ADAPTER_H +#include +#include +#include "flutter/shell/platform/ohos/ohos_touch_processor.h" +#include "napi/native_api.h" +#include "napi_common.h" + +namespace flutter { + +class XComponentAdapter { + public: + XComponentAdapter(/* args */); + ~XComponentAdapter(); + static XComponentAdapter* GetInstance(); + bool Export(napi_env env, napi_value exports); + OH_NativeXComponent* GetNativeXComponent(std::string& id); + void SetNativeXComponent(std::string& id, + OH_NativeXComponent* nativeXComponent); + OH_NativeXComponent_Callback* GetNXComponentCallback(); + + // Callback, called by ACE XComponent + void OnSurfaceCreated(OH_NativeXComponent* component, void* window); + void OnSurfaceChanged(OH_NativeXComponent* component, void* window); + void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); + void DispatchTouchEvent(OH_NativeXComponent* component, void* window); + + void BindXComponentCallback(); + void PackPointerDataAndDispatch( + const OH_NativeXComponent_TouchEvent touchEvent); + + public: + static OH_NativeXComponent_Callback callback_; + std::string id_; + uint64_t width_; + uint64_t height_; + OH_NativeXComponent_TouchEvent touchEvent_; + + private: + static XComponentAdapter mXComponentAdapter; + OH_NativeXComponent* nativeXComponent_; + int64_t shell_holder; + OhosTouchProcessor ohosTouchProcessor_; +}; + +} // namespace flutter + +#endif diff --git a/shell/platform/ohos/platform_message_handler_ohos.cpp b/shell/platform/ohos/platform_message_handler_ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..111334f721368bebc5bea4aed8d4b0f4392790f6 --- /dev/null +++ b/shell/platform/ohos/platform_message_handler_ohos.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/platform_message_handler_ohos.h" +#include "flutter/fml/make_copyable.h" + +namespace flutter { + +PlatformMessageHandlerOHOS::PlatformMessageHandlerOHOS( + const std::shared_ptr& napi_facede, + fml::RefPtr platform_task_runner) + : napi_facade_(napi_facede), + platform_task_runner_(std::move(platform_task_runner)) {} + +void PlatformMessageHandlerOHOS::HandlePlatformMessage( + std::unique_ptr message) { + int response_id = next_response_id_.fetch_add(1); + if (auto response = message->response()) { + std::lock_guard lock(pending_responses_mutex_); + pending_responses_[response_id] = response; + } + + platform_task_runner_->PostTask( + fml::MakeCopyable([response_id = response_id, napi_facede = napi_facade_, + message = std::move(message)]() mutable { + napi_facede->FlutterViewHandlePlatformMessage(response_id, + std::move(message)); + })); +} + +void PlatformMessageHandlerOHOS::InvokePlatformMessageResponseCallback( + int response_id, + std::unique_ptr mapping) { + if (!response_id) { + return; + } + // TODO(gaaclarke): Move the jump to the ui thread here from + // PlatformMessageResponseDart so we won't need to use a mutex anymore. + fml::RefPtr message_response; + { + std::lock_guard lock(pending_responses_mutex_); + auto it = pending_responses_.find(response_id); + if (it == pending_responses_.end()) { + return; + } + message_response = std::move(it->second); + pending_responses_.erase(it); + } + + message_response->Complete(std::move(mapping)); +} + +void PlatformMessageHandlerOHOS::InvokePlatformMessageEmptyResponseCallback( + int response_id) { + if (!response_id) { + return; + } + fml::RefPtr message_response; + { + std::lock_guard lock(pending_responses_mutex_); + auto it = pending_responses_.find(response_id); + if (it == pending_responses_.end()) { + return; + } + message_response = std::move(it->second); + pending_responses_.erase(it); + } + message_response->CompleteEmpty(); +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/platform_message_handler_ohos.h b/shell/platform/ohos/platform_message_handler_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..5536f269015b8f3dfe29b88ccc1c09d628a96f67 --- /dev/null +++ b/shell/platform/ohos/platform_message_handler_ohos.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef PLATFORM_MESSAGE_HANDLER_OHOS_H +#define PLATFORM_MESSAGE_HANDLER_OHOS_H +#include +#include +#include + +#include "flutter/fml/task_runner.h" +#include "flutter/lib/ui/window/platform_message.h" +#include "flutter/shell/common/platform_message_handler.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +namespace flutter { + +class PlatformMessageHandlerOHOS : public PlatformMessageHandler { + public: + explicit PlatformMessageHandlerOHOS( + const std::shared_ptr& napi_facede, + fml::RefPtr platform_task_runner); + void HandlePlatformMessage(std::unique_ptr message) override; + bool DoesHandlePlatformMessageOnPlatformThread() const override { + return true; + } + void InvokePlatformMessageResponseCallback( + int response_id, + std::unique_ptr mapping) override; + + void InvokePlatformMessageEmptyResponseCallback(int response_id) override; + + private: + const std::shared_ptr napi_facade_; + const fml::RefPtr platform_task_runner_; + std::atomic next_response_id_ = 1; + std::unordered_map> + pending_responses_; + std::mutex pending_responses_mutex_; +}; + +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/platform_message_response_ohos.cpp b/shell/platform/ohos/platform_message_response_ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d24283f791c8d86b3e4dafe2f37c8e1458cd8a9 --- /dev/null +++ b/shell/platform/ohos/platform_message_response_ohos.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/platform_message_response_ohos.h" +#include +#include "flutter/fml/make_copyable.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +namespace flutter { + +PlatformMessageResponseOHOS::PlatformMessageResponseOHOS( + int response_id, + std::shared_ptr napi_facade, + fml::RefPtr platform_task_runner) + : response_id_(response_id), + napi_facade_(std::move(napi_facade)), + platform_task_runner_(std::move(platform_task_runner)) {} + +PlatformMessageResponseOHOS::~PlatformMessageResponseOHOS() = default; + +void PlatformMessageResponseOHOS::Complete(std::unique_ptr data) { + // async post + + platform_task_runner_->PostTask( + fml::MakeCopyable([response_id = response_id_, data = std::move(data), + napi_facede = napi_facade_]() mutable { + napi_facede->FlutterViewHandlePlatformMessageResponse(response_id, + std::move(data)); + })); +} + +void PlatformMessageResponseOHOS::CompleteEmpty() { + platform_task_runner_->PostTask( + fml::MakeCopyable([response_id = response_id_, // + napi_facede = napi_facade_ // + ]() { + // Make the response call into Java. + napi_facede->FlutterViewHandlePlatformMessageResponse(response_id, + nullptr); + })); +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/platform_message_response_ohos.h b/shell/platform/ohos/platform_message_response_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..eaf144f10cb5080f3eddc73b74dea47f1c542567 --- /dev/null +++ b/shell/platform/ohos/platform_message_response_ohos.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef PLATFORM_MESSAGE_REPONSE_OHOS_H +#define PLATFORM_MESSAGE_REPONSE_OHOS_H + +#include "flutter/fml/macros.h" +#include "flutter/fml/task_runner.h" +#include "flutter/lib/ui/window/platform_message_response.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" + +namespace flutter { + +class PlatformMessageResponseOHOS : public flutter::PlatformMessageResponse { + public: + // |flutter::PlatformMessageResponse| + void Complete(std::unique_ptr data) override; + + // |flutter::PlatformMessageResponse| + void CompleteEmpty() override; + + private: + PlatformMessageResponseOHOS( + int response_id, + std::shared_ptr napi_facade, + fml::RefPtr platform_task_runner); + + ~PlatformMessageResponseOHOS() override; + + const int response_id_; + const std::shared_ptr napi_facade_; + const fml::RefPtr platform_task_runner_; + + FML_FRIEND_MAKE_REF_COUNTED(PlatformMessageResponseOHOS); + FML_DISALLOW_COPY_AND_ASSIGN(PlatformMessageResponseOHOS); +}; + +} // namespace flutter +#endif \ No newline at end of file diff --git a/shell/platform/ohos/platform_view_ohos.cpp b/shell/platform/ohos/platform_view_ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fc6b6b1a67a53f250101317a0b4fc7d256775d0 --- /dev/null +++ b/shell/platform/ohos/platform_view_ohos.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/platform_view_ohos.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/lib/ui/window/viewport_metrics.h" +#include "flutter/shell/common/shell_io_manager.h" +#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h" +#include "flutter/shell/platform/ohos/ohos_surface_gl_skia.h" +#include "flutter/shell/platform/ohos/ohos_surface_software.h" +#include "flutter/shell/platform/ohos/platform_message_response_ohos.h" +#include "napi_common.h" +#include "ohos_context_gl_impeller.h" +#include "ohos_surface_gl_impeller.h" + +namespace flutter { + +OhosSurfaceFactoryImpl::OhosSurfaceFactoryImpl( + const std::shared_ptr& context, + bool enable_impeller) + : ohos_context_(context), enable_impeller_(enable_impeller) {} + +OhosSurfaceFactoryImpl::~OhosSurfaceFactoryImpl() = default; + +std::unique_ptr OhosSurfaceFactoryImpl::CreateSurface() { + switch (ohos_context_->RenderingApi()) { + case OHOSRenderingAPI::kSoftware: + return std::make_unique(ohos_context_); + case OHOSRenderingAPI::kOpenGLES: + if (enable_impeller_) { + return std::make_unique(ohos_context_); + } else { + FML_LOG(INFO) << "OhosSurfaceFactoryImpl::OhosSurfaceGLSkia "; + return std::make_unique(ohos_context_); + } + default: + FML_DCHECK(false); + return nullptr; + } +} + +std::unique_ptr CreateOHOSContext( + bool use_software_rendering, + const flutter::TaskRunners& task_runners, + uint8_t msaa_samples, + bool enable_impeller) { + if (use_software_rendering) { + return std::make_unique(OHOSRenderingAPI::kSoftware); + } + if (enable_impeller) { + return std::make_unique(); + } + + return std::make_unique( + OHOSRenderingAPI::kOpenGLES, fml::MakeRefCounted(), + task_runners, msaa_samples); +} + +PlatformViewOHOS::PlatformViewOHOS( + PlatformView::Delegate& delegate, + const flutter::TaskRunners& task_runners, + const std::shared_ptr& napi_facade, + bool use_software_rendering, + uint8_t msaa_samples) + : PlatformViewOHOS( + delegate, + task_runners, + napi_facade, + CreateOHOSContext( + use_software_rendering, + task_runners, + msaa_samples, + delegate.OnPlatformViewGetSettings().enable_impeller)) {} + +PlatformViewOHOS::PlatformViewOHOS( + PlatformView::Delegate& delegate, + const flutter::TaskRunners& task_runners, + const std::shared_ptr& napi_facade, + const std::shared_ptr& ohos_context) + : PlatformView(delegate, task_runners), + napi_facade_(napi_facade), + ohos_context_(ohos_context), + platform_message_handler_(new PlatformMessageHandlerOHOS( + napi_facade, + task_runners_.GetPlatformTaskRunner())) { + if (ohos_context_) { + FML_CHECK(ohos_context_->IsValid()) + << "Could not create surface from invalid Android context."; + LOGI("ohos_surface_ end 1"); + surface_factory_ = std::make_shared( + ohos_context_, delegate.OnPlatformViewGetSettings().enable_impeller); + LOGI("ohos_surface_ end 2"); + ohos_surface_ = surface_factory_->CreateSurface(); + LOGI("ohos_surface_ end 3"); + FML_CHECK(ohos_surface_ && ohos_surface_->IsValid()) + << "Could not create an OpenGL, Vulkan or Software surface to set " + "up " + "rendering."; + } +} + +PlatformViewOHOS::~PlatformViewOHOS() {} + +void PlatformViewOHOS::NotifyCreate( + fml::RefPtr native_window) { + LOGI("NotifyCreate start"); + if (ohos_surface_) { + InstallFirstFrameCallback(); + LOGI("NotifyCreate start1"); + fml::AutoResetWaitableEvent latch; + fml::TaskRunner::RunNowOrPostTask( + task_runners_.GetRasterTaskRunner(), + [&latch, surface = ohos_surface_.get(), + native_window = std::move(native_window)]() { + LOGI("NotifyCreate start4"); + surface->SetNativeWindow(native_window); + latch.Signal(); + }); + latch.Wait(); + } + + PlatformView::NotifyCreated(); +} + +void PlatformViewOHOS::NotifySurfaceWindowChanged( + fml::RefPtr native_window) { + LOGI("PlatformViewOHOS NotifySurfaceWindowChanged enter"); + if (ohos_surface_) { + fml::AutoResetWaitableEvent latch; + fml::TaskRunner::RunNowOrPostTask( + task_runners_.GetRasterTaskRunner(), + [&latch, surface = ohos_surface_.get(), + native_window = std::move(native_window)]() { + surface->TeardownOnScreenContext(); + surface->SetNativeWindow(native_window); + latch.Signal(); + }); + latch.Wait(); + } +} + +void PlatformViewOHOS::NotifyChanged(const SkISize& size) { + LOGI("PlatformViewOHOS NotifyChanged enter"); + if (ohos_surface_) { + fml::AutoResetWaitableEvent latch; + fml::TaskRunner::RunNowOrPostTask( + task_runners_.GetRasterTaskRunner(), // + [&latch, surface = ohos_surface_.get(), size]() { + surface->OnScreenSurfaceResize(size); + latch.Signal(); + }); + latch.Wait(); + } +} + +// |PlatformView| +void PlatformViewOHOS::NotifyDestroyed() { + LOGI("PlatformViewOHOS NotifyDestroyed enter"); + if (ohos_surface_) { + fml::AutoResetWaitableEvent latch; + fml::TaskRunner::RunNowOrPostTask( + task_runners_.GetRasterTaskRunner(), + [&latch, surface = ohos_surface_.get()]() { + surface->TeardownOnScreenContext(); + latch.Signal(); + }); + latch.Wait(); + } +} + +// todo + +void PlatformViewOHOS::DispatchPlatformMessage(std::string name, + void* message, + int messageLenth, + int reponseId) { + FML_DLOG(INFO) << "DispatchSemanticsAction(" << name << ",," << messageLenth + << "," << reponseId; + fml::MallocMapping mapMessage = + fml::MallocMapping::Copy(message, messageLenth); + + fml::RefPtr response; + response = fml::MakeRefCounted( + reponseId, napi_facade_, task_runners_.GetPlatformTaskRunner()); + + PlatformView::DispatchPlatformMessage( + std::make_unique( + std::move(name), std::move(mapMessage), std::move(response))); +} + +void PlatformViewOHOS::DispatchEmptyPlatformMessage(std::string name, + int reponseId) { + FML_DLOG(INFO) << "DispatchEmptyPlatformMessage(" << name << "" + << "," << reponseId; + fml::RefPtr response; + response = fml::MakeRefCounted( + reponseId, napi_facade_, task_runners_.GetPlatformTaskRunner()); + + PlatformView::DispatchPlatformMessage( + std::make_unique(std::move(name), + std::move(response))); +} + +void PlatformViewOHOS::DispatchSemanticsAction(int id, + int action, + void* actionData, + int actionDataLenth) { + FML_DLOG(INFO) << "DispatchSemanticsAction(" << id << "," << action << "," + << actionDataLenth; + auto args_vector = fml::MallocMapping::Copy(actionData, actionDataLenth); + + PlatformView::DispatchSemanticsAction( + id, static_cast(action), + std::move(args_vector)); +} + +// |PlatformView| +void PlatformViewOHOS::LoadDartDeferredLibrary( + intptr_t loading_unit_id, + std::unique_ptr snapshot_data, + std::unique_ptr snapshot_instructions) { + FML_DLOG(INFO) << "LoadDartDeferredLibrary:" << loading_unit_id; + delegate_.LoadDartDeferredLibrary(loading_unit_id, std::move(snapshot_data), + std::move(snapshot_instructions)); +} + +void PlatformViewOHOS::LoadDartDeferredLibraryError( + intptr_t loading_unit_id, + const std::string error_message, + bool transient) { + FML_DLOG(INFO) << "LoadDartDeferredLibraryError:" << loading_unit_id << ":" + << error_message; + delegate_.LoadDartDeferredLibraryError(loading_unit_id, error_message, + transient); +} + +// |PlatformView| +void PlatformViewOHOS::UpdateAssetResolverByType( + std::unique_ptr updated_asset_resolver, + AssetResolver::AssetResolverType type) { + FML_DLOG(INFO) << "UpdateAssetResolverByType"; + delegate_.UpdateAssetResolverByType(std::move(updated_asset_resolver), type); +} + +// todo +void PlatformViewOHOS::UpdateSemantics( + flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions) { + FML_DLOG(INFO) << "UpdateSemantics"; +} + +// |PlatformView| +void PlatformViewOHOS::HandlePlatformMessage( + std::unique_ptr message) { + FML_DLOG(INFO) << "HandlePlatformMessage"; + platform_message_handler_->HandlePlatformMessage(std::move(message)); +} + +// |PlatformView| +void PlatformViewOHOS::OnPreEngineRestart() const { + FML_DLOG(INFO) << "OnPreEngineRestart"; + task_runners_.GetPlatformTaskRunner()->PostTask( + fml::MakeCopyable([napi_facede = napi_facade_]() mutable { + napi_facede->FlutterViewOnPreEngineRestart(); + })); +} + +// |PlatformView| +std::unique_ptr PlatformViewOHOS::CreateVSyncWaiter() { + FML_DLOG(INFO) << "CreateVSyncWaiter"; + return std::make_unique(task_runners_); +} + +// |PlatformView| +std::unique_ptr PlatformViewOHOS::CreateRenderingSurface() { + FML_DLOG(INFO) << "CreateRenderingSurface"; + if (ohos_surface_ == nullptr) { + FML_DLOG(ERROR) << "CreateRenderingSurface Failed.ohos_surface_ is null "; + return nullptr; + } + + LOGD("return CreateGPUSurface"); + return ohos_surface_->CreateGPUSurface( + ohos_context_->GetMainSkiaContext().get()); +} + +// |PlatformView| +std::shared_ptr +PlatformViewOHOS::CreateExternalViewEmbedder() { + FML_DLOG(INFO) << "CreateExternalViewEmbedder"; + return nullptr; +} + +// |PlatformView| +std::unique_ptr +PlatformViewOHOS::CreateSnapshotSurfaceProducer() { + FML_DLOG(INFO) << "CreateSnapshotSurfaceProducer"; + return std::make_unique(*(ohos_surface_.get())); +} + +// |PlatformView| +sk_sp PlatformViewOHOS::CreateResourceContext() const { + FML_DLOG(INFO) << "CreateResourceContext"; + if (!ohos_surface_) { + return nullptr; + } + sk_sp resource_context; + if (ohos_surface_->ResourceContextMakeCurrent()) { + // TODO(chinmaygarde): Currently, this code depends on the fact that only + // the OpenGL surface will be able to make a resource context current. If + // this changes, this assumption breaks. Handle the same. + resource_context = ShellIOManager::CreateCompatibleResourceLoadingContext( + GrBackend::kOpenGL_GrBackend, + GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface()); + } else { + FML_DLOG(ERROR) << "Could not make the resource context current."; + } + + return resource_context; +} + +// |PlatformView| +void PlatformViewOHOS::ReleaseResourceContext() const { + LOGI("ReleaseResourceContext"); + if (ohos_surface_) { + ohos_surface_->ResourceContextClearCurrent(); + } +} + +// |PlatformView| +std::shared_ptr PlatformViewOHOS::GetImpellerContext() + const { + FML_DLOG(INFO) << "GetImpellerContext"; + if (ohos_surface_) { + return ohos_surface_->GetImpellerContext(); + } + return nullptr; +} + +// |PlatformView| +std::unique_ptr> +PlatformViewOHOS::ComputePlatformResolvedLocales( + const std::vector& supported_locale_data) { + FML_DLOG(INFO) << "ComputePlatformResolvedLocales"; + return napi_facade_->FlutterViewComputePlatformResolvedLocales( + supported_locale_data); +} + +// |PlatformView| +void PlatformViewOHOS::RequestDartDeferredLibrary(intptr_t loading_unit_id) { + FML_DLOG(INFO) << "RequestDartDeferredLibrary:" << loading_unit_id; + return; +} + +void PlatformViewOHOS::InstallFirstFrameCallback() { + FML_DLOG(INFO) << "InstallFirstFrameCallback"; + SetNextFrameCallback( + [platform_view = GetWeakPtr(), + platform_task_runner = task_runners_.GetPlatformTaskRunner()]() { + platform_task_runner->PostTask([platform_view]() { + // Back on Platform Task Runner. + FML_DLOG(INFO) << "install InstallFirstFrameCallback "; + if (platform_view) { + reinterpret_cast(platform_view.get()) + ->FireFirstFrameCallback(); + } + }); + }); +} + +void PlatformViewOHOS::FireFirstFrameCallback() { + FML_DLOG(INFO) << "FlutterViewOnFirstFrame"; + napi_facade_->FlutterViewOnFirstFrame(); +} + +} // namespace flutter diff --git a/shell/platform/ohos/platform_view_ohos.h b/shell/platform/ohos/platform_view_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..3e81fc44a78057b8215a46aab74829ec04f9ee7c --- /dev/null +++ b/shell/platform/ohos/platform_view_ohos.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_PLATFORM_VIEW_H +#define OHOS_PLATFORM_VIEW_H + +#include +#include +#include +#include + +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/lib/ui/window/platform_message.h" +#include "flutter/shell/common/platform_view.h" +#include "flutter/shell/platform/ohos/context/ohos_context.h" +#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h" +#include "flutter/shell/platform/ohos/platform_message_handler_ohos.h" +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" +#include "flutter/shell/platform/ohos/surface/ohos_snapshot_surface_producer.h" +#include "flutter/shell/platform/ohos/surface/ohos_surface.h" +#include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" + +namespace flutter { + +class OhosSurfaceFactoryImpl : public OhosSurfaceFactory { + public: + OhosSurfaceFactoryImpl(const std::shared_ptr& context, + bool enable_impeller); + + ~OhosSurfaceFactoryImpl() override; + + std::unique_ptr CreateSurface() override; + + private: + const std::shared_ptr& ohos_context_; + const bool enable_impeller_; +}; + +class PlatformViewOHOS final : public PlatformView { + public: + PlatformViewOHOS(PlatformView::Delegate& delegate, + const flutter::TaskRunners& task_runners, + const std::shared_ptr& napi_facade, + bool use_software_rendering, + uint8_t msaa_samples); + + PlatformViewOHOS(PlatformView::Delegate& delegate, + const flutter::TaskRunners& task_runners, + const std::shared_ptr& napi_facade, + const std::shared_ptr& OHOS_context); + + ~PlatformViewOHOS() override; + + void NotifyCreate(fml::RefPtr native_window); + + void NotifySurfaceWindowChanged(fml::RefPtr native_window); + + void NotifyChanged(const SkISize& size); + + // |PlatformView| + void NotifyDestroyed() override; + + // todo + void DispatchPlatformMessage(std::string name, + void* message, + int messageLenth, + int reponseId); + + void DispatchEmptyPlatformMessage(std::string name, int reponseId); + + void DispatchSemanticsAction(int id, + int action, + void* actionData, + int actionDataLenth); + + // |PlatformView| + void LoadDartDeferredLibrary( + intptr_t loading_unit_id, + std::unique_ptr snapshot_data, + std::unique_ptr snapshot_instructions) override; + + void LoadDartDeferredLibraryError(intptr_t loading_unit_id, + const std::string error_message, + bool transient) override; + + // |PlatformView| + void UpdateAssetResolverByType( + std::unique_ptr updated_asset_resolver, + AssetResolver::AssetResolverType type) override; + + const std::shared_ptr& GetAndroidContext() { + return ohos_context_; + } + + std::shared_ptr GetPlatformMessageHandler() + const override { + return platform_message_handler_; + } + + private: + const std::shared_ptr napi_facade_; + std::shared_ptr ohos_context_; + + std::shared_ptr ohos_surface_; + std::shared_ptr platform_message_handler_; + + std::shared_ptr surface_factory_; + + // PlatformViewOhosdDelegate platform_view_ohos_delegate_; + + // |PlatformView| + void UpdateSemantics( + flutter::SemanticsNodeUpdates update, + flutter::CustomAccessibilityActionUpdates actions) override; + + // |PlatformView| + void HandlePlatformMessage( + std::unique_ptr message) override; + + // |PlatformView| + void OnPreEngineRestart() const override; + + // |PlatformView| + std::unique_ptr CreateVSyncWaiter() override; + + // |PlatformView| + std::unique_ptr CreateRenderingSurface() override; + + // |PlatformView| + std::shared_ptr CreateExternalViewEmbedder() override; + + // |PlatformView| + std::unique_ptr CreateSnapshotSurfaceProducer() + override; + + // |PlatformView| + sk_sp CreateResourceContext() const override; + + // |PlatformView| + void ReleaseResourceContext() const override; + + // |PlatformView| + std::shared_ptr GetImpellerContext() const override; + + // |PlatformView| + std::unique_ptr> ComputePlatformResolvedLocales( + const std::vector& supported_locale_data) override; + + // |PlatformView| + void RequestDartDeferredLibrary(intptr_t loading_unit_id) override; + + void InstallFirstFrameCallback(); + + void FireFirstFrameCallback(); + + FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewOHOS); +}; +} // namespace flutter +#endif diff --git a/shell/platform/ohos/surface/ohos_native_window.cpp b/shell/platform/ohos/surface/ohos_native_window.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e256eb7d67ecfaec08daad9bef4e5929c9767bc --- /dev/null +++ b/shell/platform/ohos/surface/ohos_native_window.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" +#include "flutter/fml/logging.h" + +namespace flutter { + +OHOSNativeWindow::OHOSNativeWindow(Handle window) + : window_(window), is_fake_window_(false) { + FML_LOG(INFO) << " native_window:" << (int64_t)window_; +} + +OHOSNativeWindow::~OHOSNativeWindow() { + if (window_ != nullptr) { + window_ = nullptr; + } +} + +bool OHOSNativeWindow::IsValid() const { + return window_ != nullptr; +} + +SkISize OHOSNativeWindow::GetSize() const { + if (window_ != nullptr) { + return SkISize::Make(width_, height_); + } + + return SkISize::Make(0, 0); +} + +void OHOSNativeWindow::SetWindowHeight(double height) { + height_ = height; +} + +void OHOSNativeWindow::SetWindowWidth(double width) { + width_ = width; +} + +bool OHOSNativeWindow::GetWindowWithAndHeight(double* height, double* width) { + if (window_ == nullptr) { + return false; + } + + *height = height_; + *width = width_; + + return true; +} + +OHOSNativeWindow::Handle OHOSNativeWindow::Gethandle() const { + return window_; +} + +OHOSNativeWindow::Handle OHOSNativeWindow::handle() const { + return window_; +} + +} // namespace flutter diff --git a/shell/platform/ohos/surface/ohos_native_window.h b/shell/platform/ohos/surface/ohos_native_window.h new file mode 100644 index 0000000000000000000000000000000000000000..29ecfee97a64e0e23663778039505be0fd342cb7 --- /dev/null +++ b/shell/platform/ohos/surface/ohos_native_window.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_NATIVE_WINDOW_H +#define OHOS_NATIVE_WINDOW_H + +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/ref_counted.h" +#include "third_party/skia/include/core/SkSize.h" + +#include + +namespace flutter { + +/* + class adapater for ThreadSafe +*/ +class OHOSNativeWindow : public fml::RefCountedThreadSafe { + public: + using Handle = OHNativeWindow*; + + Handle Gethandle() const; + + bool IsValid() const; + + SkISize GetSize() const; + + Handle handle() const; + + /// Returns true when this AndroidNativeWindow is not backed by a real window + /// (used for testing). + bool IsFakeWindow() const { return is_fake_window_; } + + void SetWindowHeight(double height); + + void SetWindowWidth(double width); + + bool GetWindowWithAndHeight(double* height, double* width); + + private: + Handle window_; + double height_; + double width_; + const bool is_fake_window_; + + explicit OHOSNativeWindow(Handle window); + + ~OHOSNativeWindow(); + + FML_FRIEND_MAKE_REF_COUNTED(OHOSNativeWindow); + FML_FRIEND_REF_COUNTED_THREAD_SAFE(OHOSNativeWindow); + FML_DISALLOW_COPY_AND_ASSIGN(OHOSNativeWindow); +}; +} // namespace flutter + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/surface/ohos_snapshot_surface_producer.cpp b/shell/platform/ohos/surface/ohos_snapshot_surface_producer.cpp new file mode 100755 index 0000000000000000000000000000000000000000..21d0d333f3063a4761cdf3f9b4ad6a506102788b --- /dev/null +++ b/shell/platform/ohos/surface/ohos_snapshot_surface_producer.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/surface/ohos_snapshot_surface_producer.h" + +namespace flutter { + +OHOSSnapshotSurfaceProducer::OHOSSnapshotSurfaceProducer( + OHOSSurface& ohos_surface) + : ohos_surface_(ohos_surface) { + FML_DLOG(WARNING) << "Flutter OHOSSnapshotSurfaceProducer()."; +} + +// |SnapshotSurfaceProducer| +std::unique_ptr OHOSSnapshotSurfaceProducer::CreateSnapshotSurface() { + FML_DLOG(WARNING) << "Flutter CreateSnapshotSurface()."; + return ohos_surface_.CreateSnapshotSurface(); +} + +} // namespace flutter diff --git a/shell/platform/ohos/surface/ohos_snapshot_surface_producer.h b/shell/platform/ohos/surface/ohos_snapshot_surface_producer.h new file mode 100755 index 0000000000000000000000000000000000000000..ba890b03587156759c0e33dd3436aaf0701e5db9 --- /dev/null +++ b/shell/platform/ohos/surface/ohos_snapshot_surface_producer.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SNAPSHOT_SURFACE_PRODUCER_H +#define OHOS_SNAPSHOT_SURFACE_PRODUCER_H +#include "flutter/flow/surface.h" +#include "flutter/shell/common/snapshot_surface_producer.h" +#include "flutter/shell/platform/ohos/surface/ohos_surface.h" + +namespace flutter { +class OHOSSnapshotSurfaceProducer : public SnapshotSurfaceProducer { + public: + explicit OHOSSnapshotSurfaceProducer(OHOSSurface& ohos_surface); + + // |SnapshotSurfaceProducer| + std::unique_ptr CreateSnapshotSurface() override; + + private: + OHOSSurface& ohos_surface_; +}; +} // namespace flutter + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/surface/ohos_surface.cpp b/shell/platform/ohos/surface/ohos_surface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d887f3d894704583da1b92b9eb5ea2f6f12a8fb --- /dev/null +++ b/shell/platform/ohos/surface/ohos_surface.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/surface/ohos_surface.h" +namespace flutter { + +OHOSSurface::OHOSSurface(const std::shared_ptr& ohos_context) + : ohos_context_(ohos_context) { + FML_DCHECK(ohos_context->IsValid()); + ohos_context_ = ohos_context; +} + +std::unique_ptr OHOSSurface::CreateSnapshotSurface() { + return nullptr; +} + +OHOSSurface::~OHOSSurface() = default; + +std::shared_ptr OHOSSurface::GetImpellerContext() { + return nullptr; +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/ohos/surface/ohos_surface.h b/shell/platform/ohos/surface/ohos_surface.h new file mode 100644 index 0000000000000000000000000000000000000000..b87757d5f5d7d6b2d55118ee93ff445b1cd7d346 --- /dev/null +++ b/shell/platform/ohos/surface/ohos_surface.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef OHOS_SURFACE_H +#define OHOS_SURFACE_H + +#include +#include "flutter/flow/surface.h" +#include "flutter/shell/platform/ohos/context/ohos_context.h" +#include "flutter/shell/platform/ohos/surface/ohos_native_window.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace impeller { +class Context; +} // namespace impeller + +namespace flutter { + +class OHOSSurface { + public: + virtual ~OHOSSurface(); + virtual bool IsValid() const = 0; + virtual void TeardownOnScreenContext() = 0; + + virtual bool OnScreenSurfaceResize(const SkISize& size) = 0; + + virtual bool ResourceContextMakeCurrent() = 0; + + virtual bool ResourceContextClearCurrent() = 0; + + virtual bool SetNativeWindow(fml::RefPtr window) = 0; + + virtual std::unique_ptr CreateSnapshotSurface(); + + virtual std::unique_ptr CreateGPUSurface( + GrDirectContext* gr_context = nullptr) = 0; + + virtual std::shared_ptr GetImpellerContext(); + + protected: + explicit OHOSSurface(const std::shared_ptr& ohos_context); + std::shared_ptr ohos_context_; +}; + +class OhosSurfaceFactory { + public: + OhosSurfaceFactory() = default; + + virtual ~OhosSurfaceFactory() = default; + + virtual std::unique_ptr CreateSurface() = 0; +}; +} // namespace flutter + +#endif \ No newline at end of file diff --git a/shell/platform/ohos/vsync_waiter_ohos.cpp b/shell/platform/ohos/vsync_waiter_ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26cc3d2d8b70f30aff8ce278e8b5592a489782d2 --- /dev/null +++ b/shell/platform/ohos/vsync_waiter_ohos.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 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. + */ + +#include "flutter/shell/platform/ohos/vsync_waiter_ohos.h" +#include "flutter/fml/logging.h" +#include "napi_common.h" + +namespace flutter { + +static std::atomic_uint g_refresh_rate_ = 60; + +const char* flutterSyncName = "flutter_connect"; + +VsyncWaiterOHOS::VsyncWaiterOHOS(const flutter::TaskRunners& task_runners) + : VsyncWaiter(task_runners) { + vsyncHandle = + OH_NativeVSync_Create("flutterSyncName", strlen(flutterSyncName)); +} + +VsyncWaiterOHOS::~VsyncWaiterOHOS() { + OH_NativeVSync_Destroy(vsyncHandle); +} + +void VsyncWaiterOHOS::AwaitVSync() { + if (vsyncHandle == nullptr) { + LOGE("AwaitVSync vsyncHandle is nullptr"); + return; + } + auto* weak_this = new std::weak_ptr(shared_from_this()); + OH_NativeVSync* handle = vsyncHandle; + + fml::TaskRunner::RunNowOrPostTask( + task_runners_.GetUITaskRunner(), [weak_this, handle]() { + int32_t ret = 0; + if (0 != (ret = OH_NativeVSync_RequestFrame(handle, &OnVsyncFromOHOS, + weak_this))) { + FML_DLOG(ERROR) << "AwaitVSync...failed:" << ret; + } + }); +} + +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); + ConsumePendingCallback(weak_this, frame_time, target_time); +} + +void VsyncWaiterOHOS::ConsumePendingCallback( + std::weak_ptr* weak_this, + fml::TimePoint frame_start_time, + fml::TimePoint frame_target_time) { + std::shared_ptr shared_this = weak_this->lock(); + delete weak_this; + + if (shared_this) { + shared_this->FireCallback(frame_start_time, frame_target_time); + } +} + +void VsyncWaiterOHOS::OnUpdateRefreshRate(long long refresh_rate) { + FML_DCHECK(refresh_rate > 0); + g_refresh_rate_ = static_cast(refresh_rate); +} + +} // namespace flutter diff --git a/shell/platform/ohos/vsync_waiter_ohos.h b/shell/platform/ohos/vsync_waiter_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..5650a7f64cf11421e001a119f322af57291a9255 --- /dev/null +++ b/shell/platform/ohos/vsync_waiter_ohos.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef VSYNC_WAITER_OHOS_H +#define VSYNC_WAITER_OHOS_H +#include + +#include +#include "flutter/fml/macros.h" +#include "flutter/shell/common/vsync_waiter.h" + +namespace flutter { + +class VsyncWaiterOHOS final : public VsyncWaiter { + public: + explicit VsyncWaiterOHOS(const flutter::TaskRunners& task_runners); + static void OnUpdateRefreshRate(long long refresh_rate); + + ~VsyncWaiterOHOS() override; + + private: + // |VsyncWaiter| + void AwaitVSync() override; + + static void OnVsyncFromOHOS(long long timestamp, void* data); + static void ConsumePendingCallback(std::weak_ptr* weak_this, + fml::TimePoint frame_start_time, + fml::TimePoint frame_target_time); + + OH_NativeVSync* vsyncHandle; + FML_DISALLOW_COPY_AND_ASSIGN(VsyncWaiterOHOS); +}; +} // namespace flutter +#endif diff --git a/shell/version/version.gni b/shell/version/version.gni index a5a6a99a38d6e58a5a3b1bd6f661c7b2376de41a..d397b9c8704fa63250fc8f50e54b21ed6bea45bf 100644 --- a/shell/version/version.gni +++ b/shell/version/version.gni @@ -3,11 +3,9 @@ # found in the LICENSE file. declare_args() { - engine_version = "" - - skia_version = "" - - dart_version = "" + engine_version = "1a65d409c7a1438a34d21b60bf30a6fd5db59314" + skia_version = "7e1844439eaa3eb24d00c6314ddc81ca532fdd1b" + dart_version = "5b8936496673a285bf8f37472119bc2afb38a295" } _flutter_root = "//flutter" @@ -44,3 +42,7 @@ if (dart_version == "") { "list lines") dart_version = dart_version_lines[0] } + +print("engine_version:"+engine_version) +print("dart_version:"+dart_version) +print("skia_version:"+skia_version) diff --git a/third_party/txt/BUILD.gn b/third_party/txt/BUILD.gn index 3060859fe4773063213691660124e4193f3a5f3e..0aaa87464c73004e8aee84daa40c2569960d6774 100644 --- a/third_party/txt/BUILD.gn +++ b/third_party/txt/BUILD.gn @@ -172,6 +172,8 @@ source_set("txt") { deps += [ "//flutter/fml" ] } else if (is_android) { sources += [ "src/txt/platform_android.cc" ] + } else if (is_ohos) { + sources += [ "src/txt/platform_ohos.cc" ] } else if (is_linux) { sources += [ "src/txt/platform_linux.cc" ] } else if (is_fuchsia) { diff --git a/third_party/txt/src/txt/platform_ohos.cc b/third_party/txt/src/txt/platform_ohos.cc new file mode 100644 index 0000000000000000000000000000000000000000..3a0be33881a7846ee40672e9ccdc027f44b4951d --- /dev/null +++ b/third_party/txt/src/txt/platform_ohos.cc @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2023 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. +*/ + +#include "txt/platform.h" + +namespace txt { + +std::vector GetDefaultFontFamilies() { + return {"sans-serif"}; +} + +sk_sp GetDefaultFontManager(uint32_t font_initialization_data) { + return SkFontMgr::RefDefault(); +} + +} // namespace txt + diff --git a/tools/gn b/tools/gn index 27f65988f53b3a0f2dbe1a4b511c9801c669b7a6..5882b343a643b1bd3f76092e915661115ef8562a 100755 --- a/tools/gn +++ b/tools/gn @@ -52,6 +52,9 @@ def get_out_dir(args): if args.linux_cpu is not None: target_dir.append(args.linux_cpu) +# if args.ohos_cpu is not None: +# target_dir.append(args.ohos_cpu) + if args.windows_cpu != 'x64': target_dir.append(args.windows_cpu) @@ -102,6 +105,8 @@ def is_host_build(args): # target_os='linux' and linux-cpu='arm64' if args.target_os == 'linux' and args.linux_cpu == 'arm64': return True +#if args.target_os == 'ohos' and args.ohos_cpu == 'arm64': +# return True # The Mac and host targets are redundant. Again, necessary to disambiguate # during cross-compilation. if args.target_os == 'mac': @@ -128,6 +133,9 @@ def can_use_prebuilt_dart(args): prebuilt = 'linux-x64' elif args.target_os == 'linux' and args.linux_cpu in ['x64', 'arm64']: prebuilt = 'linux-%s' % args.linux_cpu + elif args.target_os == 'ohos' and args.ohos_cpu in ['x64', 'arm64']: + prebuilt = 'linux-%s' % args.ohos_cpu + #prebuilt = 'ohos-%s' % args.ohos_cpu elif args.target_os == 'mac' and args.mac_cpu in ['x64', 'arm64']: prebuilt = 'macos-%s' % args.mac_cpu elif args.target_os == 'win' and args.windows_cpu in ['x64', 'arm64']: @@ -192,6 +200,8 @@ def get_target_cpu(args): return args.mac_cpu if args.target_os == 'linux': return args.linux_cpu + if args.target_os == 'ohos': + return args.ohos_cpu if args.target_os == 'fuchsia': return args.fuchsia_cpu if args.target_os == 'wasm': @@ -213,6 +223,7 @@ def to_gn_args(args): if args.target_os != 'ios': raise Exception('--simulator is only supported for iOS') + print('args.target_os:%s' % args.target_os ) runtime_mode = args.runtime_mode gn_args = {} @@ -269,6 +280,9 @@ def to_gn_args(args): if args.enable_unittests: gn_args['enable_unittests'] = args.enable_unittests + gn_args['enable_unittests'] = False + print("enable_unittests:%s" % gn_args['enable_unittests'] ); + # Skia GN args. gn_args['skia_enable_flutter_defines' ] = True # Enable Flutter API guards in Skia. @@ -319,6 +333,7 @@ def to_gn_args(args): # Set OS, CPU arch for host or target build. if is_host_build(args): + print('is host build ') gn_args['host_os'] = get_host_os() gn_args['host_cpu'] = get_host_cpu() gn_args['target_os'] = gn_args['host_os'] @@ -329,6 +344,7 @@ def to_gn_args(args): gn_args['target_cpu'] = get_target_cpu(args) gn_args['dart_target_arch'] = gn_args['target_cpu'] + print("ARGS.target_os:%s-%s" % (args.target_os,gn_args['target_os'] ) ) # We cannot cross-compile for 32 bit arm on a Windows host. We work around # this by leaving 'target_cpu' and 'dart_target_arch' set to 'arm' so that # Dart tools such as gen_snapshot that are built for the host will correctly @@ -446,7 +462,7 @@ def to_gn_args(args): # Enable Vulkan on all platforms except for iOS. This is just # to save on mobile binary size, as there's no reason the Vulkan embedder # features can't work on these platforms. - if args.target_os not in ['ios']: + if args.target_os not in ['ios','mac','ohos']: gn_args['skia_use_vulkan'] = True gn_args['skia_use_vma'] = False gn_args['shell_enable_vulkan'] = True @@ -461,7 +477,7 @@ def to_gn_args(args): # Make symbols visible in order to enable symbolization of unit test crash backtraces on Linux gn_args['disable_hidden_visibility' - ] = args.target_os == 'linux' and args.unoptimized + ] = (args.target_os == 'linux' or args.target_os == 'ohos') and args.unoptimized if args.arm_float_abi: gn_args['arm_float_abi'] = args.arm_float_abi @@ -696,7 +712,7 @@ def parse_args(args): parser.add_argument( '--target-os', type=str, - choices=['android', 'ios', 'mac', 'linux', 'fuchsia', 'wasm', 'win'] + choices=['android', 'ios', 'mac', 'linux', 'fuchsia', 'wasm', 'win','ohos'] ) parser.add_argument( '--android', dest='target_os', action='store_const', const='android' @@ -723,6 +739,9 @@ def parse_args(args): parser.add_argument( '--linux', dest='target_os', action='store_const', const='linux' ) + parser.add_argument( + '--ohos', dest='target_os', action='store_const', const='ohos' + ) parser.add_argument( '--fuchsia', dest='target_os', action='store_const', const='fuchsia' ) @@ -737,6 +756,9 @@ def parse_args(args): parser.add_argument( '--linux-cpu', type=str, choices=['x64', 'x86', 'arm64', 'arm'] ) + parser.add_argument( + '--ohos-cpu', type=str, choices=['x64', 'x86', 'arm64', 'arm'] + ) parser.add_argument( '--fuchsia-cpu', type=str, choices=['x64', 'arm64'], default='x64' ) @@ -1018,6 +1040,16 @@ def main(argv): '--export-compile-commands', ] + print('XX ohos_cpu:%s' % args.ohos_cpu ) + # print('linux_cpu:'+ args.linux_cpu ) + print('XX target_os:%s' % args.target_os) + + if args.target_os == 'ohos': + if args.ohos_cpu is not None: + args.linux_cpu = args.ohos_cpu + elif args.linux_cpu is not None : + args.ohos_cpu = args.linux_cpu + if not args.web: if args.ide != '': command.append('--ide=%s' % args.ide) @@ -1037,6 +1069,10 @@ def main(argv): command.append(out_dir) command.append('--args=%s' % ' '.join(gn_args)) + + + print('gn ARGS : %s' % ' '.join(gn_args)) + if args.trace_gn: command.append('--tracelog=%s/gn_trace.json' % out_dir)