diff --git a/.ci.yaml b/.ci.yaml index dfcbad39ffce4..77377e923ebcd 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -24,11 +24,10 @@ platform_properties: ios_debug: "false" ios_profile: "false" ios_release: "false" - no_bitcode: "false" # CIPD flutter_internal/java/openjdk/$platform dependencies: >- [ - {"dependency": "open_jdk", "version": "version:1.8.0u202-b08"}, + {"dependency": "open_jdk", "version": "version:11"}, {"dependency": "gradle_cache", "version": "none"} ] device_type: none @@ -47,11 +46,10 @@ platform_properties: ios_debug: "false" ios_profile: "false" ios_release: "false" - no_bitcode: "false" # CIPD flutter_internal/java/openjdk/$platform dependencies: >- [ - {"dependency": "open_jdk", "version": "version:1.8.0u202-b08"} + {"dependency": "open_jdk", "version": "version:11"} ] device_type: none cpu: x86 @@ -70,11 +68,10 @@ platform_properties: ios_debug: "false" ios_profile: "false" ios_release: "false" - no_bitcode: "false" # CIPD flutter_internal/java/openjdk/$platform dependencies: >- [ - {"dependency": "open_jdk", "version": "version:1.8.0u202-b08"} + {"dependency": "open_jdk", "version": "version:11"} ] device_type: none os: Windows-10 @@ -150,6 +147,7 @@ targets: - name: Linux Fuchsia FEMU recipe: engine/femu_test + bringup: true properties: add_recipes_cq: "true" build_fuchsia: "true" @@ -308,6 +306,8 @@ targets: - master properties: add_recipes_cq: "true" + gclient_variables: >- + {"download_emsdk": true} dependencies: >- [ {"dependency": "chrome_and_driver", "version": "version:96.2"}, @@ -333,7 +333,6 @@ targets: android_sdk_license: \n24333f8a63b6825ea9c5514f83c2829b004d1fee android_sdk_preview_license: \n84831b9409646a918e30573bab4c9c91346d8abd build_android_aot: "true" - jazzy_version: "0.14.1" timeout: 60 - name: Mac Host Engine @@ -343,7 +342,6 @@ targets: {"download_emsdk": true} add_recipes_cq: "true" build_host: "true" - jazzy_version: "0.14.1" timeout: 75 - name: Mac mac_android_aot_engine @@ -367,7 +365,6 @@ targets: recipe: engine/engine_unopt properties: add_recipes_cq: "true" - jazzy_version: "0.14.1" runtime_versions: >- [ "ios-16-0_14a5294e" @@ -379,7 +376,6 @@ targets: properties: add_recipes_cq: "true" cores: "12" - jazzy_version: "0.14.1" lint_host: "true" lint_ios: "false" timeout: 75 @@ -401,7 +397,6 @@ targets: recipe: engine/engine_lint properties: add_recipes_cq: "true" - jazzy_version: "0.14.1" lint_host: "false" lint_ios: "true" timeout: 75 @@ -425,7 +420,6 @@ targets: add_recipes_cq: "true" build_ios: "true" ios_debug: "true" - jazzy_version: "0.14.1" timeout: 60 - name: Mac Web Engine @@ -545,7 +539,6 @@ targets: properties: build_ios: "true" ios_profile: "true" - jazzy_version: "0.14.1" timeout: 90 runIf: - DEPS @@ -557,7 +550,6 @@ targets: properties: build_ios: "true" ios_release: "true" - jazzy_version: "0.14.1" timeout: 90 runIf: - DEPS diff --git a/BUILD.gn b/BUILD.gn index d1b7a573af375..0b7cca847deb4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -183,6 +183,9 @@ group("unittests") { if (is_mac) { public_deps += [ "//flutter/shell/platform/darwin:flutter_channels_unittests" ] + public_deps += [ + "//flutter/third_party/spring_animation:spring_animation_unittests", + ] } if (!is_win && !is_fuchsia) { diff --git a/DEPS b/DEPS index e724c0153cbb7..a6d9e2539bbbc 100644 --- a/DEPS +++ b/DEPS @@ -18,7 +18,7 @@ vars = { 'llvm_git': 'https://llvm.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '393fb1ec80f41d8ad7d104921b6920e69749fda1', + 'skia_revision': 'e238cde8581d462e9801cdee37f8fa09854f44bc', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. @@ -40,7 +40,7 @@ vars = { # The list of revisions for these tools comes from Fuchsia, here: # https://fuchsia.googlesource.com/integration/+/HEAD/toolchain # If there are problems with the toolchain, contact fuchsia-toolchain@. - 'clang_version': 'git_revision:a93d03310e2c02fa5e24544df4706650f85788f7', + 'clang_version': 'git_revision:20d06c833d833ef6b2d0f519cc4a7998d49a2803', # When updating the Dart revision, ensure that all entries that are # dependencies of Dart are also updated to match the entries in the @@ -48,24 +48,27 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'de14a48187ce7d6063ae1d31a3a51b323a2c03f4', + 'dart_revision': '63b8dc1906e57d56d32452cf6f0262eb4bfd2741', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py - 'dart_binaryen_rev': '36e2abbcdd22b2b1707757b49fb4ac8844f28e5d', + 'dart_binaryen_rev': '4471b81a0a0b94c75bad6e81d0413860944ecb1f', 'dart_boringssl_gen_rev': 'ced85ef0a00bbca77ce5a91261a5f2ae61b1e62f', 'dart_boringssl_rev': '87f316d7748268eb56f2dc147bd593254ae93198', - 'dart_browser_launcher_rev': 'f2f01e4c7e719c633ca3c35d55c5331d4fe8b54b', - 'dart_clock_rev': '65e8a13ddf26c9d21884ccc8f8532725697d40df', - 'dart_collection_rev': '85e987cf1b8aaba60bdc8b16dd1ee6233436549f', - 'dart_devtools_rev': 'c7a81f64dabb4b9f2cae0cf2c9411ef8bb805191', - 'dart_protobuf_rev': 'cc0f287fb6a8680e431eb9210225f1d0ac33c047', - 'dart_pub_rev': '0cbaf7a2fb8c8ca543c6f222bf25d5f5c63abbf3', + 'dart_browser_launcher_rev': 'bc2dc4ef53a6619032e9f01450848e9ed40a9437', + 'dart_clock_rev': '5abb4816bad6cf3bfab64d65d501752d19760bd0', + 'dart_collection_rev': '0d0e184a5f70ca4e23dab23df686127ec40bfb11', + 'dart_devtools_rev': 'a7c581e3923357c9768c9d8ead62327dbbcc3a50', + 'dart_libprotobuf_rev': '24487dd1045c7f3d64a21f38a3f0c06cc4cf2edb', + 'dart_perfetto_rev': 'b8da07095979310818f0efde2ef3c69ea70d62c5', + 'dart_protobuf_gn_rev': 'b9517855b24624ec4edf4a11c1b7060f4ef237e6', + 'dart_protobuf_rev': '75bc380a6e9601565606a13dee16c5ab2bf5019c', + 'dart_pub_rev': '048e3ad2b5e1b4ebe6883addbc95722be6904a7b', 'dart_root_certificates_rev': '692f6d6488af68e0121317a9c2c9eb393eb0ee50', - 'dart_watcher_rev': '3b49c7ea087cc158bdcba19fe8919283fdc1cd86', - 'dart_webdev_rev': 'f978b90cdfc97967b8caec1b5e2a4919ce9fa3d2', - 'dart_webkit_inspection_protocol_rev': '15244ffbab9221f1603eb04eaae74ae7c7ca3944', - 'dart_yaml_edit_rev': '299f74594ff9fda412c1da5c0b5d5231d0c6fc42', + 'dart_watcher_rev': '0ca663817ee879477a35fa2724f0e47c15facf13', + 'dart_webdev_rev': '6255c85948f0271f3d9689c4f704791717ff38b7', + 'dart_webkit_inspection_protocol_rev': '8401098ace995e4dcd9855a2741c2dacccaa780b', + 'dart_yaml_edit_rev': '998eea2e4fc474a5e95cfea117e4233d35c3069b', 'dart_zlib_rev': '27c2f474b71d0d20764f86f60ef8b00da1a16cda', 'ocmock_rev': 'c4ec0e3a7a9f56cfdbd0aa01f4f97bb4b75c5ef8', # v3.7.1 @@ -236,7 +239,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + 'f8d0fe6494e35c84b069a09ddac9eecf303b1510', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '0180f88340ebe497a724d71fbd3df7d0f4f993d6', # Fuchsia compatibility # @@ -269,7 +272,7 @@ deps = { Var('github_git') + '/google/flatbuffers.git' + '@' + '0a80646371179f8a7a5c1f42c31ee1d44dcf6709', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '2cce76fd67afce170560afaaac1872efefe64fdb', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '266a46937f05303da1ac4c68f2c94f9a1caa3f76', 'src/third_party/khronos': Var('chromium_git') + '/chromium/src/third_party/khronos.git' + '@' + '676d544d2b8f48903b7da9fceffaa534a5613978', @@ -292,34 +295,44 @@ deps = { 'src/third_party/boringssl/src': 'https://boringssl.googlesource.com/boringssl.git' + '@' + Var('dart_boringssl_rev'), + 'src/third_party/perfetto': + Var('fuchsia_git') + "/third_party/android.googlesource.com/platform/external/perfetto" + + '@' + Var('dart_perfetto_rev'), + + 'src/third_party/protobuf': + Var('fuchsia_git') + '/third_party/protobuf' + '@' + Var('dart_libprotobuf_rev'), + + 'src/build/secondary/third_party/protobuf': + Var('fuchsia_git') + '/protobuf-gn' + '@' + Var('dart_protobuf_gn_rev'), + 'src/third_party/dart': Var('dart_git') + '/sdk.git' + '@' + Var('dart_revision'), # WARNING: Unused Dart dependencies in the list below till "WARNING:" marker are removed automatically - see create_updated_flutter_deps.py. 'src/third_party/dart/third_party/binaryen/src': - Var('chromium_git') + '/external/github.com/WebAssembly/binaryen.git@36e2abbcdd22b2b1707757b49fb4ac8844f28e5d', + Var('chromium_git') + '/external/github.com/WebAssembly/binaryen.git@4471b81a0a0b94c75bad6e81d0413860944ecb1f', 'src/third_party/dart/third_party/devtools': - {'packages': [{'version': 'git_revision:c7a81f64dabb4b9f2cae0cf2c9411ef8bb805191', 'package': 'dart/third_party/flutter/devtools'}], 'dep_type': 'cipd'}, + {'packages': [{'version': 'git_revision:a7c581e3923357c9768c9d8ead62327dbbcc3a50', 'package': 'dart/third_party/flutter/devtools'}], 'dep_type': 'cipd'}, 'src/third_party/dart/third_party/pkg/args': - Var('dart_git') + '/args.git@ac0e2c82f94d049b2d3b318b487863bf288258b1', + Var('dart_git') + '/args.git@bd3ac8537c78e267d55d261d95c2f79d10faee83', 'src/third_party/dart/third_party/pkg/async': - Var('dart_git') + '/async.git@de1ce93c6f58c22fda4dd4d6267ecebebed622c3', + Var('dart_git') + '/async.git@8deaa40439b05babb0093554ac58b982891076ff', 'src/third_party/dart/third_party/pkg/bazel_worker': - Var('dart_git') + '/bazel_worker.git@b35c25e6cecced319b80c6686b9d025e462c7053', + Var('dart_git') + '/bazel_worker.git@11246923516148dd5fa7f20dfaf82bf432e7c38d', 'src/third_party/dart/third_party/pkg/boolean_selector': - Var('dart_git') + '/boolean_selector.git@ba7d86b66382aa808576cd55840d4c34f0225066', + Var('dart_git') + '/boolean_selector.git@16e6ad3c8000e08a7f1c213aef2a692d872a16c7', 'src/third_party/dart/third_party/pkg/browser_launcher': Var('dart_git') + '/browser_launcher.git' + '@' + Var('dart_browser_launcher_rev'), 'src/third_party/dart/third_party/pkg/cli_util': - Var('dart_git') + '/cli_util.git@32bc0779a604c1bde1bb0782789c99cac222e651', + Var('dart_git') + '/cli_util.git@fd38b5fb282a4f3d4f7c2acb1c1d4c0d62e000ae', 'src/third_party/dart/third_party/pkg/clock': Var('dart_git') + '/clock.git' + '@' + Var('dart_clock_rev'), @@ -328,76 +341,76 @@ deps = { Var('dart_git') + '/collection.git' + '@' + Var('dart_collection_rev'), 'src/third_party/dart/third_party/pkg/convert': - Var('dart_git') + '/convert.git@20d136c2fa4edc229fc3d7684bbeb8df5105580b', + Var('dart_git') + '/convert.git@83886e3fd895211a98e49b7595a92796fa216641', 'src/third_party/dart/third_party/pkg/crypto': - Var('dart_git') + '/crypto.git@f854f2fa730acb107aa41ebe431403081f7161e4', + Var('dart_git') + '/crypto.git@03eb2c9098069a7816bbace581dc2d6e196c63ca', 'src/third_party/dart/third_party/pkg/csslib': - Var('dart_git') + '/csslib.git@7054945b62bd83c4c7a0fab693fa73c3f137c202', + Var('dart_git') + '/csslib.git@f33d63211f77e2a895b90bcf22508ab7a0af4466', 'src/third_party/dart/third_party/pkg/dart_style': Var('dart_git') + '/dart_style.git@d0c6b1da52c9f80679a7aaa05e5935ef5c6bb52f', 'src/third_party/dart/third_party/pkg/dartdoc': - Var('dart_git') + '/dartdoc.git@ed56883d7b3c31aea3faa27232c3bffc2c97aaa4', + Var('dart_git') + '/dartdoc.git@494a6bed4992ea4ee1d831e6bcf20ab645da950b', 'src/third_party/dart/third_party/pkg/ffi': - Var('dart_git') + '/ffi.git@2a56c2a9a87122c057168874bde384debbb806b0', + Var('dart_git') + '/ffi.git@69d759613f9be3a897ce9a67910e9914694c96f3', 'src/third_party/dart/third_party/pkg/file': - Var('dart_git') + '/external/github.com/google/file.dart@b768f79dcd104a5feabafab47101c4355b71cd8f', + Var('dart_git') + '/external/github.com/google/file.dart@72a67c33f90bfb7e10057e286e06d2fe3baa4d98', 'src/third_party/dart/third_party/pkg/fixnum': - Var('dart_git') + '/fixnum.git@71f0d4d16054e6be7d8e22bdb3b082b9f82061be', + Var('dart_git') + '/fixnum.git@f8379d94436f3a73f71ea078f3207897c6700498', 'src/third_party/dart/third_party/pkg/glob': - Var('dart_git') + '/glob.git@4579281741e59e2e4ad02a197e0b1f4d6558dede', + Var('dart_git') + '/glob.git@a828420ece453a2b6560d261284b322e0cc863ac', 'src/third_party/dart/third_party/pkg/html': - Var('dart_git') + '/html.git@3dd00b0ca99e222697e6b6dc653774dc877da420', + Var('dart_git') + '/html.git@0b8025c16e1e5a5bcd451fb3a81cd98df218dcd4', 'src/third_party/dart/third_party/pkg/http': - Var('dart_git') + '/http.git@57c53b05e9f42546149f51348bc063bc7279283c', + Var('dart_git') + '/http.git@8386923d3b4c8bce2cc47a17196fbfb1d21de03d', 'src/third_party/dart/third_party/pkg/http_multi_server': - Var('dart_git') + '/http_multi_server.git@cce50802b66d33f703f82b3189988aa8e51976ac', + Var('dart_git') + '/http_multi_server.git@2cd53558a80fb0609532cdd4d3d65f2fa22448a8', 'src/third_party/dart/third_party/pkg/http_parser': - Var('dart_git') + '/http_parser.git@6f73e4a399df013ded8f4c81f151d122b36d361b', + Var('dart_git') + '/http_parser.git@1c0c17a1a5d9ca62c85f0940d9edbf2a98209bfa', 'src/third_party/dart/third_party/pkg/intl': - Var('dart_git') + '/intl.git@6140b600b3fd42d86e289f7d92c18488fe7e4bb9', + Var('dart_git') + '/intl.git@fca552f2ec5d682b5fa36f02bdd72a5a4e2edcee', 'src/third_party/dart/third_party/pkg/json_rpc_2': - Var('dart_git') + '/json_rpc_2.git@bd9f8d90ec9ce9d0da5c11f3e71b87af3aaca3b4', + Var('dart_git') + '/json_rpc_2.git@0280ac6cb4f3905d81c47ba927123ba2b95f7940', 'src/third_party/dart/third_party/pkg/linter': - Var('dart_git') + '/linter.git@8f7b75f8a3501ca2c4d5bbc1f003d90d66447544', + Var('dart_git') + '/linter.git@70fb087e39e6882ad331ee1e3f52f3f3a88e2d16', 'src/third_party/dart/third_party/pkg/logging': - Var('dart_git') + '/logging.git@34ed68fe23291c82bb685984e4e2ffc06860a4a8', + Var('dart_git') + '/logging.git@abef3717d958158eb8b0ddb2871f4b15a9804cd4', 'src/third_party/dart/third_party/pkg/markdown': - Var('dart_git') + '/markdown.git@ee3f4e976efcfed87c6ec78364bc2dd3c6e717b9', + Var('dart_git') + '/markdown.git@f51c24c5c5603ac20b6d88aded78ef3aa23619ac', 'src/third_party/dart/third_party/pkg/matcher': - Var('dart_git') + '/matcher.git@deedda179c33b00b3e06aa107ebfc3dd2f8a5f49', + Var('dart_git') + '/matcher.git@c1a07043de3da4968e1736fcde1c521802821859', 'src/third_party/dart/third_party/pkg/mime': - Var('dart_git') + '/mime.git@034471a60d5603a6988de6d9811bee1cb0657f70', + Var('dart_git') + '/mime.git@1a51be02b3cbc742c79d83575bd096ae8c295c1f', 'src/third_party/dart/third_party/pkg/mockito': - Var('dart_git') + '/mockito.git@9cc958a991dc6d6b563196893a77973eee58603c', + Var('dart_git') + '/mockito.git@d2a8df169706d1c1e5daaf0c96ee03b8238bd599', 'src/third_party/dart/third_party/pkg/package_config': - Var('dart_git') + '/package_config.git@2e1a8eca1ebeac01f45003642c25e24e63d45b50', + Var('dart_git') + '/package_config.git@74ac1cb90ad7f4f05bd92c952eaf9756c516fca3', 'src/third_party/dart/third_party/pkg/path': - Var('dart_git') + '/path.git@9768908ef81cf92fc77cb259c2cf01ca8725de88', + Var('dart_git') + '/path.git@a95f1e911dc9e2d407662c03edab0d550f2d1fa5', 'src/third_party/dart/third_party/pkg/pool': - Var('dart_git') + '/pool.git@ad4e2a7fde6a2937b2f7f59af271b437376d8e3d', + Var('dart_git') + '/pool.git@51f1131f707f81c5c9120bed5d290c8be83dc5d3', 'src/third_party/dart/third_party/pkg/protobuf': Var('dart_git') + '/protobuf.git' + '@' + Var('dart_protobuf_rev'), @@ -406,52 +419,52 @@ deps = { Var('dart_git') + '/pub.git' + '@' + Var('dart_pub_rev'), 'src/third_party/dart/third_party/pkg/pub_semver': - Var('dart_git') + '/pub_semver.git@3946e33446365aa6af84abc0b1f47ad3a6f3b490', + Var('dart_git') + '/pub_semver.git@e9c600c40986f6468b657a0ef967b32d668f4661', 'src/third_party/dart/third_party/pkg/shelf': - Var('dart_git') + '/shelf.git@a44e95e00324b6051bbee5ea235355f843795d1c', + Var('dart_git') + '/shelf.git@9d1fb8ac5db71885bf8621e3a58cd5dd93ab6f02', 'src/third_party/dart/third_party/pkg/source_map_stack_trace': - Var('dart_git') + '/source_map_stack_trace.git@adea3e51269f355514b59b66a4fcecabd1fa6e95', + Var('dart_git') + '/source_map_stack_trace.git@a60ef54b36147b103d8b7d0317d6b578ebf874cc', 'src/third_party/dart/third_party/pkg/source_maps': - Var('dart_git') + '/source_maps.git@d995912983f4f4c33a040c629952fb4632aeea70', + Var('dart_git') + '/source_maps.git@5f67212c86f34082aee7c278455d228b670c339c', 'src/third_party/dart/third_party/pkg/source_span': - Var('dart_git') + '/source_span.git@72d5c55e455c3940c37fe768730f5922e7a1f309', + Var('dart_git') + '/source_span.git@3951ba50ec29b9870c3131c6ddcc88700d26f3ee', 'src/third_party/dart/third_party/pkg/sse': - Var('dart_git') + '/sse.git@be426a2467108d88354dc36a44493d2d17019993', + Var('dart_git') + '/sse.git@8c03b73f90d951f5b33dd496593718107c79f97a', 'src/third_party/dart/third_party/pkg/stack_trace': - Var('dart_git') + '/stack_trace.git@c08ee90b83380381a893d1e77a9a533d632f40e0', + Var('dart_git') + '/stack_trace.git@6ceb191ace71c18ccf5648f6b2e8be52da39c56f', 'src/third_party/dart/third_party/pkg/stream_channel': - Var('dart_git') + '/stream_channel.git@3b9926876dc06970b583c34d0cb359ef976c4350', + Var('dart_git') + '/stream_channel.git@0850515bb74ca3a40fd5c19ef0dd3a63834d21cf', 'src/third_party/dart/third_party/pkg/string_scanner': - Var('dart_git') + '/string_scanner.git@045498024df8f0a1cd0f717f12d60aec77d3d8ae', + Var('dart_git') + '/string_scanner.git@29e471ea98762db8052cca0e6a69ef9c7999abed', 'src/third_party/dart/third_party/pkg/term_glyph': - Var('dart_git') + '/term_glyph.git@8cd931827bc3bfc1c62fd7ea44cbbc99b8a94f4d', + Var('dart_git') + '/term_glyph.git@520784dffff95d769c0cbe612471855f0417a7d2', 'src/third_party/dart/third_party/pkg/test': - Var('dart_git') + '/test.git@19582a8d45670a53fa4fca8d06a3746d1616d46e', + Var('dart_git') + '/test.git@da7c667126121e5b12a2232a28113225f9e1f893', 'src/third_party/dart/third_party/pkg/test_reflective_loader': - Var('dart_git') + '/test_reflective_loader.git@cf58259b91c4d3cccc90abd4c0b44273e6421646', + Var('dart_git') + '/test_reflective_loader.git@c4c2d5c3f94a96f3fc79e9e28944fba391bc544c', 'src/third_party/dart/third_party/pkg/typed_data': - Var('dart_git') + '/typed_data.git@9c209b9c99ca7528a45c23d5d09579788b3ea81b', + Var('dart_git') + '/typed_data.git@6fbbd95bd32db331e0c3ba92537d4089b633a2b7', 'src/third_party/dart/third_party/pkg/usage': - Var('dart_git') + '/usage.git@2773c7d334db9a902582feb8c5f38899c83d7b54', + Var('dart_git') + '/usage.git@399770f45ed2d384d79395c0341a04fb25609a4d', 'src/third_party/dart/third_party/pkg/watcher': Var('dart_git') + '/watcher.git' + '@' + Var('dart_watcher_rev'), 'src/third_party/dart/third_party/pkg/web_socket_channel': - Var('dart_git') + '/web_socket_channel.git@28d7b82986cf931e6d977d973a7849cfc7c0bab9', + Var('dart_git') + '/web_socket_channel.git@e2fe7f665997ab8e28aa76a8b26483f9903221a8', 'src/third_party/dart/third_party/pkg/webdev': Var('dart_git') + '/webdev.git' + '@' + Var('dart_webdev_rev'), @@ -460,13 +473,13 @@ deps = { Var('dart_git') + '/external/github.com/google/webkit_inspection_protocol.dart.git' + '@' + Var('dart_webkit_inspection_protocol_rev'), 'src/third_party/dart/third_party/pkg/yaml': - Var('dart_git') + '/yaml.git@b2fce6cb8f07f091967b849d5434ed495cbb305f', + Var('dart_git') + '/yaml.git@a6d8781744d34c391368664b4c1e174f0433bbb6', 'src/third_party/dart/third_party/pkg/yaml_edit': Var('dart_git') + '/yaml_edit.git' + '@' + Var('dart_yaml_edit_rev'), 'src/third_party/dart/tools/sdks': - {'packages': [{'version': 'version:2.19.0-374.0.dev', 'package': 'dart/dart-sdk/${{platform}}'}], 'dep_type': 'cipd'}, + {'packages': [{'version': 'version:3.0.0-187.0.dev', 'package': 'dart/dart-sdk/${{platform}}'}], 'dep_type': 'cipd'}, # WARNING: end of dart dependencies list that is cleaned up automatically - see create_updated_flutter_deps.py. @@ -741,7 +754,7 @@ deps = { 'packages': [ { 'package': 'infra/3pp/tools/ninja/${{platform}}', - 'version': 'version:2@1.8.2.chromium.3', + 'version': 'version:2@1.11.1.chromium.4', } ], 'dep_type': 'cipd', @@ -816,7 +829,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': '_H53AyDxR9Pm2TbwNGuozNh9lNZ1xW-yT2_4RuHy3PAC' + 'version': 's0lx1q5xbqV1jkRZMLTA0YcPN6HUJPY1c0Wevv-ViLMC' } ], 'condition': 'host_os == "mac" and not download_fuchsia_sdk', @@ -826,7 +839,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'pGX7tanT1okL8XCg-uOPtKPzEwpxK3W3lhrFYrE77zcC' + 'version': 'cn89DIQTewbdhBTO-CRjAdS8yoSkKFm4rC6f1994hdkC' } ], 'condition': 'host_os == "linux" and not download_fuchsia_sdk', diff --git a/README.md b/README.md index 0f2caad12a804..fad82d833db89 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Flutter Engine ============== -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/flutter/engine/badge)](https://api.securityscorecards.dev/projects/github.com/flutter/engine) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/flutter/engine/badge)](https://deps.dev/project/github/flutter%2Fengine) Flutter is Google's SDK for crafting beautiful, fast user experiences for mobile, web, and desktop from a single codebase. Flutter works with existing diff --git a/build/archives/BUILD.gn b/build/archives/BUILD.gn index 023cafdffee65..49097396468f1 100644 --- a/build/archives/BUILD.gn +++ b/build/archives/BUILD.gn @@ -229,6 +229,7 @@ if (host_os == "win") { zip_bundle("windows_flutter") { output = "$full_target_platform_name-$flutter_runtime_mode/$full_target_platform_name-flutter.zip" deps = [ + "//flutter:gen_snapshot", "//flutter/shell/platform/common:publish_headers", "//flutter/shell/platform/windows:flutter_windows", "//flutter/shell/platform/windows:publish_headers_windows", @@ -258,6 +259,22 @@ if (host_os == "win") { source = "$root_out_dir/flutter_windows.dll" destination = "flutter_windows.dll" }, + { + source = "$root_out_dir/flutter_windows.dll.exp" + destination = "flutter_windows.dll.exp" + }, + { + source = "$root_out_dir/flutter_windows.dll.lib" + destination = "flutter_windows.dll.lib" + }, + { + source = "$root_out_dir/flutter_windows.dll.pdb" + destination = "flutter_windows.dll.pdb" + }, + { + source = "$root_out_dir/gen_snapshot/gen_snapshot.exe" + destination = "gen_snapshot.exe" + }, ] } } diff --git a/ci/builders/linux_android_debug_engine.json b/ci/builders/linux_android_debug_engine.json index e004a47b6822f..07be90ab6c690 100644 --- a/ci/builders/linux_android_debug_engine.json +++ b/ci/builders/linux_android_debug_engine.json @@ -33,7 +33,7 @@ }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for android_jit_release_x86", "parameters": [ "--variant", @@ -115,7 +115,7 @@ }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for android_debug", "parameters": [ "--variant", diff --git a/ci/builders/linux_arm_host_engine.json b/ci/builders/linux_arm_host_engine.json index 46cf1bd06d8fa..3b4d5cda6091a 100644 --- a/ci/builders/linux_arm_host_engine.json +++ b/ci/builders/linux_arm_host_engine.json @@ -59,7 +59,6 @@ "gn": [ "--runtime-mode", "debug", - "--full-dart-sdk", "--target-os=linux", "--linux-cpu=arm64", "--prebuilt-dart-sdk" diff --git a/ci/builders/linux_host_engine.json b/ci/builders/linux_host_engine.json index ab15c65433336..957b79f1759e8 100644 --- a/ci/builders/linux_host_engine.json +++ b/ci/builders/linux_host_engine.json @@ -52,7 +52,7 @@ }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for host_debug_impeller_vulkan", "parameters": [ "--variant", @@ -78,7 +78,6 @@ "out/host_debug/zip_archives/linux-x64/font-subset.zip", "out/host_debug/zip_archives/flutter_patched_sdk.zip", "out/host_debug/zip_archives/dart-sdk-linux-x64.zip", - "out/host_debug/zip_archives/flutter-web-sdk-linux-x64.zip", "out/host_debug/zip_archives/linux-x64/linux-x64-flutter-gtk.zip" ] } @@ -93,7 +92,6 @@ "gn": [ "--runtime-mode", "debug", - "--full-dart-sdk", "--prebuilt-dart-sdk", "--build-embedder-examples" ], @@ -105,7 +103,6 @@ "flutter/build/archives:embedder", "flutter/build/archives:flutter_patched_sdk", "flutter/build/archives:dart_sdk_archive", - "flutter/web_sdk", "flutter/tools/font-subset", "flutter/shell/platform/linux:flutter_gtk" ] @@ -147,7 +144,7 @@ }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for host_profile", "parameters": [ "--variant", @@ -197,7 +194,7 @@ }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for host_release", "parameters": [ "--variant", diff --git a/ci/builders/mac_host_engine.json b/ci/builders/mac_host_engine.json index 834563eeb142a..a5957064929d0 100644 --- a/ci/builders/mac_host_engine.json +++ b/ci/builders/mac_host_engine.json @@ -8,8 +8,7 @@ "include_paths": [ "out/host_debug/zip_archives/darwin-x64/artifacts.zip", "out/host_debug/zip_archives/darwin-x64/FlutterEmbedder.framework.zip", - "out/host_debug/zip_archives/dart-sdk-darwin-x64.zip", - "out/host_debug/zip_archives/flutter-web-sdk-darwin-x64.zip" + "out/host_debug/zip_archives/dart-sdk-darwin-x64.zip" ], "name": "host_debug" } @@ -26,7 +25,6 @@ "--runtime-mode", "debug", "--no-lto", - "--full-dart-sdk", "--prebuilt-dart-sdk", "--build-embedder-examples" ], @@ -37,7 +35,6 @@ "flutter/shell/platform/darwin/macos:zip_macos_flutter_framework", "flutter/build/archives:artifacts", "flutter/build/archives:dart_sdk_archive", - "flutter/web_sdk", "flutter/build/archives:archive_gen_snapshot", "flutter/build/archives:flutter_embedder_framework" ] @@ -82,7 +79,7 @@ }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for host_profile", "parameters": [ "--variant", @@ -162,7 +159,6 @@ "--runtime-mode", "debug", "--no-lto", - "--full-dart-sdk", "--prebuilt-dart-sdk" ], "name": "mac_debug_arm64", diff --git a/ci/builders/mac_ios_engine.json b/ci/builders/mac_ios_engine.json index 68fc73f63ba68..9ae1f41b812bb 100644 --- a/ci/builders/mac_ios_engine.json +++ b/ci/builders/mac_ios_engine.json @@ -87,7 +87,7 @@ "out/ios_debug_sim_arm64" ], "script": "flutter/sky/tools/create_full_ios_framework.py", - "language": "python" + "language": "python3" }, { "name": "obj-c-doc", diff --git a/ci/builders/mac_ios_engine_profile.json b/ci/builders/mac_ios_engine_profile.json index ee762339ded0b..2d9891355a021 100644 --- a/ci/builders/mac_ios_engine_profile.json +++ b/ci/builders/mac_ios_engine_profile.json @@ -83,7 +83,7 @@ "out/ios_debug_sim_arm64" ], "script": "flutter/sky/tools/create_full_ios_framework.py", - "language": "python" + "language": "python3" } ] }, diff --git a/ci/builders/mac_ios_engine_release.json b/ci/builders/mac_ios_engine_release.json index 269dd67d0e8cb..2de17631cf171 100644 --- a/ci/builders/mac_ios_engine_release.json +++ b/ci/builders/mac_ios_engine_release.json @@ -85,7 +85,7 @@ "--strip" ], "script": "flutter/sky/tools/create_full_ios_framework.py", - "language": "python" + "language": "python3" }, { "name": "release-nobitcode-FlutterMacOS.framework", @@ -102,7 +102,7 @@ "--strip" ], "script": "flutter/sky/tools/create_full_ios_framework.py", - "language": "python" + "language": "python3" }, { "name": "Release-macos-gen-snapshots", @@ -113,7 +113,7 @@ "out/ios_release" ], "script": "flutter/sky/tools/create_macos_gen_snapshots.py", - "language": "python" + "language": "python3" } ] }, diff --git a/ci/builders/web_engine.json b/ci/builders/web_engine.json index 1aa3d7331fd27..1ce92ddf05c47 100644 --- a/ci/builders/web_engine.json +++ b/ci/builders/web_engine.json @@ -1,102 +1,41 @@ { - "builds": [ - { - "archives": [], - "drone_dimensions": [ - "device_type=none", - "os=Windows-10" - ], - "gn": [ - "--runtime-mode", - "debug", - "--unoptimized", - "--full-dart-sdk", - "--prebuilt-dart-sdk" - ], - "name": "windows_host_debug", - "ninja": { - "config": "host_debug_unopt", - "targets": [] - }, - "platform": "Windows", - "tests": [] - }, - { - "archives": [], - "drone_dimensions": [ - "device_type=none", - "os=Linux" - ], - "generators": { - "pub_dirs": [ - "flutter/lib/web_ui/", - "flutter/web_sdk/web_engine_tester/" + "generators": { + "pub_dirs": [ + "flutter/lib/web_ui/", + "flutter/web_sdk/web_engine_tester/" + ], + "tasks": [ + { + "name": "compile web_tests", + "parameters": [ + "run", + "compile_tests" ], - "tasks": [ - { - "name": "compile web_tests", - "parameters": [ - "run", - "compile_tests" - ], - "scripts": [ - "out/host_debug_unopt/dart-sdk/bin/dart", - "flutter/lib/web_ui/dev/felt.dart" - ] - }, - { - "name": "check licenses", - "parameters": [ - "check-licenses" - ], - "scripts": [ - "out/host_debug_unopt/dart-sdk/bin/dart", - "flutter/lib/web_ui/dev/felt.dart" - ] - }, - { - "name": "web engine analysis", - "parameters": [], - "scripts": [ - "flutter/lib/web_ui/dev/web_engine_analysis.sh" - ] - } + "scripts": [ + "out/host_debug_unopt/dart-sdk/bin/dart", + "flutter/lib/web_ui/dev/felt.dart" ] }, - "gn": [ - "--runtime-mode", - "debug", - "--unoptimized", - "--full-dart-sdk" - ], - "name": "linux_host_debug_unopt", - "ninja": { - "config": "host_debug_unopt", - "targets": [] - }, - "platform": "Linux", - "tests": [] - }, - { - "archives": [], - "drone_dimensions": [ - "device_type=none", - "os=Mac" - ], - "gn": [ - "--runtime-mode", - "debug", - "--unoptimized", - "--full-dart-sdk", - "--prebuilt-dart-sdk" - ], - "name": "mac_host_debug_unopt", - "ninja": { - "config": "host_debug_unopt", - "targets": [] + { + "name": "check licenses", + "parameters": [ + "check-licenses" + ], + "scripts": [ + "out/host_debug_unopt/dart-sdk/bin/dart", + "flutter/lib/web_ui/dev/felt.dart" + ] }, - "platform": "Mac", - "tests": [] - } - ] + { + "name": "web engine analysis", + "parameters": [ + "analyze" + ], + "scripts": [ + "out/host_debug_unopt/dart-sdk/bin/dart", + "flutter/lib/web_ui/dev/felt.dart" + ] + } + ] + } } diff --git a/ci/builders/windows_arm_host_engine.json b/ci/builders/windows_arm_host_engine.json index a0c20004f0671..dfa170b3632d1 100644 --- a/ci/builders/windows_arm_host_engine.json +++ b/ci/builders/windows_arm_host_engine.json @@ -11,8 +11,7 @@ "out/host_debug_arm64/zip_archives/windows-arm64/font-subset.zip", "out/host_debug_arm64/zip_archives/dart-sdk-windows-arm64.zip", "out/host_debug_arm64/zip_archives/windows-arm64-debug/windows-arm64-flutter.zip", - "out/host_debug_arm64/zip_archives/windows-arm64/flutter-cpp-client-wrapper.zip", - "out/host_debug_arm64/zip_archives/flutter-web-sdk-windows-arm64.zip" + "out/host_debug_arm64/zip_archives/windows-arm64/flutter-cpp-client-wrapper.zip" ], "name": "host_debug_arm64" } @@ -27,7 +26,6 @@ "gn": [ "--runtime-mode", "debug", - "--full-dart-sdk", "--no-lto", "--windows-cpu", "arm64" @@ -41,8 +39,7 @@ "flutter/tools/font-subset", "flutter/build/archives:dart_sdk_archive", "flutter/shell/platform/windows/client_wrapper:client_wrapper_archive", - "flutter/build/archives:windows_flutter", - "flutter/web_sdk" + "flutter/build/archives:windows_flutter" ] }, "tests": [] diff --git a/ci/builders/windows_host_engine.json b/ci/builders/windows_host_engine.json index a22943aae63db..ad48a3e6433ff 100644 --- a/ci/builders/windows_host_engine.json +++ b/ci/builders/windows_host_engine.json @@ -11,8 +11,7 @@ "out/host_debug/zip_archives/windows-x64/font-subset.zip", "out/host_debug/zip_archives/dart-sdk-windows-x64.zip", "out/host_debug/zip_archives/windows-x64-debug/windows-x64-flutter.zip", - "out/host_debug/zip_archives/windows-x64/flutter-cpp-client-wrapper.zip", - "out/host_debug/zip_archives/flutter-web-sdk-windows-x64.zip" + "out/host_debug/zip_archives/windows-x64/flutter-cpp-client-wrapper.zip" ], "name": "host_debug" } @@ -27,7 +26,6 @@ "gn": [ "--runtime-mode", "debug", - "--full-dart-sdk", "--no-lto" ], "name": "host_debug", @@ -40,13 +38,12 @@ "flutter/tools/font-subset", "flutter/build/archives:dart_sdk_archive", "flutter/shell/platform/windows/client_wrapper:client_wrapper_archive", - "flutter/build/archives:windows_flutter", - "flutter/web_sdk" + "flutter/build/archives:windows_flutter" ] }, "tests": [ { - "language": "python", + "language": "python3", "name": "Host Tests for host_debug", "parameters": [ "--variant", diff --git a/ci/compatibility_helper.py b/ci/compatibility_helper.py new file mode 100644 index 0000000000000..0d8231ca178e7 --- /dev/null +++ b/ci/compatibility_helper.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This script contains helper function(s) for supporting both +# python 2 and python 3 infrastructure code. + +ENCODING = 'UTF-8' + + +def byte_str_decode(str_or_bytes): + """Returns a string if given either a string or bytes. + + TODO: This function should be removed when the supported python + version is only python 3. + + Args: + str_or_bytes (string or bytes) we want to convert or return as + the possible value changes depending on the version of python + used. + """ + return str_or_bytes if isinstance(str_or_bytes, + str) else str_or_bytes.decode(ENCODING) diff --git a/ci/firebase_testlab.py b/ci/firebase_testlab.py index 92069a7c1f584..510f582e8b82d 100755 --- a/ci/firebase_testlab.py +++ b/ci/firebase_testlab.py @@ -10,6 +10,7 @@ import os import subprocess import sys +from compatibility_helper import byte_str_decode if 'STORAGE_BUCKET' not in os.environ: print('The GCP storage bucket must be provided as an environment variable.') @@ -67,6 +68,7 @@ def check_logcat(results_dir): 'gsutil', 'cat', '%s/%s/*/logcat' % (BUCKET, results_dir) ]) + logcat = byte_str_decode(logcat) if not logcat: sys.exit(1) @@ -82,7 +84,9 @@ def check_timeline(results_dir): 'gsutil', 'du', '%s/%s/*/game_loop_results/results_scenario_0.json' % (BUCKET, results_dir) - ]).strip() + ]) + gsutil_du = byte_str_decode(gsutil_du) + gsutil_du = gsutil_du.strip() if gsutil_du == '0': print('Failed to produce a timeline.') sys.exit(1) @@ -113,8 +117,9 @@ def main(): return 1 git_revision = subprocess.check_output(['git', 'rev-parse', 'HEAD'], - cwd=script_dir).strip() - + cwd=script_dir) + git_revision = byte_str_decode(git_revision) + git_revision = git_revision.strip() results = [] apk = None for apk in apks: diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index a58886dbd6c41..d800da415d156 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -587,6 +587,7 @@ ../../../fuchsia/sdk/linux/fidl/fuchsia.web/meta.json ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.common/meta.json ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.ieee80211/meta.json +../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.phyimpl/meta.json ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.policy/meta.json ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.product.deprecatedclient/meta.json ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.product.deprecatedconfiguration/meta.json @@ -601,6 +602,7 @@ ../../../fuchsia/sdk/linux/pkg/async-loop/meta.json ../../../fuchsia/sdk/linux/pkg/async-testing/meta.json ../../../fuchsia/sdk/linux/pkg/async/meta.json +../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/meta.json ../../../fuchsia/sdk/linux/pkg/fdio/meta.json ../../../fuchsia/sdk/linux/pkg/fidl/meta.json ../../../fuchsia/sdk/linux/pkg/fidl_base/meta.json @@ -1593,6 +1595,7 @@ ../../../third_party/dart/runtime/vm/compiler/backend/inliner_test.cc ../../../third_party/dart/runtime/vm/compiler/backend/locations_helpers_test.cc ../../../third_party/dart/runtime/vm/compiler/backend/loops_test.cc +../../../third_party/dart/runtime/vm/compiler/backend/memory_copy_test.cc ../../../third_party/dart/runtime/vm/compiler/backend/range_analysis_test.cc ../../../third_party/dart/runtime/vm/compiler/backend/reachability_fence_test.cc ../../../third_party/dart/runtime/vm/compiler/backend/redundancy_elimination_test.cc @@ -1728,6 +1731,7 @@ ../../../third_party/dart/third_party/firefox_jsshell ../../../third_party/dart/third_party/mdn/browser-compat-data/README.google ../../../third_party/dart/third_party/pkg +../../../third_party/dart/third_party/protobuf/src/test ../../../third_party/dart/third_party/requirejs ../../../third_party/dart/third_party/tcmalloc/.gitignore ../../../third_party/dart/third_party/tcmalloc/OWNERS @@ -2340,6 +2344,126 @@ ../../../third_party/libwebp/webp_js ../../../third_party/libxml ../../../third_party/ocmock +../../../third_party/perfetto/.clang-format +../../../third_party/perfetto/.clang-tidy +../../../third_party/perfetto/.git +../../../third_party/perfetto/.gitattributes +../../../third_party/perfetto/.github +../../../third_party/perfetto/.gitignore +../../../third_party/perfetto/.gn +../../../third_party/perfetto/.style.yapf +../../../third_party/perfetto/CHANGELOG +../../../third_party/perfetto/DIR_METADATA +../../../third_party/perfetto/METADATA +../../../third_party/perfetto/OWNERS +../../../third_party/perfetto/PRESUBMIT.py +../../../third_party/perfetto/README.chromium +../../../third_party/perfetto/README.md +../../../third_party/perfetto/WORKSPACE +../../../third_party/perfetto/bazel/deps.bzl +../../../third_party/perfetto/bazel/proto_gen.bzl +../../../third_party/perfetto/bazel/rules.bzl +../../../third_party/perfetto/bazel/standalone/README.md +../../../third_party/perfetto/bazel/standalone/perfetto_cfg.bzl +../../../third_party/perfetto/buildtools/.gitignore +../../../third_party/perfetto/buildtools/README.md +../../../third_party/perfetto/codereview.settings +../../../third_party/perfetto/debian +../../../third_party/perfetto/docs/.gitignore +../../../third_party/perfetto/docs/README.md +../../../third_party/perfetto/examples +../../../third_party/perfetto/gn/standalone/build_tool_wrapper.py +../../../third_party/perfetto/gn/standalone/cp.py +../../../third_party/perfetto/gn/standalone/protoc.py +../../../third_party/perfetto/gn/standalone/toolchain/linux_find_llvm.py +../../../third_party/perfetto/gn/standalone/toolchain/llvm-strip.py +../../../third_party/perfetto/gn/standalone/toolchain/mac_find_llvm.py +../../../third_party/perfetto/gn/standalone/toolchain/win_find_msvc.py +../../../third_party/perfetto/gn/write_buildflag_header.py +../../../third_party/perfetto/include/README.md +../../../third_party/perfetto/include/perfetto/README.md +../../../third_party/perfetto/include/perfetto/profiling/OWNERS +../../../third_party/perfetto/include/perfetto/test +../../../third_party/perfetto/include/perfetto/trace_processor/OWNERS +../../../third_party/perfetto/include/perfetto/tracing/OWNERS +../../../third_party/perfetto/infra +../../../third_party/perfetto/meson.build +../../../third_party/perfetto/protos +../../../third_party/perfetto/python/README.md +../../../third_party/perfetto/python/example.py +../../../third_party/perfetto/python/perfetto/__init__.py +../../../third_party/perfetto/python/perfetto/batch_trace_processor/__init__.py +../../../third_party/perfetto/python/perfetto/batch_trace_processor/api.py +../../../third_party/perfetto/python/perfetto/batch_trace_processor/platform.py +../../../third_party/perfetto/python/perfetto/common/repo_utils.py +../../../third_party/perfetto/python/perfetto/experimental/slice_breakdown/__init__.py +../../../third_party/perfetto/python/perfetto/experimental/slice_breakdown/breakdown.py +../../../third_party/perfetto/python/perfetto/prebuilts/manifests/trace_processor_shell.py +../../../third_party/perfetto/python/perfetto/prebuilts/manifests/tracebox.py +../../../third_party/perfetto/python/perfetto/prebuilts/manifests/traceconv.py +../../../third_party/perfetto/python/perfetto/prebuilts/perfetto_prebuilts.py +../../../third_party/perfetto/python/perfetto/trace_processor +../../../third_party/perfetto/python/perfetto/trace_uri_resolver/path.py +../../../third_party/perfetto/python/perfetto/trace_uri_resolver/registry.py +../../../third_party/perfetto/python/perfetto/trace_uri_resolver/resolver.py +../../../third_party/perfetto/python/perfetto/trace_uri_resolver/util.py +../../../third_party/perfetto/python/run_tests.py +../../../third_party/perfetto/python/setup.py +../../../third_party/perfetto/python/test +../../../third_party/perfetto/python/tools/batch_trace_processor_shell.py +../../../third_party/perfetto/python/tools/cpu_profile.py +../../../third_party/perfetto/python/tools/heap_profile.py +../../../third_party/perfetto/python/tools/record_android_trace.py +../../../third_party/perfetto/python/tools/slice_breakdown.py +../../../third_party/perfetto/python/tools/trace_processor.py +../../../third_party/perfetto/python/tools/tracebox.py +../../../third_party/perfetto/python/tools/traceconv.py +../../../third_party/perfetto/src/android_internal/README.md +../../../third_party/perfetto/src/base/test +../../../third_party/perfetto/src/ipc +../../../third_party/perfetto/src/profiling/OWNERS +../../../third_party/perfetto/src/profiling/memory +../../../third_party/perfetto/src/protozero/test +../../../third_party/perfetto/src/tools +../../../third_party/perfetto/src/trace_processor +../../../third_party/perfetto/src/traced +../../../third_party/perfetto/src/tracing +../../../third_party/perfetto/test +../../../third_party/perfetto/tools/add_tp_diff_test.py +../../../third_party/perfetto/tools/analyze_profiling_sampling_distribution.py +../../../third_party/perfetto/tools/check_sql_metrics.py +../../../third_party/perfetto/tools/compat.py +../../../third_party/perfetto/tools/diff_test_trace_processor.py +../../../third_party/perfetto/tools/download_changed_screenshots.py +../../../third_party/perfetto/tools/export_power_profiles.py +../../../third_party/perfetto/tools/find_scan_roots.py +../../../third_party/perfetto/tools/gen_amalgamated_sql.py +../../../third_party/perfetto/tools/gen_cc_proto_descriptor.py +../../../third_party/perfetto/tools/gn_utils.py +../../../third_party/perfetto/tools/measure_tp_performance.py +../../../third_party/perfetto/tools/print_descriptor.py +../../../third_party/perfetto/tools/proto_utils.py +../../../third_party/perfetto/tools/protoc_helper.py +../../../third_party/perfetto/tools/pull_ftrace_format_files.py +../../../third_party/perfetto/tools/run_buildtools_binary.py +../../../third_party/perfetto/tools/serialize_test_trace.py +../../../third_party/perfetto/tools/setup_all_configs.py +../../../third_party/perfetto/tools/test_gen_amalgamated.py +../../../third_party/perfetto/tools/touch_file.py +../../../third_party/perfetto/tools/write_version_header.py +../../../third_party/perfetto/ui/.clang-format +../../../third_party/perfetto/ui/.eslintrc.js +../../../third_party/perfetto/ui/.gitignore +../../../third_party/perfetto/ui/OWNERS +../../../third_party/perfetto/ui/PRESUBMIT.py +../../../third_party/perfetto/ui/README.md +../../../third_party/perfetto/ui/config/.gitignore +../../../third_party/perfetto/ui/package.json +../../../third_party/perfetto/ui/release/OWNERS +../../../third_party/perfetto/ui/release/build_all_channels.py +../../../third_party/perfetto/ui/src/assets/.gitignore +../../../third_party/perfetto/ui/src/base/utils/package.json +../../../third_party/perfetto/ui/src/test ../../../third_party/pkg/archive ../../../third_party/pkg/equatable ../../../third_party/pkg/file @@ -2351,6 +2475,7 @@ ../../../third_party/pkg/process_runner ../../../third_party/pkg/quiver ../../../third_party/pkg/vector_math +../../../third_party/protobuf ../../../third_party/pyyaml ../../../third_party/rapidjson/.git ../../../third_party/rapidjson/.gitattributes diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 19fcdcfa36442..5df8365e518f4 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -714,9 +714,11 @@ SOFTWARE. ==================================================================================================== LIBRARY: spring_animation -ORIGIN: ../../../flutter/third_party/spring_animation/Libraries/Animated/animations/SpringAnimation.js + ../../../flutter/third_party/spring_animation/LICENSE +ORIGIN: ../../../flutter/third_party/spring_animation/spring_animation.h + ../../../flutter/third_party/spring_animation/LICENSE +ORIGIN: ../../../flutter/third_party/spring_animation/spring_animation.mm + ../../../flutter/third_party/spring_animation/LICENSE TYPE: LicenseType.mit -FILE: ../../../flutter/third_party/spring_animation/Libraries/Animated/animations/SpringAnimation.js +FILE: ../../../flutter/third_party/spring_animation/spring_animation.h +FILE: ../../../flutter/third_party/spring_animation/spring_animation.mm ---------------------------------------------------------------------------------------------------- Copyright (c) Meta Platforms, Inc. and affiliates. @@ -791,6 +793,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: accessibility LIBRARY: engine +LIBRARY: spring_animation LIBRARY: tonic LIBRARY: txt LIBRARY: web_unicode @@ -1223,6 +1226,8 @@ ORIGIN: ../../../flutter/impeller/compiler/switches.cc + ../../../flutter/LICENS ORIGIN: ../../../flutter/impeller/compiler/switches.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/compiler/types.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/compiler/types.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/compiler/uniform_sorter.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/compiler/uniform_sorter.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/compiler/utilities.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/compiler/utilities.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/display_list/display_list_dispatcher.cc + ../../../flutter/LICENSE @@ -1337,7 +1342,9 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/border_mask_blur.vert + ../../. ORIGIN: ../../../flutter/impeller/entity/shaders/color_matrix_color_filter.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/color_matrix_color_filter.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur.frag + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur.glsl + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur.vert + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur_decal.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas_sdf.frag + ../../../flutter/LICENSE @@ -1499,6 +1506,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc + ../../../flutter/LICENSE @@ -1507,6 +1516,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc + ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.cc + ../../../flutter/LICENSE @@ -2506,6 +2517,8 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterChann ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponderTest.mm + ../../../flutter/LICENSE @@ -2526,8 +2539,6 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySe ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManagerTest.mm + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h + ../../../flutter/LICENSE @@ -3164,6 +3175,7 @@ ORIGIN: ../../../flutter/third_party/accessibility/base/string_utils.cc + ../../ ORIGIN: ../../../flutter/third_party/accessibility/base/string_utils.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/accessibility/gfx/transform.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/accessibility/gfx/transform.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/third_party/spring_animation/SpringAnimationTest.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/third_party/tonic/common/build_config.h + ../../../flutter/third_party/tonic/LICENSE ORIGIN: ../../../flutter/third_party/tonic/common/log.cc + ../../../flutter/third_party/tonic/LICENSE ORIGIN: ../../../flutter/third_party/tonic/common/log.h + ../../../flutter/third_party/tonic/LICENSE @@ -3699,6 +3711,8 @@ FILE: ../../../flutter/impeller/compiler/switches.cc FILE: ../../../flutter/impeller/compiler/switches.h FILE: ../../../flutter/impeller/compiler/types.cc FILE: ../../../flutter/impeller/compiler/types.h +FILE: ../../../flutter/impeller/compiler/uniform_sorter.cc +FILE: ../../../flutter/impeller/compiler/uniform_sorter.h FILE: ../../../flutter/impeller/compiler/utilities.cc FILE: ../../../flutter/impeller/compiler/utilities.h FILE: ../../../flutter/impeller/display_list/display_list_dispatcher.cc @@ -3813,7 +3827,9 @@ FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.vert FILE: ../../../flutter/impeller/entity/shaders/color_matrix_color_filter.frag FILE: ../../../flutter/impeller/entity/shaders/color_matrix_color_filter.vert FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.frag +FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.glsl FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur.vert +FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur_decal.frag FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas_sdf.frag @@ -3975,6 +3991,8 @@ FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -3983,6 +4001,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h +FILE: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.cc +FILE: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h FILE: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.cc @@ -4166,6 +4186,7 @@ FILE: ../../../flutter/impeller/toolkit/egl/egl.cc FILE: ../../../flutter/impeller/toolkit/egl/egl.h FILE: ../../../flutter/impeller/toolkit/egl/surface.cc FILE: ../../../flutter/impeller/toolkit/egl/surface.h +FILE: ../../../flutter/impeller/tools/malioc.json FILE: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.cc FILE: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.h FILE: ../../../flutter/impeller/typographer/backends/skia/text_render_context_skia.cc @@ -4992,6 +5013,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterChannel FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponderTest.mm @@ -5012,8 +5035,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySeco FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManagerTest.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h @@ -5668,6 +5689,7 @@ FILE: ../../../flutter/third_party/accessibility/base/string_utils.cc FILE: ../../../flutter/third_party/accessibility/base/string_utils.h FILE: ../../../flutter/third_party/accessibility/gfx/transform.cc FILE: ../../../flutter/third_party/accessibility/gfx/transform.h +FILE: ../../../flutter/third_party/spring_animation/SpringAnimationTest.mm FILE: ../../../flutter/third_party/tonic/common/build_config.h FILE: ../../../flutter/third_party/tonic/common/log.cc FILE: ../../../flutter/third_party/tonic/common/log.h diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index 92e64d040ea98..e819bea39de40 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: 649516db81c9de640c9c778a9b426cd9 +Signature: 9eb7a378a04930dc6b8e3d4ae85c42a9 ==================================================================================================== LIBRARY: fuchsia_sdk @@ -2877,7 +2877,6 @@ ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/device.dart + ../../../fuch ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/diagnostics.dart + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/feedback_data_provider.dart + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/proxy.dart + ../../../fuchsia/sdk/linux/LICENSE -ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/tiles.dart + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/time.dart + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/trace_processing/metrics/gpu_metrics.dart + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/trace_processing/metrics/total_trace_wall_time.dart + ../../../fuchsia/sdk/linux/LICENSE @@ -3043,7 +3042,6 @@ FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/device.dart FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/diagnostics.dart FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/feedback_data_provider.dart FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/proxy.dart -FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/tiles.dart FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/time.dart FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/trace_processing/metrics/gpu_metrics.dart FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/trace_processing/metrics/total_trace_wall_time.dart @@ -3683,11 +3681,13 @@ ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.common/driver_features.fidl ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.common/overview.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.ieee80211/fields.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.ieee80211/overview.fidl + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.phyimpl/phyimpl.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.policy/overview.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/zx/overview.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/pkg/async-cpp/include/lib/async/cpp/sequence_checker.h + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/pkg/async-cpp/sequence_checker.cc + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/pkg/async/include/lib/async/sequence_id.h + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/constants.h + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/pkg/fidl_base/include/lib/fidl/cpp/transaction_header.h + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/pkg/fidl_base/include/lib/fidl/cpp/transport_err.h + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/pkg/fidl_base/include/lib/fidl/cpp/wire_format_metadata.h + ../../../fuchsia/sdk/linux/LICENSE @@ -3902,11 +3902,13 @@ FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.common/driver_features.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.common/overview.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.ieee80211/fields.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.ieee80211/overview.fidl +FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.phyimpl/phyimpl.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.wlan.policy/overview.fidl FILE: ../../../fuchsia/sdk/linux/fidl/zx/overview.fidl FILE: ../../../fuchsia/sdk/linux/pkg/async-cpp/include/lib/async/cpp/sequence_checker.h FILE: ../../../fuchsia/sdk/linux/pkg/async-cpp/sequence_checker.cc FILE: ../../../fuchsia/sdk/linux/pkg/async/include/lib/async/sequence_id.h +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/constants.h FILE: ../../../fuchsia/sdk/linux/pkg/fidl_base/include/lib/fidl/cpp/transaction_header.h FILE: ../../../fuchsia/sdk/linux/pkg/fidl_base/include/lib/fidl/cpp/transport_err.h FILE: ../../../fuchsia/sdk/linux/pkg/fidl_base/include/lib/fidl/cpp/wire_format_metadata.h @@ -4018,13 +4020,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: fuchsia_sdk +ORIGIN: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/flatland_example.dart + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.hardware.network/history.fidl + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.lowpan.thread/feature.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.net.routes/ipv4.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.net.routes/ipv6.fidl + ../../../fuchsia/sdk/linux/LICENSE ORIGIN: ../../../fuchsia/sdk/linux/fidl/fuchsia.tracing/tracing.fidl + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/clone.h + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/internal.h + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/protocol.h + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/service.h + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/internal.cc + ../../../fuchsia/sdk/linux/LICENSE +ORIGIN: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/protocol.cc + ../../../fuchsia/sdk/linux/LICENSE TYPE: LicenseType.bsd +FILE: ../../../fuchsia/sdk/linux/dart/sl4f/lib/src/flatland_example.dart +FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.hardware.network/history.fidl +FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.lowpan.thread/feature.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.net.routes/ipv4.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.net.routes/ipv6.fidl FILE: ../../../fuchsia/sdk/linux/fidl/fuchsia.tracing/tracing.fidl +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/clone.h +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/internal.h +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/protocol.h +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/include/lib/component/incoming/cpp/service.h +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/internal.cc +FILE: ../../../fuchsia/sdk/linux/pkg/component_incoming_cpp/protocol.cc ---------------------------------------------------------------------------------------------------- Copyright 2023 The Fuchsia Authors. All rights reserved. diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 751c2ba9a85c8..1d2f8b7c60538 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: a9da8a6e3643f28c49bcc2571400f56b +Signature: f87426862686fbafaafe6f04955322a7 ==================================================================================================== LIBRARY: etc1 @@ -645,7 +645,14 @@ ORIGIN: ../../../third_party/skia/include/utils/SkCamera.h + ../../../third_part ORIGIN: ../../../third_party/skia/include/utils/SkParse.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/utils/SkParsePath.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/utils/SkRandom.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkBuffer.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkBuffer.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkDeque.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkTSearch.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkTSearch.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkTSort.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkUtils.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkUtils.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkAlphaRuns.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkAnalyticEdge.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkAnalyticEdge.h + ../../../third_party/skia/LICENSE @@ -659,8 +666,6 @@ ORIGIN: ../../../third_party/skia/src/core/SkBlitter_Sprite.cpp + ../../../third ORIGIN: ../../../third_party/skia/src/core/SkBlurMF.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkBlurMask.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkBlurMask.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkBuffer.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkBuffer.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkColor.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkColorFilter.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkColorFilterBase.h + ../../../third_party/skia/LICENSE @@ -707,11 +712,6 @@ ORIGIN: ../../../third_party/skia/src/core/SkString.cpp + ../../../third_party/s ORIGIN: ../../../third_party/skia/src/core/SkStroke.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkStrokerPriv.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkStrokerPriv.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkTSearch.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkTSearch.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkTSort.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkUtils.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkUtils.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkXfermode.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkXfermodePriv.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/Sk1DPathEffect.cpp + ../../../third_party/skia/LICENSE @@ -794,7 +794,14 @@ FILE: ../../../third_party/skia/include/utils/SkCamera.h FILE: ../../../third_party/skia/include/utils/SkParse.h FILE: ../../../third_party/skia/include/utils/SkParsePath.h FILE: ../../../third_party/skia/include/utils/SkRandom.h +FILE: ../../../third_party/skia/src/base/SkBuffer.cpp +FILE: ../../../third_party/skia/src/base/SkBuffer.h FILE: ../../../third_party/skia/src/base/SkDeque.cpp +FILE: ../../../third_party/skia/src/base/SkTSearch.cpp +FILE: ../../../third_party/skia/src/base/SkTSearch.h +FILE: ../../../third_party/skia/src/base/SkTSort.h +FILE: ../../../third_party/skia/src/base/SkUtils.cpp +FILE: ../../../third_party/skia/src/base/SkUtils.h FILE: ../../../third_party/skia/src/core/SkAlphaRuns.cpp FILE: ../../../third_party/skia/src/core/SkAnalyticEdge.cpp FILE: ../../../third_party/skia/src/core/SkAnalyticEdge.h @@ -808,8 +815,6 @@ FILE: ../../../third_party/skia/src/core/SkBlitter_Sprite.cpp FILE: ../../../third_party/skia/src/core/SkBlurMF.cpp FILE: ../../../third_party/skia/src/core/SkBlurMask.cpp FILE: ../../../third_party/skia/src/core/SkBlurMask.h -FILE: ../../../third_party/skia/src/core/SkBuffer.cpp -FILE: ../../../third_party/skia/src/core/SkBuffer.h FILE: ../../../third_party/skia/src/core/SkColor.cpp FILE: ../../../third_party/skia/src/core/SkColorFilter.cpp FILE: ../../../third_party/skia/src/core/SkColorFilterBase.h @@ -856,11 +861,6 @@ FILE: ../../../third_party/skia/src/core/SkString.cpp FILE: ../../../third_party/skia/src/core/SkStroke.h FILE: ../../../third_party/skia/src/core/SkStrokerPriv.cpp FILE: ../../../third_party/skia/src/core/SkStrokerPriv.h -FILE: ../../../third_party/skia/src/core/SkTSearch.cpp -FILE: ../../../third_party/skia/src/core/SkTSearch.h -FILE: ../../../third_party/skia/src/core/SkTSort.h -FILE: ../../../third_party/skia/src/core/SkUtils.cpp -FILE: ../../../third_party/skia/src/core/SkUtils.h FILE: ../../../third_party/skia/src/core/SkXfermode.cpp FILE: ../../../third_party/skia/src/core/SkXfermodePriv.h FILE: ../../../third_party/skia/src/effects/Sk1DPathEffect.cpp @@ -1880,6 +1880,7 @@ ORIGIN: ../../../third_party/skia/include/private/SkPathRef.h + ../../../third_p ORIGIN: ../../../third_party/skia/include/private/SkWeakRefCnt.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/utils/SkNullCanvas.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkMathPriv.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkTInternalLList.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkColorTable.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkAnnotation.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkFontDescriptor.cpp + ../../../third_party/skia/LICENSE @@ -1895,7 +1896,6 @@ ORIGIN: ../../../third_party/skia/src/core/SkRTree.cpp + ../../../third_party/sk ORIGIN: ../../../third_party/skia/src/core/SkRTree.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkReadBuffer.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkStrokeRec.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkTInternalLList.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkWriteBuffer.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/ganesh/GrMemoryPool.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/ganesh/GrMemoryPool.h + ../../../third_party/skia/LICENSE @@ -2038,6 +2038,7 @@ FILE: ../../../third_party/skia/include/private/SkPathRef.h FILE: ../../../third_party/skia/include/private/SkWeakRefCnt.h FILE: ../../../third_party/skia/include/utils/SkNullCanvas.h FILE: ../../../third_party/skia/src/base/SkMathPriv.h +FILE: ../../../third_party/skia/src/base/SkTInternalLList.h FILE: ../../../third_party/skia/src/codec/SkColorTable.h FILE: ../../../third_party/skia/src/core/SkAnnotation.cpp FILE: ../../../third_party/skia/src/core/SkFontDescriptor.cpp @@ -2053,7 +2054,6 @@ FILE: ../../../third_party/skia/src/core/SkRTree.cpp FILE: ../../../third_party/skia/src/core/SkRTree.h FILE: ../../../third_party/skia/src/core/SkReadBuffer.cpp FILE: ../../../third_party/skia/src/core/SkStrokeRec.cpp -FILE: ../../../third_party/skia/src/core/SkTInternalLList.h FILE: ../../../third_party/skia/src/core/SkWriteBuffer.cpp FILE: ../../../third_party/skia/src/gpu/ganesh/GrMemoryPool.cpp FILE: ../../../third_party/skia/src/gpu/ganesh/GrMemoryPool.h @@ -2189,10 +2189,46 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== +==================================================================================================== +LIBRARY: skia +ORIGIN: ../../../third_party/skia/src/base/SkBezierCurves.cpp + ../../../third_party/skia/LICENSE +TYPE: LicenseType.bsd +FILE: ../../../third_party/skia/src/base/SkBezierCurves.cpp +---------------------------------------------------------------------------------------------------- +Copyright 2012 Google LLC + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +==================================================================================================== + ==================================================================================================== LIBRARY: skia ORIGIN: ../../../third_party/skia/src/core/SkImageFilter.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkUtilsArm.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp + ../../../third_party/skia/LICENSE @@ -2202,7 +2238,6 @@ ORIGIN: ../../../third_party/skia/src/effects/imagefilters/SkMorphologyImageFilt ORIGIN: ../../../third_party/skia/src/images/SkImageEncoderFns.h + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd FILE: ../../../third_party/skia/src/core/SkImageFilter.cpp -FILE: ../../../third_party/skia/src/core/SkUtilsArm.cpp FILE: ../../../third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp FILE: ../../../third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp FILE: ../../../third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp @@ -2648,7 +2683,8 @@ ORIGIN: ../../../third_party/skia/include/core/SkTextBlob.h + ../../../third_par ORIGIN: ../../../third_party/skia/include/gpu/gl/GrGLAssembleInterface.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/ports/SkFontMgr_indirect.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/ports/SkRemotableFontMgr.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/include/private/SkHalf.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkHalf.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkHalf.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkBBHFactory.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkBitmapCache.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkBitmapCache.h + ../../../third_party/skia/LICENSE @@ -2661,7 +2697,6 @@ ORIGIN: ../../../third_party/skia/src/core/SkDistanceFieldGen.h + ../../../third ORIGIN: ../../../third_party/skia/src/core/SkDrawable.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkFont.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkFont_serial.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkHalf.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkImageGenerator.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkMaskCache.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkMaskCache.h + ../../../third_party/skia/LICENSE @@ -2814,7 +2849,8 @@ FILE: ../../../third_party/skia/include/core/SkTextBlob.h FILE: ../../../third_party/skia/include/gpu/gl/GrGLAssembleInterface.h FILE: ../../../third_party/skia/include/ports/SkFontMgr_indirect.h FILE: ../../../third_party/skia/include/ports/SkRemotableFontMgr.h -FILE: ../../../third_party/skia/include/private/SkHalf.h +FILE: ../../../third_party/skia/src/base/SkHalf.cpp +FILE: ../../../third_party/skia/src/base/SkHalf.h FILE: ../../../third_party/skia/src/core/SkBBHFactory.cpp FILE: ../../../third_party/skia/src/core/SkBitmapCache.cpp FILE: ../../../third_party/skia/src/core/SkBitmapCache.h @@ -2827,7 +2863,6 @@ FILE: ../../../third_party/skia/src/core/SkDistanceFieldGen.h FILE: ../../../third_party/skia/src/core/SkDrawable.cpp FILE: ../../../third_party/skia/src/core/SkFont.cpp FILE: ../../../third_party/skia/src/core/SkFont_serial.cpp -FILE: ../../../third_party/skia/src/core/SkHalf.cpp FILE: ../../../third_party/skia/src/core/SkImageGenerator.cpp FILE: ../../../third_party/skia/src/core/SkMaskCache.cpp FILE: ../../../third_party/skia/src/core/SkMaskCache.h @@ -3119,6 +3154,7 @@ ORIGIN: ../../../third_party/skia/include/private/base/SkThreadID.h + ../../../t ORIGIN: ../../../third_party/skia/include/svg/SkSVGCanvas.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/utils/SkPaintFilterCanvas.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkSemaphore.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkTDPQueue.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkThreadID.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkAndroidCodec.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkAndroidCodecAdapter.cpp + ../../../third_party/skia/LICENSE @@ -3182,7 +3218,6 @@ ORIGIN: ../../../third_party/skia/src/core/SkRecords.cpp + ../../../third_party/ ORIGIN: ../../../third_party/skia/src/core/SkSharedMutex.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkSharedMutex.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkSpinlock.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkTDPQueue.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkTHash.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkTime.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkXfermodeInterpretation.cpp + ../../../third_party/skia/LICENSE @@ -3408,6 +3443,7 @@ FILE: ../../../third_party/skia/include/private/base/SkThreadID.h FILE: ../../../third_party/skia/include/svg/SkSVGCanvas.h FILE: ../../../third_party/skia/include/utils/SkPaintFilterCanvas.h FILE: ../../../third_party/skia/src/base/SkSemaphore.cpp +FILE: ../../../third_party/skia/src/base/SkTDPQueue.h FILE: ../../../third_party/skia/src/base/SkThreadID.cpp FILE: ../../../third_party/skia/src/codec/SkAndroidCodec.cpp FILE: ../../../third_party/skia/src/codec/SkAndroidCodecAdapter.cpp @@ -3471,7 +3507,6 @@ FILE: ../../../third_party/skia/src/core/SkRecords.cpp FILE: ../../../third_party/skia/src/core/SkSharedMutex.cpp FILE: ../../../third_party/skia/src/core/SkSharedMutex.h FILE: ../../../third_party/skia/src/core/SkSpinlock.cpp -FILE: ../../../third_party/skia/src/core/SkTDPQueue.h FILE: ../../../third_party/skia/src/core/SkTHash.h FILE: ../../../third_party/skia/src/core/SkTime.cpp FILE: ../../../third_party/skia/src/core/SkXfermodeInterpretation.cpp @@ -3886,6 +3921,7 @@ ORIGIN: ../../../third_party/skia/src/core/SkSpecialImage.h + ../../../third_par ORIGIN: ../../../third_party/skia/src/core/SkSpecialSurface.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkSpecialSurface.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkSwizzle.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/core/SkSwizzlePriv.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/SkOverdrawColorFilter.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/effects/imagefilters/SkShaderImageFilter.cpp + ../../../third_party/skia/LICENSE @@ -4199,6 +4235,7 @@ FILE: ../../../third_party/skia/src/core/SkSpecialImage.h FILE: ../../../third_party/skia/src/core/SkSpecialSurface.cpp FILE: ../../../third_party/skia/src/core/SkSpecialSurface.h FILE: ../../../third_party/skia/src/core/SkSwizzle.cpp +FILE: ../../../third_party/skia/src/core/SkSwizzlePriv.h FILE: ../../../third_party/skia/src/effects/SkOverdrawColorFilter.cpp FILE: ../../../third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp FILE: ../../../third_party/skia/src/effects/imagefilters/SkShaderImageFilter.cpp @@ -5773,7 +5810,6 @@ ORIGIN: ../../../third_party/skia/include/gpu/GrRecordingContext.h + ../../../th ORIGIN: ../../../third_party/skia/include/gpu/dawn/GrDawnTypes.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/ports/SkCFObject.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkSLDefines.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/include/private/base/SkVx.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/chromium/GrVkSecondaryCBDrawContext.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/gpu/ganesh/GrContext_Base.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/gpu/ganesh/GrImageContext.h + ../../../third_party/skia/LICENSE @@ -5819,6 +5855,8 @@ ORIGIN: ../../../third_party/skia/modules/sksg/src/SkSGRenderEffect.cpp + ../../ ORIGIN: ../../../third_party/skia/modules/sksg/src/SkSGTransformPriv.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/modules/svg/include/SkSVGText.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/modules/svg/src/SkSVGText.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkVx.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkZip.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkScalingCodec.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkDescriptor.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkDraw_atlas.cpp + ../../../third_party/skia/LICENSE @@ -5831,7 +5869,6 @@ ORIGIN: ../../../third_party/skia/src/core/SkStrikeSpec.h + ../../../third_party ORIGIN: ../../../third_party/skia/src/core/SkVMBlitter.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkYUVMath.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkYUVMath.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/core/SkZip.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/GrAHardwareBufferUtils.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/ganesh/GrAHardwareBufferUtils.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/ganesh/GrAHardwareBufferUtils_impl.h + ../../../third_party/skia/LICENSE @@ -5920,7 +5957,6 @@ FILE: ../../../third_party/skia/include/gpu/GrRecordingContext.h FILE: ../../../third_party/skia/include/gpu/dawn/GrDawnTypes.h FILE: ../../../third_party/skia/include/ports/SkCFObject.h FILE: ../../../third_party/skia/include/private/SkSLDefines.h -FILE: ../../../third_party/skia/include/private/base/SkVx.h FILE: ../../../third_party/skia/include/private/chromium/GrVkSecondaryCBDrawContext.h FILE: ../../../third_party/skia/include/private/gpu/ganesh/GrContext_Base.h FILE: ../../../third_party/skia/include/private/gpu/ganesh/GrImageContext.h @@ -5966,6 +6002,8 @@ FILE: ../../../third_party/skia/modules/sksg/src/SkSGRenderEffect.cpp FILE: ../../../third_party/skia/modules/sksg/src/SkSGTransformPriv.h FILE: ../../../third_party/skia/modules/svg/include/SkSVGText.h FILE: ../../../third_party/skia/modules/svg/src/SkSVGText.cpp +FILE: ../../../third_party/skia/src/base/SkVx.h +FILE: ../../../third_party/skia/src/base/SkZip.h FILE: ../../../third_party/skia/src/codec/SkScalingCodec.h FILE: ../../../third_party/skia/src/core/SkDescriptor.cpp FILE: ../../../third_party/skia/src/core/SkDraw_atlas.cpp @@ -5978,7 +6016,6 @@ FILE: ../../../third_party/skia/src/core/SkStrikeSpec.h FILE: ../../../third_party/skia/src/core/SkVMBlitter.cpp FILE: ../../../third_party/skia/src/core/SkYUVMath.cpp FILE: ../../../third_party/skia/src/core/SkYUVMath.h -FILE: ../../../third_party/skia/src/core/SkZip.h FILE: ../../../third_party/skia/src/gpu/GrAHardwareBufferUtils.h FILE: ../../../third_party/skia/src/gpu/ganesh/GrAHardwareBufferUtils.cpp FILE: ../../../third_party/skia/src/gpu/ganesh/GrAHardwareBufferUtils_impl.h @@ -7361,7 +7398,6 @@ ORIGIN: ../../../third_party/skia/src/gpu/graphite/Buffer.cpp + ../../../third_p ORIGIN: ../../../third_party/skia/src/gpu/graphite/Buffer.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/BufferManager.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/BufferManager.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/gpu/graphite/DrawBufferManager.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/mtl/MtlBlitCommandEncoder.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/mtl/MtlBuffer.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/mtl/MtlBuffer.mm + ../../../third_party/skia/LICENSE @@ -7448,7 +7484,6 @@ FILE: ../../../third_party/skia/src/gpu/graphite/Buffer.cpp FILE: ../../../third_party/skia/src/gpu/graphite/Buffer.h FILE: ../../../third_party/skia/src/gpu/graphite/BufferManager.cpp FILE: ../../../third_party/skia/src/gpu/graphite/BufferManager.h -FILE: ../../../third_party/skia/src/gpu/graphite/DrawBufferManager.h FILE: ../../../third_party/skia/src/gpu/graphite/mtl/MtlBlitCommandEncoder.h FILE: ../../../third_party/skia/src/gpu/graphite/mtl/MtlBuffer.h FILE: ../../../third_party/skia/src/gpu/graphite/mtl/MtlBuffer.mm @@ -8196,9 +8231,6 @@ ORIGIN: ../../../third_party/skia/modules/svg/include/SkSVGOpenTypeSVGDecoder.h ORIGIN: ../../../third_party/skia/modules/svg/src/SkSVGOpenTypeSVGDecoder.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkAvifCodec.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkAvifCodec.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/codec/SkJpegRCodec.cpp + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/codec/SkJpegRCodec.h + ../../../third_party/skia/LICENSE -ORIGIN: ../../../third_party/skia/src/codec/SkStubJpegRDecoderAPI.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/mtl/MtlComputeCommandEncoder.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/sfnt/SkOTTable_hmtx.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp + ../../../third_party/skia/LICENSE @@ -8229,9 +8261,6 @@ FILE: ../../../third_party/skia/modules/svg/include/SkSVGOpenTypeSVGDecoder.h FILE: ../../../third_party/skia/modules/svg/src/SkSVGOpenTypeSVGDecoder.cpp FILE: ../../../third_party/skia/src/codec/SkAvifCodec.cpp FILE: ../../../third_party/skia/src/codec/SkAvifCodec.h -FILE: ../../../third_party/skia/src/codec/SkJpegRCodec.cpp -FILE: ../../../third_party/skia/src/codec/SkJpegRCodec.h -FILE: ../../../third_party/skia/src/codec/SkStubJpegRDecoderAPI.h FILE: ../../../third_party/skia/src/gpu/graphite/mtl/MtlComputeCommandEncoder.h FILE: ../../../third_party/skia/src/sfnt/SkOTTable_hmtx.h FILE: ../../../third_party/skia/src/sksl/codegen/SkSLRasterPipelineBuilder.cpp @@ -8877,30 +8906,44 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: skia +ORIGIN: ../../../third_party/skia/gm/coordclampshader.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/gm/imagefiltersunpremul.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkGainmapInfo.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkGainmapShader.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/include/private/SkJpegGainmapEncoder.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkJpegGainmap.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkJpegGainmap.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkJpegMultiPicture.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkJpegMultiPicture.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkJpegSegmentScan.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/codec/SkJpegSegmentScan.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/codec/SkJpegSourceMgr.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/codec/SkJpegSourceMgr.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/codec/SkJpegXmp.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/codec/SkJpegXmp.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkRasterPipelineOpContexts.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkRasterPipelineOpList.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/images/SkJpegGainmapEncoder.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/shaders/SkGainmapShader.cpp + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd +FILE: ../../../third_party/skia/gm/coordclampshader.cpp FILE: ../../../third_party/skia/gm/imagefiltersunpremul.cpp FILE: ../../../third_party/skia/include/private/SkGainmapInfo.h FILE: ../../../third_party/skia/include/private/SkGainmapShader.h +FILE: ../../../third_party/skia/include/private/SkJpegGainmapEncoder.h FILE: ../../../third_party/skia/src/codec/SkJpegGainmap.cpp FILE: ../../../third_party/skia/src/codec/SkJpegGainmap.h FILE: ../../../third_party/skia/src/codec/SkJpegMultiPicture.cpp FILE: ../../../third_party/skia/src/codec/SkJpegMultiPicture.h FILE: ../../../third_party/skia/src/codec/SkJpegSegmentScan.cpp FILE: ../../../third_party/skia/src/codec/SkJpegSegmentScan.h +FILE: ../../../third_party/skia/src/codec/SkJpegSourceMgr.cpp +FILE: ../../../third_party/skia/src/codec/SkJpegSourceMgr.h +FILE: ../../../third_party/skia/src/codec/SkJpegXmp.cpp +FILE: ../../../third_party/skia/src/codec/SkJpegXmp.h FILE: ../../../third_party/skia/src/core/SkRasterPipelineOpContexts.h FILE: ../../../third_party/skia/src/core/SkRasterPipelineOpList.h +FILE: ../../../third_party/skia/src/images/SkJpegGainmapEncoder.cpp FILE: ../../../third_party/skia/src/shaders/SkGainmapShader.cpp ---------------------------------------------------------------------------------------------------- Copyright 2023 Google Inc. @@ -8941,30 +8984,48 @@ ORIGIN: ../../../third_party/skia/fuzz/oss_fuzz/FuzzCubicQuadRoots.cpp + ../../. ORIGIN: ../../../third_party/skia/include/private/SkMalloc.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkTemplates.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/base/SkCPUTypes.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/base/SkBezierCurves.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkCubics.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkCubics.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkFloatingPoint.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkQuads.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkQuads.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/base/SkSafeMath.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/core/SkRSXform.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/core/SkTSearch.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/Image_Base_Graphite.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/graphite/Image_Base_Graphite.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.h + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/sksl/analysis/SkSLGetLoopControlFlowInfo.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/sksl/analysis/SkSLGetReturnComplexity.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/sksl/analysis/SkSLIsDynamicallyUniformExpression.cpp + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd FILE: ../../../third_party/skia/fuzz/FuzzCubicQuadRoots.cpp FILE: ../../../third_party/skia/fuzz/oss_fuzz/FuzzCubicQuadRoots.cpp FILE: ../../../third_party/skia/include/private/SkMalloc.h FILE: ../../../third_party/skia/include/private/SkTemplates.h FILE: ../../../third_party/skia/include/private/base/SkCPUTypes.h +FILE: ../../../third_party/skia/src/base/SkBezierCurves.h FILE: ../../../third_party/skia/src/base/SkCubics.cpp FILE: ../../../third_party/skia/src/base/SkCubics.h FILE: ../../../third_party/skia/src/base/SkFloatingPoint.cpp FILE: ../../../third_party/skia/src/base/SkQuads.cpp FILE: ../../../third_party/skia/src/base/SkQuads.h FILE: ../../../third_party/skia/src/base/SkSafeMath.cpp +FILE: ../../../third_party/skia/src/core/SkRSXform.cpp +FILE: ../../../third_party/skia/src/core/SkTSearch.h FILE: ../../../third_party/skia/src/gpu/graphite/Image_Base_Graphite.cpp FILE: ../../../third_party/skia/src/gpu/graphite/Image_Base_Graphite.h +FILE: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.cpp +FILE: ../../../third_party/skia/src/gpu/graphite/Image_YUVA_Graphite.h +FILE: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.cpp +FILE: ../../../third_party/skia/src/gpu/graphite/YUVATextureProxies.h +FILE: ../../../third_party/skia/src/sksl/analysis/SkSLGetLoopControlFlowInfo.cpp FILE: ../../../third_party/skia/src/sksl/analysis/SkSLGetReturnComplexity.cpp +FILE: ../../../third_party/skia/src/sksl/analysis/SkSLIsDynamicallyUniformExpression.cpp ---------------------------------------------------------------------------------------------------- Copyright 2023 Google LLC @@ -8997,4 +9058,41 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== -Total license count: 64 +==================================================================================================== +LIBRARY: skia +ORIGIN: ../../../third_party/skia/src/shaders/SkCoordClampShader.cpp + ../../../third_party/skia/LICENSE +TYPE: LicenseType.bsd +FILE: ../../../third_party/skia/src/shaders/SkCoordClampShader.cpp +---------------------------------------------------------------------------------------------------- +Copyright 2023 The Android Open Source Project + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +==================================================================================================== + +Total license count: 66 diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index 08170dfa4db0d..3c0bf2b26ef04 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: 2022cc3aab27da301615a103bfe68833 +Signature: bb4689eace80fa19571c375ed760f822 ==================================================================================================== LIBRARY: angle @@ -278,6 +278,7 @@ LIBRARY: flatbuffers LIBRARY: fuchsia-vulkan LIBRARY: glslang LIBRARY: khronos +LIBRARY: perfetto LIBRARY: shaderc LIBRARY: spirv-cross LIBRARY: vulkan-headers @@ -673,6 +674,477 @@ ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_ ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/fuchsia-vulkan/include/vulkan/vk_sdk_platform.h ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/khronos/GLES2/gl2platform.h ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/khronos/GLES3/gl3platform.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/Android.bp +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/PerfettoIntegrationTests.xml +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/bazel/BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/bazel/jsoncpp.BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/bazel/linenoise.BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/bazel/llvm_demangle.BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/bazel/sqlite.BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/bazel/zlib.BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/buildtools/libbacktrace_config/backtrace-supported.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/buildtools/libbacktrace_config/config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/gn/standalone/.emscripten +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/heapprofd.rc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/build_config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/compiler.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/export.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/flat_set.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/logging.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/platform_handle.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/proc_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/status.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/task_runner.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/template_util.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/thread_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/base/time.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/android_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/base64.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/circular_queue.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/container_annotations.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/crash_keys.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/ctrl_c_handler.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/endian.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/event_fd.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/file_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/flat_hash_map.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/getopt.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/getopt_compat.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/hash.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/http/http_server.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/http/sha1.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/metatrace.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/metatrace_events.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/no_destructor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/optional.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/paged_memory.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/periodic_task.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/pipe.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/scoped_file.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/small_set.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/small_vector.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/string_splitter.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/string_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/string_view.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/string_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/subprocess.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/sys_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/temp_file.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/thread_annotations.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/thread_checker.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/thread_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/unix_socket.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/unix_task_runner.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/uuid.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/version.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/waitable_event.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/watchdog.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/watchdog_noop.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/watchdog_posix.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/base/weak_ptr.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/async_result.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/basic_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/client.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/client_info.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/codegen_helpers.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/deferred.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/host.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/service.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/service_descriptor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/ipc/service_proxy.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/demangle.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/traced/data_source_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/traced/sys_stats_counters.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/traced/traced.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/basic_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/observable_events.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/producer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_abi.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/slice.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/trace_stats.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/default_socket.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/producer_ipc_client.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/service_ipc_host.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/profiling/parse_smaps.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/profiling/pprof_builder.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/copyable_ptr.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/cpp_message_obj.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/field.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/field_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/message.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/message_arena.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/message_handle.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/packed_repeated_fields.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/proto_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/root_message.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/protozero/static_buffer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/public/abi/export.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/public/abi/stream_writer_abi.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/public/compiler.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/public/stream_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/basic_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/iterator.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/read_trace.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/ref_counted.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/status.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/trace_blob.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/trace_blob_view.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/trace_processor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/backend_type.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/buffer_exhausted_policy.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/console_interceptor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/chrome_config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/data_source_config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/data_source_descriptor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/forward_decls.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/trace_config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/tracing_service_capabilities.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/core/tracing_service_state.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/data_source.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/debug_annotation.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/event_context.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/interceptor.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/basic_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/checked_scope.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/compile_time_hash.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/data_source_internal.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/in_process_tracing_backend.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/interceptor_trace_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/system_tracing_backend.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/tracing_backend_fake.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/tracing_muxer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/tracing_tls.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_data_source.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_interned_fields.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_macros.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/internal/write_track_event_args.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/locked_handle.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/platform.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/string_helpers.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/trace_writer_base.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/traced_proto.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/traced_value.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/traced_value_forward.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/tracing.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/tracing_backend.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/tracing_policy.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track_event.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track_event_args.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track_event_category_registry.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track_event_legacy.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/include/perfetto/tracing/track_event_state_tracker.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/perfetto.rc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/python/BUILD +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/sdk/perfetto.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/sdk/perfetto.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/atrace_hal.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/atrace_hal.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/health_hal.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/health_hal.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/incident_service.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/incident_service.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/lazy_library_loader.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/lazy_library_loader.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/power_stats.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/power_stats.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/statsd_logging.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/statsd_logging.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/tracing_service_proxy.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_internal/tracing_service_proxy.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_stats/perfetto_atoms.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_stats/statsd_logging_helper.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/android_stats/statsd_logging_helper.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/android_utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/base64.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/base64_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/circular_queue_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/crash_keys.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/ctrl_c_handler.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/debug_crash_stack_trace.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/event_fd.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/file_utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/flat_hash_map_benchmark.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/flat_hash_map_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/flat_set_benchmark.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/flat_set_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/getopt_compat.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/getopt_compat_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/hash_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/http/http_server.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/http/http_server_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/http/sha1.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/http/sha1_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/log_ring_buffer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/logging.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/logging_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/metatrace.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/metatrace_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/no_destructor_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/optional_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/paged_memory.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/paged_memory_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/periodic_task.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/periodic_task_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/pipe.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/scoped_file_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/small_vector_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/status.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_splitter.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_splitter_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_utils_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_view.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_view_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/string_writer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/subprocess.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/subprocess_posix.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/subprocess_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/subprocess_windows.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/task_runner_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/temp_file.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/temp_file_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/thread_checker.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/thread_checker_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/thread_task_runner.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/thread_task_runner_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/thread_utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/time.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/time_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/unix_socket.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/unix_socket_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/unix_task_runner.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/utils_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/uuid.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/uuid_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/version.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/virtual_destructors.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/waitable_event.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/watchdog_posix.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/watchdog_posix_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/watchdog_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/base/weak_ptr_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map_benchmark.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/lazy_kernel_symbolizer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/lazy_kernel_symbolizer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kallsyms/lazy_kernel_symbolizer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscall_table.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscall_table.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscalls_aarch32.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscalls_aarch64.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscalls_armeabi.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscalls_x86.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/kernel_utils/syscalls_x86_64.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/config.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/config_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/main.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/packet_writer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/packet_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/packet_writer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/pbtxt_to_pb.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/pbtxt_to_pb.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/pbtxt_to_pb_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd_android.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd_state.proto +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/rate_limiter.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/rate_limiter.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/rate_limiter_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/trigger_perfetto.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/trigger_perfetto_main.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/trigger_producer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/perfetto_cmd/trigger_producer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/callstack_trie.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/callstack_trie.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/interner.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/interner_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/interning_output.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/interning_output.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/proc_cmdline.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/proc_cmdline.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/proc_cmdline_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/proc_utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/proc_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/proc_utils_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/producer_support.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/producer_support.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/producer_support_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/profiler_guardrails.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/profiler_guardrails.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/profiler_guardrails_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/unwind_support.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/common/unwind_support.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/deobfuscator.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/deobfuscator.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/deobfuscator_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/common_types.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/event_config.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/event_config.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/event_config_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/event_reader.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/event_reader.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/main.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/perf_producer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/perf_producer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/perf_producer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/proc_descriptors.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/proc_descriptors.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/regs_parsing.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/regs_parsing.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/traced_perf.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/traced_perf.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/unwind_queue.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/unwind_queue_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/unwinding.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/perf/unwinding.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_parser.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_parser.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_parser_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_symbolizer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_symbolizer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_symbolizer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/elf.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/local_symbolizer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/local_symbolizer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/local_symbolizer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/scoped_read_mmap.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/scoped_read_mmap_posix.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/scoped_read_mmap_windows.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/subprocess.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/subprocess_posix.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/subprocess_windows.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/symbolize_database.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/symbolize_database.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/symbolizer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/profiling/symbolizer/symbolizer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/copyable_ptr_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/field.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_common.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_generator.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_generator.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_generator_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser_fuzzer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_util.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_util.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/filter_util_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_filter.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_filter.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_filter_benchmark.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_filter_fuzzer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_filter_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_tokenizer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/filtering/message_tokenizer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/message.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/message_arena.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/message_arena_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/message_handle.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/message_handle_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/message_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/packed_repeated_fields.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_decoder.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_decoder_fuzzer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_decoder_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_ring_buffer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_ring_buffer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_ring_buffer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/proto_utils_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/protoc_plugin/cppgen_plugin.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/protoc_plugin/protozero_plugin.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/scattered_heap_buffer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/scattered_stream_null_delegate.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/scattered_stream_writer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/scattered_stream_writer_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/static_buffer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/protozero/virtual_destructors.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/shared_lib/stream_writer.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/shared_lib/stream_writer.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/tracebox/tracebox.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/deobfuscate_profile.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/deobfuscate_profile.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/lite_fallbacks.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/main.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/pprof_builder.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/proto_full_utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/proto_full_utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/symbolize_profile.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/symbolize_profile.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_hprof.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_hprof.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_json.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_json.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_profile.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_profile.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_systrace.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_systrace.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_text.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_text.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/trace_to_text_unittest.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/utils.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/traceconv/utils.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/websocket_bridge/websocket_bridge.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/websocket_bridge/websocket_bridge.h +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/src/websocket_bridge/websocket_bridge_main.cc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/traced_perf.rc +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/build.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/integrationtest_env.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/integrationtest_setup.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/integrationtest_teardown.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/jest.integrationtest.config.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/jest.unittest.config.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/rollup-serviceworker.config.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/config/rollup.config.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/analyze_page.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/common.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/details.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/flags_page.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/home_page.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/metrics_page.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/modal.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/perfetto.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/record.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/sidebar.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/topbar.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/assets/trace_info_page.scss +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/base/utils/index-browser.js +ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/perfetto/ui/src/base/utils/index.js ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/shaderc/android_test/test.cpp ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/shaderc/glslc/src/dependency_info.cc ORIGIN: http://www.apache.org/licenses/LICENSE-2.0 referenced by ../../../third_party/shaderc/glslc/src/dependency_info.h @@ -2332,6 +2804,477 @@ FILE: ../../../third_party/khronos/EGL/eglext.h FILE: ../../../third_party/khronos/EGL/eglplatform.h FILE: ../../../third_party/khronos/GLES2/gl2platform.h FILE: ../../../third_party/khronos/GLES3/gl3platform.h +FILE: ../../../third_party/perfetto/Android.bp +FILE: ../../../third_party/perfetto/BUILD +FILE: ../../../third_party/perfetto/PerfettoIntegrationTests.xml +FILE: ../../../third_party/perfetto/bazel/BUILD +FILE: ../../../third_party/perfetto/bazel/jsoncpp.BUILD +FILE: ../../../third_party/perfetto/bazel/linenoise.BUILD +FILE: ../../../third_party/perfetto/bazel/llvm_demangle.BUILD +FILE: ../../../third_party/perfetto/bazel/sqlite.BUILD +FILE: ../../../third_party/perfetto/bazel/zlib.BUILD +FILE: ../../../third_party/perfetto/buildtools/libbacktrace_config/backtrace-supported.h +FILE: ../../../third_party/perfetto/buildtools/libbacktrace_config/config.h +FILE: ../../../third_party/perfetto/gn/standalone/.emscripten +FILE: ../../../third_party/perfetto/heapprofd.rc +FILE: ../../../third_party/perfetto/include/perfetto/base/build_config.h +FILE: ../../../third_party/perfetto/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h +FILE: ../../../third_party/perfetto/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h +FILE: ../../../third_party/perfetto/include/perfetto/base/compiler.h +FILE: ../../../third_party/perfetto/include/perfetto/base/export.h +FILE: ../../../third_party/perfetto/include/perfetto/base/flat_set.h +FILE: ../../../third_party/perfetto/include/perfetto/base/logging.h +FILE: ../../../third_party/perfetto/include/perfetto/base/platform_handle.h +FILE: ../../../third_party/perfetto/include/perfetto/base/proc_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/base/status.h +FILE: ../../../third_party/perfetto/include/perfetto/base/task_runner.h +FILE: ../../../third_party/perfetto/include/perfetto/base/template_util.h +FILE: ../../../third_party/perfetto/include/perfetto/base/thread_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/base/time.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/android_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/base64.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/circular_queue.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/container_annotations.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/crash_keys.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/ctrl_c_handler.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/endian.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/event_fd.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/file_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/flat_hash_map.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/getopt.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/getopt_compat.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/hash.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/http/http_server.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/http/sha1.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/metatrace.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/metatrace_events.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/no_destructor.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/optional.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/paged_memory.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/periodic_task.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/pipe.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/scoped_file.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/small_set.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/small_vector.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/string_splitter.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/string_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/string_view.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/string_writer.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/subprocess.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/sys_types.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/temp_file.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/thread_annotations.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/thread_checker.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/thread_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/unix_socket.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/unix_task_runner.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/utils.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/uuid.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/version.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/waitable_event.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/watchdog.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/watchdog_noop.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/watchdog_posix.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/base/weak_ptr.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/async_result.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/basic_types.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/client.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/client_info.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/codegen_helpers.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/deferred.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/host.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/service.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/service_descriptor.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/ipc/service_proxy.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/demangle.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_allocator_node_id.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/memory_graph_edge.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_memory_graph_node.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/raw_process_memory_node.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/traced/data_source_types.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/traced/sys_stats_counters.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/traced/traced.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/basic_types.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/observable_events.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/producer.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_abi.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/slice.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/trace_stats.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/default_socket.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/producer_ipc_client.h +FILE: ../../../third_party/perfetto/include/perfetto/ext/tracing/ipc/service_ipc_host.h +FILE: ../../../third_party/perfetto/include/perfetto/profiling/parse_smaps.h +FILE: ../../../third_party/perfetto/include/perfetto/profiling/pprof_builder.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/copyable_ptr.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/cpp_message_obj.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/field.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/field_writer.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/message.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/message_arena.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/message_handle.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/packed_repeated_fields.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/proto_utils.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/root_message.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h +FILE: ../../../third_party/perfetto/include/perfetto/protozero/static_buffer.h +FILE: ../../../third_party/perfetto/include/perfetto/public/abi/export.h +FILE: ../../../third_party/perfetto/include/perfetto/public/abi/stream_writer_abi.h +FILE: ../../../third_party/perfetto/include/perfetto/public/compiler.h +FILE: ../../../third_party/perfetto/include/perfetto/public/stream_writer.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/basic_types.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/iterator.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/read_trace.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/ref_counted.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/status.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/trace_blob.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/trace_blob_view.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/trace_processor.h +FILE: ../../../third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/backend_type.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/buffer_exhausted_policy.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/console_interceptor.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/chrome_config.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/data_source_config.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/data_source_descriptor.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/forward_decls.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/trace_config.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/tracing_service_capabilities.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/core/tracing_service_state.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/data_source.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/debug_annotation.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/event_context.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/interceptor.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/basic_types.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/checked_scope.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/compile_time_hash.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/data_source_internal.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/in_process_tracing_backend.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/interceptor_trace_writer.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/system_tracing_backend.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/tracing_backend_fake.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/tracing_muxer.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/tracing_tls.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_data_source.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_interned_fields.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/track_event_macros.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/internal/write_track_event_args.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/locked_handle.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/platform.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/string_helpers.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/trace_writer_base.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/traced_proto.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/traced_value.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/traced_value_forward.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/tracing.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/tracing_backend.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/tracing_policy.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track_event.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track_event_args.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track_event_category_registry.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track_event_legacy.h +FILE: ../../../third_party/perfetto/include/perfetto/tracing/track_event_state_tracker.h +FILE: ../../../third_party/perfetto/perfetto.rc +FILE: ../../../third_party/perfetto/python/BUILD +FILE: ../../../third_party/perfetto/sdk/perfetto.cc +FILE: ../../../third_party/perfetto/sdk/perfetto.h +FILE: ../../../third_party/perfetto/src/android_internal/atrace_hal.cc +FILE: ../../../third_party/perfetto/src/android_internal/atrace_hal.h +FILE: ../../../third_party/perfetto/src/android_internal/health_hal.cc +FILE: ../../../third_party/perfetto/src/android_internal/health_hal.h +FILE: ../../../third_party/perfetto/src/android_internal/incident_service.cc +FILE: ../../../third_party/perfetto/src/android_internal/incident_service.h +FILE: ../../../third_party/perfetto/src/android_internal/lazy_library_loader.cc +FILE: ../../../third_party/perfetto/src/android_internal/lazy_library_loader.h +FILE: ../../../third_party/perfetto/src/android_internal/power_stats.cc +FILE: ../../../third_party/perfetto/src/android_internal/power_stats.h +FILE: ../../../third_party/perfetto/src/android_internal/statsd_logging.cc +FILE: ../../../third_party/perfetto/src/android_internal/statsd_logging.h +FILE: ../../../third_party/perfetto/src/android_internal/tracing_service_proxy.cc +FILE: ../../../third_party/perfetto/src/android_internal/tracing_service_proxy.h +FILE: ../../../third_party/perfetto/src/android_stats/perfetto_atoms.h +FILE: ../../../third_party/perfetto/src/android_stats/statsd_logging_helper.cc +FILE: ../../../third_party/perfetto/src/android_stats/statsd_logging_helper.h +FILE: ../../../third_party/perfetto/src/base/android_utils.cc +FILE: ../../../third_party/perfetto/src/base/base64.cc +FILE: ../../../third_party/perfetto/src/base/base64_unittest.cc +FILE: ../../../third_party/perfetto/src/base/circular_queue_unittest.cc +FILE: ../../../third_party/perfetto/src/base/crash_keys.cc +FILE: ../../../third_party/perfetto/src/base/ctrl_c_handler.cc +FILE: ../../../third_party/perfetto/src/base/debug_crash_stack_trace.cc +FILE: ../../../third_party/perfetto/src/base/event_fd.cc +FILE: ../../../third_party/perfetto/src/base/file_utils.cc +FILE: ../../../third_party/perfetto/src/base/flat_hash_map_benchmark.cc +FILE: ../../../third_party/perfetto/src/base/flat_hash_map_unittest.cc +FILE: ../../../third_party/perfetto/src/base/flat_set_benchmark.cc +FILE: ../../../third_party/perfetto/src/base/flat_set_unittest.cc +FILE: ../../../third_party/perfetto/src/base/getopt_compat.cc +FILE: ../../../third_party/perfetto/src/base/getopt_compat_unittest.cc +FILE: ../../../third_party/perfetto/src/base/hash_unittest.cc +FILE: ../../../third_party/perfetto/src/base/http/http_server.cc +FILE: ../../../third_party/perfetto/src/base/http/http_server_unittest.cc +FILE: ../../../third_party/perfetto/src/base/http/sha1.cc +FILE: ../../../third_party/perfetto/src/base/http/sha1_unittest.cc +FILE: ../../../third_party/perfetto/src/base/log_ring_buffer.h +FILE: ../../../third_party/perfetto/src/base/logging.cc +FILE: ../../../third_party/perfetto/src/base/logging_unittest.cc +FILE: ../../../third_party/perfetto/src/base/metatrace.cc +FILE: ../../../third_party/perfetto/src/base/metatrace_unittest.cc +FILE: ../../../third_party/perfetto/src/base/no_destructor_unittest.cc +FILE: ../../../third_party/perfetto/src/base/optional_unittest.cc +FILE: ../../../third_party/perfetto/src/base/paged_memory.cc +FILE: ../../../third_party/perfetto/src/base/paged_memory_unittest.cc +FILE: ../../../third_party/perfetto/src/base/periodic_task.cc +FILE: ../../../third_party/perfetto/src/base/periodic_task_unittest.cc +FILE: ../../../third_party/perfetto/src/base/pipe.cc +FILE: ../../../third_party/perfetto/src/base/scoped_file_unittest.cc +FILE: ../../../third_party/perfetto/src/base/small_vector_unittest.cc +FILE: ../../../third_party/perfetto/src/base/status.cc +FILE: ../../../third_party/perfetto/src/base/string_splitter.cc +FILE: ../../../third_party/perfetto/src/base/string_splitter_unittest.cc +FILE: ../../../third_party/perfetto/src/base/string_utils.cc +FILE: ../../../third_party/perfetto/src/base/string_utils_unittest.cc +FILE: ../../../third_party/perfetto/src/base/string_view.cc +FILE: ../../../third_party/perfetto/src/base/string_view_unittest.cc +FILE: ../../../third_party/perfetto/src/base/string_writer_unittest.cc +FILE: ../../../third_party/perfetto/src/base/subprocess.cc +FILE: ../../../third_party/perfetto/src/base/subprocess_posix.cc +FILE: ../../../third_party/perfetto/src/base/subprocess_unittest.cc +FILE: ../../../third_party/perfetto/src/base/subprocess_windows.cc +FILE: ../../../third_party/perfetto/src/base/task_runner_unittest.cc +FILE: ../../../third_party/perfetto/src/base/temp_file.cc +FILE: ../../../third_party/perfetto/src/base/temp_file_unittest.cc +FILE: ../../../third_party/perfetto/src/base/thread_checker.cc +FILE: ../../../third_party/perfetto/src/base/thread_checker_unittest.cc +FILE: ../../../third_party/perfetto/src/base/thread_task_runner.cc +FILE: ../../../third_party/perfetto/src/base/thread_task_runner_unittest.cc +FILE: ../../../third_party/perfetto/src/base/thread_utils.cc +FILE: ../../../third_party/perfetto/src/base/time.cc +FILE: ../../../third_party/perfetto/src/base/time_unittest.cc +FILE: ../../../third_party/perfetto/src/base/unix_socket.cc +FILE: ../../../third_party/perfetto/src/base/unix_socket_unittest.cc +FILE: ../../../third_party/perfetto/src/base/unix_task_runner.cc +FILE: ../../../third_party/perfetto/src/base/utils.cc +FILE: ../../../third_party/perfetto/src/base/utils_unittest.cc +FILE: ../../../third_party/perfetto/src/base/uuid.cc +FILE: ../../../third_party/perfetto/src/base/uuid_unittest.cc +FILE: ../../../third_party/perfetto/src/base/version.cc +FILE: ../../../third_party/perfetto/src/base/virtual_destructors.cc +FILE: ../../../third_party/perfetto/src/base/waitable_event.cc +FILE: ../../../third_party/perfetto/src/base/watchdog_posix.cc +FILE: ../../../third_party/perfetto/src/base/watchdog_posix_unittest.cc +FILE: ../../../third_party/perfetto/src/base/watchdog_unittest.cc +FILE: ../../../third_party/perfetto/src/base/weak_ptr_unittest.cc +FILE: ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map.cc +FILE: ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map.h +FILE: ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map_benchmark.cc +FILE: ../../../third_party/perfetto/src/kallsyms/kernel_symbol_map_unittest.cc +FILE: ../../../third_party/perfetto/src/kallsyms/lazy_kernel_symbolizer.cc +FILE: ../../../third_party/perfetto/src/kallsyms/lazy_kernel_symbolizer.h +FILE: ../../../third_party/perfetto/src/kallsyms/lazy_kernel_symbolizer_unittest.cc +FILE: ../../../third_party/perfetto/src/kernel_utils/syscall_table.cc +FILE: ../../../third_party/perfetto/src/kernel_utils/syscall_table.h +FILE: ../../../third_party/perfetto/src/kernel_utils/syscalls_aarch32.h +FILE: ../../../third_party/perfetto/src/kernel_utils/syscalls_aarch64.h +FILE: ../../../third_party/perfetto/src/kernel_utils/syscalls_armeabi.h +FILE: ../../../third_party/perfetto/src/kernel_utils/syscalls_x86.h +FILE: ../../../third_party/perfetto/src/kernel_utils/syscalls_x86_64.h +FILE: ../../../third_party/perfetto/src/perfetto_cmd/config.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/config.h +FILE: ../../../third_party/perfetto/src/perfetto_cmd/config_unittest.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/main.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/packet_writer.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/packet_writer.h +FILE: ../../../third_party/perfetto/src/perfetto_cmd/packet_writer_unittest.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/pbtxt_to_pb.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/pbtxt_to_pb.h +FILE: ../../../third_party/perfetto/src/perfetto_cmd/pbtxt_to_pb_unittest.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd.h +FILE: ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd_android.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/perfetto_cmd_state.proto +FILE: ../../../third_party/perfetto/src/perfetto_cmd/rate_limiter.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/rate_limiter.h +FILE: ../../../third_party/perfetto/src/perfetto_cmd/rate_limiter_unittest.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/trigger_perfetto.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/trigger_perfetto_main.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/trigger_producer.cc +FILE: ../../../third_party/perfetto/src/perfetto_cmd/trigger_producer.h +FILE: ../../../third_party/perfetto/src/profiling/common/callstack_trie.cc +FILE: ../../../third_party/perfetto/src/profiling/common/callstack_trie.h +FILE: ../../../third_party/perfetto/src/profiling/common/interner.h +FILE: ../../../third_party/perfetto/src/profiling/common/interner_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/common/interning_output.cc +FILE: ../../../third_party/perfetto/src/profiling/common/interning_output.h +FILE: ../../../third_party/perfetto/src/profiling/common/proc_cmdline.cc +FILE: ../../../third_party/perfetto/src/profiling/common/proc_cmdline.h +FILE: ../../../third_party/perfetto/src/profiling/common/proc_cmdline_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/common/proc_utils.cc +FILE: ../../../third_party/perfetto/src/profiling/common/proc_utils.h +FILE: ../../../third_party/perfetto/src/profiling/common/proc_utils_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/common/producer_support.cc +FILE: ../../../third_party/perfetto/src/profiling/common/producer_support.h +FILE: ../../../third_party/perfetto/src/profiling/common/producer_support_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/common/profiler_guardrails.cc +FILE: ../../../third_party/perfetto/src/profiling/common/profiler_guardrails.h +FILE: ../../../third_party/perfetto/src/profiling/common/profiler_guardrails_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/common/unwind_support.cc +FILE: ../../../third_party/perfetto/src/profiling/common/unwind_support.h +FILE: ../../../third_party/perfetto/src/profiling/deobfuscator.cc +FILE: ../../../third_party/perfetto/src/profiling/deobfuscator.h +FILE: ../../../third_party/perfetto/src/profiling/deobfuscator_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/common_types.h +FILE: ../../../third_party/perfetto/src/profiling/perf/event_config.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/event_config.h +FILE: ../../../third_party/perfetto/src/profiling/perf/event_config_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/event_reader.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/event_reader.h +FILE: ../../../third_party/perfetto/src/profiling/perf/main.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/perf_producer.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/perf_producer.h +FILE: ../../../third_party/perfetto/src/profiling/perf/perf_producer_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/proc_descriptors.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/proc_descriptors.h +FILE: ../../../third_party/perfetto/src/profiling/perf/regs_parsing.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/regs_parsing.h +FILE: ../../../third_party/perfetto/src/profiling/perf/traced_perf.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/traced_perf.h +FILE: ../../../third_party/perfetto/src/profiling/perf/unwind_queue.h +FILE: ../../../third_party/perfetto/src/profiling/perf/unwind_queue_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/unwinding.cc +FILE: ../../../third_party/perfetto/src/profiling/perf/unwinding.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_parser.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_parser.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_parser_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_symbolizer.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_symbolizer.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/breakpad_symbolizer_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/elf.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/local_symbolizer.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/local_symbolizer.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/local_symbolizer_unittest.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/scoped_read_mmap.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/scoped_read_mmap_posix.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/scoped_read_mmap_windows.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/subprocess.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/subprocess_posix.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/subprocess_windows.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/symbolize_database.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/symbolize_database.h +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/symbolizer.cc +FILE: ../../../third_party/perfetto/src/profiling/symbolizer/symbolizer.h +FILE: ../../../third_party/perfetto/src/protozero/copyable_ptr_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/field.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_common.h +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_generator.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_generator.h +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_generator_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser.h +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser_fuzzer.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_bytecode_parser_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_util.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_util.h +FILE: ../../../third_party/perfetto/src/protozero/filtering/filter_util_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_filter.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_filter.h +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_filter_benchmark.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_filter_fuzzer.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_filter_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_tokenizer.h +FILE: ../../../third_party/perfetto/src/protozero/filtering/message_tokenizer_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/message.cc +FILE: ../../../third_party/perfetto/src/protozero/message_arena.cc +FILE: ../../../third_party/perfetto/src/protozero/message_arena_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/message_handle.cc +FILE: ../../../third_party/perfetto/src/protozero/message_handle_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/message_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/packed_repeated_fields.cc +FILE: ../../../third_party/perfetto/src/protozero/proto_decoder.cc +FILE: ../../../third_party/perfetto/src/protozero/proto_decoder_fuzzer.cc +FILE: ../../../third_party/perfetto/src/protozero/proto_decoder_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/proto_ring_buffer.cc +FILE: ../../../third_party/perfetto/src/protozero/proto_ring_buffer.h +FILE: ../../../third_party/perfetto/src/protozero/proto_ring_buffer_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/proto_utils_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/protoc_plugin/cppgen_plugin.cc +FILE: ../../../third_party/perfetto/src/protozero/protoc_plugin/protozero_plugin.cc +FILE: ../../../third_party/perfetto/src/protozero/scattered_heap_buffer.cc +FILE: ../../../third_party/perfetto/src/protozero/scattered_stream_null_delegate.cc +FILE: ../../../third_party/perfetto/src/protozero/scattered_stream_writer.cc +FILE: ../../../third_party/perfetto/src/protozero/scattered_stream_writer_unittest.cc +FILE: ../../../third_party/perfetto/src/protozero/static_buffer.cc +FILE: ../../../third_party/perfetto/src/protozero/virtual_destructors.cc +FILE: ../../../third_party/perfetto/src/shared_lib/stream_writer.cc +FILE: ../../../third_party/perfetto/src/shared_lib/stream_writer.h +FILE: ../../../third_party/perfetto/src/tracebox/tracebox.cc +FILE: ../../../third_party/perfetto/src/traceconv/deobfuscate_profile.cc +FILE: ../../../third_party/perfetto/src/traceconv/deobfuscate_profile.h +FILE: ../../../third_party/perfetto/src/traceconv/lite_fallbacks.cc +FILE: ../../../third_party/perfetto/src/traceconv/main.cc +FILE: ../../../third_party/perfetto/src/traceconv/pprof_builder.cc +FILE: ../../../third_party/perfetto/src/traceconv/proto_full_utils.cc +FILE: ../../../third_party/perfetto/src/traceconv/proto_full_utils.h +FILE: ../../../third_party/perfetto/src/traceconv/symbolize_profile.cc +FILE: ../../../third_party/perfetto/src/traceconv/symbolize_profile.h +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_hprof.cc +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_hprof.h +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_json.cc +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_json.h +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_profile.cc +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_profile.h +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_systrace.cc +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_systrace.h +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_text.cc +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_text.h +FILE: ../../../third_party/perfetto/src/traceconv/trace_to_text_unittest.cc +FILE: ../../../third_party/perfetto/src/traceconv/utils.cc +FILE: ../../../third_party/perfetto/src/traceconv/utils.h +FILE: ../../../third_party/perfetto/src/websocket_bridge/websocket_bridge.cc +FILE: ../../../third_party/perfetto/src/websocket_bridge/websocket_bridge.h +FILE: ../../../third_party/perfetto/src/websocket_bridge/websocket_bridge_main.cc +FILE: ../../../third_party/perfetto/traced_perf.rc +FILE: ../../../third_party/perfetto/ui/build.js +FILE: ../../../third_party/perfetto/ui/config/integrationtest_env.js +FILE: ../../../third_party/perfetto/ui/config/integrationtest_setup.js +FILE: ../../../third_party/perfetto/ui/config/integrationtest_teardown.js +FILE: ../../../third_party/perfetto/ui/config/jest.integrationtest.config.js +FILE: ../../../third_party/perfetto/ui/config/jest.unittest.config.js +FILE: ../../../third_party/perfetto/ui/config/rollup-serviceworker.config.js +FILE: ../../../third_party/perfetto/ui/config/rollup.config.js +FILE: ../../../third_party/perfetto/ui/src/assets/analyze_page.scss +FILE: ../../../third_party/perfetto/ui/src/assets/common.scss +FILE: ../../../third_party/perfetto/ui/src/assets/details.scss +FILE: ../../../third_party/perfetto/ui/src/assets/flags_page.scss +FILE: ../../../third_party/perfetto/ui/src/assets/home_page.scss +FILE: ../../../third_party/perfetto/ui/src/assets/metrics_page.scss +FILE: ../../../third_party/perfetto/ui/src/assets/modal.scss +FILE: ../../../third_party/perfetto/ui/src/assets/perfetto.scss +FILE: ../../../third_party/perfetto/ui/src/assets/record.scss +FILE: ../../../third_party/perfetto/ui/src/assets/sidebar.scss +FILE: ../../../third_party/perfetto/ui/src/assets/topbar.scss +FILE: ../../../third_party/perfetto/ui/src/assets/trace_info_page.scss +FILE: ../../../third_party/perfetto/ui/src/base/utils/index-browser.js +FILE: ../../../third_party/perfetto/ui/src/base/utils/index.js FILE: ../../../third_party/shaderc/DEVELOPMENT.howto.md FILE: ../../../third_party/shaderc/android_test/test.cpp FILE: ../../../third_party/shaderc/downloads.md @@ -5407,6 +6350,695 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================================================== +==================================================================================================== +LIBRARY: perfetto +ORIGIN: ../../../third_party/perfetto/LICENSE +TYPE: LicenseType.apache +FILE: ../../../third_party/perfetto/.git-blame-ignore-revs +FILE: ../../../third_party/perfetto/Android.bp.extras +FILE: ../../../third_party/perfetto/BUILD.extras +FILE: ../../../third_party/perfetto/MODULE_LICENSE_APACHE2 +FILE: ../../../third_party/perfetto/TEST_MAPPING +FILE: ../../../third_party/perfetto/buildtools/libcxx_config/__config_site +FILE: ../../../third_party/perfetto/docs/_coverpage.md +FILE: ../../../third_party/perfetto/docs/analysis/batch-trace-processor.md +FILE: ../../../third_party/perfetto/docs/analysis/common-queries.md +FILE: ../../../third_party/perfetto/docs/analysis/metrics.md +FILE: ../../../third_party/perfetto/docs/analysis/pivot-tables.md +FILE: ../../../third_party/perfetto/docs/analysis/trace-processor.md +FILE: ../../../third_party/perfetto/docs/case-studies/android-boot-tracing.md +FILE: ../../../third_party/perfetto/docs/case-studies/memory.md +FILE: ../../../third_party/perfetto/docs/concepts/buffers.md +FILE: ../../../third_party/perfetto/docs/concepts/clock-sync.md +FILE: ../../../third_party/perfetto/docs/concepts/config.md +FILE: ../../../third_party/perfetto/docs/concepts/detached-mode.md +FILE: ../../../third_party/perfetto/docs/concepts/service-model.md +FILE: ../../../third_party/perfetto/docs/contributing/build-instructions.md +FILE: ../../../third_party/perfetto/docs/contributing/chrome-branches.md +FILE: ../../../third_party/perfetto/docs/contributing/common-tasks.md +FILE: ../../../third_party/perfetto/docs/contributing/embedding.md +FILE: ../../../third_party/perfetto/docs/contributing/getting-started.md +FILE: ../../../third_party/perfetto/docs/contributing/perfetto-in-the-press.md +FILE: ../../../third_party/perfetto/docs/contributing/sdk-releasing.md +FILE: ../../../third_party/perfetto/docs/contributing/testing.md +FILE: ../../../third_party/perfetto/docs/contributing/ui-development.md +FILE: ../../../third_party/perfetto/docs/data-sources/android-game-intervention-list.md +FILE: ../../../third_party/perfetto/docs/data-sources/android-log.md +FILE: ../../../third_party/perfetto/docs/data-sources/atrace.md +FILE: ../../../third_party/perfetto/docs/data-sources/battery-counters.md +FILE: ../../../third_party/perfetto/docs/data-sources/cpu-freq.md +FILE: ../../../third_party/perfetto/docs/data-sources/cpu-scheduling.md +FILE: ../../../third_party/perfetto/docs/data-sources/frametimeline.md +FILE: ../../../third_party/perfetto/docs/data-sources/gpu.md +FILE: ../../../third_party/perfetto/docs/data-sources/java-heap-profiler.md +FILE: ../../../third_party/perfetto/docs/data-sources/memory-counters.md +FILE: ../../../third_party/perfetto/docs/data-sources/native-heap-profiler.md +FILE: ../../../third_party/perfetto/docs/data-sources/syscalls.md +FILE: ../../../third_party/perfetto/docs/data-sources/system-log.md +FILE: ../../../third_party/perfetto/docs/design-docs/api-and-abi.md +FILE: ../../../third_party/perfetto/docs/design-docs/batch-trace-processor.md +FILE: ../../../third_party/perfetto/docs/design-docs/checkpoint-atoms.md +FILE: ../../../third_party/perfetto/docs/design-docs/continuous-integration.md +FILE: ../../../third_party/perfetto/docs/design-docs/extensions.md +FILE: ../../../third_party/perfetto/docs/design-docs/heapprofd-design.md +FILE: ../../../third_party/perfetto/docs/design-docs/heapprofd-sampling.md +FILE: ../../../third_party/perfetto/docs/design-docs/heapprofd-wire-protocol.md +FILE: ../../../third_party/perfetto/docs/design-docs/life-of-a-tracing-session.md +FILE: ../../../third_party/perfetto/docs/design-docs/protozero.md +FILE: ../../../third_party/perfetto/docs/design-docs/security-model.md +FILE: ../../../third_party/perfetto/docs/faq.md +FILE: ../../../third_party/perfetto/docs/images/android_game_interventions.png +FILE: ../../../third_party/perfetto/docs/images/android_logs.png +FILE: ../../../third_party/perfetto/docs/images/annotation-counter.png +FILE: ../../../third_party/perfetto/docs/images/annotation-slice.png +FILE: ../../../third_party/perfetto/docs/images/api-and-abi.png +FILE: ../../../third_party/perfetto/docs/images/atrace-slices.png +FILE: ../../../third_party/perfetto/docs/images/battery-counters-ui.png +FILE: ../../../third_party/perfetto/docs/images/battery-counters.png +FILE: ../../../third_party/perfetto/docs/images/buffers.png +FILE: ../../../third_party/perfetto/docs/images/camera-slices.png +FILE: ../../../third_party/perfetto/docs/images/continuous-integration.png +FILE: ../../../third_party/perfetto/docs/images/counter-events.png +FILE: ../../../third_party/perfetto/docs/images/counters.png +FILE: ../../../third_party/perfetto/docs/images/cpu-bar-graphs.png +FILE: ../../../third_party/perfetto/docs/images/cpu-frequency.png +FILE: ../../../third_party/perfetto/docs/images/cpu-profile-diamond.png +FILE: ../../../third_party/perfetto/docs/images/cpu-profile-flame.png +FILE: ../../../third_party/perfetto/docs/images/cpu-sched-details.png +FILE: ../../../third_party/perfetto/docs/images/cpu-slice-track.png +FILE: ../../../third_party/perfetto/docs/images/cpu-zoomed.png +FILE: ../../../third_party/perfetto/docs/images/dataflow.svg +FILE: ../../../third_party/perfetto/docs/images/debug-slices-random.png +FILE: ../../../third_party/perfetto/docs/images/description.png +FILE: ../../../third_party/perfetto/docs/images/enable-profile-flame-graph.png +FILE: ../../../third_party/perfetto/docs/images/example_pd_graph.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/app-timelines.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/app-vsyncid.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/blue.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/green.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/light-green.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/red.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/select-app-slice.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/select-sf-slice-1.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/select-sf-slice-2.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/selection.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/sf-vsyncid.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/timeline_tracks.png +FILE: ../../../third_party/perfetto/docs/images/frametimeline/yellow.png +FILE: ../../../third_party/perfetto/docs/images/gpu-counters.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Android-Heap0.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Android-Heap1.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Android-Heap2.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Android-Heap3.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Architecture.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Service.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/Shared-Memory0.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/shmem-detail.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-design/shmem-overview.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-sampling/conditional-expected-error.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-sampling/expected-error.png +FILE: ../../../third_party/perfetto/docs/images/heapprofd-sampling/one-sample.png +FILE: ../../../third_party/perfetto/docs/images/java-flamegraph-focus.png +FILE: ../../../third_party/perfetto/docs/images/java-flamegraph.png +FILE: ../../../third_party/perfetto/docs/images/latency.png +FILE: ../../../third_party/perfetto/docs/images/lmk_lmkd.png +FILE: ../../../third_party/perfetto/docs/images/metrics-summary.png +FILE: ../../../third_party/perfetto/docs/images/native-flamegraph-focus.png +FILE: ../../../third_party/perfetto/docs/images/native-flamegraph.png +FILE: ../../../third_party/perfetto/docs/images/oom-score.png +FILE: ../../../third_party/perfetto/docs/images/oop-table-inheritance.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-btp-flattening.svg +FILE: ../../../third_party/perfetto/docs/images/perfetto-btp-overview.svg +FILE: ../../../third_party/perfetto/docs/images/perfetto-stack.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-stack.svg +FILE: ../../../third_party/perfetto/docs/images/perfetto-ui-channel-autopush-toggle.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-ui-channel-toggle.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-ui-channel.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-ui-disable-metrics.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-ui-screenshot.png +FILE: ../../../third_party/perfetto/docs/images/perfetto-ui-version.png +FILE: ../../../third_party/perfetto/docs/images/pivot-tables/pivot-table-area-selection.png +FILE: ../../../third_party/perfetto/docs/images/pivot-tables/pivot-table-design.png +FILE: ../../../third_party/perfetto/docs/images/pivot-tables/pivot-table-editor.png +FILE: ../../../third_party/perfetto/docs/images/pivot-tables/pivot-table-expanded-cell.png +FILE: ../../../third_party/perfetto/docs/images/pivot-tables/pivot-table-query.png +FILE: ../../../third_party/perfetto/docs/images/pivot-tables/pivot-table.png +FILE: ../../../third_party/perfetto/docs/images/power-rails.png +FILE: ../../../third_party/perfetto/docs/images/proc_stat.png +FILE: ../../../third_party/perfetto/docs/images/profile-diamond.png +FILE: ../../../third_party/perfetto/docs/images/protozero-ssw.png +FILE: ../../../third_party/perfetto/docs/images/rail-mode-debug-slices.png +FILE: ../../../third_party/perfetto/docs/images/record-trace-chrome.png +FILE: ../../../third_party/perfetto/docs/images/record-trace.png +FILE: ../../../third_party/perfetto/docs/images/rss_stat_and_mm_event.png +FILE: ../../../third_party/perfetto/docs/images/sched-slices.png +FILE: ../../../third_party/perfetto/docs/images/shmem-abi-concepts.png +FILE: ../../../third_party/perfetto/docs/images/shmem-abi-overview.png +FILE: ../../../third_party/perfetto/docs/images/shmem-abi-page.png +FILE: ../../../third_party/perfetto/docs/images/shmem-abi-spans.png +FILE: ../../../third_party/perfetto/docs/images/slices.png +FILE: ../../../third_party/perfetto/docs/images/socket-protocol.png +FILE: ../../../third_party/perfetto/docs/images/span-join.png +FILE: ../../../third_party/perfetto/docs/images/sys_stat_counters.png +FILE: ../../../third_party/perfetto/docs/images/syscalls.png +FILE: ../../../third_party/perfetto/docs/images/syssrv-apk-assets-focus.png +FILE: ../../../third_party/perfetto/docs/images/syssrv-apk-assets-two.png +FILE: ../../../third_party/perfetto/docs/images/thread-states.png +FILE: ../../../third_party/perfetto/docs/images/tp-table-inheritance.png +FILE: ../../../third_party/perfetto/docs/images/trace-processor.png +FILE: ../../../third_party/perfetto/docs/images/trace-rss-camera.png +FILE: ../../../third_party/perfetto/docs/images/trace-view.png +FILE: ../../../third_party/perfetto/docs/images/trace_config.png +FILE: ../../../third_party/perfetto/docs/images/trace_config_buffer_mapping.png +FILE: ../../../third_party/perfetto/docs/images/traceconv-summary.png +FILE: ../../../third_party/perfetto/docs/images/tracing-categories-chrome.png +FILE: ../../../third_party/perfetto/docs/images/tracing-protocol.png +FILE: ../../../third_party/perfetto/docs/images/track-events.png +FILE: ../../../third_party/perfetto/docs/images/track-timeline.png +FILE: ../../../third_party/perfetto/docs/images/tracks.png +FILE: ../../../third_party/perfetto/docs/images/userspace.png +FILE: ../../../third_party/perfetto/docs/instrumentation/heapprofd-api.md +FILE: ../../../third_party/perfetto/docs/instrumentation/interceptors.md +FILE: ../../../third_party/perfetto/docs/instrumentation/tracing-sdk.md +FILE: ../../../third_party/perfetto/docs/instrumentation/track-events.md +FILE: ../../../third_party/perfetto/docs/logo.png +FILE: ../../../third_party/perfetto/docs/quickstart/android-tracing.md +FILE: ../../../third_party/perfetto/docs/quickstart/callstack-sampling.md +FILE: ../../../third_party/perfetto/docs/quickstart/chrome-tracing.md +FILE: ../../../third_party/perfetto/docs/quickstart/heap-profiling.md +FILE: ../../../third_party/perfetto/docs/quickstart/linux-tracing.md +FILE: ../../../third_party/perfetto/docs/quickstart/trace-analysis.md +FILE: ../../../third_party/perfetto/docs/quickstart/traceconv.md +FILE: ../../../third_party/perfetto/docs/reference/heap_profile-cli.md +FILE: ../../../third_party/perfetto/docs/reference/perfetto-cli.md +FILE: ../../../third_party/perfetto/docs/toc.md +FILE: ../../../third_party/perfetto/docs/visualization/deep-linking-to-perfetto-ui.md +FILE: ../../../third_party/perfetto/docs/visualization/large-traces.md +FILE: ../../../third_party/perfetto/docs/visualization/perfetto-ui-release-process.md +FILE: ../../../third_party/perfetto/docs/visualization/perfetto-ui.md +FILE: ../../../third_party/perfetto/gn/standalone/wasm_typescript_declaration.d.ts +FILE: ../../../third_party/perfetto/tools/test_data.txt +FILE: ../../../third_party/perfetto/ui/config/gn_deprecation_banner.txt +FILE: ../../../third_party/perfetto/ui/package-lock.json +FILE: ../../../third_party/perfetto/ui/release/channels.json +FILE: ../../../third_party/perfetto/ui/src/assets/brand.png +FILE: ../../../third_party/perfetto/ui/src/assets/favicon.png +FILE: ../../../third_party/perfetto/ui/src/assets/hiring_banner.scss +FILE: ../../../third_party/perfetto/ui/src/assets/index.html +FILE: ../../../third_party/perfetto/ui/src/assets/logo-128.png +FILE: ../../../third_party/perfetto/ui/src/assets/logo-3d.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_atrace.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_battery_counters.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_board_voltage.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_cpu_coarse.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_cpu_fine.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_cpu_freq.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_cpu_voltage.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_frame_timeline.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_ftrace.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_gpu_mem_total.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_java_heap_dump.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_lmk.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_logcat.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_long_trace.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_mem_hifreq.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_meminfo.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_native_heap_profiler.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_one_shot.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_ps_stats.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_ring_buf.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_syscalls.png +FILE: ../../../third_party/perfetto/ui/src/assets/rec_vmstat.png +FILE: ../../../third_party/perfetto/ui/src/assets/typefaces.scss +FILE: ../../../third_party/perfetto/ui/src/base/binary_search.ts +FILE: ../../../third_party/perfetto/ui/src/base/binary_search_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/base/deferred.ts +FILE: ../../../third_party/perfetto/ui/src/base/deferred_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/base/generic_set.ts +FILE: ../../../third_party/perfetto/ui/src/base/http_utils.ts +FILE: ../../../third_party/perfetto/ui/src/base/logging.ts +FILE: ../../../third_party/perfetto/ui/src/base/string_utils.ts +FILE: ../../../third_party/perfetto/ui/src/base/string_utils_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/base/trace_config_utils.ts +FILE: ../../../third_party/perfetto/ui/src/chrome_extension/chrome_tracing_controller.ts +FILE: ../../../third_party/perfetto/ui/src/chrome_extension/devtools_socket.ts +FILE: ../../../third_party/perfetto/ui/src/chrome_extension/index.ts +FILE: ../../../third_party/perfetto/ui/src/chrome_extension/manifest.json +FILE: ../../../third_party/perfetto/ui/src/common/actions.ts +FILE: ../../../third_party/perfetto/ui/src/common/actions_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/aggregation_data.ts +FILE: ../../../third_party/perfetto/ui/src/common/arg_types.ts +FILE: ../../../third_party/perfetto/ui/src/common/array_buffer_builder.ts +FILE: ../../../third_party/perfetto/ui/src/common/cache_manager.ts +FILE: ../../../third_party/perfetto/ui/src/common/canvas_utils.ts +FILE: ../../../third_party/perfetto/ui/src/common/canvas_utils_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/channels.ts +FILE: ../../../third_party/perfetto/ui/src/common/colorizer.ts +FILE: ../../../third_party/perfetto/ui/src/common/colorizer_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/comparator_builder.ts +FILE: ../../../third_party/perfetto/ui/src/common/constants.ts +FILE: ../../../third_party/perfetto/ui/src/common/conversion_jobs.ts +FILE: ../../../third_party/perfetto/ui/src/common/empty_state.ts +FILE: ../../../third_party/perfetto/ui/src/common/engine.ts +FILE: ../../../third_party/perfetto/ui/src/common/errors.ts +FILE: ../../../third_party/perfetto/ui/src/common/feature_flags.ts +FILE: ../../../third_party/perfetto/ui/src/common/feature_flags_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/flamegraph_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/flamegraph_util.ts +FILE: ../../../third_party/perfetto/ui/src/common/http_rpc_engine.ts +FILE: ../../../third_party/perfetto/ui/src/common/immer_init.ts +FILE: ../../../third_party/perfetto/ui/src/common/logs.ts +FILE: ../../../third_party/perfetto/ui/src/common/metatracing.ts +FILE: ../../../third_party/perfetto/ui/src/common/metric_data.ts +FILE: ../../../third_party/perfetto/ui/src/common/plugin_api.ts +FILE: ../../../third_party/perfetto/ui/src/common/plugins.ts +FILE: ../../../third_party/perfetto/ui/src/common/plugins_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/proto_ring_buffer.ts +FILE: ../../../third_party/perfetto/ui/src/common/proto_ring_buffer_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/protos.ts +FILE: ../../../third_party/perfetto/ui/src/common/protos_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/queries.ts +FILE: ../../../third_party/perfetto/ui/src/common/query_result.ts +FILE: ../../../third_party/perfetto/ui/src/common/query_result_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/adb_connection_impl.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/adb_connection_over_websocket.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/adb_connection_over_webusb.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/adb_file_handler.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/auth/adb_auth.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/auth/adb_key_manager.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/auth/credentials_interfaces.d.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/chrome_traced_tracing_session.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/host_os_byte_stream.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/recording_config_utils.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/recording_error_handling.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/recording_interfaces_v2.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/recording_page_controller.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/recording_utils.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/android_websocket_target_factory.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/android_websocket_target_factory_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/android_webusb_target_factory.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/chrome_target_factory.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/chrome_target_factory_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/host_os_target_factory.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/index.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factories/virtual_target_factory.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/target_factory_registry.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/targets/android_target.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/targets/android_virtual_target.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/targets/android_websocket_target.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/targets/android_webusb_target.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/targets/chrome_target.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/targets/host_os_target.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/traced_tracing_session.ts +FILE: ../../../third_party/perfetto/ui/src/common/recordingV2/websocket_menu_controller.ts +FILE: ../../../third_party/perfetto/ui/src/common/registry.ts +FILE: ../../../third_party/perfetto/ui/src/common/registry_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/search_data.ts +FILE: ../../../third_party/perfetto/ui/src/common/state.ts +FILE: ../../../third_party/perfetto/ui/src/common/state_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/thread_state.ts +FILE: ../../../third_party/perfetto/ui/src/common/time.ts +FILE: ../../../third_party/perfetto/ui/src/common/time_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/common/track_data.ts +FILE: ../../../third_party/perfetto/ui/src/common/upload_utils.ts +FILE: ../../../third_party/perfetto/ui/src/common/wasm_engine_proxy.ts +FILE: ../../../third_party/perfetto/ui/src/common/worker_messages.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb_base_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb_interfaces.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb_jsdomtest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb_record_controller_jsdomtest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb_shell_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/adb_socket_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/counter_aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/cpu_aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/cpu_by_process_aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/frame_aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/slice_aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/aggregation/thread_aggregation_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/app_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/area_selection_handler.ts +FILE: ../../../third_party/perfetto/ui/src/controller/area_selection_handler_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/args_parser.ts +FILE: ../../../third_party/perfetto/ui/src/controller/chrome_proxy_record_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/consumer_port_types.ts +FILE: ../../../third_party/perfetto/ui/src/controller/controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/controller_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/cpu_profile_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/flamegraph_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/flow_events_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/globals.ts +FILE: ../../../third_party/perfetto/ui/src/controller/index.ts +FILE: ../../../third_party/perfetto/ui/src/controller/loading_manager.ts +FILE: ../../../third_party/perfetto/ui/src/controller/logs_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/metrics_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/permalink_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/pivot_table_redux_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/query_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/record_config_types.ts +FILE: ../../../third_party/perfetto/ui/src/controller/record_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/record_controller_interfaces.ts +FILE: ../../../third_party/perfetto/ui/src/controller/record_controller_jsdomtest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/search_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/search_controller_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/selection_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/trace_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/trace_error_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/trace_stream.ts +FILE: ../../../third_party/perfetto/ui/src/controller/track_controller.ts +FILE: ../../../third_party/perfetto/ui/src/controller/track_decider.ts +FILE: ../../../third_party/perfetto/ui/src/controller/validators.ts +FILE: ../../../third_party/perfetto/ui/src/controller/validators_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/controller/visualised_args_controller.ts +FILE: ../../../third_party/perfetto/ui/src/engine/index.ts +FILE: ../../../third_party/perfetto/ui/src/engine/wasm_bridge.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/aggregation_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/analytics.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/analyze_page.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/android_bug_tool.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/animation.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/base_slice_track.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/base_slice_track_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/checkerboard.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/chrome_slice_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/clipboard.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/cookie_consent.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/counter_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/cpu_profile_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/css_constants.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/details_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/drag/border_drag_strategy.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/drag/drag_strategy.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/drag/inner_drag_strategy.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/drag/outer_drag_strategy.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/drag_gesture_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/error_dialog.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/events.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/file_drop_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/flags_page.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/flamegraph.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/flamegraph_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/flamegraph_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/flow_events_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/flow_events_renderer.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/frontend_local_state.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/globals.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/gridline_helper.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/gridline_helper_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/help_modal.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/home_page.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/hsluv_cache.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/icons.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/index.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/keyboard_event_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/legacy_trace_viewer.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/live_reload.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/logs_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/metrics_page.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/modal.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/named_slice_track.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/notes_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/overview_timeline_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/pages.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/pan_and_zoom_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/panel_container.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/perf.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/perf_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/pivot_table_redux.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/pivot_table_redux_argument_popup.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/pivot_table_redux_query_generator.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/pivot_table_redux_types.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/popup_menu.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/post_message_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/publish.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/query_history.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/query_table.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/raf_scheduler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/rate_limiters.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/record_config.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/record_page.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/record_page_v2.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/record_widgets.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/advanced_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/android_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/chrome_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/cpu_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/gpu_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/memory_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/power_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/recording_multiple_choice.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/recording_sections.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/recording_settings.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/recording_ui_utils.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/reset_interface_modal.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/recording/reset_target_modal.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/reorderable_cells.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/router.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/router_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/rpc_http_dialog.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/scroll_helper.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/search_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/service_worker_controller.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/sidebar.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/slice.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/slice_details_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/slice_layout.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/slice_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/task_tracker.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/task_tracker_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/thread_state_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/tickmark_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/time_axis_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/time_scale.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/time_scale_unittest.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/time_selection_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/topbar.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/trace_attrs.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/trace_converter.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/trace_info_page.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/trace_url_handler.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/track.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/track_group_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/track_panel.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/track_registry.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/vertical_line_helper.ts +FILE: ../../../third_party/perfetto/ui/src/frontend/viewer_page.ts +FILE: ../../../third_party/perfetto/ui/src/service_worker/service_worker.ts +FILE: ../../../third_party/perfetto/ui/src/service_worker/tsconfig.json +FILE: ../../../third_party/perfetto/ui/src/traceconv/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/actual_frames/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/android_log/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/async_slices/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/chrome_scroll_jank/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/chrome_slices/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/counter/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/cpu_freq/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/cpu_profile/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/cpu_slices/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/debug_slices/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/expected_frames/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/generic_slice_track/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/heap_profile/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/null_track/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/perf_samples_profile/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/process_scheduling/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/process_summary/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/thread_state/index.ts +FILE: ../../../third_party/perfetto/ui/src/tracks/visualised_args/index.ts +FILE: ../../../third_party/perfetto/ui/tsconfig.base.json +FILE: ../../../third_party/perfetto/ui/tsconfig.json +---------------------------------------------------------------------------------------------------- +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright (c) 2017, The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +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. +==================================================================================================== + ==================================================================================================== LIBRARY: libcxx LIBRARY: libcxxabi @@ -34844,7 +36476,6 @@ ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart + ../ ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart + ../../../third_party/dart/LICENSE -ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/empty_source.dart + ../../../third_party/dart/LICENSE @@ -34864,15 +36495,16 @@ ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart + . ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart + ../../../third_party/dart/LICENSE -ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/array_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/bool_patch.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/date_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/integers_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/map_patch.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/string_buffer_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/async/async.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/async/async_error.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/async/broadcast_stream_controller.dart + ../../../third_party/dart/LICENSE @@ -35210,7 +36842,6 @@ FILE: ../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart -FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/empty_source.dart @@ -35230,15 +36861,16 @@ FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart -FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/array_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/bool_patch.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/date_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/integers_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/map_patch.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/vm_shared/lib/string_buffer_patch.dart FILE: ../../../third_party/dart/sdk/lib/async/async.dart FILE: ../../../third_party/dart/sdk/lib/async/async_error.dart FILE: ../../../third_party/dart/sdk/lib/async/broadcast_stream_controller.dart @@ -40211,12 +41843,10 @@ ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/bool.dart + ../../. ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/class_id.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/convert_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/core_patch.dart + ../../../third_party/dart/LICENSE -ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/date_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/deferred.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/developer.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/double.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/errors_patch.dart + ../../../third_party/dart/LICENSE -ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/expando_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/growable_list.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/hash_factories.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/identical_patch.dart + ../../../third_party/dart/LICENSE @@ -40236,7 +41866,6 @@ ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/regexp_patch.dart + ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/simd_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/stack_trace_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/stopwatch_patch.dart + ../../../third_party/dart/LICENSE -ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/string_buffer_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/string_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/symbol_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/timer_patch.dart + ../../../third_party/dart/LICENSE @@ -40297,12 +41926,10 @@ FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/bool.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/class_id.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/convert_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/core_patch.dart -FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/date_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/deferred.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/developer.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/double.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/errors_patch.dart -FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/expando_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/growable_list.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/hash_factories.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/identical_patch.dart @@ -40322,7 +41949,6 @@ FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/regexp_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/simd_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/stack_trace_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/stopwatch_patch.dart -FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/string_buffer_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/string_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/symbol_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/timer_patch.dart @@ -40370,15 +41996,33 @@ LIBRARY: dart ORIGIN: ../../../third_party/dart/runtime/bin/main_impl.h + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/runtime/vm/ffi/native_assets.cc + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/runtime/vm/ffi/native_assets.h + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/js_runtime/lib/records.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/js_shared/lib/js_interop_patch.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/js_shared/lib/js_types.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/closure.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/date_patch_patch.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/js_interop_patch.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/js_types.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/string_buffer_create.dart + ../../../third_party/dart/LICENSE +ORIGIN: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/weak_patch.dart + ../../../third_party/dart/LICENSE ORIGIN: ../../../third_party/dart/sdk/lib/_js_interop/js_interop.dart + ../../../third_party/dart/LICENSE TYPE: LicenseType.bsd FILE: ../../../third_party/dart/runtime/bin/main_impl.h FILE: ../../../third_party/dart/runtime/vm/ffi/native_assets.cc FILE: ../../../third_party/dart/runtime/vm/ffi/native_assets.h +FILE: ../../../third_party/dart/sdk/lib/_internal/js_dev_runtime/patch/js_allow_interop_patch.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/js_runtime/lib/js_allow_interop_patch.dart FILE: ../../../third_party/dart/sdk/lib/_internal/js_runtime/lib/records.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/js_shared/lib/js_interop_patch.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/js_shared/lib/js_types.dart FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/closure.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/date_patch_patch.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/js_interop_patch.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/js_types.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/string_buffer_create.dart +FILE: ../../../third_party/dart/sdk/lib/_internal/wasm/lib/weak_patch.dart FILE: ../../../third_party/dart/sdk/lib/_js_interop/js_interop.dart ---------------------------------------------------------------------------------------------------- Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file @@ -63922,4 +65566,4 @@ freely, subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. ==================================================================================================== -Total license count: 871 +Total license count: 872 diff --git a/ci/licenses_golden/tool_signature b/ci/licenses_golden/tool_signature index 55e23e24539b1..7d300f7b83bf6 100644 --- a/ci/licenses_golden/tool_signature +++ b/ci/licenses_golden/tool_signature @@ -1,2 +1,2 @@ -Signature: ccf8317fb6539998c8f4ff0a96d7f698 +Signature: 90df0faca032ae220230aef5e61ca020 diff --git a/ci/scan_flattened_deps.py b/ci/scan_flattened_deps.py index 2f51bdf09b683..67759b3d710a0 100644 --- a/ci/scan_flattened_deps.py +++ b/ci/scan_flattened_deps.py @@ -17,6 +17,7 @@ import subprocess import sys from urllib import request +from compatibility_helper import byte_str_decode SCRIPT_DIR = os.path.dirname(sys.argv[0]) CHECKOUT_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) @@ -206,7 +207,9 @@ def get_common_ancestor_commit(dep, deps_list): 'git --git-dir ' + temp_dep_dir + '/.git remote show upstream ' + "| sed -n \'/HEAD branch/s/.*: //p\'", shell=True - ).decode().strip() + ) + default_branch = byte_str_decode(default_branch) + default_branch = default_branch.strip() print( 'default_branch found: {default_branch}'.format( default_branch=default_branch @@ -223,7 +226,8 @@ def get_common_ancestor_commit(dep, deps_list): "--format=\'%(objectname:short)\' refs/heads/upstream", shell=True ) - commit = commit.decode().strip() + commit = byte_str_decode(commit) + commit = commit.strip() # perform merge-base on most recent default branch commit and pinned mirror commit ancestor_commit = subprocess.check_output( @@ -232,7 +236,8 @@ def get_common_ancestor_commit(dep, deps_list): ), shell=True ) - ancestor_commit = ancestor_commit.decode().strip() + ancestor_commit = byte_str_decode(ancestor_commit) + ancestor_commit = ancestor_commit.strip() print('Ancestor commit: ' + ancestor_commit) return ancestor_commit except subprocess.CalledProcessError as error: diff --git a/common/settings.h b/common/settings.h index 39017dbc1cd40..75f1e262fb0eb 100644 --- a/common/settings.h +++ b/common/settings.h @@ -161,23 +161,23 @@ struct Settings { // Platform.executable from dart:io. If unknown, defaults to "Flutter". std::string executable_name = "Flutter"; - // Observatory settings + // VM Service settings // Whether the Dart VM service should be enabled. - bool enable_observatory = false; + bool enable_vm_service = false; - // Whether to publish the observatory URL over mDNS. + // Whether to publish the VM Service URL over mDNS. // On iOS 14 this prompts a local network permission dialog, // which cannot be accepted or dismissed in a CI environment. - bool enable_observatory_publication = true; + bool enable_vm_service_publication = true; // The IP address to which the Dart VM service is bound. - std::string observatory_host; + std::string vm_service_host; // The port to which the Dart VM service is bound. When set to `0`, a free // port will be automatically selected by the OS. A message is logged on the // target indicating the URL at which the VM service can be accessed. - uint32_t observatory_port = 0; + uint32_t vm_service_port = 0; // Determines whether an authentication code is required to communicate with // the VM service. diff --git a/display_list/display_list_benchmarks.cc b/display_list/display_list_benchmarks.cc index efc01e3b4d540..03dd0a49172c0 100644 --- a/display_list/display_list_benchmarks.cc +++ b/display_list/display_list_benchmarks.cc @@ -7,6 +7,7 @@ #include "flutter/display_list/display_list_flags.h" #include "third_party/skia/include/core/SkPoint.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkTextBlob.h" namespace flutter { diff --git a/display_list/display_list_benchmarks_gl.cc b/display_list/display_list_benchmarks_gl.cc index a86a27dbd48e9..fcf5f967d4884 100644 --- a/display_list/display_list_benchmarks_gl.cc +++ b/display_list/display_list_benchmarks_gl.cc @@ -6,6 +6,7 @@ #include "flutter/display_list/display_list_benchmarks.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkSurface.h" namespace flutter { namespace testing { diff --git a/display_list/display_list_benchmarks_gl.h b/display_list/display_list_benchmarks_gl.h index 0c0d05aa85437..e00eaeb118b80 100644 --- a/display_list/display_list_benchmarks_gl.h +++ b/display_list/display_list_benchmarks_gl.h @@ -6,8 +6,11 @@ #define FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_GL_H_ #include "flutter/display_list/display_list_benchmarks_canvas_provider.h" + #include "flutter/testing/test_gl_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/display_list/display_list_benchmarks_metal.cc b/display_list/display_list_benchmarks_metal.cc index 904fa7d58b4c3..2437663d62024 100644 --- a/display_list/display_list_benchmarks_metal.cc +++ b/display_list/display_list_benchmarks_metal.cc @@ -6,6 +6,7 @@ #include "flutter/display_list/display_list_benchmarks.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkSurface.h" namespace flutter { namespace testing { diff --git a/display_list/display_list_benchmarks_metal.h b/display_list/display_list_benchmarks_metal.h index 3df8a11a8b850..bb8f635cdadbb 100644 --- a/display_list/display_list_benchmarks_metal.h +++ b/display_list/display_list_benchmarks_metal.h @@ -8,6 +8,8 @@ #include "flutter/display_list/display_list_benchmarks_canvas_provider.h" #include "flutter/testing/test_metal_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/display_list/display_list_benchmarks_software.cc b/display_list/display_list_benchmarks_software.cc index f05bf95b05733..7e2e7f40a53af 100644 --- a/display_list/display_list_benchmarks_software.cc +++ b/display_list/display_list_benchmarks_software.cc @@ -5,6 +5,8 @@ #include "flutter/display_list/display_list_benchmarks_software.h" #include "flutter/display_list/display_list_benchmarks.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index eca8e94d74909..91ec814c53f7f 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -21,6 +21,8 @@ #include "flutter/testing/display_list_testing.h" #include "flutter/testing/testing.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/examples/vulkan_glfw/CMakeLists.txt b/examples/vulkan_glfw/CMakeLists.txt index 6b6a1ed1b72eb..e107a37d24fae 100644 --- a/examples/vulkan_glfw/CMakeLists.txt +++ b/examples/vulkan_glfw/CMakeLists.txt @@ -40,7 +40,7 @@ set(GLFW_VULKAN_STATIC OFF CACHE BOOL "" FORCE) add_subdirectory(${GLFW_REPOSITORY} build_glfw) target_link_libraries(${EXE_NAME} PRIVATE glfw) -target_include_directories(${EXE_NAME} PRIVATE $(GLFW_REPOSITORY)/include) +target_include_directories(${EXE_NAME} PRIVATE ${GLFW_REPOSITORY}/include) # Dependency: Flutter Engine diff --git a/examples/vulkan_glfw/src/main.cc b/examples/vulkan_glfw/src/main.cc index e97a874afdd95..7d226055b56ed 100644 --- a/examples/vulkan_glfw/src/main.cc +++ b/examples/vulkan_glfw/src/main.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 #include #include #include diff --git a/flow/instrumentation.h b/flow/instrumentation.h index 618197efc7a7f..acf2c013eaea6 100644 --- a/flow/instrumentation.h +++ b/flow/instrumentation.h @@ -10,7 +10,9 @@ #include "flutter/fml/macros.h" #include "flutter/fml/time/time_delta.h" #include "flutter/fml/time/time_point.h" + #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkSurface.h" namespace flutter { diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index f51d8d5ca2fae..9f791ef6064ac 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -11,6 +11,8 @@ #include "flutter/fml/macros.h" #include "flutter/testing/mock_canvas.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/flow/surface_frame.cc b/flow/surface_frame.cc index f9b162f8f98e9..dd70b478f52c6 100644 --- a/flow/surface_frame.cc +++ b/flow/surface_frame.cc @@ -9,6 +9,8 @@ #include "flutter/fml/logging.h" #include "flutter/fml/trace_event.h" + +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" namespace flutter { diff --git a/flow/surface_frame.h b/flow/surface_frame.h index f97281ac9281c..ecacb5b8063c4 100644 --- a/flow/surface_frame.h +++ b/flow/surface_frame.h @@ -12,6 +12,7 @@ #include "flutter/display_list/display_list_canvas_recorder.h" #include "flutter/fml/macros.h" #include "flutter/fml/time/time_point.h" + #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkSurface.h" diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 623b311b08347..d7bcab300b4df 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -381,6 +381,59 @@ TEST_P(AiksTest, CanRenderLinearGradient) { ASSERT_TRUE(OpenPlaygroundHere(callback)); } +TEST_P(AiksTest, CanRenderLinearGradientWithOverlappingStops) { + auto callback = [&](AiksContext& renderer, RenderTarget& render_target) { + const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"}; + const Entity::TileMode tile_modes[] = { + Entity::TileMode::kClamp, Entity::TileMode::kRepeat, + Entity::TileMode::kMirror, Entity::TileMode::kDecal}; + + static int selected_tile_mode = 0; + static float alpha = 1; + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::SliderFloat("Alpha", &alpha, 0, 1); + ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names, + sizeof(tile_mode_names) / sizeof(char*)); + static Matrix matrix = { + 1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1 // + }; + std::string label = "##1"; + for (int i = 0; i < 4; i++) { + ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]), + 4, NULL, NULL, "%.2f", 0); + label[2]++; + } + ImGui::End(); + + Canvas canvas; + Paint paint; + canvas.Translate({100.0, 100.0, 0}); + auto tile_mode = tile_modes[selected_tile_mode]; + paint.color_source = [tile_mode]() { + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}}; + std::vector stops = {0.0, 0.5, 0.5, 1.0}; + + auto contents = std::make_shared(); + contents->SetEndPoints({0, 0}, {500, 500}); + contents->SetColors(std::move(colors)); + contents->SetStops(std::move(stops)); + contents->SetTileMode(tile_mode); + contents->SetEffectTransform(matrix); + return contents; + }; + paint.color = Color(1.0, 1.0, 1.0, alpha); + canvas.DrawRect({0, 0, 500, 500}, paint); + return renderer.Render(canvas.EndRecordingAsPicture(), render_target); + }; + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + TEST_P(AiksTest, CanRenderLinearGradientManyColors) { auto callback = [&](AiksContext& renderer, RenderTarget& render_target) { const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"}; @@ -1067,7 +1120,8 @@ bool RenderTextInCanvas(const std::shared_ptr& context, Canvas& canvas, const std::string& text, const std::string& font_fixture, - Scalar font_size = 50.0) { + Scalar font_size = 50.0, + Scalar alpha = 1.0) { Scalar baseline = 200.0; Point text_position = {100, baseline}; @@ -1094,7 +1148,7 @@ bool RenderTextInCanvas(const std::shared_ptr& context, auto frame = TextFrameFromTextBlob(blob); Paint text_paint; - text_paint.color = Color::Yellow(); + text_paint.color = Color::Yellow().WithAlpha(alpha); canvas.DrawTextFrame(frame, text_position, text_paint); return true; } @@ -1117,7 +1171,8 @@ TEST_P(AiksTest, CanRenderItalicizedText) { TEST_P(AiksTest, CanRenderEmojiTextFrame) { Canvas canvas; - ASSERT_TRUE(RenderTextInCanvas(GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", + ASSERT_TRUE(RenderTextInCanvas(GetContext(), canvas, + "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", #if FML_OS_MACOSX "Apple Color Emoji.ttc")); #else @@ -1126,6 +1181,18 @@ TEST_P(AiksTest, CanRenderEmojiTextFrame) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, CanRenderEmojiTextFrameWithAlpha) { + Canvas canvas; + ASSERT_TRUE(RenderTextInCanvas(GetContext(), canvas, + "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", +#if FML_OS_MACOSX + "Apple Color Emoji.ttc", 50, 0.5)); +#else + "NotoColorEmoji.ttf", 50, 0.5)); +#endif + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + TEST_P(AiksTest, CanRenderTextInSaveLayer) { Canvas canvas; canvas.DrawPaint({.color = Color::White()}); @@ -1788,5 +1855,37 @@ TEST_P(AiksTest, SceneColorSource) { ASSERT_TRUE(OpenPlaygroundHere(callback)); } +TEST_P(AiksTest, PaintWithFilters) { + // validate that a paint with a color filter "HasFilters", no other filters + // impact this setting. + Paint paint; + + ASSERT_FALSE(paint.HasColorFilter()); + + paint.color_filter = [](FilterInput::Ref input) { + return ColorFilterContents::MakeBlend(BlendMode::kSourceOver, + {std::move(input)}, Color::Blue()); + }; + + ASSERT_TRUE(paint.HasColorFilter()); + + paint.image_filter = [](const FilterInput::Ref& input, + const Matrix& effect_transform) { + return FilterContents::MakeGaussianBlur( + input, Sigma(1.0), Sigma(1.0), FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp, effect_transform); + }; + + ASSERT_TRUE(paint.HasColorFilter()); + + paint.mask_blur_descriptor = {}; + + ASSERT_TRUE(paint.HasColorFilter()); + + paint.color_filter = std::nullopt; + + ASSERT_FALSE(paint.HasColorFilter()); +} + } // namespace testing } // namespace impeller diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 536fb378df21a..6ba4d872f619b 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -306,6 +306,7 @@ void Canvas::DrawImageRect(const std::shared_ptr& image, contents->SetSourceRect(source); contents->SetSamplerDescriptor(std::move(sampler)); contents->SetOpacity(paint.color.alpha); + contents->SetDeferApplyingOpacity(paint.HasColorFilter()); Entity entity; entity.SetBlendMode(paint.blend_mode); @@ -377,7 +378,7 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame, GetCurrentPass().AddEntity(entity); } -void Canvas::DrawVertices(std::unique_ptr vertices, +void Canvas::DrawVertices(const std::shared_ptr& vertices, BlendMode blend_mode, const Paint& paint) { Entity entity; @@ -385,21 +386,24 @@ void Canvas::DrawVertices(std::unique_ptr vertices, entity.SetStencilDepth(GetStencilDepth()); entity.SetBlendMode(paint.blend_mode); - if (paint.color_source.has_value()) { - auto& source = paint.color_source.value(); - auto contents = source(); - contents->SetGeometry(std::move(vertices)); - contents->SetAlpha(paint.color.alpha); - entity.SetContents(paint.WithFilters(std::move(contents), true)); - } else { - std::shared_ptr contents = - std::make_shared(); - contents->SetColor(paint.color); - contents->SetBlendMode(blend_mode); - contents->SetGeometry(std::move(vertices)); - entity.SetContents(paint.WithFilters(std::move(contents), true)); + if (!vertices->HasVertexColors()) { + auto contents = paint.CreateContentsForGeometry(vertices); + entity.SetContents(paint.WithFilters(std::move(contents))); + GetCurrentPass().AddEntity(entity); + return; } + auto src_paint = paint; + src_paint.color = paint.color.WithAlpha(1.0); + auto src_contents = src_paint.CreateContentsForGeometry(vertices); + + auto contents = std::make_shared(); + contents->SetAlpha(paint.color.alpha); + contents->SetBlendMode(blend_mode); + contents->SetGeometry(vertices); + contents->SetSourceContents(std::move(src_contents)); + entity.SetContents(paint.WithFilters(std::move(contents))); + GetCurrentPass().AddEntity(entity); } @@ -414,11 +418,6 @@ void Canvas::DrawAtlas(const std::shared_ptr& atlas, if (!atlas) { return; } - auto size = atlas->GetSize(); - - if (size.IsEmpty()) { - return; - } std::shared_ptr contents = std::make_shared(); contents->SetColors(std::move(colors)); diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index aacbe513b2e99..35144e61a4aec 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -97,7 +97,7 @@ class Canvas { Point position, const Paint& paint); - void DrawVertices(std::unique_ptr vertices, + void DrawVertices(const std::shared_ptr& vertices, BlendMode blend_mode, const Paint& paint); diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index 04b93e248bea1..d0cbc7b0a1c4f 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -40,6 +40,21 @@ std::shared_ptr Paint::CreateContentsForGeometry( return solid_color; } +std::shared_ptr Paint::CreateContentsForGeometry( + const std::shared_ptr& geometry) const { + if (color_source.has_value()) { + auto& source = color_source.value(); + auto contents = source(); + contents->SetGeometry(geometry); + contents->SetAlpha(color.alpha); + return contents; + } + auto solid_color = std::make_shared(); + solid_color->SetGeometry(geometry); + solid_color->SetColor(color); + return solid_color; +} + std::shared_ptr Paint::WithFilters( std::shared_ptr input, std::optional is_solid_color, @@ -107,4 +122,8 @@ std::shared_ptr Paint::MaskBlurDescriptor::CreateMaskBlur( effect_transform); } +bool Paint::HasColorFilter() const { + return color_filter.has_value(); +} + } // namespace impeller diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index 7db7b4223a49e..f18aca1953c3e 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -106,6 +106,12 @@ struct Paint { std::shared_ptr CreateContentsForGeometry( std::unique_ptr geometry) const; + std::shared_ptr CreateContentsForGeometry( + const std::shared_ptr& geometry) const; + + /// @brief Whether this paint has a color filter that can apply opacity + bool HasColorFilter() const; + private: std::shared_ptr WithMaskBlur(std::shared_ptr input, bool is_solid_color, diff --git a/impeller/compiler/BUILD.gn b/impeller/compiler/BUILD.gn index dc06f32fd421d..49a5ec2ab66a6 100644 --- a/impeller/compiler/BUILD.gn +++ b/impeller/compiler/BUILD.gn @@ -52,6 +52,8 @@ impeller_component("compiler_lib") { "switches.h", "types.cc", "types.h", + "uniform_sorter.cc", + "uniform_sorter.h", ] public_deps = [ diff --git a/impeller/compiler/compiler.cc b/impeller/compiler/compiler.cc index fdb9ebd8f9130..a3a67c8f8d56c 100644 --- a/impeller/compiler/compiler.cc +++ b/impeller/compiler/compiler.cc @@ -16,6 +16,7 @@ #include "impeller/compiler/includer.h" #include "impeller/compiler/logger.h" #include "impeller/compiler/types.h" +#include "impeller/compiler/uniform_sorter.h" namespace impeller { namespace compiler { @@ -36,42 +37,49 @@ static CompilerBackend CreateMSLCompiler(const spirv_cross::ParsedIR& ir, spirv_cross::CompilerMSL::Options::make_msl_version(1, 2); sl_compiler->set_msl_options(sl_options); - // Set metal resource mappings to be consistent with location based mapping - // used on other backends when creating fragment shaders. This doesn't seem - // to work with the generated bindings for compute shaders, nor for certain - // shaders in the flutter/engine tree. - if (source_options.remap_samplers) { - std::vector sampler_offsets; - ir.for_each_typed_id( - [&](uint32_t, const spirv_cross::SPIRVariable& var) { - if (var.storage != spv::StorageClassUniformConstant) { - return; - } - const auto spir_type = sl_compiler->get_type(var.basetype); - auto location = sl_compiler->get_decoration( - var.self, spv::Decoration::DecorationLocation); - if (spir_type.basetype == - spirv_cross::SPIRType::BaseType::SampledImage) { - sampler_offsets.push_back(location); - } - }); - if (sampler_offsets.size() > 0) { - auto start_offset = - *std::min_element(sampler_offsets.begin(), sampler_offsets.end()); - for (auto offset : sampler_offsets) { - sl_compiler->add_msl_resource_binding({ - .stage = spv::ExecutionModel::ExecutionModelFragment, - .basetype = spirv_cross::SPIRType::BaseType::SampledImage, - .binding = offset, - .count = 1u, - // A sampled image is both an image and a sampler, so both - // offsets need to be set or depending on the partiular shader - // the bindings may be incorrect. - .msl_texture = offset - start_offset, - .msl_sampler = offset - start_offset, - }); - } - } + // Sort the float and sampler uniforms according to their declared/decorated + // order. For user authored fragment shaders, the API for setting uniform + // values uses the index of the uniform in the declared order. By default, the + // metal backend of spirv-cross will order uniforms according to usage. To fix + // this, we use the sorted order and the add_msl_resource_binding API to force + // the ordering to match the declared order. Note that while this code runs + // for all compiled shaders, it will only affect fragment shaders due to the + // specified stage. + auto floats = + SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float); + auto images = + SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage); + + uint32_t buffer_offset = 0; + uint32_t sampler_offset = 0; + for (auto& float_id : floats) { + sl_compiler->add_msl_resource_binding( + {.stage = spv::ExecutionModel::ExecutionModelFragment, + .basetype = spirv_cross::SPIRType::BaseType::Float, + .desc_set = sl_compiler->get_decoration(float_id, + spv::DecorationDescriptorSet), + .binding = + sl_compiler->get_decoration(float_id, spv::DecorationBinding), + .count = 1u, + .msl_buffer = buffer_offset}); + buffer_offset++; + } + for (auto& image_id : images) { + sl_compiler->add_msl_resource_binding({ + .stage = spv::ExecutionModel::ExecutionModelFragment, + .basetype = spirv_cross::SPIRType::BaseType::SampledImage, + .desc_set = + sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet), + .binding = + sl_compiler->get_decoration(image_id, spv::DecorationBinding), + .count = 1u, + // A sampled image is both an image and a sampler, so both + // offsets need to be set or depending on the partiular shader + // the bindings may be incorrect. + .msl_texture = sampler_offset, + .msl_sampler = sampler_offset, + }); + sampler_offset++; } return CompilerBackend(sl_compiler); diff --git a/impeller/compiler/compiler_backend.h b/impeller/compiler/compiler_backend.h index b8225fce186ef..deb57e9235107 100644 --- a/impeller/compiler/compiler_backend.h +++ b/impeller/compiler/compiler_backend.h @@ -44,6 +44,8 @@ struct CompilerBackend { const spirv_cross::Compiler* operator->() const; + spirv_cross::Compiler* GetCompiler(); + operator bool() const; enum class ExtendedResourceIndex { @@ -55,8 +57,6 @@ struct CompilerBackend { const spirv_cross::Compiler* GetCompiler() const; - spirv_cross::Compiler* GetCompiler(); - private: Type type_ = Type::kMSL; Compiler compiler_; diff --git a/impeller/compiler/impellerc_main.cc b/impeller/compiler/impellerc_main.cc index f412c21d86495..f25ecd3f86509 100644 --- a/impeller/compiler/impellerc_main.cc +++ b/impeller/compiler/impellerc_main.cc @@ -73,7 +73,6 @@ bool Main(const fml::CommandLine& command_line) { switches.source_file_name, options.type, options.source_language, switches.entry_point); options.json_format = switches.json_format; - options.remap_samplers = switches.remap_samplers; options.gles_language_version = switches.gles_language_version; Reflector::Options reflector_options; diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index 9b911dfef4ded..09ad507111f9d 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -16,6 +16,7 @@ #include "impeller/base/strings.h" #include "impeller/base/validation.h" #include "impeller/compiler/code_gen_template.h" +#include "impeller/compiler/uniform_sorter.h" #include "impeller/compiler/utilities.h" #include "impeller/geometry/matrix.h" #include "impeller/geometry/scalar.h" @@ -359,23 +360,25 @@ std::shared_ptr Reflector::GenerateRuntimeStageData() const { if (sksl_data_) { data->SetSkSLData(sksl_data_); } - ir_->for_each_typed_id( - [&](uint32_t, const spirv_cross::SPIRVariable& var) { - if (var.storage != spv::StorageClassUniformConstant) { - return; - } - const auto spir_type = compiler_->get_type(var.basetype); - UniformDescription uniform_description; - uniform_description.name = compiler_->get_name(var.self); - uniform_description.location = compiler_->get_decoration( - var.self, spv::Decoration::DecorationLocation); - uniform_description.type = spir_type.basetype; - uniform_description.rows = spir_type.vecsize; - uniform_description.columns = spir_type.columns; - uniform_description.bit_width = spir_type.width; - uniform_description.array_elements = GetArrayElements(spir_type); - data->AddUniformDescription(std::move(uniform_description)); - }); + + // Sort the IR so that the uniforms are in declaration order. + std::vector uniforms = + SortUniforms(ir_.get(), compiler_.GetCompiler()); + + for (auto& sorted_id : uniforms) { + auto var = ir_->ids[sorted_id].get(); + const auto spir_type = compiler_->get_type(var.basetype); + UniformDescription uniform_description; + uniform_description.name = compiler_->get_name(var.self); + uniform_description.location = compiler_->get_decoration( + var.self, spv::Decoration::DecorationLocation); + uniform_description.type = spir_type.basetype; + uniform_description.rows = spir_type.vecsize; + uniform_description.columns = spir_type.columns; + uniform_description.bit_width = spir_type.width; + uniform_description.array_elements = GetArrayElements(spir_type); + data->AddUniformDescription(std::move(uniform_description)); + } return data; } diff --git a/impeller/compiler/shader_lib/impeller/texture.glsl b/impeller/compiler/shader_lib/impeller/texture.glsl index d478a3a268cca..e91eaabb26962 100644 --- a/impeller/compiler/shader_lib/impeller/texture.glsl +++ b/impeller/compiler/shader_lib/impeller/texture.glsl @@ -19,6 +19,13 @@ vec4 IPSample(sampler2D texture_sampler, vec2 coords, float y_coord_scale) { return texture(texture_sampler, coords); } +vec2 IPRemapCoords(vec2 coords, float y_coord_scale) { + if (y_coord_scale < 0.0) { + coords.y = 1.0 - coords.y; + } + return coords; +} + /// Sample from a texture. /// /// If `y_coord_scale` < 0.0, the Y coordinate is flipped. This is useful @@ -119,6 +126,15 @@ vec4 IPSampleLinearWithTileMode(sampler2D tex, y_coord_scale, half_texel); } +/// Sample a texture with decal tile mode. +vec4 IPSampleDecal(sampler2D texture_sampler, vec2 coords) { + if (any(lessThan(coords, vec2(0))) || + any(greaterThanEqual(coords, vec2(1)))) { + return vec4(0); + } + return texture(texture_sampler, coords); +} + /// Sample a texture, emulating a specific tile mode. /// /// This is useful for Impeller graphics backend that don't have native support diff --git a/impeller/compiler/source_options.h b/impeller/compiler/source_options.h index 100462ea0d095..ccd264562a3d0 100644 --- a/impeller/compiler/source_options.h +++ b/impeller/compiler/source_options.h @@ -27,7 +27,6 @@ struct SourceOptions { uint32_t gles_language_version = 100; std::vector defines; bool json_format = false; - bool remap_samplers = false; SourceOptions(); diff --git a/impeller/compiler/spirv_sksl.cc b/impeller/compiler/spirv_sksl.cc index 2f2d2d4617cf9..99b14d863ba5a 100644 --- a/impeller/compiler/spirv_sksl.cc +++ b/impeller/compiler/spirv_sksl.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "impeller/compiler/spirv_sksl.h" +#include "impeller/compiler/uniform_sorter.h" using namespace spv; using namespace SPIRV_CROSS_NAMESPACE; @@ -219,47 +220,14 @@ bool CompilerSkSL::emit_uniform_resources() { bool emitted = false; // Output Uniform Constants (values, samplers, images, etc). - std::vector regular_uniforms; - std::vector shader_uniforms; - for (auto& id : ir.ids) { - if (id.get_type() == TypeVariable) { - auto& var = id.get(); - auto& type = get(var.basetype); - if (var.storage != StorageClassFunction && !is_hidden_variable(var) && - type.pointer && - (type.storage == StorageClassUniformConstant || - type.storage == StorageClassAtomicCounter)) { - // Separate out the uniforms that will be of SkSL 'shader' type since - // we need to make sure they are emitted only after the other uniforms. - if (type.basetype == SPIRType::SampledImage) { - shader_uniforms.push_back(var.self); - } else { - regular_uniforms.push_back(var.self); - } - emitted = true; - } - } + std::vector regular_uniforms = + SortUniforms(&ir, this, SPIRType::SampledImage, /*include=*/false); + std::vector shader_uniforms = + SortUniforms(&ir, this, SPIRType::SampledImage); + if (regular_uniforms.size() > 0 || shader_uniforms.size() > 0) { + emitted = true; } - // Sort uniforms by location. - auto compare_locations = [this](ID id1, ID id2) { - auto& flags1 = get_decoration_bitset(id1); - auto& flags2 = get_decoration_bitset(id2); - // Put the uniforms with no location after the ones that have a location. - if (!flags1.get(DecorationLocation)) { - return false; - } - if (!flags2.get(DecorationLocation)) { - return true; - } - // Sort in increasing order of location. - return get_decoration(id1, DecorationLocation) < - get_decoration(id2, DecorationLocation); - }; - std::sort(regular_uniforms.begin(), regular_uniforms.end(), - compare_locations); - std::sort(shader_uniforms.begin(), shader_uniforms.end(), compare_locations); - for (const auto& id : regular_uniforms) { auto& var = get(id); emit_uniform(var); @@ -476,9 +444,8 @@ std::string CompilerSkSL::to_function_args(const TextureFunctionArguments& args, std::string glsl_args = CompilerGLSL::to_function_args(args, p_forward); // SkSL only supports coordinates. All other arguments to texture are // unsupported and will generate invalid SkSL. - if (args.grad_x || args.grad_y || args.lod || args.coffset || args.offset || - args.sample || args.min_lod || args.sparse_texel || args.bias || - args.component) { + if (args.grad_x || args.grad_y || args.lod || args.offset || args.sample || + args.min_lod || args.sparse_texel || args.bias || args.component) { FLUTTER_CROSS_THROW( "Only sampler and position arguments are supported in texture() " "calls."); diff --git a/impeller/compiler/switches.cc b/impeller/compiler/switches.cc index d84e107eeef9a..8fbb9e65e8465 100644 --- a/impeller/compiler/switches.cc +++ b/impeller/compiler/switches.cc @@ -128,7 +128,6 @@ Switches::Switches(const fml::CommandLine& command_line) command_line.GetOptionValueWithDefault("reflection-cc", "")), depfile_path(command_line.GetOptionValueWithDefault("depfile", "")), json_format(command_line.HasOption("json")), - remap_samplers(command_line.HasOption("remap-samplers")), gles_language_version( stoi(command_line.GetOptionValueWithDefault("gles-language-version", "0"))), diff --git a/impeller/compiler/switches.h b/impeller/compiler/switches.h index 198c67590443e..01774285e7f27 100644 --- a/impeller/compiler/switches.h +++ b/impeller/compiler/switches.h @@ -32,7 +32,6 @@ struct Switches { std::string depfile_path; std::vector defines; bool json_format; - bool remap_samplers; SourceLanguage source_language = SourceLanguage::kUnknown; uint32_t gles_language_version; std::string entry_point; diff --git a/impeller/compiler/uniform_sorter.cc b/impeller/compiler/uniform_sorter.cc new file mode 100644 index 0000000000000..21ebdf7d02a8f --- /dev/null +++ b/impeller/compiler/uniform_sorter.cc @@ -0,0 +1,48 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/compiler/uniform_sorter.h" + +namespace impeller { + +std::vector SortUniforms( + const spirv_cross::ParsedIR* ir, + const spirv_cross::Compiler* compiler, + std::optional type_filter, + bool include) { + // Sort the IR so that the uniforms are in declaration order. + std::vector uniforms; + ir->for_each_typed_id( + [&](uint32_t, const spirv_cross::SPIRVariable& var) { + if (var.storage != spv::StorageClassUniformConstant) { + return; + } + const auto type = compiler->get_type(var.basetype); + if (!type_filter.has_value() || + (include && type_filter.value() == type.basetype) || + (!include && type_filter.value() != type.basetype)) { + uniforms.push_back(var.self); + } + }); + + auto compare_locations = [&ir](spirv_cross::ID id1, spirv_cross::ID id2) { + auto& flags1 = ir->get_decoration_bitset(id1); + auto& flags2 = ir->get_decoration_bitset(id2); + // Put the uniforms with no location after the ones that have a location. + if (!flags1.get(spv::Decoration::DecorationLocation)) { + return false; + } + if (!flags2.get(spv::Decoration::DecorationLocation)) { + return true; + } + // Sort in increasing order of location. + return ir->get_decoration(id1, spv::Decoration::DecorationLocation) < + ir->get_decoration(id2, spv::Decoration::DecorationLocation); + }; + std::sort(uniforms.begin(), uniforms.end(), compare_locations); + + return uniforms; +} + +} // namespace impeller diff --git a/impeller/compiler/uniform_sorter.h b/impeller/compiler/uniform_sorter.h new file mode 100644 index 0000000000000..5279aaecb6cf5 --- /dev/null +++ b/impeller/compiler/uniform_sorter.h @@ -0,0 +1,27 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "impeller/compiler/compiler_backend.h" + +#include "spirv_msl.hpp" +#include "spirv_parser.hpp" + +namespace impeller { + +/// @brief Sorts uniform declarations in an IR according to decoration order. +/// +/// The [type_filter] may be optionally supplied to limit which types are +/// returned The [include] value can be set to false change this filter to +/// exclude instead of include. +std::vector SortUniforms( + const spirv_cross::ParsedIR* ir, + const spirv_cross::Compiler* compiler, + std::optional type_filter = std::nullopt, + bool include = true); + +} // namespace impeller diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 937a987a158a7..58e826ab1654e 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -136,6 +136,9 @@ static impeller::SamplerDescriptor ToSamplerDescriptor( desc.label = "Nearest Sampler"; break; case flutter::DlImageSampling::kLinear: + // Impeller doesn't support cubic sampling, but linear is closer to correct + // than nearest for this case. + case flutter::DlImageSampling::kCubic: desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; desc.label = "Linear Sampler"; break; @@ -144,8 +147,6 @@ static impeller::SamplerDescriptor ToSamplerDescriptor( desc.mip_filter = impeller::MipFilter::kLinear; desc.label = "Mipmap Linear Sampler"; break; - default: - break; } return desc; } @@ -1040,7 +1041,6 @@ void DisplayListDispatcher::drawOval(const SkRect& bounds) { // |flutter::Dispatcher| void DisplayListDispatcher::drawCircle(const SkPoint& center, SkScalar radius) { - auto path = PathBuilder{}.AddCircle(ToPoint(center), radius).TakePath(); canvas_.DrawCircle(ToPoint(center), radius, paint_); } diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index b1c535badbd34..0bf56ff87efcc 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -34,6 +34,15 @@ namespace impeller { namespace testing { +flutter::DlColor toColor(const float* components) { + auto value = (((std::lround(components[3] * 255) & 0xff) << 24) | + ((std::lround(components[0] * 255) & 0xff) << 16) | + ((std::lround(components[1] * 255) & 0xff) << 8) | + ((std::lround(components[2] * 255) & 0xff) << 0)) & + 0xFFFFFFFF; + return flutter::DlColor(value); +} + using DisplayListTest = DisplayListPlayground; INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest); @@ -112,13 +121,34 @@ TEST_P(DisplayListTest, CanDrawArc) { static float stroke_width = 10; static bool use_center = true; + static int selected_cap = 0; + const char* cap_names[] = {"Butt", "Round", "Square"}; + flutter::DlStrokeCap cap; + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); ImGui::SliderFloat("Start angle", &start_angle, -360, 360); ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360); ImGui::SliderFloat("Stroke width", &stroke_width, 0, 100); + ImGui::Combo("Cap", &selected_cap, cap_names, + sizeof(cap_names) / sizeof(char*)); ImGui::Checkbox("Use center", &use_center); ImGui::End(); + switch (selected_cap) { + case 0: + cap = flutter::DlStrokeCap::kButt; + break; + case 1: + cap = flutter::DlStrokeCap::kRound; + break; + case 2: + cap = flutter::DlStrokeCap::kSquare; + break; + default: + cap = flutter::DlStrokeCap::kButt; + break; + } + auto [p1, p2] = IMPELLER_PLAYGROUND_LINE( Point(200, 200), Point(400, 400), 20, Color::White(), Color::White()); @@ -127,7 +157,7 @@ TEST_P(DisplayListTest, CanDrawArc) { Vector2 scale = GetContentScale(); builder.scale(scale.x, scale.y); builder.setStyle(flutter::DlDrawStyle::kStroke); - builder.setStrokeCap(flutter::DlStrokeCap::kButt); + builder.setStrokeCap(cap); builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter); builder.setStrokeMiter(10); auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y); @@ -1164,6 +1194,97 @@ TEST_P(DisplayListTest, DrawShapes) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(DisplayListTest, DrawVerticesBlendModes) { + std::vector blend_mode_names; + std::vector blend_mode_values; + { + const std::vector> blends = { + // Pipeline blends (Porter-Duff alpha compositing) + {"Clear", flutter::DlBlendMode::kClear}, + {"Source", flutter::DlBlendMode::kSrc}, + {"Destination", flutter::DlBlendMode::kDst}, + {"SourceOver", flutter::DlBlendMode::kSrcOver}, + {"DestinationOver", flutter::DlBlendMode::kDstOver}, + {"SourceIn", flutter::DlBlendMode::kSrcIn}, + {"DestinationIn", flutter::DlBlendMode::kDstIn}, + {"SourceOut", flutter::DlBlendMode::kSrcOut}, + {"DestinationOut", flutter::DlBlendMode::kDstOut}, + {"SourceATop", flutter::DlBlendMode::kSrcATop}, + {"DestinationATop", flutter::DlBlendMode::kDstATop}, + {"Xor", flutter::DlBlendMode::kXor}, + {"Plus", flutter::DlBlendMode::kPlus}, + {"Modulate", flutter::DlBlendMode::kModulate}, + // Advanced blends (color component blends) + {"Screen", flutter::DlBlendMode::kScreen}, + {"Overlay", flutter::DlBlendMode::kOverlay}, + {"Darken", flutter::DlBlendMode::kDarken}, + {"Lighten", flutter::DlBlendMode::kLighten}, + {"ColorDodge", flutter::DlBlendMode::kColorDodge}, + {"ColorBurn", flutter::DlBlendMode::kColorBurn}, + {"HardLight", flutter::DlBlendMode::kHardLight}, + {"SoftLight", flutter::DlBlendMode::kSoftLight}, + {"Difference", flutter::DlBlendMode::kDifference}, + {"Exclusion", flutter::DlBlendMode::kExclusion}, + {"Multiply", flutter::DlBlendMode::kMultiply}, + {"Hue", flutter::DlBlendMode::kHue}, + {"Saturation", flutter::DlBlendMode::kSaturation}, + {"Color", flutter::DlBlendMode::kColor}, + {"Luminosity", flutter::DlBlendMode::kLuminosity}, + }; + assert(blends.size() == + static_cast(flutter::DlBlendMode::kLastMode) + 1); + for (const auto& [name, mode] : blends) { + blend_mode_names.push_back(name); + blend_mode_values.push_back(mode); + } + } + + auto callback = [&]() { + static int current_blend_index = 3; + static float dst_alpha = 1; + static float src_alpha = 1; + static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f}; + static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f}; + static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f}; + static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + { + ImGui::ListBox("Blending mode", ¤t_blend_index, + blend_mode_names.data(), blend_mode_names.size()); + ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1); + ImGui::ColorEdit4("Color A", color0); + ImGui::ColorEdit4("Color B", color1); + ImGui::ColorEdit4("Color C", color2); + ImGui::ColorEdit4("Source Color", src_color); + ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1); + } + ImGui::End(); + + std::vector positions = {SkPoint::Make(100, 300), + SkPoint::Make(200, 100), + SkPoint::Make(300, 300)}; + std::vector colors = { + toColor(color0).modulateOpacity(dst_alpha), + toColor(color1).modulateOpacity(dst_alpha), + toColor(color2).modulateOpacity(dst_alpha)}; + + auto vertices = flutter::DlVertices::Make( + flutter::DlVertexMode::kTriangles, 3, positions.data(), + /*texture_coorindates=*/nullptr, colors.data()); + + flutter::DisplayListBuilder builder; + flutter::DlPaint paint; + + paint.setColor(toColor(src_color).modulateOpacity(src_alpha)); + builder.drawVertices(vertices, blend_mode_values[current_blend_index], + paint); + return builder.Build(); + }; + + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + #ifdef IMPELLER_ENABLE_3D TEST_P(DisplayListTest, SceneColorSource) { // Load up the scene. diff --git a/impeller/display_list/display_list_vertices_geometry.cc b/impeller/display_list/display_list_vertices_geometry.cc index e7ddf3a1a4923..52caeea8be218 100644 --- a/impeller/display_list/display_list_vertices_geometry.cc +++ b/impeller/display_list/display_list_vertices_geometry.cc @@ -58,9 +58,9 @@ static std::vector fromFanIndices( /////// Vertices Geometry /////// // static -std::unique_ptr DLVerticesGeometry::MakeVertices( +std::shared_ptr DLVerticesGeometry::MakeVertices( const flutter::DlVertices* vertices) { - return std::make_unique(vertices); + return std::make_shared(vertices); } DLVerticesGeometry::DLVerticesGeometry(const flutter::DlVertices* vertices) @@ -100,6 +100,10 @@ static PrimitiveType GetPrimitiveType(const flutter::DlVertices* vertices) { } } +bool DLVerticesGeometry::HasVertexColors() const { + return vertices_->colors() != nullptr; +} + GeometryResult DLVerticesGeometry::GetPositionBuffer( const ContentContext& renderer, const Entity& entity, @@ -154,9 +158,7 @@ GeometryResult DLVerticesGeometry::GetPositionBuffer( GeometryResult DLVerticesGeometry::GetPositionColorBuffer( const ContentContext& renderer, const Entity& entity, - RenderPass& pass, - Color paint_color, - BlendMode blend_mode) { + RenderPass& pass) { using VS = GeometryColorPipeline::VertexShader; auto index_count = normalized_indices_.size() == 0 @@ -173,9 +175,9 @@ GeometryResult DLVerticesGeometry::GetPositionColorBuffer( { for (auto i = 0; i < vertex_count; i++) { auto dl_color = dl_colors[i]; - auto pre_color = Color(dl_color.getRedF(), dl_color.getGreenF(), - dl_color.getBlueF(), dl_color.getAlphaF()); - auto color = Color::BlendColor(paint_color, pre_color, blend_mode); + auto color = Color(dl_color.getRedF(), dl_color.getGreenF(), + dl_color.getBlueF(), dl_color.getAlphaF()) + .Premultiply(); auto sk_point = dl_vertices[i]; vertex_data[i] = { .position = Point(sk_point.x(), sk_point.y()), diff --git a/impeller/display_list/display_list_vertices_geometry.h b/impeller/display_list/display_list_vertices_geometry.h index 510f496a30110..3ebfa897800f3 100644 --- a/impeller/display_list/display_list_vertices_geometry.h +++ b/impeller/display_list/display_list_vertices_geometry.h @@ -23,15 +23,13 @@ class DLVerticesGeometry : public VerticesGeometry { ~DLVerticesGeometry(); - static std::unique_ptr MakeVertices( + static std::shared_ptr MakeVertices( const flutter::DlVertices* vertices); // |VerticesGeometry| GeometryResult GetPositionColorBuffer(const ContentContext& renderer, const Entity& entity, - RenderPass& pass, - Color paint_color, - BlendMode blend_mode) override; + RenderPass& pass) override; // |VerticesGeometry| GeometryResult GetPositionUVBuffer(const ContentContext& renderer, @@ -49,6 +47,9 @@ class DLVerticesGeometry : public VerticesGeometry { // |Geometry| GeometryVertexType GetVertexType() const override; + // |VerticesGeometry| + bool HasVertexColors() const override; + private: void NormalizeIndices(); diff --git a/impeller/docs/shader_optimization.md b/impeller/docs/shader_optimization.md index 397d4787f3f66..b557da720b137 100644 --- a/impeller/docs/shader_optimization.md +++ b/impeller/docs/shader_optimization.md @@ -267,7 +267,7 @@ vec4 FrobnicateColor(vec4 color) { vec4 result; if (color.a == 0) { - result vec4(0); + result = vec4(0); } else { result = DoExtremelyExpensiveThing(color); } diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 261a89a0ac27c..a66ff8329e89a 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -31,6 +31,7 @@ impeller_shaders("entity_shaders") { "shaders/color_matrix_color_filter.frag", "shaders/color_matrix_color_filter.vert", "shaders/gaussian_blur.frag", + "shaders/gaussian_blur_decal.frag", "shaders/gaussian_blur.vert", "shaders/glyph_atlas.frag", "shaders/glyph_atlas.vert", diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc index 69a4f07679c94..26268a1c2f2f9 100644 --- a/impeller/entity/contents/atlas_contents.cc +++ b/impeller/entity/contents/atlas_contents.cc @@ -126,8 +126,6 @@ bool AtlasContents::Render(const ContentContext& renderer, auto dst_contents = std::make_shared(*this); dst_contents->SetCoverage(coverage); - // For some reason this looks backwards compared to Skia unless - // we reverse the src/dst. auto contents = ColorFilterContents::MakeBlend( blend_mode_, {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)}); diff --git a/impeller/entity/contents/clip_contents.cc b/impeller/entity/contents/clip_contents.cc index a00a423261ad4..d958822b45b7a 100644 --- a/impeller/entity/contents/clip_contents.cc +++ b/impeller/entity/contents/clip_contents.cc @@ -136,6 +136,11 @@ ClipRestoreContents::ClipRestoreContents() = default; ClipRestoreContents::~ClipRestoreContents() = default; +void ClipRestoreContents::SetRestoreCoverage( + std::optional restore_coverage) { + restore_coverage_ = restore_coverage; +} + std::optional ClipRestoreContents::GetCoverage( const Entity& entity) const { return std::nullopt; @@ -164,19 +169,20 @@ bool ClipRestoreContents::Render(const ContentContext& renderer, auto options = OptionsFromPassAndEntity(pass, entity); options.stencil_compare = CompareFunction::kLess; options.stencil_operation = StencilOperation::kSetToReferenceValue; + options.primitive_type = PrimitiveType::kTriangleStrip; cmd.pipeline = renderer.GetClipPipeline(options); cmd.stencil_reference = entity.GetStencilDepth(); - // Create a rect that covers the whole render target. - auto size = pass.GetRenderTargetSize(); + // Create a rect that covers either the given restore area, or the whole + // render target texture. + auto ltrb = restore_coverage_.value_or(Rect(Size(pass.GetRenderTargetSize()))) + .GetLTRB(); VertexBufferBuilder vtx_builder; vtx_builder.AddVertices({ - {Point(0.0, 0.0)}, - {Point(size.width, 0.0)}, - {Point(size.width, size.height)}, - {Point(0.0, 0.0)}, - {Point(size.width, size.height)}, - {Point(0.0, size.height)}, + {Point(ltrb[0], ltrb[1])}, + {Point(ltrb[2], ltrb[1])}, + {Point(ltrb[0], ltrb[3])}, + {Point(ltrb[2], ltrb[3])}, }); cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); diff --git a/impeller/entity/contents/clip_contents.h b/impeller/entity/contents/clip_contents.h index b70c8ba863c02..86606d2f59db7 100644 --- a/impeller/entity/contents/clip_contents.h +++ b/impeller/entity/contents/clip_contents.h @@ -55,6 +55,12 @@ class ClipRestoreContents final : public Contents { ~ClipRestoreContents(); + /// @brief The area on the pass texture where this clip restore will be + /// applied. If unset, the entire pass texture will be restored. + /// + /// @note This rectangle is not transformed by the entity's transformation. + void SetRestoreCoverage(std::optional coverage); + // |Contents| std::optional GetCoverage(const Entity& entity) const override; @@ -73,6 +79,8 @@ class ClipRestoreContents final : public Contents { RenderPass& pass) const override; private: + std::optional restore_coverage_; + FML_DISALLOW_COPY_AND_ASSIGN(ClipRestoreContents); }; diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 1f0f8c4c37130..984d9b8095f22 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -207,6 +207,8 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); gaussian_blur_pipelines_[{}] = CreateDefaultPipeline(*context_); + gaussian_blur_decal_pipelines_[{}] = + CreateDefaultPipeline(*context_); border_mask_blur_pipelines_[{}] = CreateDefaultPipeline(*context_); morphology_filter_pipelines_[{}] = @@ -258,11 +260,12 @@ bool ContentContext::IsValid() const { std::shared_ptr ContentContext::MakeSubpass( ISize texture_size, - const SubpassCallback& subpass_callback) const { + const SubpassCallback& subpass_callback, + bool msaa_enabled) const { auto context = GetContext(); RenderTarget subpass_target; - if (context->SupportsOffscreenMSAA()) { + if (context->SupportsOffscreenMSAA() && msaa_enabled) { subpass_target = RenderTarget::CreateOffscreenMSAA(*context, texture_size); } else { subpass_target = RenderTarget::CreateOffscreen(*context, texture_size); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index e8cabf188c246..e109ae4aad2db 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -36,6 +36,7 @@ #include "impeller/entity/entity.h" #include "impeller/entity/gaussian_blur.frag.h" #include "impeller/entity/gaussian_blur.vert.h" +#include "impeller/entity/gaussian_blur_decal.frag.h" #include "impeller/entity/glyph_atlas.frag.h" #include "impeller/entity/glyph_atlas.vert.h" #include "impeller/entity/glyph_atlas_sdf.frag.h" @@ -146,6 +147,8 @@ using TiledTexturePipeline = RenderPipelineT; using GaussianBlurPipeline = RenderPipelineT; +using GaussianBlurDecalPipeline = + RenderPipelineT; using BorderMaskBlurPipeline = RenderPipelineT; using MorphologyFilterPipeline = @@ -281,6 +284,11 @@ class ContentContext { return GetPipeline(gaussian_blur_pipelines_, opts); } + std::shared_ptr> GetGaussianBlurDecalPipeline( + ContentContextOptions opts) const { + return GetPipeline(gaussian_blur_decal_pipelines_, opts); + } + std::shared_ptr> GetBorderMaskBlurPipeline( ContentContextOptions opts) const { return GetPipeline(border_mask_blur_pipelines_, opts); @@ -424,9 +432,9 @@ class ContentContext { /// @brief Creates a new texture of size `texture_size` and calls /// `subpass_callback` with a `RenderPass` for drawing to the texture. - std::shared_ptr MakeSubpass( - ISize texture_size, - const SubpassCallback& subpass_callback) const; + std::shared_ptr MakeSubpass(ISize texture_size, + const SubpassCallback& subpass_callback, + bool msaa_enabled = true) const; private: std::shared_ptr context_; @@ -455,6 +463,7 @@ class ContentContext { mutable Variants texture_pipelines_; mutable Variants tiled_texture_pipelines_; mutable Variants gaussian_blur_pipelines_; + mutable Variants gaussian_blur_decal_pipelines_; mutable Variants border_mask_blur_pipelines_; mutable Variants morphology_filter_pipelines_; mutable Variants diff --git a/impeller/entity/contents/contents.cc b/impeller/entity/contents/contents.cc index dc841cf1cb9fd..f6f52cd519f63 100644 --- a/impeller/entity/contents/contents.cc +++ b/impeller/entity/contents/contents.cc @@ -40,7 +40,9 @@ Contents::StencilCoverage Contents::GetStencilCoverage( std::optional Contents::RenderToSnapshot( const ContentContext& renderer, - const Entity& entity) const { + const Entity& entity, + const std::optional& sampler_descriptor, + bool msaa_enabled) const { auto coverage = GetCoverage(entity); if (!coverage.has_value()) { return std::nullopt; @@ -56,14 +58,22 @@ std::optional Contents::RenderToSnapshot( Matrix::MakeTranslation(Vector3(-coverage->origin)) * entity.GetTransformation()); return contents.Render(renderer, sub_entity, pass); - }); + }, + msaa_enabled); if (!texture) { return std::nullopt; } - return Snapshot{.texture = texture, - .transform = Matrix::MakeTranslation(coverage->origin)}; + auto snapshot = Snapshot{ + .texture = texture, + .transform = Matrix::MakeTranslation(coverage->origin), + }; + if (sampler_descriptor.has_value()) { + snapshot.sampler_descriptor = sampler_descriptor.value(); + } + + return snapshot; } bool Contents::ShouldRender(const Entity& entity, diff --git a/impeller/entity/contents/contents.h b/impeller/entity/contents/contents.h index 6d7b6edd55524..ec9919097c17b 100644 --- a/impeller/entity/contents/contents.h +++ b/impeller/entity/contents/contents.h @@ -10,6 +10,7 @@ #include "flutter/fml/macros.h" #include "impeller/geometry/rect.h" +#include "impeller/renderer/sampler_descriptor.h" #include "impeller/renderer/snapshot.h" #include "impeller/renderer/texture.h" @@ -60,7 +61,9 @@ class Contents { /// `GetCoverage(entity)`. virtual std::optional RenderToSnapshot( const ContentContext& renderer, - const Entity& entity) const; + const Entity& entity, + const std::optional& sampler_descriptor = std::nullopt, + bool msaa_enabled = true) const; virtual bool ShouldRender(const Entity& entity, const std::optional& stencil_coverage) const; diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index a46af9635be01..ddfc723379c99 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -14,6 +14,7 @@ #include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/entity.h" #include "impeller/geometry/path_builder.h" +#include "impeller/renderer/formats.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/sampler_library.h" @@ -107,8 +108,9 @@ static std::optional AdvancedBlend( typename FS::BlendInfo blend_info; - auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); - FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, sampler); + auto dst_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler( + dst_snapshot->sampler_descriptor); + FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, dst_sampler); blend_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale(); blend_info.dst_input_alpha = absorb_opacity ? dst_snapshot->opacity : 1.0; @@ -118,10 +120,12 @@ static std::optional AdvancedBlend( // This texture will not be sampled from due to the color factor. But // this is present so that validation doesn't trip on a missing // binding. - FS::BindTextureSamplerSrc(cmd, dst_snapshot->texture, sampler); + FS::BindTextureSamplerSrc(cmd, dst_snapshot->texture, dst_sampler); } else { + auto src_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler( + src_snapshot->sampler_descriptor); blend_info.color_factor = 0; - FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, sampler); + FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, src_sampler); blend_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale(); } auto blend_uniform = host_buffer.EmplaceUniform(blend_info); @@ -145,7 +149,10 @@ static std::optional AdvancedBlend( return Snapshot{.texture = out_texture, .transform = Matrix::MakeTranslation(coverage.origin), - .sampler_descriptor = dst_snapshot->sampler_descriptor, + // Since we absorbed the transform of the inputs and used the + // respective snapshot sampling modes when blending, pass on + // the default NN clamp sampler. + .sampler_descriptor = {}, .opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) * alpha.value_or(1.0)}; } @@ -168,8 +175,6 @@ static std::optional PipelineBlend( RenderPass& pass) { auto& host_buffer = pass.GetTransientsBuffer(); - auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); - Command cmd; cmd.label = "Pipeline Blend Filter"; auto options = OptionsFromPass(pass); @@ -183,6 +188,8 @@ static std::optional PipelineBlend( return false; } + auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler( + input->sampler_descriptor); FS::BindTextureSamplerSrc(cmd, input->texture, sampler); auto size = input->texture->GetSize(); @@ -205,7 +212,7 @@ static std::optional PipelineBlend( FS::FragInfo frag_info; frag_info.texture_sampler_y_coord_scale = input->texture->GetYCoordScale(); - frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0f; + frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0; FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); @@ -262,13 +269,14 @@ static std::optional PipelineBlend( } out_texture->SetLabel("Pipeline Blend Filter Texture"); - return Snapshot{ - .texture = out_texture, - .transform = Matrix::MakeTranslation(coverage.origin), - .sampler_descriptor = - inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor, - .opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) * - alpha.value_or(1.0)}; + return Snapshot{.texture = out_texture, + .transform = Matrix::MakeTranslation(coverage.origin), + // Since we absorbed the transform of the inputs and used the + // respective snapshot sampling modes when blending, pass on + // the default NN clamp sampler. + .sampler_descriptor = {}, + .opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) * + alpha.value_or(1.0)}; } #define BLEND_CASE(mode) \ @@ -346,6 +354,7 @@ std::optional BlendFilterContents::RenderFilter( foreground_color_, GetAbsorbOpacity(), GetAlpha()); } + FML_UNREACHABLE(); } diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index d43e4298c8845..cf10504d244c7 100644 --- a/impeller/entity/contents/filters/filter_contents.cc +++ b/impeller/entity/contents/filters/filter_contents.cc @@ -236,7 +236,9 @@ std::optional FilterContents::GetFilterCoverage( std::optional FilterContents::RenderToSnapshot( const ContentContext& renderer, - const Entity& entity) const { + const Entity& entity, + const std::optional& sampler_descriptor, + bool msaa_enabled) const { Entity entity_with_local_transform = entity; entity_with_local_transform.SetTransformation( GetTransform(entity.GetTransformation())); diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index 9387e7ce7d014..74c10397eccb0 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -116,8 +116,11 @@ class FilterContents : public Contents { std::optional GetCoverage(const Entity& entity) const override; // |Contents| - std::optional RenderToSnapshot(const ContentContext& renderer, - const Entity& entity) const override; + std::optional RenderToSnapshot( + const ContentContext& renderer, + const Entity& entity, + const std::optional& sampler_descriptor = std::nullopt, + bool msaa_enabled = true) const override; virtual Matrix GetLocalTransform(const Matrix& parent_transform) const; diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 782615cca274e..d3d056727acc9 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -183,13 +183,12 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); - - FS::FragInfo frag_info; - frag_info.texture_sampler_y_coord_scale = + frame_info.texture_sampler_y_coord_scale = input_snapshot->texture->GetYCoordScale(); - frag_info.alpha_mask_sampler_y_coord_scale = + frame_info.alpha_mask_sampler_y_coord_scale = source_snapshot->texture->GetYCoordScale(); + FS::FragInfo frag_info; auto r = Radius{transformed_blur_radius_length}; frag_info.blur_sigma = Sigma{r}.sigma; frag_info.blur_radius = r.radius; @@ -198,7 +197,6 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( frag_info.blur_direction = pass_transform.Invert().TransformDirection(Vector2(1, 0)).Normalize(); - frag_info.tile_mode = static_cast(tile_mode_); frag_info.src_factor = src_color_factor_; frag_info.inner_blur_factor = inner_blur_factor_; frag_info.outer_blur_factor = outer_blur_factor_; @@ -207,19 +205,48 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( Command cmd; cmd.label = SPrintF("Gaussian Blur Filter (Radius=%.2f)", transformed_blur_radius_length); + cmd.BindVertices(vtx_buffer); + auto options = OptionsFromPass(pass); options.blend_mode = BlendMode::kSource; - cmd.pipeline = renderer.GetGaussianBlurPipeline(options); - cmd.BindVertices(vtx_buffer); + auto input_descriptor = input_snapshot->sampler_descriptor; + auto source_descriptor = source_snapshot->sampler_descriptor; + switch (tile_mode_) { + case Entity::TileMode::kDecal: + cmd.pipeline = renderer.GetGaussianBlurDecalPipeline(options); + break; + case Entity::TileMode::kClamp: + cmd.pipeline = renderer.GetGaussianBlurPipeline(options); + input_descriptor.width_address_mode = SamplerAddressMode::kClampToEdge; + input_descriptor.height_address_mode = SamplerAddressMode::kClampToEdge; + source_descriptor.width_address_mode = SamplerAddressMode::kClampToEdge; + source_descriptor.height_address_mode = + SamplerAddressMode::kClampToEdge; + break; + case Entity::TileMode::kMirror: + cmd.pipeline = renderer.GetGaussianBlurPipeline(options); + input_descriptor.width_address_mode = SamplerAddressMode::kMirror; + input_descriptor.height_address_mode = SamplerAddressMode::kMirror; + source_descriptor.width_address_mode = SamplerAddressMode::kMirror; + source_descriptor.height_address_mode = SamplerAddressMode::kMirror; + break; + case Entity::TileMode::kRepeat: + cmd.pipeline = renderer.GetGaussianBlurPipeline(options); + input_descriptor.width_address_mode = SamplerAddressMode::kRepeat; + input_descriptor.height_address_mode = SamplerAddressMode::kRepeat; + source_descriptor.width_address_mode = SamplerAddressMode::kRepeat; + source_descriptor.height_address_mode = SamplerAddressMode::kRepeat; + break; + } FS::BindTextureSampler( cmd, input_snapshot->texture, renderer.GetContext()->GetSamplerLibrary()->GetSampler( - input_snapshot->sampler_descriptor)); + input_descriptor)); FS::BindAlphaMaskSampler( cmd, source_snapshot->texture, renderer.GetContext()->GetSamplerLibrary()->GetSampler( - source_snapshot->sampler_descriptor)); + source_descriptor)); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); @@ -281,7 +308,7 @@ std::optional DirectionalGaussianBlurFilterContents::GetFilterCoverage( auto transform = inputs[0]->GetTransform(entity) * effect_transform; auto transformed_blur_vector = - transform.TransformDirection(blur_direction_ * Radius{blur_sigma_}.radius) + transform.TransformDirection(blur_direction_* Radius{blur_sigma_}.radius) .Abs(); auto extent = coverage->size + transformed_blur_vector * 2; return Rect(coverage->origin - transformed_blur_vector, diff --git a/impeller/entity/contents/filters/inputs/contents_filter_input.cc b/impeller/entity/contents/filters/inputs/contents_filter_input.cc index fda5df7760efa..e6e40224a4cff 100644 --- a/impeller/entity/contents/filters/inputs/contents_filter_input.cc +++ b/impeller/entity/contents/filters/inputs/contents_filter_input.cc @@ -4,12 +4,14 @@ #include "impeller/entity/contents/filters/inputs/contents_filter_input.h" +#include #include namespace impeller { -ContentsFilterInput::ContentsFilterInput(std::shared_ptr contents) - : contents_(std::move(contents)) {} +ContentsFilterInput::ContentsFilterInput(std::shared_ptr contents, + bool msaa_enabled) + : contents_(std::move(contents)), msaa_enabled_(msaa_enabled) {} ContentsFilterInput::~ContentsFilterInput() = default; @@ -21,7 +23,8 @@ std::optional ContentsFilterInput::GetSnapshot( const ContentContext& renderer, const Entity& entity) const { if (!snapshot_.has_value()) { - snapshot_ = contents_->RenderToSnapshot(renderer, entity); + snapshot_ = contents_->RenderToSnapshot(renderer, entity, std::nullopt, + msaa_enabled_); } return snapshot_; } diff --git a/impeller/entity/contents/filters/inputs/contents_filter_input.h b/impeller/entity/contents/filters/inputs/contents_filter_input.h index 7309c17ffa5f0..61254a9fba692 100644 --- a/impeller/entity/contents/filters/inputs/contents_filter_input.h +++ b/impeller/entity/contents/filters/inputs/contents_filter_input.h @@ -23,10 +23,11 @@ class ContentsFilterInput final : public FilterInput { std::optional GetCoverage(const Entity& entity) const override; private: - ContentsFilterInput(std::shared_ptr contents); + ContentsFilterInput(std::shared_ptr contents, bool msaa_enabled); std::shared_ptr contents_; mutable std::optional snapshot_; + bool msaa_enabled_; friend FilterInput; }; diff --git a/impeller/entity/contents/filters/inputs/filter_input.cc b/impeller/entity/contents/filters/inputs/filter_input.cc index 4f61ba49fa9d5..3a50a44b48465 100644 --- a/impeller/entity/contents/filters/inputs/filter_input.cc +++ b/impeller/entity/contents/filters/inputs/filter_input.cc @@ -15,7 +15,7 @@ namespace impeller { -FilterInput::Ref FilterInput::Make(Variant input) { +FilterInput::Ref FilterInput::Make(Variant input, bool msaa_enabled) { if (auto filter = std::get_if>(&input)) { return std::static_pointer_cast( std::shared_ptr( @@ -25,7 +25,7 @@ FilterInput::Ref FilterInput::Make(Variant input) { if (auto contents = std::get_if>(&input)) { return std::static_pointer_cast( std::shared_ptr( - new ContentsFilterInput(*contents))); + new ContentsFilterInput(*contents, msaa_enabled))); } if (auto texture = std::get_if>(&input)) { diff --git a/impeller/entity/contents/filters/inputs/filter_input.h b/impeller/entity/contents/filters/inputs/filter_input.h index 7bd631f600e44..38090d679052c 100644 --- a/impeller/entity/contents/filters/inputs/filter_input.h +++ b/impeller/entity/contents/filters/inputs/filter_input.h @@ -36,7 +36,7 @@ class FilterInput { virtual ~FilterInput(); - static FilterInput::Ref Make(Variant input); + static FilterInput::Ref Make(Variant input, bool msaa_enabled = true); static FilterInput::Ref Make(std::shared_ptr input, Matrix local_transform); diff --git a/impeller/entity/contents/gradient_generator.cc b/impeller/entity/contents/gradient_generator.cc index 6a53719a90594..ee10bb937cdc2 100644 --- a/impeller/entity/contents/gradient_generator.cc +++ b/impeller/entity/contents/gradient_generator.cc @@ -42,4 +42,15 @@ std::shared_ptr CreateGradientTexture( return texture; } +std::vector CreateGradientColors(const std::vector& colors, + const std::vector& stops) { + FML_DCHECK(stops.size() == colors.size()); + + std::vector result(stops.size()); + for (auto i = 0u; i < stops.size(); i++) { + result[i] = {.color = colors[i], .stop = stops[i]}; + } + return result; +} + } // namespace impeller diff --git a/impeller/entity/contents/gradient_generator.h b/impeller/entity/contents/gradient_generator.h index 2074d2a3e0440..36f81e087d63f 100644 --- a/impeller/entity/contents/gradient_generator.h +++ b/impeller/entity/contents/gradient_generator.h @@ -14,6 +14,7 @@ #include "impeller/geometry/gradient.h" #include "impeller/geometry/path.h" #include "impeller/geometry/point.h" +#include "impeller/renderer/shader_types.h" namespace impeller { @@ -27,4 +28,20 @@ std::shared_ptr CreateGradientTexture( const GradientData& gradient_data, const std::shared_ptr& context); +struct StopData { + Color color; + Scalar stop; + Padding<12> _padding_; +}; + +/** + * @brief Populate a vector with the color and stop data for a gradient + * + * @param colors + * @param stops + * @return StopData + */ +std::vector CreateGradientColors(const std::vector& colors, + const std::vector& stops); + } // namespace impeller diff --git a/impeller/entity/contents/linear_gradient_contents.cc b/impeller/entity/contents/linear_gradient_contents.cc index f19d9077abf3c..323a71971a79a 100644 --- a/impeller/entity/contents/linear_gradient_contents.cc +++ b/impeller/entity/contents/linear_gradient_contents.cc @@ -111,7 +111,9 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } @@ -129,11 +131,11 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, gradient_info.alpha = GetAlpha(); auto& host_buffer = pass.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_).value_or(colors_); + auto colors = CreateGradientColors(colors_, stops_); gradient_info.colors_length = colors.size(); auto color_buffer = host_buffer.Emplace( - colors.data(), colors.size() * sizeof(Color), alignof(Color)); + colors.data(), colors.size() * sizeof(StopData), alignof(StopData)); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * @@ -165,7 +167,9 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/radial_gradient_contents.cc b/impeller/entity/contents/radial_gradient_contents.cc index ab94c3bde9221..ee330fbdfa1a2 100644 --- a/impeller/entity/contents/radial_gradient_contents.cc +++ b/impeller/entity/contents/radial_gradient_contents.cc @@ -67,11 +67,11 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, gradient_info.alpha = GetAlpha(); auto& host_buffer = pass.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_).value_or(colors_); + auto colors = CreateGradientColors(colors_, stops_); gradient_info.colors_length = colors.size(); auto color_buffer = host_buffer.Emplace( - colors.data(), colors.size() * sizeof(Color), alignof(Color)); + colors.data(), colors.size() * sizeof(StopData), alignof(StopData)); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * @@ -103,7 +103,9 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } @@ -166,7 +168,9 @@ bool RadialGradientContents::RenderTexture(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index 68c95acefe8d5..24a91d1149e00 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -151,9 +151,9 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, /// Fragment stage uniforms. /// + size_t minimum_sampler_index = 100000000; size_t buffer_index = 0; size_t buffer_offset = 0; - size_t sampler_index = 0; for (auto uniform : runtime_stage_->GetUniforms()) { // TODO(113715): Populate this metadata once GLES is able to handle // non-struct uniform names. @@ -161,20 +161,16 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, switch (uniform.type) { case kSampledImage: { - FML_DCHECK(sampler_index < texture_inputs_.size()); - auto& input = texture_inputs_[sampler_index]; - - auto sampler = - context->GetSamplerLibrary()->GetSampler(input.sampler_descriptor); - - SampledImageSlot image_slot; - image_slot.name = uniform.name.c_str(); - image_slot.texture_index = sampler_index; - image_slot.sampler_index = sampler_index; - cmd.BindResource(ShaderStage::kFragment, image_slot, metadata, - input.texture, sampler); - - sampler_index++; + // Sampler uniforms are ordered in the IPLR according to their + // declaration and the uniform location reflects the correct offset to + // be mapped to - except that it may include all proceeding float + // uniforms. For example, a float sampler that comes after 4 float + // uniforms may have a location of 4. To convert to the actual offset we + // need to find the largest location assigned to a float uniform and + // then subtract this from all uniform locations. This is more or less + // the same operation we previously performed in the shader compiler. + minimum_sampler_index = + std::min(minimum_sampler_index, uniform.location); break; } case kFloat: { @@ -186,7 +182,7 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, ShaderUniformSlot uniform_slot; uniform_slot.name = uniform.name.c_str(); - uniform_slot.ext_res_0 = buffer_index; + uniform_slot.ext_res_0 = uniform.location; cmd.BindResource(ShaderStage::kFragment, uniform_slot, metadata, buffer_view); buffer_index++; @@ -210,10 +206,41 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, } } + size_t sampler_index = 0; + for (auto uniform : runtime_stage_->GetUniforms()) { + // TODO(113715): Populate this metadata once GLES is able to handle + // non-struct uniform names. + ShaderMetadata metadata; + + switch (uniform.type) { + case kSampledImage: { + FML_DCHECK(sampler_index < texture_inputs_.size()); + auto& input = texture_inputs_[sampler_index]; + + auto sampler = + context->GetSamplerLibrary()->GetSampler(input.sampler_descriptor); + + SampledImageSlot image_slot; + image_slot.name = uniform.name.c_str(); + image_slot.texture_index = uniform.location - minimum_sampler_index; + image_slot.sampler_index = uniform.location - minimum_sampler_index; + cmd.BindResource(ShaderStage::kFragment, image_slot, metadata, + input.texture, sampler); + + sampler_index++; + break; + } + default: + continue; + } + } + pass.AddCommand(std::move(cmd)); if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/solid_color_contents.cc b/impeller/entity/contents/solid_color_contents.cc index 43cf7a913240c..afc55af0d9ba7 100644 --- a/impeller/entity/contents/solid_color_contents.cc +++ b/impeller/entity/contents/solid_color_contents.cc @@ -24,7 +24,7 @@ const Color& SolidColorContents::GetColor() const { return color_; } -void SolidColorContents::SetGeometry(std::unique_ptr geometry) { +void SolidColorContents::SetGeometry(std::shared_ptr geometry) { geometry_ = std::move(geometry); } @@ -83,7 +83,9 @@ bool SolidColorContents::Render(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/solid_color_contents.h b/impeller/entity/contents/solid_color_contents.h index e43e7292a7452..81148b133232a 100644 --- a/impeller/entity/contents/solid_color_contents.h +++ b/impeller/entity/contents/solid_color_contents.h @@ -29,7 +29,7 @@ class SolidColorContents final : public Contents { static std::unique_ptr Make(const Path& path, Color color); - void SetGeometry(std::unique_ptr geometry); + void SetGeometry(std::shared_ptr geometry); void SetColor(Color color); @@ -48,7 +48,7 @@ class SolidColorContents final : public Contents { RenderPass& pass) const override; private: - std::unique_ptr geometry_; + std::shared_ptr geometry_; Color color_; diff --git a/impeller/entity/contents/sweep_gradient_contents.cc b/impeller/entity/contents/sweep_gradient_contents.cc index 395acc543c0d3..d6319392e76df 100644 --- a/impeller/entity/contents/sweep_gradient_contents.cc +++ b/impeller/entity/contents/sweep_gradient_contents.cc @@ -73,11 +73,11 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, gradient_info.alpha = GetAlpha(); auto& host_buffer = pass.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_).value_or(colors_); + auto colors = CreateGradientColors(colors_, stops_); gradient_info.colors_length = colors.size(); auto color_buffer = host_buffer.Emplace( - colors.data(), colors.size() * sizeof(Color), alignof(Color)); + colors.data(), colors.size() * sizeof(StopData), alignof(StopData)); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * @@ -109,7 +109,9 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } @@ -173,7 +175,9 @@ bool SweepGradientContents::RenderTexture(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index 754396bbd78a1..fc127a2622b36 100644 --- a/impeller/entity/contents/texture_contents.cc +++ b/impeller/entity/contents/texture_contents.cc @@ -66,7 +66,9 @@ std::optional TextureContents::GetCoverage(const Entity& entity) const { std::optional TextureContents::RenderToSnapshot( const ContentContext& renderer, - const Entity& entity) const { + const Entity& entity, + const std::optional& sampler_descriptor, + bool msaa_enabled) const { auto bounds = path_.GetBoundingBox(); if (!bounds.has_value()) { return std::nullopt; @@ -77,14 +79,16 @@ std::optional TextureContents::RenderToSnapshot( if (is_rect_ && source_rect_ == Rect::MakeSize(texture_->GetSize()) && (opacity_ >= 1 - kEhCloseEnough || defer_applying_opacity_)) { auto scale = Vector2(bounds->size / Size(texture_->GetSize())); - return Snapshot{.texture = texture_, - .transform = entity.GetTransformation() * - Matrix::MakeTranslation(bounds->origin) * - Matrix::MakeScale(scale), - .sampler_descriptor = sampler_descriptor_, - .opacity = opacity_}; + return Snapshot{ + .texture = texture_, + .transform = entity.GetTransformation() * + Matrix::MakeTranslation(bounds->origin) * + Matrix::MakeScale(scale), + .sampler_descriptor = sampler_descriptor.value_or(sampler_descriptor_), + .opacity = opacity_}; } - return Contents::RenderToSnapshot(renderer, entity); + return Contents::RenderToSnapshot( + renderer, entity, sampler_descriptor.value_or(sampler_descriptor_)); } bool TextureContents::Render(const ContentContext& renderer, diff --git a/impeller/entity/contents/texture_contents.h b/impeller/entity/contents/texture_contents.h index 9502881cca3f6..fec23fba6505a 100644 --- a/impeller/entity/contents/texture_contents.h +++ b/impeller/entity/contents/texture_contents.h @@ -52,8 +52,11 @@ class TextureContents final : public Contents { std::optional GetCoverage(const Entity& entity) const override; // |Contents| - std::optional RenderToSnapshot(const ContentContext& renderer, - const Entity& entity) const override; + std::optional RenderToSnapshot( + const ContentContext& renderer, + const Entity& entity, + const std::optional& sampler_descriptor = std::nullopt, + bool msaa_enabled = true) const override; // |Contents| bool Render(const ContentContext& renderer, diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc index 90f1c15b22fbb..3324863613d68 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -96,7 +96,9 @@ bool TiledTextureContents::Render(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc index 65b8c88762b48..3c5dcedf00782 100644 --- a/impeller/entity/contents/vertices_contents.cc +++ b/impeller/entity/contents/vertices_contents.cc @@ -5,6 +5,9 @@ #include "vertices_contents.h" #include "impeller/entity/contents/content_context.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" +#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/position.vert.h" #include "impeller/entity/position_color.vert.h" #include "impeller/entity/position_uv.vert.h" @@ -25,12 +28,20 @@ std::optional VerticesContents::GetCoverage(const Entity& entity) const { return geometry_->GetCoverage(entity.GetTransformation()); }; -void VerticesContents::SetGeometry(std::unique_ptr geometry) { +void VerticesContents::SetGeometry(std::shared_ptr geometry) { geometry_ = std::move(geometry); } -void VerticesContents::SetColor(Color color) { - color_ = color.Premultiply(); +void VerticesContents::SetSourceContents(std::shared_ptr contents) { + src_contents_ = std::move(contents); +} + +std::shared_ptr VerticesContents::GetGeometry() const { + return geometry_; +} + +void VerticesContents::SetAlpha(Scalar alpha) { + alpha_ = alpha; } void VerticesContents::SetBlendMode(BlendMode blend_mode) { @@ -40,57 +51,65 @@ void VerticesContents::SetBlendMode(BlendMode blend_mode) { bool VerticesContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - auto& host_buffer = pass.GetTransientsBuffer(); - auto vertex_type = geometry_->GetVertexType(); + if (blend_mode_ == BlendMode::kClear) { + return true; + } + auto dst_contents = std::make_shared(*this); + + auto contents = ColorFilterContents::MakeBlend( + blend_mode_, {FilterInput::Make(dst_contents, false), + FilterInput::Make(src_contents_, false)}); + contents->SetAlpha(alpha_); + + return contents->Render(renderer, entity, pass); +} + +//------------------------------------------------------ +// VerticesColorContents + +VerticesColorContents::VerticesColorContents(const VerticesContents& parent) + : parent_(parent) {} + +VerticesColorContents::~VerticesColorContents() {} + +// |Contents| +std::optional VerticesColorContents::GetCoverage( + const Entity& entity) const { + return parent_.GetCoverage(entity); +} + +void VerticesColorContents::SetAlpha(Scalar alpha) { + alpha_ = alpha; +} + +// |Contents| +bool VerticesColorContents::Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = GeometryColorPipeline::VertexShader; + using FS = GeometryColorPipeline::FragmentShader; Command cmd; - cmd.label = "Vertices"; - cmd.stencil_reference = entity.GetStencilDepth(); + cmd.label = "VerticesColors"; + auto& host_buffer = pass.GetTransientsBuffer(); + auto geometry = parent_.GetGeometry(); + auto geometry_result = + geometry->GetPositionColorBuffer(renderer, entity, pass); auto opts = OptionsFromPassAndEntity(pass, entity); + opts.primitive_type = geometry_result.type; + cmd.pipeline = renderer.GetGeometryColorPipeline(opts); + cmd.BindVertices(geometry_result.vertex_buffer); - switch (vertex_type) { - case GeometryVertexType::kColor: { - using VS = GeometryColorPipeline::VertexShader; - - auto geometry_result = geometry_->GetPositionColorBuffer( - renderer, entity, pass, color_, blend_mode_); - opts.primitive_type = geometry_result.type; - cmd.pipeline = renderer.GetGeometryColorPipeline(opts); - cmd.BindVertices(geometry_result.vertex_buffer); - - VS::VertInfo vert_info; - vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation(); - VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info)); - break; - } - case GeometryVertexType::kUV: - case GeometryVertexType::kPosition: { - using VS = GeometryPositionPipeline::VertexShader; - - auto geometry_result = - geometry_->GetPositionBuffer(renderer, entity, pass); - opts.primitive_type = geometry_result.type; - cmd.pipeline = renderer.GetGeometryPositionPipeline(opts); - cmd.BindVertices(geometry_result.vertex_buffer); - - VS::VertInfo vert_info; - vert_info.mvp = geometry_result.transform; - vert_info.color = color_.Premultiply(); - VS::BindVertInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(vert_info)); - break; - } - } - using FS = GeometryColorPipeline::FragmentShader; - FS::FragInfo frag_info; - frag_info.alpha = 1.0; - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + VS::VertInfo vert_info; + vert_info.mvp = geometry_result.transform; + VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info)); - pass.AddCommand(std::move(cmd)); + FS::FragInfo frag_info; + frag_info.alpha = alpha_; + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); - return true; + return pass.AddCommand(std::move(cmd)); } } // namespace impeller diff --git a/impeller/entity/contents/vertices_contents.h b/impeller/entity/contents/vertices_contents.h index 0f754c4c8ea25..b2459d549f6c3 100644 --- a/impeller/entity/contents/vertices_contents.h +++ b/impeller/entity/contents/vertices_contents.h @@ -25,12 +25,16 @@ class VerticesContents final : public Contents { ~VerticesContents() override; - void SetGeometry(std::unique_ptr geometry); + void SetGeometry(std::shared_ptr geometry); - void SetColor(Color color); + void SetAlpha(Scalar alpha); void SetBlendMode(BlendMode blend_mode); + void SetSourceContents(std::shared_ptr contents); + + std::shared_ptr GetGeometry() const; + // |Contents| std::optional GetCoverage(const Entity& entity) const override; @@ -39,12 +43,36 @@ class VerticesContents final : public Contents { const Entity& entity, RenderPass& pass) const override; - public: - Color color_; - std::unique_ptr geometry_; + private: + Scalar alpha_; + std::shared_ptr geometry_; BlendMode blend_mode_ = BlendMode::kSource; + std::shared_ptr src_contents_; FML_DISALLOW_COPY_AND_ASSIGN(VerticesContents); }; +class VerticesColorContents final : public Contents { + public: + explicit VerticesColorContents(const VerticesContents& parent); + + ~VerticesColorContents() override; + + // |Contents| + std::optional GetCoverage(const Entity& entity) const override; + + // |Contents| + bool Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + void SetAlpha(Scalar alpha); + + private: + const VerticesContents& parent_; + Scalar alpha_ = 1.0; + + FML_DISALLOW_COPY_AND_ASSIGN(VerticesColorContents); +}; + } // namespace impeller diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 346e636eb763d..df9e860f2c48b 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -322,14 +322,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement( return EntityPass::EntityResult::Skip(); } - RenderTarget subpass_target; - if (subpass->reads_from_pass_texture_ > 0) { - subpass_target = CreateRenderTarget( - renderer, ISize::Ceil(subpass_coverage->size), true); - } else { - subpass_target = CreateRenderTarget( - renderer, ISize::Ceil(subpass_coverage->size), false); - } + auto subpass_target = + CreateRenderTarget(renderer, // + ISize(subpass_coverage->size), // + subpass->reads_from_pass_texture_ > 0); auto subpass_texture = subpass_target.GetRenderTargetTexture(); diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc index 6e1dd8a28df08..368cf4c06ba06 100644 --- a/impeller/entity/geometry.cc +++ b/impeller/entity/geometry.cc @@ -302,6 +302,7 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( HostBuffer& buffer, Scalar stroke_width, Scalar scaled_miter_limit, + Cap cap, const StrokePathGeometry::JoinProc& join_proc, const StrokePathGeometry::CapProc& cap_proc, Scalar tolerance) { @@ -370,9 +371,15 @@ VertexBuffer StrokePathGeometry::CreateSolidStrokeVertices( // Generate start cap. if (!polyline.contours[contour_i].is_closed) { - auto cap_offset = - Vector2(contour.start_direction.y, -contour.start_direction.x) * - stroke_width * 0.5; + Vector2 direction; + if (cap == Cap::kButt) { + direction = + Vector2(contour.start_direction.y, -contour.start_direction.x); + } else { + direction = + Vector2(-contour.start_direction.y, contour.start_direction.x); + } + auto cap_offset = direction * stroke_width * 0.5; cap_proc(vtx_builder, polyline.points[contour_start_point_i], cap_offset, tolerance); } @@ -439,7 +446,8 @@ GeometryResult StrokePathGeometry::GetPositionBuffer( auto& host_buffer = pass.GetTransientsBuffer(); auto vertex_buffer = CreateSolidStrokeVertices( path_, host_buffer, stroke_width, miter_limit_ * stroke_width_ * 0.5, - GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), tolerance); + stroke_cap_, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), + tolerance); return GeometryResult{ .type = PrimitiveType::kTriangleStrip, diff --git a/impeller/entity/geometry.h b/impeller/entity/geometry.h index dabab1d1dc42a..d5eb6afe49dde 100644 --- a/impeller/entity/geometry.h +++ b/impeller/entity/geometry.h @@ -75,13 +75,13 @@ class VerticesGeometry : public Geometry { public: virtual GeometryResult GetPositionColorBuffer(const ContentContext& renderer, const Entity& entity, - RenderPass& pass, - Color paint_color, - BlendMode blend_mode) = 0; + RenderPass& pass) = 0; virtual GeometryResult GetPositionUVBuffer(const ContentContext& renderer, const Entity& entity, RenderPass& pass) = 0; + + virtual bool HasVertexColors() const = 0; }; /// @brief A geometry that is created from a filled path object. @@ -164,6 +164,7 @@ class StrokePathGeometry : public Geometry { HostBuffer& buffer, Scalar stroke_width, Scalar scaled_miter_limit, + Cap cap, const JoinProc& join_proc, const CapProc& cap_proc, Scalar tolerance); diff --git a/impeller/entity/shaders/gaussian_blur.frag b/impeller/entity/shaders/gaussian_blur.frag index b831baa6f8c77..8b483ae45de30 100644 --- a/impeller/entity/shaders/gaussian_blur.frag +++ b/impeller/entity/shaders/gaussian_blur.frag @@ -2,80 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// 1D (directional) gaussian blur. -// -// Paths for future optimization: -// * Remove the uv bounds multiplier in SampleColor by adding optional -// support for SamplerAddressMode::ClampToBorder in the texture sampler. -// * Render both blur passes into a smaller texture than the source image -// (~1/radius size). -// * If doing the small texture render optimization, cache misses can be -// reduced in the first pass by sampling the source textures with a mip -// level of log2(min_radius). - -#include -#include #include -#include - -uniform sampler2D texture_sampler; -uniform sampler2D alpha_mask_sampler; - -uniform FragInfo { - float texture_sampler_y_coord_scale; - float alpha_mask_sampler_y_coord_scale; - - vec2 texture_size; - vec2 blur_direction; - float tile_mode; - - // The blur sigma and radius have a linear relationship which is defined - // host-side, but both are useful controls here. Sigma (pixels per standard - // deviation) is used to define the gaussian function itself, whereas the - // radius is used to limit how much of the function is integrated. - float blur_sigma; - float blur_radius; - - float src_factor; - float inner_blur_factor; - float outer_blur_factor; +vec4 Sample(sampler2D tex, vec2 coords) { + return texture(tex, coords); } -frag_info; - -in vec2 v_texture_coords; -in vec2 v_src_texture_coords; -out vec4 frag_color; - -void main() { - vec4 total_color = vec4(0); - float gaussian_integral = 0; - vec2 blur_uv_offset = frag_info.blur_direction / frag_info.texture_size; - - for (float i = -frag_info.blur_radius; i <= frag_info.blur_radius; i++) { - float gaussian = IPGaussian(i, frag_info.blur_sigma); - gaussian_integral += gaussian; - total_color += - gaussian * - IPSampleWithTileMode( - texture_sampler, // sampler - v_texture_coords + blur_uv_offset * i, // texture coordinates - frag_info.texture_sampler_y_coord_scale, // y coordinate scale - frag_info.tile_mode // tile mode - ); - } - - vec4 blur_color = total_color / gaussian_integral; - - vec4 src_color = IPSampleWithTileMode( - alpha_mask_sampler, // sampler - v_src_texture_coords, // texture coordinates - frag_info.alpha_mask_sampler_y_coord_scale, // y coordinate scale - frag_info.tile_mode // tile mode - ); - float blur_factor = frag_info.inner_blur_factor * float(src_color.a > 0) + - frag_info.outer_blur_factor * float(src_color.a == 0); - - frag_color = blur_color * blur_factor + src_color * frag_info.src_factor; -} +#include "gaussian_blur.glsl" diff --git a/impeller/entity/shaders/gaussian_blur.glsl b/impeller/entity/shaders/gaussian_blur.glsl new file mode 100644 index 0000000000000..718b4826021c0 --- /dev/null +++ b/impeller/entity/shaders/gaussian_blur.glsl @@ -0,0 +1,70 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// 1D (directional) gaussian blur. +// +// Paths for future optimization: +// * Remove the uv bounds multiplier in SampleColor by adding optional +// support for SamplerAddressMode::ClampToBorder in the texture sampler. +// * Render both blur passes into a smaller texture than the source image +// (~1/radius size). +// * If doing the small texture render optimization, cache misses can be +// reduced in the first pass by sampling the source textures with a mip +// level of log2(min_radius). + +#include +#include +#include +#include + +uniform sampler2D texture_sampler; +uniform sampler2D alpha_mask_sampler; + +uniform FragInfo { + vec2 texture_size; + vec2 blur_direction; + + // The blur sigma and radius have a linear relationship which is defined + // host-side, but both are useful controls here. Sigma (pixels per standard + // deviation) is used to define the gaussian function itself, whereas the + // radius is used to limit how much of the function is integrated. + float blur_sigma; + float blur_radius; + + float src_factor; + float inner_blur_factor; + float outer_blur_factor; +} +frag_info; + +in vec2 v_texture_coords; +in vec2 v_src_texture_coords; + +out vec4 frag_color; + +void main() { + vec4 total_color = vec4(0); + float gaussian_integral = 0; + vec2 blur_uv_offset = frag_info.blur_direction / frag_info.texture_size; + + for (float i = -frag_info.blur_radius; i <= frag_info.blur_radius; i++) { + float gaussian = IPGaussian(i, frag_info.blur_sigma); + gaussian_integral += gaussian; + total_color += + gaussian * + Sample(texture_sampler, // sampler + v_texture_coords + blur_uv_offset * i // texture coordinates + ); + } + + vec4 blur_color = total_color / gaussian_integral; + + vec4 src_color = Sample(alpha_mask_sampler, // sampler + v_src_texture_coords // texture coordinates + ); + float blur_factor = frag_info.inner_blur_factor * float(src_color.a > 0) + + frag_info.outer_blur_factor * float(src_color.a == 0); + + frag_color = blur_color * blur_factor + src_color * frag_info.src_factor; +} diff --git a/impeller/entity/shaders/gaussian_blur.vert b/impeller/entity/shaders/gaussian_blur.vert index 1fac06eb058b8..f402003b13bf1 100644 --- a/impeller/entity/shaders/gaussian_blur.vert +++ b/impeller/entity/shaders/gaussian_blur.vert @@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include uniform FrameInfo { mat4 mvp; + float texture_sampler_y_coord_scale; + float alpha_mask_sampler_y_coord_scale; } frame_info; @@ -18,6 +21,8 @@ out vec2 v_src_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(vertices, 0.0, 1.0); - v_texture_coords = texture_coords; - v_src_texture_coords = src_texture_coords; + v_texture_coords = + IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale); + v_src_texture_coords = IPRemapCoords( + src_texture_coords, frame_info.alpha_mask_sampler_y_coord_scale); } diff --git a/impeller/entity/shaders/gaussian_blur_decal.frag b/impeller/entity/shaders/gaussian_blur_decal.frag new file mode 100644 index 0000000000000..c3076c7f7f902 --- /dev/null +++ b/impeller/entity/shaders/gaussian_blur_decal.frag @@ -0,0 +1,11 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +vec4 Sample(sampler2D tex, vec2 coords) { + return IPSampleDecal(tex, coords); +} + +#include "gaussian_blur.glsl" diff --git a/impeller/entity/shaders/glyph_atlas.frag b/impeller/entity/shaders/glyph_atlas.frag index acfed85a3204b..c57482ce287a5 100644 --- a/impeller/entity/shaders/glyph_atlas.frag +++ b/impeller/entity/shaders/glyph_atlas.frag @@ -24,7 +24,8 @@ void main() { vec2 uv_position = v_source_position / frag_info.atlas_size; if (v_has_color == 1.0) { frag_color = - texture(glyph_atlas_sampler, v_unit_position * uv_size + uv_position); + texture(glyph_atlas_sampler, v_unit_position * uv_size + uv_position) * + frag_info.text_color.a; } else { frag_color = texture(glyph_atlas_sampler, v_unit_position * uv_size + uv_position) diff --git a/impeller/entity/shaders/linear_gradient_ssbo_fill.frag b/impeller/entity/shaders/linear_gradient_ssbo_fill.frag index a2443ece8cadf..2893994b5aae1 100644 --- a/impeller/entity/shaders/linear_gradient_ssbo_fill.frag +++ b/impeller/entity/shaders/linear_gradient_ssbo_fill.frag @@ -6,8 +6,13 @@ #include #include -readonly buffer ColorData { - vec4 colors[]; +struct ColorPoint { + vec4 color; + float stop; +}; + +layout(std140) readonly buffer ColorData { + ColorPoint colors[]; } color_data; @@ -35,10 +40,22 @@ void main() { return; } t = IPFloatTile(t, gradient_info.tile_mode); - vec3 values = IPComputeFixedGradientValues(t, gradient_info.colors_length); - frag_color = mix(color_data.colors[int(values.x)], - color_data.colors[int(values.y)], values.z); - frag_color = - vec4(frag_color.xyz * frag_color.a, frag_color.a) * gradient_info.alpha; + vec4 result_color = vec4(0); + for (int i = 1; i < gradient_info.colors_length; i++) { + ColorPoint prev_point = color_data.colors[i - 1]; + ColorPoint current_point = color_data.colors[i]; + if (t >= prev_point.stop && t <= current_point.stop) { + float delta = (current_point.stop - prev_point.stop); + if (delta < 0.001) { + result_color = current_point.color; + } else { + float ratio = (t - prev_point.stop) / delta; + result_color = mix(prev_point.color, current_point.color, ratio); + } + break; + } + } + frag_color = vec4(result_color.xyz * result_color.a, result_color.a) * + gradient_info.alpha; } diff --git a/impeller/entity/shaders/radial_gradient_ssbo_fill.frag b/impeller/entity/shaders/radial_gradient_ssbo_fill.frag index 0b6496c0d7a68..6d837e0e3c0ec 100644 --- a/impeller/entity/shaders/radial_gradient_ssbo_fill.frag +++ b/impeller/entity/shaders/radial_gradient_ssbo_fill.frag @@ -6,8 +6,13 @@ #include #include -readonly buffer ColorData { - vec4 colors[]; +struct ColorPoint { + vec4 color; + float stop; +}; + +layout(std140) readonly buffer ColorData { + ColorPoint colors[]; } color_data; @@ -33,10 +38,22 @@ void main() { return; } t = IPFloatTile(t, gradient_info.tile_mode); - vec3 values = IPComputeFixedGradientValues(t, gradient_info.colors_length); - frag_color = mix(color_data.colors[int(values.x)], - color_data.colors[int(values.y)], values.z); - frag_color = - vec4(frag_color.xyz * frag_color.a, frag_color.a) * gradient_info.alpha; + vec4 result_color = vec4(0); + for (int i = 1; i < gradient_info.colors_length; i++) { + ColorPoint prev_point = color_data.colors[i - 1]; + ColorPoint current_point = color_data.colors[i]; + if (t >= prev_point.stop && t <= current_point.stop) { + float delta = (current_point.stop - prev_point.stop); + if (delta < 0.001) { + result_color = current_point.color; + } else { + float ratio = (t - prev_point.stop) / delta; + result_color = mix(prev_point.color, current_point.color, ratio); + } + break; + } + } + frag_color = vec4(result_color.xyz * result_color.a, result_color.a) * + gradient_info.alpha; } diff --git a/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag b/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag index 9fe30f94ad99c..5bb2f5402dfb3 100644 --- a/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag +++ b/impeller/entity/shaders/sweep_gradient_ssbo_fill.frag @@ -7,8 +7,13 @@ #include #include -readonly buffer ColorData { - vec4 colors[]; +struct ColorPoint { + vec4 color; + float stop; +}; + +layout(std140) readonly buffer ColorData { + ColorPoint colors[]; } color_data; @@ -37,10 +42,22 @@ void main() { return; } t = IPFloatTile(t, gradient_info.tile_mode); - vec3 values = IPComputeFixedGradientValues(t, gradient_info.colors_length); - frag_color = mix(color_data.colors[int(values.x)], - color_data.colors[int(values.y)], values.z); - frag_color = - vec4(frag_color.xyz * frag_color.a, frag_color.a) * gradient_info.alpha; + vec4 result_color = vec4(0); + for (int i = 1; i < gradient_info.colors_length; i++) { + ColorPoint prev_point = color_data.colors[i - 1]; + ColorPoint current_point = color_data.colors[i]; + if (t >= prev_point.stop && t <= current_point.stop) { + float delta = (current_point.stop - prev_point.stop); + if (delta < 0.001) { + result_color = current_point.color; + } else { + float ratio = (t - prev_point.stop) / delta; + result_color = mix(prev_point.color, current_point.color, ratio); + } + break; + } + } + frag_color = vec4(result_color.xyz * result_color.a, result_color.a) * + gradient_info.alpha; } diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index 36c07aca0f116..5ab4baa1d0830 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -666,6 +666,8 @@ TEST(GeometryTest, CanGenerateMipCounts) { ASSERT_EQ((Size{128, 0}.MipCount()), 1u); ASSERT_EQ((Size{128, -25}.MipCount()), 1u); ASSERT_EQ((Size{-128, 25}.MipCount()), 1u); + ASSERT_EQ((Size{1, 1}.MipCount()), 1u); + ASSERT_EQ((Size{0, 0}.MipCount()), 1u); } TEST(GeometryTest, CanConvertTTypesExplicitly) { @@ -1912,73 +1914,5 @@ TEST(GeometryTest, Gradient) { } } -TEST(GeometryTest, GradientSSBO) { - { - // Simple 2 color gradient produces std::nullopt, as original - // color vector should be used. - std::vector colors = {Color::Red(), Color::Blue()}; - std::vector stops = {0.0, 1.0}; - - auto gradient = CreateGradientColors(colors, stops); - - ASSERT_EQ(gradient, std::nullopt); - } - - { - // Gradient with duplicate stops does not create an empty texture. - std::vector colors = {Color::Red(), Color::Yellow(), Color::Black(), - Color::Blue()}; - std::vector stops = {0.0, 0.25, 0.25, 1.0}; - - auto gradient = CreateGradientColors(colors, stops); - ASSERT_EQ(gradient.value().size(), 5u); - } - - { - // Simple N color gradient produces color buffer containing exactly those - // values. - std::vector colors = {Color::Red(), Color::Blue(), Color::Green(), - Color::White()}; - std::vector stops = {0.0, 0.33, 0.66, 1.0}; - - auto gradient = CreateGradientColors(colors, stops); - - ASSERT_EQ(gradient, std::nullopt); - } - - { - // Gradient with color stops will lerp and scale buffer. - std::vector colors = {Color::Red(), Color::Blue(), Color::Green()}; - std::vector stops = {0.0, 0.25, 1.0}; - - auto gradient = CreateGradientColors(colors, stops); - - std::vector lerped_colors = { - Color::Red(), - Color::Blue(), - Color::lerp(Color::Blue(), Color::Green(), 0.3333), - Color::lerp(Color::Blue(), Color::Green(), 0.6666), - Color::Green(), - }; - - ASSERT_COLORS_NEAR(gradient.value(), lerped_colors); - ASSERT_EQ(gradient.value().size(), 5u); - } - - { - // Gradient size is capped at 1024. - std::vector colors = {}; - std::vector stops = {}; - for (auto i = 0u; i < 1025; i++) { - colors.push_back(Color::Blue()); - stops.push_back(i / 1025.0); - } - - auto gradient = CreateGradientColors(colors, stops); - - ASSERT_EQ(gradient.value().size(), 1024u); - } -} - } // namespace testing } // namespace impeller diff --git a/impeller/geometry/gradient.cc b/impeller/geometry/gradient.cc index e668827e80ea4..becaf7c2c1f60 100644 --- a/impeller/geometry/gradient.cc +++ b/impeller/geometry/gradient.cc @@ -98,80 +98,4 @@ GradientData CreateGradientBuffer(const std::vector& colors, return data; } -std::optional> CreateGradientColors( - const std::vector& colors, - const std::vector& stops) { - FML_DCHECK(stops.size() == colors.size()); - - if (stops.size() == 2) { - // Use original buffer. - return std::nullopt; - } - - auto minimum_delta = 1.0; - for (size_t i = 1; i < stops.size(); i++) { - auto value = stops[i] - stops[i - 1]; - // Smaller than kEhCloseEnough - if (value < 0.0001) { - continue; - } - if (value < minimum_delta) { - minimum_delta = value; - } - } - // Avoid creating buffers that are absurdly large due to stops that are - // very close together. - uint32_t color_count = std::min( - static_cast(std::round(1.0 / minimum_delta)) + 1, 1024u); - - if (color_count == colors.size()) { - // Use original buffer. - return std::nullopt; - } - - std::vector data; - data.reserve(color_count); - - Color previous_color = colors[0]; - auto previous_stop = 0.0; - auto previous_color_index = 0; - - // The first index is always equal to the first color, exactly. - data.push_back(colors[0]); - - for (auto i = 1u; i < color_count - 1; i++) { - auto scaled_i = i / (color_count - 1.0); - Color next_color = colors[previous_color_index + 1]; - auto next_stop = stops[previous_color_index + 1]; - // We're almost exactly equal to the next stop. - if (ScalarNearlyEqual(scaled_i, next_stop)) { - data.push_back(next_color); - - previous_color = next_color; - previous_stop = next_stop; - previous_color_index += 1; - } else if (scaled_i < next_stop) { - // We're still between the current stop and the next stop. - auto t = (scaled_i - previous_stop) / (next_stop - previous_stop); - auto mixed_color = Color::lerp(previous_color, next_color, t); - - data.push_back(mixed_color); - } else { - // We've slightly overshot the previous stop. - previous_color = next_color; - previous_stop = next_stop; - previous_color_index += 1; - next_color = colors[previous_color_index + 1]; - auto next_stop = stops[previous_color_index + 1]; - - auto t = (scaled_i - previous_stop) / (next_stop - previous_stop); - auto mixed_color = Color::lerp(previous_color, next_color, t); - data.push_back(mixed_color); - } - } - // The last index is always equal to the last color, exactly. - data.push_back(colors.back()); - return data; -} - } // namespace impeller diff --git a/impeller/geometry/gradient.h b/impeller/geometry/gradient.h index 2d8e737adab35..b99f63b4a44bf 100644 --- a/impeller/geometry/gradient.h +++ b/impeller/geometry/gradient.h @@ -30,19 +30,4 @@ struct GradientData { GradientData CreateGradientBuffer(const std::vector& colors, const std::vector& stops); -/** - * @brief Populate a vector with the interpolated colors for the linear gradient - * described by colors and stops. - * - * If the returned result is std::nullopt, the original color buffer can be used - * instead. - * - * @param colors - * @param stops - * @return GradientData - */ -std::optional> CreateGradientColors( - const std::vector& colors, - const std::vector& stops); - } // namespace impeller diff --git a/impeller/geometry/size.h b/impeller/geometry/size.h index 6cb55cab47472..dc6abd4126d6e 100644 --- a/impeller/geometry/size.h +++ b/impeller/geometry/size.h @@ -99,10 +99,12 @@ struct TSize { } constexpr size_t MipCount() const { + constexpr size_t minimum_mip = 1u; if (!IsPositive()) { - return 1u; + return minimum_mip; } - return std::max(ceil(log2(width)), ceil(log2(height))); + size_t result = std::max(ceil(log2(width)), ceil(log2(height))); + return std::max(result, minimum_mip); } }; diff --git a/impeller/renderer/backend/vulkan/BUILD.gn b/impeller/renderer/backend/vulkan/BUILD.gn index 3ba6c17ccdc53..dd1514a326b9f 100644 --- a/impeller/renderer/backend/vulkan/BUILD.gn +++ b/impeller/renderer/backend/vulkan/BUILD.gn @@ -8,6 +8,8 @@ impeller_component("vulkan") { sources = [ "allocator_vk.cc", "allocator_vk.h", + "blit_command_vk.cc", + "blit_command_vk.h", "blit_pass_vk.cc", "blit_pass_vk.h", "capabilities_vk.cc", @@ -16,6 +18,8 @@ impeller_component("vulkan") { "command_buffer_vk.h", "command_pool_vk.cc", "command_pool_vk.h", + "commands_vk.cc", + "commands_vk.h", "context_vk.cc", "context_vk.h", "deletion_queue_vk.cc", diff --git a/impeller/renderer/backend/vulkan/blit_command_vk.cc b/impeller/renderer/backend/vulkan/blit_command_vk.cc new file mode 100644 index 0000000000000..8a9dd4ca9a208 --- /dev/null +++ b/impeller/renderer/backend/vulkan/blit_command_vk.cc @@ -0,0 +1,182 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/renderer/backend/vulkan/blit_command_vk.h" + +#include "impeller/renderer/backend/vulkan/commands_vk.h" +#include "impeller/renderer/backend/vulkan/texture_vk.h" + +namespace impeller { + +BlitEncodeVK::~BlitEncodeVK() = default; + +//------------------------------------------------------------------------------ +/// BlitCopyTextureToTextureCommandVK +/// + +BlitCopyTextureToTextureCommandVK::~BlitCopyTextureToTextureCommandVK() = + default; + +std::string BlitCopyTextureToTextureCommandVK::GetLabel() const { + return label; +} + +[[nodiscard]] bool BlitCopyTextureToTextureCommandVK::Encode( + FencedCommandBufferVK* fenced_command_buffer) const { + // cast source and destination to TextureVK + const auto& source_tex_vk = TextureVK::Cast(*source); + const auto& dest_tex_vk = TextureVK::Cast(*destination); + + // get the vulkan image and image view + const auto source_image = source_tex_vk.GetImage(); + const auto dest_image = dest_tex_vk.GetImage(); + + // copy the source image to the destination image, from source_region to + // destination_origin. + vk::ImageCopy image_copy; + image_copy.setSrcSubresource( + vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1)); + image_copy.setDstSubresource( + vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1)); + + image_copy.srcOffset = + vk::Offset3D(source_region.origin.x, source_region.origin.y, 0); + image_copy.dstOffset = + vk::Offset3D(destination_origin.x, destination_origin.y, 0); + image_copy.extent = + vk::Extent3D(source_region.size.width, source_region.size.height, 1); + + // get single use command buffer + auto copy_cmd = fenced_command_buffer->GetSingleUseChild(); + + vk::CommandBufferBeginInfo begin_info; + begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + auto res = copy_cmd.begin(begin_info); + + if (res != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res); + return false; + } + + // transition the source image to transfer source optimal + TransitionImageLayoutCommandVK transition_source_cmd = + TransitionImageLayoutCommandVK(source_image, vk::ImageLayout::eUndefined, + vk::ImageLayout::eTransferSrcOptimal); + bool success = transition_source_cmd.Submit(fenced_command_buffer); + if (!success) { + VALIDATION_LOG << "Failed to transition source image layout"; + return false; + } + + // transition the destination image to transfer destination optimal + TransitionImageLayoutCommandVK transition_dest_cmd = + TransitionImageLayoutCommandVK(dest_image, vk::ImageLayout::eUndefined, + vk::ImageLayout::eTransferDstOptimal); + success = transition_dest_cmd.Submit(fenced_command_buffer); + if (!success) { + VALIDATION_LOG << "Failed to transition destination image layout"; + return false; + } + + // issue the copy command + copy_cmd.copyImage(source_image, vk::ImageLayout::eTransferSrcOptimal, + dest_image, vk::ImageLayout::eTransferDstOptimal, + image_copy); + res = copy_cmd.end(); + if (res != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res); + return false; + } + + return true; +} + +//------------------------------------------------------------------------------ +/// BlitCopyTextureToBufferCommandVK +/// + +BlitCopyTextureToBufferCommandVK::~BlitCopyTextureToBufferCommandVK() = default; + +std::string BlitCopyTextureToBufferCommandVK::GetLabel() const { + return label; +} + +[[nodiscard]] bool BlitCopyTextureToBufferCommandVK::Encode( + FencedCommandBufferVK* fenced_command_buffer) const { + // cast source and destination to TextureVK + const auto& source_tex_vk = TextureVK::Cast(*source); + const auto& dest_buf_vk = DeviceBufferVK::Cast(*destination); + + // get the vulkan image and image view + const auto source_image = source_tex_vk.GetImage(); + + // get buffer image handle + const auto dest_buffer = dest_buf_vk.GetVKBufferHandle(); + + // copy the source image to the destination buffer, from source_region to + // destination_origin. + vk::BufferImageCopy image_copy{}; + image_copy.setBufferOffset(destination_offset); + image_copy.setBufferRowLength(0); + image_copy.setBufferImageHeight(0); + image_copy.setImageSubresource( + vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1)); + image_copy.setImageOffset( + vk::Offset3D(source_region.origin.x, source_region.origin.y, 0)); + image_copy.setImageExtent( + vk::Extent3D(source_region.size.width, source_region.size.height, 1)); + + // transition the source image to transfer source optimal + TransitionImageLayoutCommandVK transition_source_cmd = + TransitionImageLayoutCommandVK(source_image, vk::ImageLayout::eUndefined, + vk::ImageLayout::eTransferSrcOptimal); + bool success = transition_source_cmd.Submit(fenced_command_buffer); + if (!success) { + return false; + } + + // get single use command buffer + auto copy_cmd = fenced_command_buffer->GetSingleUseChild(); + + vk::CommandBufferBeginInfo begin_info; + begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + auto res = copy_cmd.begin(begin_info); + + if (res != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res); + return false; + } + + // issue the copy command + copy_cmd.copyImageToBuffer(source_image, vk::ImageLayout::eTransferSrcOptimal, + dest_buffer, image_copy); + res = copy_cmd.end(); + if (res != vk::Result::eSuccess) { + VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res); + } + + return true; +} + +//------------------------------------------------------------------------------ +/// BlitGenerateMipmapCommandVK +/// + +BlitGenerateMipmapCommandVK::~BlitGenerateMipmapCommandVK() = default; + +std::string BlitGenerateMipmapCommandVK::GetLabel() const { + return label; +} + +[[nodiscard]] bool BlitGenerateMipmapCommandVK::Encode( + FencedCommandBufferVK* fenced_command_buffer) const { + // TODO(https://github.com/flutter/flutter/issues/120134): Support generating + // mipmaps on Vulkan. + IMPELLER_UNIMPLEMENTED; + return true; +} + +// END: BlitGenerateMipmapCommandVK + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/blit_command_vk.h b/impeller/renderer/backend/vulkan/blit_command_vk.h new file mode 100644 index 0000000000000..dda7f4266b71e --- /dev/null +++ b/impeller/renderer/backend/vulkan/blit_command_vk.h @@ -0,0 +1,57 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include +#include "impeller/base/backend_cast.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" +#include "impeller/renderer/blit_command.h" +#include "impeller/renderer/context.h" + +namespace impeller { + +/// Mixin for dispatching Vulkan commands. +struct BlitEncodeVK : BackendCast { + virtual ~BlitEncodeVK(); + + virtual std::string GetLabel() const = 0; + + [[nodiscard]] virtual bool Encode( + FencedCommandBufferVK* fenced_command_buffer) const = 0; +}; + +struct BlitCopyTextureToTextureCommandVK + : public BlitCopyTextureToTextureCommand, + public BlitEncodeVK { + ~BlitCopyTextureToTextureCommandVK() override; + + std::string GetLabel() const override; + + [[nodiscard]] bool Encode( + FencedCommandBufferVK* fenced_command_buffer) const override; +}; + +struct BlitCopyTextureToBufferCommandVK : public BlitCopyTextureToBufferCommand, + public BlitEncodeVK { + ~BlitCopyTextureToBufferCommandVK() override; + + std::string GetLabel() const override; + + [[nodiscard]] bool Encode( + FencedCommandBufferVK* fenced_command_buffer) const override; +}; + +struct BlitGenerateMipmapCommandVK : public BlitGenerateMipmapCommand, + public BlitEncodeVK { + ~BlitGenerateMipmapCommandVK() override; + + std::string GetLabel() const override; + + [[nodiscard]] bool Encode( + FencedCommandBufferVK* fenced_command_buffer) const override; +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.cc b/impeller/renderer/backend/vulkan/blit_pass_vk.cc index 03f0510ada630..bdbd5915dcead 100644 --- a/impeller/renderer/backend/vulkan/blit_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/blit_pass_vk.cc @@ -4,8 +4,92 @@ #include "impeller/renderer/backend/vulkan/blit_pass_vk.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/trace_event.h" + namespace impeller { -// +BlitPassVK::BlitPassVK(std::shared_ptr command_buffer) + : command_buffer_(std::move(command_buffer)) {} + +BlitPassVK::~BlitPassVK() = default; + +void BlitPassVK::OnSetLabel(std::string label) { + if (label.empty()) { + return; + } + label_ = std::move(label); +} + +// |BlitPass| +bool BlitPassVK::IsValid() const { + return command_buffer_ != nullptr; +} + +// |BlitPass| +bool BlitPassVK::EncodeCommands( + const std::shared_ptr& transients_allocator) const { + TRACE_EVENT0("impeller", "BlitPassVK::EncodeCommands"); + + if (!IsValid()) { + return false; + } + + for (auto& command : commands_) { + bool encode_res = command->Encode(command_buffer_.get()); + if (!encode_res) { + return false; + } + } + + return true; +} + +// |BlitPass| +bool BlitPassVK::OnCopyTextureToTextureCommand( + std::shared_ptr source, + std::shared_ptr destination, + IRect source_region, + IPoint destination_origin, + std::string label) { + auto command = std::make_unique(); + command->source = std::move(source); + command->destination = std::move(destination); + command->source_region = source_region; + command->destination_origin = destination_origin; + command->label = std::move(label); + + commands_.push_back(std::move(command)); + return true; +} + +// |BlitPass| +bool BlitPassVK::OnCopyTextureToBufferCommand( + std::shared_ptr source, + std::shared_ptr destination, + IRect source_region, + size_t destination_offset, + std::string label) { + auto command = std::make_unique(); + command->source = std::move(source); + command->destination = std::move(destination); + command->source_region = source_region; + command->destination_offset = destination_offset; + command->label = std::move(label); + + commands_.push_back(std::move(command)); + return true; +} + +// |BlitPass| +bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr texture, + std::string label) { + auto command = std::make_unique(); + command->texture = std::move(texture); + command->label = std::move(label); + + commands_.push_back(std::move(command)); + return true; +} } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.h b/impeller/renderer/backend/vulkan/blit_pass_vk.h index a76e5a71ecb0b..aa8a3919e8f9c 100644 --- a/impeller/renderer/backend/vulkan/blit_pass_vk.h +++ b/impeller/renderer/backend/vulkan/blit_pass_vk.h @@ -5,19 +5,25 @@ #pragma once #include "flutter/fml/macros.h" +#include "impeller/renderer/backend/vulkan/blit_command_vk.h" +#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" #include "impeller/renderer/blit_pass.h" namespace impeller { class BlitPassVK final : public BlitPass { public: + explicit BlitPassVK(std::shared_ptr command_buffer); + // |BlitPass| ~BlitPassVK() override; private: friend class CommandBufferVK; - BlitPassVK(); + std::shared_ptr command_buffer_; + std::vector> commands_; + std::string label_; // |BlitPass| bool IsValid() const override; diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.cc b/impeller/renderer/backend/vulkan/command_buffer_vk.cc index 98f1e86fd806e..01fc6f3dffbe8 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.cc @@ -9,6 +9,7 @@ #include "flutter/fml/logging.h" #include "impeller/base/validation.h" +#include "impeller/renderer/backend/vulkan/blit_pass_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" @@ -120,7 +121,16 @@ std::shared_ptr CommandBufferVK::OnCreateRenderPass( std::shared_ptr CommandBufferVK::OnCreateBlitPass() const { // TODO(kaushikiska): https://github.com/flutter/flutter/issues/112649 - return nullptr; + if (!IsValid()) { + return nullptr; + } + + auto pass = std::make_shared(fenced_command_buffer_); + if (!pass->IsValid()) { + return nullptr; + } + + return pass; } std::shared_ptr CommandBufferVK::OnCreateComputePass() const { diff --git a/impeller/renderer/backend/vulkan/commands_vk.cc b/impeller/renderer/backend/vulkan/commands_vk.cc new file mode 100644 index 0000000000000..6eab7785cf2af --- /dev/null +++ b/impeller/renderer/backend/vulkan/commands_vk.cc @@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/renderer/backend/vulkan/commands_vk.h" + +namespace impeller { + +TransitionImageLayoutCommandVK::TransitionImageLayoutCommandVK( + vk::Image image, + vk::ImageLayout old_layout, + vk::ImageLayout new_layout) + : image_(image), old_layout_(old_layout), new_layout_(new_layout) {} + +TransitionImageLayoutCommandVK::~TransitionImageLayoutCommandVK() = default; + +bool TransitionImageLayoutCommandVK::Submit( + FencedCommandBufferVK* command_buffer) { + if (!command_buffer) { + return false; + } + + vk::ImageMemoryBarrier barrier = + vk::ImageMemoryBarrier() + .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite | + vk::AccessFlagBits::eTransferWrite) + .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | + vk::AccessFlagBits::eShaderRead) + .setOldLayout(old_layout_) + .setNewLayout(new_layout_) + .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED) + .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED) + .setImage(image_) + .setSubresourceRange( + vk::ImageSubresourceRange() + .setAspectMask(vk::ImageAspectFlagBits::eColor) + .setBaseMipLevel(0) + .setLevelCount(1) + .setBaseArrayLayer(0) + .setLayerCount(1)); + + vk::PipelineStageFlags src_stage = vk::PipelineStageFlagBits::eAllGraphics; + vk::PipelineStageFlags dst_stage = vk::PipelineStageFlagBits::eAllGraphics; + + auto transition_cmd = command_buffer->GetSingleUseChild(); + + vk::CommandBufferBeginInfo begin_info; + begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + auto res = transition_cmd.begin(begin_info); + + if (res != vk::Result::eSuccess) { + FML_LOG(ERROR) << "Failed to begin command buffer: " << vk::to_string(res); + return false; + } + + transition_cmd.pipelineBarrier(src_stage, dst_stage, {}, nullptr, nullptr, + barrier); + res = transition_cmd.end(); + if (res != vk::Result::eSuccess) { + FML_LOG(ERROR) << "Failed to end command buffer: " << vk::to_string(res); + return false; + } + + return true; +} + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/commands_vk.h b/impeller/renderer/backend/vulkan/commands_vk.h new file mode 100644 index 0000000000000..31c1c12285650 --- /dev/null +++ b/impeller/renderer/backend/vulkan/commands_vk.h @@ -0,0 +1,31 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h" + +// Set of common utility commands for Vulkan. +namespace impeller { + +class TransitionImageLayoutCommandVK { + public: + TransitionImageLayoutCommandVK(vk::Image image, + vk::ImageLayout old_layout, + vk::ImageLayout new_layout); + + ~TransitionImageLayoutCommandVK(); + + bool Submit(FencedCommandBufferVK* command_buffer); + + private: + vk::Image image_; + vk::ImageLayout old_layout_; + vk::ImageLayout new_layout_; + + FML_DISALLOW_COPY_AND_ASSIGN(TransitionImageLayoutCommandVK); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index 5c3e3984088d6..720ecf9159fd8 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -9,6 +9,7 @@ #include "fml/logging.h" #include "impeller/base/validation.h" +#include "impeller/renderer/backend/vulkan/commands_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" @@ -394,46 +395,9 @@ vk::Framebuffer RenderPassVK::CreateFrameBuffer( bool RenderPassVK::TransitionImageLayout(vk::Image image, vk::ImageLayout layout_old, vk::ImageLayout layout_new) const { - auto transition_cmd = command_buffer_->GetSingleUseChild(); - - vk::CommandBufferBeginInfo begin_info; - begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit); - auto res = transition_cmd.begin(begin_info); - - if (res != vk::Result::eSuccess) { - VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res); - return false; - } - - vk::ImageMemoryBarrier barrier = - vk::ImageMemoryBarrier() - .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eTransferWrite) - .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | - vk::AccessFlagBits::eShaderRead) - .setOldLayout(layout_old) - .setNewLayout(layout_new) - .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED) - .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED) - .setImage(image) - .setSubresourceRange( - vk::ImageSubresourceRange() - .setAspectMask(vk::ImageAspectFlagBits::eColor) - .setBaseMipLevel(0) - .setLevelCount(1) - .setBaseArrayLayer(0) - .setLayerCount(1)); - transition_cmd.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, - vk::PipelineStageFlagBits::eAllGraphics, {}, - nullptr, nullptr, barrier); - - res = transition_cmd.end(); - if (res != vk::Result::eSuccess) { - VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res); - return false; - } - - return true; + auto transition_cmd = + TransitionImageLayoutCommandVK(image, layout_old, layout_new); + return transition_cmd.Submit(command_buffer_.get()); } bool RenderPassVK::CopyBufferToImage(const TextureVK& texture_vk) const { diff --git a/impeller/renderer/sampler_descriptor.cc b/impeller/renderer/sampler_descriptor.cc index 35251848bc742..b2e10cab10d49 100644 --- a/impeller/renderer/sampler_descriptor.cc +++ b/impeller/renderer/sampler_descriptor.cc @@ -3,9 +3,19 @@ // found in the LICENSE file. #include "impeller/renderer/sampler_descriptor.h" +#include "fml/logging.h" namespace impeller { -// +SamplerDescriptor::SamplerDescriptor() = default; + +SamplerDescriptor::SamplerDescriptor(std::string label, + MinMagFilter min_filter, + MinMagFilter mag_filter, + MipFilter mip_filter) + : min_filter(min_filter), + mag_filter(mag_filter), + mip_filter(mip_filter), + label(std::move(label)) {} } // namespace impeller diff --git a/impeller/renderer/sampler_descriptor.h b/impeller/renderer/sampler_descriptor.h index 6ebb96e4e70cf..01d0f293b9054 100644 --- a/impeller/renderer/sampler_descriptor.h +++ b/impeller/renderer/sampler_descriptor.h @@ -26,6 +26,13 @@ struct SamplerDescriptor final : public Comparable { std::string label = "NN Clamp Sampler"; + SamplerDescriptor(); + + SamplerDescriptor(std::string label, + MinMagFilter min_filter, + MinMagFilter mag_filter, + MipFilter mip_filter); + // Comparable std::size_t GetHash() const override { return fml::HashCombine(min_filter, mag_filter, mip_filter, diff --git a/impeller/renderer/snapshot.h b/impeller/renderer/snapshot.h index 26fe49d894d2d..41ad4071445b7 100644 --- a/impeller/renderer/snapshot.h +++ b/impeller/renderer/snapshot.h @@ -11,6 +11,7 @@ #include "flutter/fml/macros.h" #include "impeller/geometry/matrix.h" #include "impeller/geometry/rect.h" +#include "impeller/renderer/formats.h" #include "impeller/renderer/sampler_descriptor.h" #include "impeller/renderer/texture.h" @@ -25,7 +26,11 @@ struct Snapshot { /// The transform that should be applied to this texture for rendering. Matrix transform; - SamplerDescriptor sampler_descriptor; + SamplerDescriptor sampler_descriptor = + SamplerDescriptor("Default Snapshot Sampler", + MinMagFilter::kLinear, + MinMagFilter::kLinear, + MipFilter::kLinear); Scalar opacity = 1.0f; diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni index 5a4c695494c03..793d9f10dc814 100644 --- a/impeller/tools/impeller.gni +++ b/impeller/tools/impeller.gni @@ -18,7 +18,7 @@ declare_args() { impeller_enable_opengles = is_mac || is_linux || is_win || is_android # Whether the Vulkan backend is enabled. - impeller_enable_vulkan = is_linux || is_android + impeller_enable_vulkan = is_mac || is_linux || is_android # Whether to use a prebuilt impellerc. # If this is the empty string, impellerc will be built. @@ -242,13 +242,9 @@ template("impellerc") { iplr = invoker.iplr } json = false - remap_samplers = false if (defined(invoker.json) && invoker.json) { json = invoker.json } - if (defined(invoker.remap_samplers) && invoker.remap_samplers) { - remap_samplers = invoker.remap_samplers - } # Not needed on every path. not_needed([ @@ -261,8 +257,6 @@ template("impellerc") { # Optional: invoker.intermediates_subdir specifies the subdirectory in which # to put intermediates. # Optional: invoker.json Causes output format to be JSON instead of flatbuffer. - # Optional: invoker.remap_samplers Output metal samplers according to - # declaration order instead of usage order. _impellerc(target_name) { sources = invoker.shaders @@ -299,9 +293,6 @@ template("impellerc") { if (json) { args += [ "--json" ] } - if (remap_samplers) { - args += [ "--remap-samplers" ] - } if (sksl) { sl_intermediate = diff --git a/impeller/tools/malioc.json b/impeller/tools/malioc.json new file mode 100644 index 0000000000000..a2a029e6101e5 --- /dev/null +++ b/impeller/tools/malioc.json @@ -0,0 +1 @@ +{"flutter/impeller/entity/gles/advanced_blend.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 4.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 4.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 7.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 7.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 7.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_color.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_color.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 84, "has_stack_spilling": false, "longest_path_cycles": [0.78125, 0.6875, 0.78125, 0.25, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.359375, 0.328125, 0.359375, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.824999988079071, 0.6875, 0.824999988079071, 0.25, 0.0, 0.25, 0.5], "uniform_registers_used": 14, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_color.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [12.869999885559082, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [6.599999904632568, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [14.333333015441895, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.925000011920929, 0.296875, 0.925000011920929, 0.3125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.5, 0.234375, 0.5, 0.25, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.96875, 0.296875, 0.96875, 0.3125, 0.0, 0.25, 0.5], "uniform_registers_used": 12, "work_registers_used": 26}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_colorburn.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [13.529999732971191, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [8.90999984741211, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [14.666666984558105, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.925000011920929, 0.265625, 0.925000011920929, 0.3125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.5, 0.203125, 0.5, 0.25, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.96875, 0.265625, 0.96875, 0.3125, 0.0, 0.25, 0.5], "uniform_registers_used": 12, "work_registers_used": 26}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_colordodge.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [13.199999809265137, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [8.579999923706055, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [14.333333015441895, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.6875, 0.203125, 0.6875, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.265625, 0.140625, 0.265625, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.737500011920929, 0.203125, 0.737500011920929, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 10, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_darken.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [8.90999984741211, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.9600000381469727, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [9.666666984558105, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.65625, 0.234375, 0.65625, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.234375, 0.171875, 0.234375, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.699999988079071, 0.234375, 0.699999988079071, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 10, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_difference.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [8.90999984741211, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.9600000381469727, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [9.666666984558105, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.65625, 0.296875, 0.65625, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.234375, 0.234375, 0.234375, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.699999988079071, 0.296875, 0.699999988079071, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 10, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_exclusion.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [9.569999694824219, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [4.619999885559082, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [10.333333015441895, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.71875, 0.484375, 0.71875, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.421875, 0.421875, 0.296875, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.762499988079071, 0.484375, 0.762499988079071, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 12, "work_registers_used": 25}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_hardlight.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [10.5600004196167, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [5.610000133514404, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [11.333333015441895, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 87, "has_stack_spilling": false, "longest_path_cycles": [0.9375, 0.800000011920929, 0.9375, 0.3125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.5, 0.328125, 0.5, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [1.03125, 0.800000011920929, 1.03125, 0.3125, 0.0, 0.25, 0.5], "uniform_registers_used": 14, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_hue.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [14.850000381469727, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [6.929999828338623, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [16.0, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.6875, 0.203125, 0.6875, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.265625, 0.140625, 0.265625, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.737500011920929, 0.203125, 0.737500011920929, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 10, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_lighten.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [8.90999984741211, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.9600000381469727, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [9.666666984558105, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 84, "has_stack_spilling": false, "longest_path_cycles": [0.78125, 0.6875, 0.78125, 0.25, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.359375, 0.328125, 0.359375, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.824999988079071, 0.6875, 0.824999988079071, 0.25, 0.0, 0.25, 0.5], "uniform_registers_used": 14, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_luminosity.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [12.869999885559082, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [6.599999904632568, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [14.333333015441895, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.65625, 0.234375, 0.65625, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.234375, 0.171875, 0.234375, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.699999988079071, 0.234375, 0.699999988079071, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 10, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_multiply.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [9.239999771118164, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [4.289999961853027, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [10.0, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.71875, 0.484375, 0.71875, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.421875, 0.421875, 0.296875, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.762499988079071, 0.484375, 0.762499988079071, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 12, "work_registers_used": 25}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_overlay.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [10.229999542236328, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [5.610000133514404, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [11.333333015441895, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 87, "has_stack_spilling": false, "longest_path_cycles": [0.9375, 0.800000011920929, 0.9375, 0.3125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.5, 0.328125, 0.5, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [1.03125, 0.800000011920929, 1.03125, 0.3125, 0.0, 0.25, 0.5], "uniform_registers_used": 14, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_saturation.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [15.180000305175781, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [7.260000228881836, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [16.33333396911621, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.65625, 0.265625, 0.65625, 0.125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.234375, 0.203125, 0.234375, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.699999988079071, 0.265625, 0.699999988079071, 0.125, 0.0, 0.25, 0.5], "uniform_registers_used": 10, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_screen.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [9.239999771118164, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [4.289999961853027, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [10.0, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.862500011920929, 0.75, 0.862500011920929, 0.3125, 0.0, 0.25, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.6875, 0.6875, 0.4375, 0.25, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.90625, 0.75, 0.90625, 0.3125, 0.0, 0.25, 0.5], "uniform_registers_used": 16, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/advanced_blend_softlight.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [13.859999656677246, 2.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [8.90999984741211, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [14.666666984558105, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/blend.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/blend.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.09375, 0.046875, 0.09375, 0.0, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.0625, 0.046875, 0.0625, 0.0, 0.0, 0.125, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.09375, 0.046875, 0.09375, 0.0, 0.0, 0.125, 0.25], "uniform_registers_used": 4, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/blend.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [1.0, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 1.0, 1.0], "thread_occupancy": 100, "total_cycles": [1.3333333730697632, 1.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/blend.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/blend.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 5.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 5.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/border_mask_blur.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/border_mask_blur.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 18, "has_stack_spilling": false, "longest_path_cycles": [0.84375, 0.84375, 0.3125, 0.4375, 0.0, 0.625, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.84375, 0.84375, 0.28125, 0.4375, 0.0, 0.625, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.84375, 0.84375, 0.3125, 0.4375, 0.0, 0.625, 0.25], "uniform_registers_used": 8, "work_registers_used": 31}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/border_mask_blur.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [8.90999984741211, 3.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [8.90999984741211, 3.0, 1.0], "thread_occupancy": 100, "total_cycles": [9.333333015441895, 3.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/border_mask_blur.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/border_mask_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 20, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0625, 0.0, 0.0625, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0625, 0.0, 0.0625, 0.0, 4.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0625, 0.0, 0.0625, 0.0, 4.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 10}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/border_mask_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.9700000286102295, 9.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.9700000286102295, 9.0, 0.0], "thread_occupancy": 100, "total_cycles": [3.0, 9.0, 0.0], "uniform_registers_used": 5, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.265625, 0.265625, 0.15625, 0.0625, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.265625, 0.265625, 0.125, 0.0625, 0.0, 0.125, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.265625, 0.265625, 0.15625, 0.0625, 0.0, 0.125, 0.25], "uniform_registers_used": 14, "work_registers_used": 23}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.299999952316284, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.299999952316284, 1.0, 1.0], "thread_occupancy": 100, "total_cycles": [3.6666667461395264, 1.0, 1.0], "uniform_registers_used": 3, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/color_matrix_color_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/gaussian_blur.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gaussian_blur.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 76, "has_stack_spilling": false, "longest_path_cycles": [null, null, null, null, null, null, null], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.109375, 0.109375, 0.09375, 0.0625, 0.0, 0.25, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.3125, 0.3125, 0.21875, 0.125, 0.0, 0.5, 0.5], "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gaussian_blur.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [null, null, null], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.9700000286102295, 2.0, 1.0], "thread_occupancy": 100, "total_cycles": [5.0, 2.0, 2.0], "uniform_registers_used": 2, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/gaussian_blur.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gaussian_blur.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0625, 0.03125, 0.0625, 0.0, 4.0, 0.0], "uniform_registers_used": 10, "work_registers_used": 8}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gaussian_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.299999952316284, 7.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.299999952316284, 7.0, 0.0], "thread_occupancy": 100, "total_cycles": [3.3333332538604736, 7.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 79, "has_stack_spilling": false, "longest_path_cycles": [null, null, null, null, null, null, null], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.25, 0.109375, 0.1875, 0.25, 0.0, 0.25, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.5, 0.3125, 0.421875, 0.5, 0.0, 0.5, 0.5], "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gaussian_blur_decal.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [null, null, null], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [4.289999961853027, 2.0, 0.0], "thread_occupancy": 100, "total_cycles": [8.333333015441895, 2.0, 2.0], "uniform_registers_used": 2, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/glyph_atlas.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 45, "has_stack_spilling": false, "longest_path_cycles": [0.125, 0.125, 0.09375, 0.0, 0.0, 0.875, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.125, 0.125, 0.046875, 0.0, 0.0, 0.875, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.15625, 0.15625, 0.09375, 0.0, 0.0, 0.875, 0.5], "uniform_registers_used": 6, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [1.649999976158142, 2.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.649999976158142, 2.0, 1.0], "thread_occupancy": 100, "total_cycles": [3.0, 2.0, 2.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/glyph_atlas.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [0.296875, 0.296875, 0.0, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.296875, 0.296875, 0.0, 0.0, 4.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.296875, 0.296875, 0.0, 0.0, 4.0, 0.0], "uniform_registers_used": 18, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.015625, 0.078125, 0.0, 7.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.015625, 0.078125, 0.0, 7.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.015625, 0.078125, 0.0, 7.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 12}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.9600000381469727, 12.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.9600000381469727, 12.0, 0.0], "thread_occupancy": 100, "total_cycles": [4.0, 12.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 60, "has_stack_spilling": false, "longest_path_cycles": [0.40625, 0.40625, 0.046875, 0.3125, 0.0, 0.75, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.40625, 0.40625, 0.015625, 0.3125, 0.0, 0.75, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.40625, 0.40625, 0.046875, 0.3125, 0.0, 0.75, 0.25], "uniform_registers_used": 10, "work_registers_used": 22}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [4.619999885559082, 2.0, 3.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [4.619999885559082, 2.0, 3.0], "thread_occupancy": 100, "total_cycles": [5.0, 2.0, 3.0], "uniform_registers_used": 2, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 90, "has_stack_spilling": false, "longest_path_cycles": [0.171875, 0.171875, 0.046875, 0.0, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.171875, 0.171875, 0.046875, 0.0, 4.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.171875, 0.171875, 0.046875, 0.0, 4.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 5.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 5.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 5.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 8}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/glyph_atlas_sdf.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.299999952316284, 10.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.299999952316284, 10.0, 0.0], "thread_occupancy": 100, "total_cycles": [3.3333332538604736, 10.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/gradient_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/gradient_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 24, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.125, 0.125, 0.0, 0.0625, 3.0, 0.0], "uniform_registers_used": 18, "work_registers_used": 9}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/gradient_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.299999952316284, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.299999952316284, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [3.3333332538604736, 4.0, 0.0], "uniform_registers_used": 5, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 70, "has_stack_spilling": false, "longest_path_cycles": [0.40625, 0.28125, 0.40625, 0.125, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.1875, 0.171875, 0.1875, 0.125, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.484375, 0.3125, 0.484375, 0.125, 0.0, 0.125, 0.25], "uniform_registers_used": 12, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/linear_gradient_fill.frag.gles", "has_uniform_computation": true, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [6.929999828338623, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.309999942779541, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [7.666666507720947, 1.0, 1.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 41, "has_stack_spilling": false, "longest_path_cycles": [0.5, 0.34375, 0.5, 0.4375, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.46875, 0.34375, 0.46875, 0.4375, 0.0, 0.125, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.5, 0.34375, 0.5, 0.4375, 0.0, 0.125, 0.25], "uniform_registers_used": 10, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [5.610000133514404, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [5.610000133514404, 1.0, 1.0], "thread_occupancy": 100, "total_cycles": [6.0, 1.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/linear_to_srgb_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/morphology_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/morphology_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [null, null, null, null, null, null, null], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.0625, 0.0, 0.0625, 0.0, 0.0, 0.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.453125, 0.0625, 0.453125, 0.0, 0.0, 0.125, 0.25], "uniform_registers_used": 8, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/morphology_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [null, null, null], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.649999976158142, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [6.333333492279053, 1.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/morphology_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/morphology_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/morphology_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 5.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 5.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/position.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/position.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 16, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.03125, 0.0, 0.03125, 0.0, 2.0, 0.0], "uniform_registers_used": 10, "work_registers_used": 5}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/position.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/position_color.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/position_color.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 7}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/position_color.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 5.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 5.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/position_uv.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/position_uv.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 20, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 4.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.125, 0.125, 0.0, 0.0625, 4.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.125, 0.125, 0.0, 0.0625, 4.0, 0.0], "uniform_registers_used": 18, "work_registers_used": 10}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/position_uv.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.299999952316284, 6.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.299999952316284, 6.0, 0.0], "thread_occupancy": 100, "total_cycles": [3.3333332538604736, 6.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 55, "has_stack_spilling": false, "longest_path_cycles": [0.40625, 0.3125, 0.40625, 0.1875, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.203125, 0.203125, 0.1875, 0.1875, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.484375, 0.34375, 0.484375, 0.1875, 0.0, 0.125, 0.25], "uniform_registers_used": 10, "work_registers_used": 20}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/radial_gradient_fill.frag.gles", "has_uniform_computation": true, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [6.929999828338623, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.309999942779541, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [7.666666507720947, 1.0, 1.0], "uniform_registers_used": 2, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/rrect_blur.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/rrect_blur.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 33, "has_stack_spilling": false, "longest_path_cycles": [1.5125000476837158, 1.5125000476837158, 0.546875, 1.5, 0.0, 0.125, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.203125, 0.203125, 0.046875, 0.0625, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [1.6375000476837158, 1.6375000476837158, 0.578125, 1.5625, 0.0, 0.125, 0.0], "uniform_registers_used": 20, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/rrect_blur.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [null, null, null], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [10.666666984558105, 1.0, 0.0], "uniform_registers_used": 1, "work_registers_used": 4}}}}, "flutter/impeller/entity/gles/rrect_blur.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/rrect_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/rrect_blur.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/runtime_effect.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/runtime_effect.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/runtime_effect.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/solid_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/solid_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0625, 0.0, 0.0625, 0.0, 0.0, 0.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.03125, 0.0, 0.03125, 0.0, 0.0, 0.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0625, 0.0, 0.0625, 0.0, 0.0, 0.0, 0.0], "uniform_registers_used": 2, "work_registers_used": 18}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/solid_fill.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [1.0, 0.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 0.0, 0.0], "thread_occupancy": 100, "total_cycles": [0.6666666865348816, 0.0, 0.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/solid_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/solid_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/solid_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 3.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 3.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 3.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 41, "has_stack_spilling": false, "longest_path_cycles": [0.546875, 0.34375, 0.546875, 0.4375, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.515625, 0.34375, 0.515625, 0.4375, 0.0, 0.125, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.546875, 0.34375, 0.546875, 0.4375, 0.0, 0.125, 0.25], "uniform_registers_used": 10, "work_registers_used": 30}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [5.610000133514404, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [5.610000133514404, 1.0, 1.0], "thread_occupancy": 100, "total_cycles": [6.0, 1.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/srgb_to_linear_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 15, "has_stack_spilling": false, "longest_path_cycles": [0.5, 0.453125, 0.5, 0.375, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.375, 0.34375, 0.28125, 0.375, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.59375, 0.484375, 0.59375, 0.375, 0.0, 0.125, 0.25], "uniform_registers_used": 18, "work_registers_used": 24}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/sweep_gradient_fill.frag.gles", "has_uniform_computation": true, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [7.920000076293945, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.9700000286102295, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [8.666666984558105, 1.0, 1.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/texture_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/texture_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.09375, 0.046875, 0.09375, 0.0, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.0625, 0.046875, 0.0625, 0.0, 0.0, 0.125, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.09375, 0.046875, 0.09375, 0.0, 0.0, 0.125, 0.25], "uniform_registers_used": 4, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/texture_fill.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [1.0, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 1.0, 1.0], "thread_occupancy": 100, "total_cycles": [1.3333333730697632, 1.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/texture_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/texture_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/texture_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 5.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 5.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 5.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.5, 0.203125, 0.5, 0.0, 0.0, 0.125, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.109375, 0.03125, 0.109375, 0.0, 0.0, 0.125, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.625, 0.265625, 0.625, 0.0, 0.0, 0.125, 0.25], "uniform_registers_used": 8, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [7.920000076293945, 1.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.3200000524520874, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [9.666666984558105, 1.0, 1.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 24, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 18, "has_stack_spilling": false, "longest_path_cycles": [0.15625, 0.15625, 0.0, 0.0625, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.15625, 0.15625, 0.0, 0.0625, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.15625, 0.15625, 0.0, 0.0625, 3.0, 0.0], "uniform_registers_used": 18, "work_registers_used": 9}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/tiled_texture_fill.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [3.9600000381469727, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [3.9600000381469727, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [4.0, 4.0, 0.0], "uniform_registers_used": 6, "work_registers_used": 3}}}}, "flutter/impeller/entity/gles/vertices.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/vertices.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.03125, 0.03125, 0.03125, 0.0, 0.0, 0.25, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.03125, 0.03125, 0.0, 0.0, 0.0, 0.25, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.03125, 0.03125, 0.03125, 0.0, 0.0, 0.25, 0.0], "uniform_registers_used": 2, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/vertices.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [1.0, 1.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 1.0, 0.0], "thread_occupancy": 100, "total_cycles": [0.6666666865348816, 1.0, 0.0], "uniform_registers_used": 1, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles", "has_side_effects": false, "has_uniform_computation": true, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 100, "has_stack_spilling": false, "longest_path_cycles": [0.171875, 0.171875, 0.109375, 0.0, 0.0, 0.125, 0.5], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.171875, 0.171875, 0.078125, 0.0, 0.0, 0.125, 0.5], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.171875, 0.171875, 0.109375, 0.0, 0.0, 0.125, 0.5], "uniform_registers_used": 12, "work_registers_used": 21}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.9700000286102295, 1.0, 2.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.9700000286102295, 1.0, 2.0], "thread_occupancy": 100, "total_cycles": [3.3333332538604736, 1.0, 2.0], "uniform_registers_used": 3, "work_registers_used": 2}}}}, "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 80, "has_stack_spilling": false, "longest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.078125, 0.078125, 0.046875, 0.0, 2.0, 0.0], "uniform_registers_used": 14, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": null, "has_stack_spilling": false, "longest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.0, 0.0, 0.0, 0.0, 3.0, 0.0], "uniform_registers_used": 8, "work_registers_used": 6}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/entity/gles/yuv_to_rgb_filter.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [2.640000104904175, 4.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [2.640000104904175, 4.0, 0.0], "thread_occupancy": 100, "total_cycles": [2.6666667461395264, 4.0, 0.0], "uniform_registers_used": 4, "work_registers_used": 2}}}}, "flutter/impeller/scene/shaders/gles/skinned.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/scene/shaders/gles/skinned.vert.gles", "has_uniform_computation": true, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [3.075000047683716, 3.075000047683716, 0.09375, 0.0, 4.0, 4.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [1.2625000476837158, 1.2625000476837158, 0.296875, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 50, "total_cycles": [3.075000047683716, 3.075000047683716, 0.359375, 0.0, 4.0, 4.0], "uniform_registers_used": 30, "work_registers_used": 64}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [3.59375, 3.59375, 0.09375, 0.0, 13.0, 4.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [1.78125, 1.78125, 0.296875, 0.0, 11.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 50, "total_cycles": [3.59375, 3.59375, 0.359375, 0.0, 13.0, 4.0], "uniform_registers_used": 26, "work_registers_used": 64}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/scene/shaders/gles/skinned.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": true, "longest_path_cycles": [23.43000030517578, 17.0, 16.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [12.210000038146973, 13.0, 0.0], "thread_occupancy": 50, "total_cycles": [20.0, 17.0, 16.0], "uniform_registers_used": 7, "work_registers_used": 8}}}}, "flutter/impeller/scene/shaders/gles/unlit.frag.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/scene/shaders/gles/unlit.frag.gles", "has_side_effects": false, "has_uniform_computation": false, "modifies_coverage": false, "reads_color_buffer": false, "type": "Fragment", "uses_late_zs_test": false, "uses_late_zs_update": false, "variants": {"Main": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [0.25, 0.25, 0.03125, 0.0, 0.0, 0.75, 0.25], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "varying", "texture"], "shortest_path_cycles": [0.25, 0.25, 0.0, 0.0, 0.0, 0.75, 0.25], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.25, 0.25, 0.03125, 0.0, 0.0, 0.75, 0.25], "uniform_registers_used": 8, "work_registers_used": 19}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/scene/shaders/gles/unlit.frag.gles", "has_uniform_computation": false, "type": "Fragment", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [1.0, 2.0, 1.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [1.0, 2.0, 1.0], "thread_occupancy": 100, "total_cycles": [1.3333333730697632, 2.0, 1.0], "uniform_registers_used": 2, "work_registers_used": 2}}}}, "flutter/impeller/scene/shaders/gles/unskinned.vert.gles": {"Mali-G78": {"core": "Mali-G78", "filename": "flutter/impeller/scene/shaders/gles/unskinned.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Position": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [0.265625, 0.265625, 0.0, 0.0, 2.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.265625, 0.265625, 0.0, 0.0, 2.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.265625, 0.265625, 0.0, 0.0, 2.0, 0.0], "uniform_registers_used": 24, "work_registers_used": 32}, "Varying": {"fp16_arithmetic": 0, "has_stack_spilling": false, "longest_path_cycles": [0.75, 0.75, 0.0, 0.0, 11.0, 0.0], "pipelines": ["arith_total", "arith_fma", "arith_cvt", "arith_sfu", "load_store", "texture"], "shortest_path_cycles": [0.75, 0.75, 0.0, 0.0, 11.0, 0.0], "stack_spill_bytes": 0, "thread_occupancy": 100, "total_cycles": [0.75, 0.75, 0.0, 0.0, 11.0, 0.0], "uniform_registers_used": 20, "work_registers_used": 32}}}, "Mali-T880": {"core": "Mali-T880", "filename": "flutter/impeller/scene/shaders/gles/unskinned.vert.gles", "has_uniform_computation": false, "type": "Vertex", "variants": {"Main": {"has_stack_spilling": false, "longest_path_cycles": [5.28000020980835, 13.0, 0.0], "pipelines": ["arithmetic", "load_store", "texture"], "shortest_path_cycles": [5.28000020980835, 13.0, 0.0], "thread_occupancy": 50, "total_cycles": [5.333333492279053, 13.0, 0.0], "uniform_registers_used": 7, "work_registers_used": 6}}}}} \ No newline at end of file diff --git a/impeller/tools/malioc_diff.py b/impeller/tools/malioc_diff.py index 6e8b7bd44eb6c..8906f59679e84 100755 --- a/impeller/tools/malioc_diff.py +++ b/impeller/tools/malioc_diff.py @@ -32,6 +32,11 @@ # If there are differences between before and after, whether positive or # negative, the exit code for this script will be 1, and 0 otherwise. +CORES = [ + 'Mali-G78', # Pixel 6 / 2020 + 'Mali-T880', # 2016 +] + def parse_args(argv): parser = argparse.ArgumentParser( @@ -86,6 +91,9 @@ def read_malioc_file(malioc_tree, json_file): results = [] for shader in json_obj['shaders']: + # Ignore cores not in the allowlist above. + if shader['hardware']['core'] not in CORES: + continue result = {} result['filename'] = os.path.relpath(shader['filename'], build_gen_dir) result['core'] = shader['hardware']['core'] @@ -200,6 +208,8 @@ def main(argv): changed = False for filename, shaders in before_json.items(): for core, before_shader in shaders.items(): + if core not in after_json[filename].keys(): + continue after_shader = after_json[filename][core] if compare_shaders(args.after, before_shader, after_shader): changed = True diff --git a/impeller/typographer/backends/skia/text_frame_skia.cc b/impeller/typographer/backends/skia/text_frame_skia.cc index bd082ffb71c76..e451695dc8b6d 100644 --- a/impeller/typographer/backends/skia/text_frame_skia.cc +++ b/impeller/typographer/backends/skia/text_frame_skia.cc @@ -27,6 +27,9 @@ static Font ToFont(const SkTextBlobRunIterator& run, Scalar scale) { Font::Metrics metrics; metrics.scale = scale; metrics.point_size = font.getSize(); + metrics.embolden = font.isEmbolden(); + metrics.skewX = font.getSkewX(); + metrics.scaleX = font.getScaleX(); return Font{std::move(typeface), metrics}; } diff --git a/impeller/typographer/backends/skia/text_render_context_skia.cc b/impeller/typographer/backends/skia/text_render_context_skia.cc index cf999db213333..cb301e97d0bfd 100644 --- a/impeller/typographer/backends/skia/text_render_context_skia.cc +++ b/impeller/typographer/backends/skia/text_render_context_skia.cc @@ -22,6 +22,11 @@ namespace impeller { +// TODO(bdero): We might be able to remove this per-glyph padding if we fix +// the underlying causes of the overlap. +// https://github.com/flutter/flutter/issues/114563 +constexpr auto kPadding = 2; + TextRenderContextSkia::TextRenderContextSkia(std::shared_ptr context) : TextRenderContext(std::move(context)) {} @@ -58,33 +63,27 @@ static FontGlyphPair::Vector CollectUniqueFontGlyphPairs( return vector; } -static size_t PairsFitInAtlasOfSize(const FontGlyphPair::Vector& pairs, - const ISize& atlas_size, - std::vector& glyph_positions) { +static size_t PairsFitInAtlasOfSize( + const FontGlyphPair::Vector& pairs, + const ISize& atlas_size, + std::vector& glyph_positions, + const std::shared_ptr& rect_packer) { if (atlas_size.IsEmpty()) { return false; } - auto rect_packer = std::unique_ptr( - GrRectanizer::Factory(atlas_size.width, atlas_size.height)); - glyph_positions.clear(); glyph_positions.reserve(pairs.size()); - // TODO(bdero): We might be able to remove this per-glyph padding if we fix - // the underlying causes of the overlap. - // https://github.com/flutter/flutter/issues/114563 - constexpr auto padding = 2; - for (size_t i = 0; i < pairs.size(); i++) { const auto& pair = pairs[i]; const auto glyph_size = ISize::Ceil((pair.glyph.bounds * pair.font.GetMetrics().scale).size); SkIPoint16 location_in_atlas; - if (!rect_packer->addRect(glyph_size.width + padding, // - glyph_size.height + padding, // - &location_in_atlas // + if (!rect_packer->addRect(glyph_size.width + kPadding, // + glyph_size.height + kPadding, // + &location_in_atlas // )) { return pairs.size() - i; } @@ -98,9 +97,48 @@ static size_t PairsFitInAtlasOfSize(const FontGlyphPair::Vector& pairs, return 0; } +static bool CanAppendToExistingAtlas( + const std::shared_ptr& atlas, + const FontGlyphPair::Vector& extra_pairs, + std::vector& glyph_positions, + ISize atlas_size, + const std::shared_ptr& rect_packer) { + TRACE_EVENT0("impeller", __FUNCTION__); + if (!rect_packer || atlas_size.IsEmpty()) { + return false; + } + + // We assume that all existing glyphs will fit. After all, they fit before. + // The glyph_positions only contains the values for the additional glyphs + // from extra_pairs. + FML_DCHECK(glyph_positions.size() == 0); + glyph_positions.reserve(extra_pairs.size()); + for (size_t i = 0; i < extra_pairs.size(); i++) { + const auto& pair = extra_pairs[i]; + + const auto glyph_size = + ISize::Ceil((pair.glyph.bounds * pair.font.GetMetrics().scale).size); + SkIPoint16 location_in_atlas; + if (!rect_packer->addRect(glyph_size.width + kPadding, // + glyph_size.height + kPadding, // + &location_in_atlas // + )) { + return false; + } + glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), // + location_in_atlas.y(), // + glyph_size.width, // + glyph_size.height // + )); + } + + return true; +} + static ISize OptimumAtlasSizeForFontGlyphPairs( const FontGlyphPair::Vector& pairs, - std::vector& glyph_positions) { + std::vector& glyph_positions, + const std::shared_ptr& atlas_context) { static constexpr auto kMinAtlasSize = 8u; static constexpr auto kMaxAtlasSize = 4096u; @@ -109,9 +147,13 @@ static ISize OptimumAtlasSizeForFontGlyphPairs( ISize current_size(kMinAtlasSize, kMinAtlasSize); size_t total_pairs = pairs.size() + 1; do { - auto remaining_pairs = - PairsFitInAtlasOfSize(pairs, current_size, glyph_positions); + auto rect_packer = std::shared_ptr( + GrRectanizer::Factory(current_size.width, current_size.height)); + + auto remaining_pairs = PairsFitInAtlasOfSize(pairs, current_size, + glyph_positions, rect_packer); if (remaining_pairs == 0) { + atlas_context->UpdateRectPacker(rect_packer); return current_size; } else if (remaining_pairs < std::ceil(total_pairs / 2)) { current_size = ISize::MakeWH( @@ -243,6 +285,66 @@ static void ConvertBitmapToSignedDistanceField(uint8_t* pixels, #undef nearestpt } +static void DrawGlyph(SkCanvas* canvas, + const FontGlyphPair& font_glyph, + const Rect& location, + bool has_color) { + const auto& metrics = font_glyph.font.GetMetrics(); + const auto position = SkPoint::Make(location.origin.x / metrics.scale, + location.origin.y / metrics.scale); + SkGlyphID glyph_id = font_glyph.glyph.index; + + SkFont sk_font( + TypefaceSkia::Cast(*font_glyph.font.GetTypeface()).GetSkiaTypeface(), + metrics.point_size, metrics.scaleX, metrics.skewX); + sk_font.setEdging(SkFont::Edging::kAntiAlias); + sk_font.setHinting(SkFontHinting::kSlight); + sk_font.setEmbolden(metrics.embolden); + + auto glyph_color = has_color ? SK_ColorWHITE : SK_ColorBLACK; + + SkPaint glyph_paint; + glyph_paint.setColor(glyph_color); + canvas->resetMatrix(); + canvas->scale(metrics.scale, metrics.scale); + canvas->drawGlyphs( + 1u, // count + &glyph_id, // glyphs + &position, // positions + SkPoint::Make(-font_glyph.glyph.bounds.GetLeft(), + -font_glyph.glyph.bounds.GetTop()), // origin + sk_font, // font + glyph_paint // paint + ); +} + +static bool UpdateAtlasBitmap(const GlyphAtlas& atlas, + const std::shared_ptr& bitmap, + const FontGlyphPair::Vector& new_pairs) { + TRACE_EVENT0("impeller", __FUNCTION__); + FML_DCHECK(bitmap != nullptr); + + auto surface = SkSurface::MakeRasterDirect(bitmap->pixmap()); + if (!surface) { + return false; + } + auto canvas = surface->getCanvas(); + if (!canvas) { + return false; + } + + bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap; + + for (const auto& pair : new_pairs) { + auto pos = atlas.FindFontGlyphPosition(pair); + if (!pos.has_value()) { + continue; + } + DrawGlyph(canvas, pair, pos.value(), has_color); + } + return true; +} + static std::shared_ptr CreateAtlasBitmap(const GlyphAtlas& atlas, const ISize& atlas_size) { TRACE_EVENT0("impeller", __FUNCTION__); @@ -263,6 +365,7 @@ static std::shared_ptr CreateAtlasBitmap(const GlyphAtlas& atlas, if (!bitmap->tryAllocPixels(image_info)) { return nullptr; } + auto surface = SkSurface::MakeRasterDirect(bitmap->pixmap()); if (!surface) { return nullptr; @@ -272,37 +375,33 @@ static std::shared_ptr CreateAtlasBitmap(const GlyphAtlas& atlas, return nullptr; } - atlas.IterateGlyphs([canvas](const FontGlyphPair& font_glyph, - const Rect& location) -> bool { - const auto& metrics = font_glyph.font.GetMetrics(); - const auto position = SkPoint::Make(location.origin.x / metrics.scale, - location.origin.y / metrics.scale); - SkGlyphID glyph_id = font_glyph.glyph.index; - - SkFont sk_font( - TypefaceSkia::Cast(*font_glyph.font.GetTypeface()).GetSkiaTypeface(), - metrics.point_size); - auto glyph_color = SK_ColorWHITE; - - SkPaint glyph_paint; - glyph_paint.setColor(glyph_color); - canvas->resetMatrix(); - canvas->scale(metrics.scale, metrics.scale); - canvas->drawGlyphs( - 1u, // count - &glyph_id, // glyphs - &position, // positions - SkPoint::Make(-font_glyph.glyph.bounds.GetLeft(), - -font_glyph.glyph.bounds.GetTop()), // origin - sk_font, // font - glyph_paint // paint - ); + bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap; + + atlas.IterateGlyphs([canvas, has_color](const FontGlyphPair& font_glyph, + const Rect& location) -> bool { + DrawGlyph(canvas, font_glyph, location, has_color); return true; }); return bitmap; } +static bool UpdateGlyphTextureAtlas(std::shared_ptr bitmap, + const std::shared_ptr& texture) { + TRACE_EVENT0("impeller", __FUNCTION__); + + FML_DCHECK(bitmap != nullptr); + auto texture_descriptor = texture->GetTextureDescriptor(); + + auto mapping = std::make_shared( + reinterpret_cast(bitmap->getAddr(0, 0)), // data + texture_descriptor.GetByteSizeOfBaseMipLevel(), // size + [bitmap](auto, auto) mutable { bitmap.reset(); } // proc + ); + + return texture->SetContents(mapping); +} + static std::shared_ptr UploadGlyphTextureAtlas( const std::shared_ptr& allocator, std::shared_ptr bitmap, @@ -367,26 +466,61 @@ std::shared_ptr TextRenderContextSkia::CreateGlyphAtlas( // Step 2: Determine if the atlas type and font glyph pairs are compatible // with the current atlas and reuse if possible. // --------------------------------------------------------------------------- - if (last_atlas->GetType() == type && - last_atlas->HasSamePairs(font_glyph_pairs)) { + auto new_glyphs = last_atlas->HasSamePairs(font_glyph_pairs); + if (last_atlas->GetType() == type && new_glyphs.size() == 0) { return last_atlas; } - auto glyph_atlas = std::make_shared(type); - atlas_context->UpdateGlyphAtlas(glyph_atlas); - // --------------------------------------------------------------------------- - // Step 3: Get the optimum size of the texture atlas. + // Step 3: Determine if the additional missing glyphs can be appended to the + // existing bitmap without recreating the atlas. // --------------------------------------------------------------------------- std::vector glyph_positions; - const auto atlas_size = - OptimumAtlasSizeForFontGlyphPairs(font_glyph_pairs, glyph_positions); + if (CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions, + atlas_context->GetAtlasSize(), + atlas_context->GetRectPacker())) { + // The old bitmap will be reused and only the additional glyphs will be + // added. + + // --------------------------------------------------------------------------- + // Step 4: Record the positions in the glyph atlas of the newly added + // glyphs. + // --------------------------------------------------------------------------- + for (size_t i = 0, count = glyph_positions.size(); i < count; i++) { + last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]); + } + + // --------------------------------------------------------------------------- + // Step 5: Draw new font-glyph pairs into the existing bitmap. + // --------------------------------------------------------------------------- + auto bitmap = atlas_context->GetBitmap(); + if (!UpdateAtlasBitmap(*last_atlas, bitmap, new_glyphs)) { + return nullptr; + } + + // --------------------------------------------------------------------------- + // Step 6: Update the existing texture with the updated bitmap. + // --------------------------------------------------------------------------- + if (!UpdateGlyphTextureAtlas(bitmap, last_atlas->GetTexture())) { + return nullptr; + } + return last_atlas; + } + // A new glyph atlas must be created. + + // --------------------------------------------------------------------------- + // Step 4: Get the optimum size of the texture atlas. + // --------------------------------------------------------------------------- + auto glyph_atlas = std::make_shared(type); + auto atlas_size = OptimumAtlasSizeForFontGlyphPairs( + font_glyph_pairs, glyph_positions, atlas_context); + + atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size); if (atlas_size.IsEmpty()) { return nullptr; } - // --------------------------------------------------------------------------- - // Step 4: Find location of font-glyph pairs in the atlas. We have this from + // Step 5: Find location of font-glyph pairs in the atlas. We have this from // the last step. So no need to do create another rect packer. But just do a // sanity check of counts. This could also be just an assertion as only a // construction issue would cause such a failure. @@ -396,7 +530,7 @@ std::shared_ptr TextRenderContextSkia::CreateGlyphAtlas( } // --------------------------------------------------------------------------- - // Step 5: Record the positions in the glyph atlas. + // Step 6: Record the positions in the glyph atlas. // --------------------------------------------------------------------------- for (size_t i = 0, count = glyph_positions.size(); i < count; i++) { glyph_atlas->AddTypefaceGlyphPosition(font_glyph_pairs[i], @@ -404,15 +538,16 @@ std::shared_ptr TextRenderContextSkia::CreateGlyphAtlas( } // --------------------------------------------------------------------------- - // Step 6: Draw font-glyph pairs in the correct spot in the atlas. + // Step 7: Draw font-glyph pairs in the correct spot in the atlas. // --------------------------------------------------------------------------- auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size); if (!bitmap) { return nullptr; } + atlas_context->UpdateBitmap(bitmap); // --------------------------------------------------------------------------- - // Step 7: Upload the atlas as a texture. + // Step 8: Upload the atlas as a texture. // --------------------------------------------------------------------------- PixelFormat format; switch (type) { @@ -434,7 +569,7 @@ std::shared_ptr TextRenderContextSkia::CreateGlyphAtlas( } // --------------------------------------------------------------------------- - // Step 8: Record the texture in the glyph atlas. + // Step 9: Record the texture in the glyph atlas. // --------------------------------------------------------------------------- glyph_atlas->SetTexture(std::move(texture)); diff --git a/impeller/typographer/font.h b/impeller/typographer/font.h index 3e56981206f52..0867edcbf71c6 100644 --- a/impeller/typographer/font.h +++ b/impeller/typographer/font.h @@ -11,6 +11,7 @@ #include "impeller/base/comparable.h" #include "impeller/typographer/glyph.h" #include "impeller/typographer/typeface.h" +#include "include/core/SkFont.h" namespace impeller { @@ -38,9 +39,13 @@ class Font : public Comparable { /// The point size of the font. /// Scalar point_size = 12.0f; + bool embolden = false; + Scalar skewX = 0.0f; + Scalar scaleX = 1.0f; constexpr bool operator==(const Metrics& o) const { - return scale == o.scale && point_size == o.point_size; + return scale == o.scale && point_size == o.point_size && + embolden == o.embolden && skewX == o.skewX && scaleX == o.scaleX; } }; diff --git a/impeller/typographer/glyph_atlas.cc b/impeller/typographer/glyph_atlas.cc index 3a6470e97404d..4d50062065c89 100644 --- a/impeller/typographer/glyph_atlas.cc +++ b/impeller/typographer/glyph_atlas.cc @@ -9,7 +9,8 @@ namespace impeller { GlyphAtlasContext::GlyphAtlasContext() - : atlas_(std::make_shared(GlyphAtlas::Type::kAlphaBitmap)) {} + : atlas_(std::make_shared(GlyphAtlas::Type::kAlphaBitmap)), + atlas_size_(ISize(0, 0)) {} GlyphAtlasContext::~GlyphAtlasContext() {} @@ -17,8 +18,31 @@ std::shared_ptr GlyphAtlasContext::GetGlyphAtlas() const { return atlas_; } -void GlyphAtlasContext::UpdateGlyphAtlas(std::shared_ptr atlas) { +const ISize& GlyphAtlasContext::GetAtlasSize() const { + return atlas_size_; +} + +std::shared_ptr GlyphAtlasContext::GetBitmap() const { + return bitmap_; +} + +std::shared_ptr GlyphAtlasContext::GetRectPacker() const { + return rect_packer_; +} + +void GlyphAtlasContext::UpdateGlyphAtlas(std::shared_ptr atlas, + ISize size) { atlas_ = std::move(atlas); + atlas_size_ = size; +} + +void GlyphAtlasContext::UpdateBitmap(std::shared_ptr bitmap) { + bitmap_ = std::move(bitmap); +} + +void GlyphAtlasContext::UpdateRectPacker( + std::shared_ptr rect_packer) { + rect_packer_ = std::move(rect_packer); } GlyphAtlas::GlyphAtlas(Type type) : type_(type) {} @@ -76,13 +100,15 @@ size_t GlyphAtlas::IterateGlyphs( return count; } -bool GlyphAtlas::HasSamePairs(const FontGlyphPair::Vector& new_glyphs) { - for (const auto& pair : new_glyphs) { +FontGlyphPair::Vector GlyphAtlas::HasSamePairs( + const FontGlyphPair::Vector& new_glyphs) { + std::vector new_pairs; + for (auto pair : new_glyphs) { if (positions_.find(pair) == positions_.end()) { - return false; + new_pairs.push_back(pair); } } - return true; + return new_pairs; } } // namespace impeller diff --git a/impeller/typographer/glyph_atlas.h b/impeller/typographer/glyph_atlas.h index 0b533643b6437..d25d1e162e32e 100644 --- a/impeller/typographer/glyph_atlas.h +++ b/impeller/typographer/glyph_atlas.h @@ -15,6 +15,11 @@ #include "impeller/renderer/texture.h" #include "impeller/typographer/font_glyph_pair.h" +class SkBitmap; +namespace skgpu { +class Rectanizer; +} + namespace impeller { //------------------------------------------------------------------------------ @@ -122,9 +127,10 @@ class GlyphAtlas { /// /// @param[in] new_glyphs The full set of new glyphs /// - /// @return Whether this atlas contains all passed pairs. + /// @return A vector containing the glyphs from new_glyphs that are not + /// present in the existing atlas. May be empty of there are none. /// - bool HasSamePairs(const FontGlyphPair::Vector& new_glyphs); + FontGlyphPair::Vector HasSamePairs(const FontGlyphPair::Vector& new_glyphs); private: const Type type_; @@ -152,12 +158,31 @@ class GlyphAtlasContext { /// @brief Retrieve the current glyph atlas. std::shared_ptr GetGlyphAtlas() const; + //---------------------------------------------------------------------------- + /// @brief Retrieve the size of the current glyph atlas. + const ISize& GetAtlasSize() const; + + //---------------------------------------------------------------------------- + /// @brief Retrieve the previous (if any) SkBitmap instance. + std::shared_ptr GetBitmap() const; + + //---------------------------------------------------------------------------- + /// @brief Retrieve the previous (if any) rect packer. + std::shared_ptr GetRectPacker() const; + //---------------------------------------------------------------------------- /// @brief Update the context with a newly constructed glyph atlas. - void UpdateGlyphAtlas(std::shared_ptr atlas); + void UpdateGlyphAtlas(std::shared_ptr atlas, ISize size); + + void UpdateBitmap(std::shared_ptr bitmap); + + void UpdateRectPacker(std::shared_ptr rect_packer); private: std::shared_ptr atlas_; + ISize atlas_size_; + std::shared_ptr bitmap_; + std::shared_ptr rect_packer_; FML_DISALLOW_COPY_AND_ASSIGN(GlyphAtlasContext); }; diff --git a/impeller/typographer/typographer_unittests.cc b/impeller/typographer/typographer_unittests.cc index 978f5d700ee05..57eefbb36d4cf 100644 --- a/impeller/typographer/typographer_unittests.cc +++ b/impeller/typographer/typographer_unittests.cc @@ -168,5 +168,38 @@ TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) { atlas->GetTexture()->GetSize().height); } +TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) { + auto context = TextRenderContext::Create(GetContext()); + auto atlas_context = std::make_shared(); + ASSERT_TRUE(context && context->IsValid()); + SkFont sk_font; + auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font); + ASSERT_TRUE(blob); + auto atlas = + context->CreateGlyphAtlas(GlyphAtlas::Type::kAlphaBitmap, atlas_context, + TextFrameFromTextBlob(blob)); + auto old_packer = atlas_context->GetRectPacker(); + + ASSERT_NE(atlas, nullptr); + ASSERT_NE(atlas->GetTexture(), nullptr); + ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas()); + + auto* first_texture = atlas->GetTexture().get(); + + // now create a new glyph atlas with a nearly identical blob. + + auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font); + auto next_atlas = + context->CreateGlyphAtlas(GlyphAtlas::Type::kAlphaBitmap, atlas_context, + TextFrameFromTextBlob(blob2)); + ASSERT_EQ(atlas, next_atlas); + auto* second_texture = next_atlas->GetTexture().get(); + + auto new_packer = atlas_context->GetRectPacker(); + + ASSERT_EQ(second_texture, first_texture); + ASSERT_EQ(old_packer, new_packer); +} + } // namespace testing } // namespace impeller diff --git a/lib/ui/fixtures/shaders/BUILD.gn b/lib/ui/fixtures/shaders/BUILD.gn index 37d881e3539f8..7d3e2169e3678 100644 --- a/lib/ui/fixtures/shaders/BUILD.gn +++ b/lib/ui/fixtures/shaders/BUILD.gn @@ -42,7 +42,6 @@ if (enable_unittests) { intermediates_subdir = "iplr-remap" sl_file_extension = "iplr" iplr = true - remap_samplers = true } test_fixtures("fixtures") { diff --git a/lib/ui/painting/image_encoding.cc b/lib/ui/painting/image_encoding.cc index 2e60d5f55f0e3..578e9d6020c33 100644 --- a/lib/ui/painting/image_encoding.cc +++ b/lib/ui/painting/image_encoding.cc @@ -18,6 +18,7 @@ #endif // IMPELLER_SUPPORTS_RENDERING #include "flutter/lib/ui/painting/image_encoding_skia.h" #include "third_party/skia/include/core/SkEncodedImageFormat.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/tonic/dart_persistent_value.h" #include "third_party/tonic/logging/dart_invoke.h" #include "third_party/tonic/typed_data/typed_list.h" diff --git a/lib/web_ui/dev/browser.dart b/lib/web_ui/dev/browser.dart index fda2bb9ca3281..b4e7d2383e833 100644 --- a/lib/web_ui/dev/browser.dart +++ b/lib/web_ui/dev/browser.dart @@ -54,11 +54,11 @@ abstract class BrowserEnvironment { /// Any errors starting or running the browser process are reported through /// [onExit]. abstract class Browser { - /// The Observatory URL for this browser. + /// The Dart VM Service URL for this browser. /// /// Returns `null` for browsers that aren't running the Dart VM, or - /// if the Observatory URL can't be found. - Future? get observatoryUrl => null; + /// if the Dart VM Service URL can't be found. + Future? get vmServiceUrl => null; /// The remote debugger URL for this browser. /// diff --git a/lib/web_ui/dev/build.dart b/lib/web_ui/dev/build.dart index 215d59a2dbf95..459445eaa1ba3 100644 --- a/lib/web_ui/dev/build.dart +++ b/lib/web_ui/dev/build.dart @@ -27,6 +27,10 @@ class BuildCommand extends Command with ArgUtils { 'by default.', defaultsTo: true ); + argParser.addFlag( + 'build-canvaskit-chromium', + help: 'Build the Chromium variant of CanvasKit. Disabled by default.', + ); argParser.addFlag( 'host', help: 'Build the host build instead of the wasm build, which is ' @@ -44,13 +48,19 @@ class BuildCommand extends Command with ArgUtils { bool get buildCanvasKit => boolArg('build-canvaskit'); + bool get buildCanvasKitChromium => boolArg('build-canvaskit-chromium'); + bool get host => boolArg('host'); @override FutureOr run() async { final FilePath libPath = FilePath.fromWebUi('lib'); final List steps = [ - GnPipelineStep(buildCanvasKit: buildCanvasKit, host: host), + GnPipelineStep( + buildCanvasKit: buildCanvasKit, + buildCanvasKitChromium: buildCanvasKitChromium, + host: host, + ), NinjaPipelineStep(target: host ? environment.hostDebugUnoptDir : environment.wasmReleaseOutDir), ]; final Pipeline buildPipeline = Pipeline(steps: steps); @@ -75,9 +85,14 @@ class BuildCommand extends Command with ArgUtils { /// Not safe to interrupt as it may leave the `out/` directory in a corrupted /// state. GN is pretty quick though, so it's OK to not support interruption. class GnPipelineStep extends ProcessStep { - GnPipelineStep({required this.buildCanvasKit, required this.host}); + GnPipelineStep({ + required this.buildCanvasKit, + required this.buildCanvasKitChromium, + required this.host, + }); final bool buildCanvasKit; + final bool buildCanvasKitChromium; final bool host; @override @@ -97,6 +112,7 @@ class GnPipelineStep extends ProcessStep { '--web', '--runtime-mode=release', if (buildCanvasKit) '--build-canvaskit', + if (buildCanvasKitChromium) '--build-canvaskit-chromium', ]; } } diff --git a/lib/web_ui/dev/felt_windows.bat b/lib/web_ui/dev/felt_windows.bat deleted file mode 100644 index 94edf0ea1d688..0000000000000 --- a/lib/web_ui/dev/felt_windows.bat +++ /dev/null @@ -1,68 +0,0 @@ -:: TODO(yjbanov): migrate LUCI to felt.bat and delete this file. -:: felt_windows: a command-line utility for Windows for building and testing -:: Flutter web engine. -:: FELT stands for Flutter Engine Local Tester. - -@ECHO OFF -SETLOCAL - -FOR /F "tokens=1-2 delims=:" %%a in ('where gclient') DO SET GCLIENT_PATH=%%b -IF %GCLIENT_PATH%==[] (ECHO "ERROR: gclient is not in your PATH") - -FOR /F "tokens=1-2 delims=:" %%a in ('where ninja') DO SET NINJA_PATH=%%b -IF %NINJA_PATH%==[] (ECHO "ERROR: ninja is not in your PATH") - -SET FELT_DIR=%~dp0 - -:: web_ui directory is the parent of felt directory. -FOR %%a IN ("%FELT_DIR:~0,-1%") DO SET WEB_UI_DIR=%%~dpa - -:: Flutter Directory is grandparent of web_ui directory. -FOR %%a IN ("%WEB_UI_DIR:~0,-1%") DO SET orTempValue=%%~dpa -FOR %%a IN ("%orTempValue:~0,-1%") DO SET FLUTTER_DIR=%%~dpa - -:: Engine source directory is the parent of flutter directory. -FOR %%a IN ("%FLUTTER_DIR:~0,-1%") DO SET ENGINE_SRC_DIR=%%~dpa - -SET DEV_DIR="%WEB_UI_DIR%dev" -SET OUT_DIR="%ENGINE_SRC_DIR%out" -SET HOST_DEBUG_UNOPT_DIR="%ENGINE_SRC_DIR%out\host_debug_unopt" -SET SCRIPT_PATH="%DEV_DIR%felt.dart" -SET STAMP_PATH="%DART_TOOL_DIR%felt.snapshot.stamp" -SET GN="%FLUTTER_DIR%tools\gn" -SET DART_TOOL_DIR="%WEB_UI_DIR%.dart_tool" -SET SNAPSHOT_PATH="%DART_TOOL_DIR%felt.snapshot" -SET SDK_PREBUILTS_DIR=%FLUTTER_DIR%\prebuilts -SET PREBUILT_TARGET=windows-x64 -IF NOT DEFINED DART_SDK_DIR ( - SET DART_SDK_DIR=%SDK_PREBUILTS_DIR%\%PREBUILT_TARGET%\dart-sdk -) - -:: Set revision from using git in Flutter directory. -CD %FLUTTER_DIR% -FOR /F "tokens=1 delims=:" %%a in ('git rev-parse HEAD') DO SET REVISION=%%a - -SET orTempValue=1 -IF NOT EXIST %OUT_DIR% (SET orTempValue=0) -IF NOT EXIST %HOST_DEBUG_UNOPT_DIR% (SET orTempValue=0) -IF %orTempValue%==0 ( - ECHO "Compiling the Dart SDK." - CALL gclient sync - CALL python %GN% --unoptimized --full-dart-sdk - CALL ninja -C %HOST_DEBUG_UNOPT_DIR%) - -:: TODO(yjbanov): The batch script does not support snapshot option. -:: Support snapshot option. -CALL :installdeps -IF "%1"=="test" (%DART_SDK_DIR%\bin\dart %DEV_DIR%\felt.dart %* --browser=chrome) ELSE ( %DART_SDK_DIR%\bin\dart %DEV_DIR%\felt.dart %* ) - -EXIT /B %ERRORLEVEL% - -:installdeps -ECHO "Running \`pub get\` in 'engine/src/flutter/web_sdk/web_engine_tester'" -cd "%FLUTTER_DIR%web_sdk\web_engine_tester" -CALL %DART_SDK_DIR%\bin\dart pub get -ECHO "Running \`pub get\` in 'engine/src/flutter/lib/web_ui'" -cd %WEB_UI_DIR% -CALL %DART_SDK_DIR%\bin\dart pub get -EXIT /B 0 diff --git a/lib/web_ui/dev/test_platform.dart b/lib/web_ui/dev/test_platform.dart index 007670b78b0b6..17a66d0eff1fc 100644 --- a/lib/web_ui/dev/test_platform.dart +++ b/lib/web_ui/dev/test_platform.dart @@ -820,7 +820,7 @@ class BrowserManager { /// Loads [_BrowserEnvironment]. Future<_BrowserEnvironment> _loadBrowserEnvironment() async { - return _BrowserEnvironment(this, await _browser.observatoryUrl, + return _BrowserEnvironment(this, await _browser.vmServiceUrl, await _browser.remoteDebuggerUrl, _onRestartController.stream); } diff --git a/lib/web_ui/dev/utils.dart b/lib/web_ui/dev/utils.dart index c71a6148eb26d..775da7f3b9802 100644 --- a/lib/web_ui/dev/utils.dart +++ b/lib/web_ui/dev/utils.dart @@ -224,8 +224,7 @@ class ProcessManager { return (await eval()).stderr; } - @alwaysThrows - void _throwProcessException({required String description, int? exitCode}) { + Never _throwProcessException({required String description, int? exitCode}) { throw ProcessException( description: description, executable: executable, diff --git a/lib/web_ui/lib/src/engine/dom.dart b/lib/web_ui/lib/src/engine/dom.dart index 47adc523919fb..89456dd375744 100644 --- a/lib/web_ui/lib/src/engine/dom.dart +++ b/lib/web_ui/lib/src/engine/dom.dart @@ -63,9 +63,6 @@ extension DomWindowExtension on DomWindow { /// The Trusted Types API (when available). /// See: https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API external DomTrustedTypePolicyFactory? get trustedTypes; - - // ignore: non_constant_identifier_names - external DomIntl get Intl; } typedef DomRequestAnimationFrameCallback = void Function(num highResTime); @@ -83,6 +80,9 @@ extension DomConsoleExtension on DomConsole { @JS('window') external DomWindow get domWindow; +@JS('Intl') +external DomIntl get domIntl; + @JS() @staticInterop class DomNavigator {} @@ -1815,7 +1815,7 @@ extension DomV8BreakIteratorExtension on DomV8BreakIterator { } DomV8BreakIterator createV8BreakIterator() { - final Object? v8BreakIterator = domWindow.Intl.v8BreakIterator; + final Object? v8BreakIterator = domIntl.v8BreakIterator; if (v8BreakIterator == null) { throw UnimplementedError('v8BreakIterator is not supported.'); } diff --git a/lib/web_ui/lib/src/engine/host_node.dart b/lib/web_ui/lib/src/engine/host_node.dart index f2a6c74cb39f5..4b0ca8e13d990 100644 --- a/lib/web_ui/lib/src/engine/host_node.dart +++ b/lib/web_ui/lib/src/engine/host_node.dart @@ -317,16 +317,16 @@ void applyGlobalCssRulesToSheet( } ''', sheet.cssRules.length); - // This css prevents an autofill overlay brought by the browser during - // text field autofill by delaying the transition effect. - // See: https://github.com/flutter/flutter/issues/61132. + // This CSS makes the autofill overlay transparent in order to prevent it + // from overlaying on top of Flutter-rendered text inputs. + // See: https://github.com/flutter/flutter/issues/118337. if (browserHasAutofillOverlay()) { sheet.insertRule(''' $cssSelectorPrefix .transparentTextEditing:-webkit-autofill, $cssSelectorPrefix .transparentTextEditing:-webkit-autofill:hover, $cssSelectorPrefix .transparentTextEditing:-webkit-autofill:focus, $cssSelectorPrefix .transparentTextEditing:-webkit-autofill:active { - -webkit-transition-delay: 99999s; + opacity: 0 !important; } ''', sheet.cssRules.length); } diff --git a/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart b/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart index 24f5fe5eb044e..4bc0bff9c33bb 100644 --- a/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart +++ b/lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart @@ -51,7 +51,11 @@ SVGSVGElement pathToSvgClipPath(ui.Path path, clipPath.setAttribute('clipPathUnits', 'objectBoundingBox'); svgPath.setAttribute('transform', 'scale($scaleX, $scaleY)'); } - + if (path.fillType == ui.PathFillType.evenOdd) { + svgPath.setAttribute('clip-rule', 'evenodd'); + } else { + svgPath.setAttribute('clip-rule', 'nonzero'); + } svgPath.setAttribute('d', pathToSvg((path as SurfacePath).pathRef, offsetX: offsetX, offsetY: offsetY)); return root; } diff --git a/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart b/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart index 272781147c78d..5a8f291a785f3 100644 --- a/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart +++ b/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart @@ -174,6 +174,9 @@ class CanvasParagraph implements ui.Paragraph { } final DomElement spanElement = domDocument.createElement('flt-span'); + if (fragment.textDirection == ui.TextDirection.rtl) { + spanElement.setAttribute('dir', 'rtl'); + } applyTextStyleToElement(element: spanElement, style: fragment.style); _positionSpanElement(spanElement, line, fragment); diff --git a/lib/web_ui/lib/src/engine/text/line_breaker.dart b/lib/web_ui/lib/src/engine/text/line_breaker.dart index c2bf0ab1e2090..594605a3ad4ad 100644 --- a/lib/web_ui/lib/src/engine/text/line_breaker.dart +++ b/lib/web_ui/lib/src/engine/text/line_breaker.dart @@ -42,7 +42,7 @@ enum LineBreakType { /// Splits [text] into fragments based on line breaks. abstract class LineBreakFragmenter extends TextFragmenter { factory LineBreakFragmenter(String text) { - if (domWindow.Intl.v8BreakIterator != null) { + if (domIntl.v8BreakIterator != null) { return V8LineBreakFragmenter(text); } return FWLineBreakFragmenter(text); @@ -66,7 +66,7 @@ class FWLineBreakFragmenter extends TextFragmenter implements LineBreakFragmente /// `v8BreakIterator` API to find line breaks in the given [text]. class V8LineBreakFragmenter extends TextFragmenter implements LineBreakFragmenter { V8LineBreakFragmenter(super.text) - : assert(domWindow.Intl.v8BreakIterator != null); + : assert(domIntl.v8BreakIterator != null); @override List fragment() { diff --git a/lib/web_ui/test/engine/canvas_test.dart b/lib/web_ui/test/engine/canvas_test.dart index 053cd9c155b6b..926ac1b3fe339 100644 --- a/lib/web_ui/test/engine/canvas_test.dart +++ b/lib/web_ui/test/engine/canvas_test.dart @@ -11,6 +11,8 @@ import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart' as ui; +import '../matchers.dart'; + void main() { internalBootstrapBrowserTest(() => testMain); } @@ -31,7 +33,7 @@ void runCanvasTests({required bool deviceClipRoundsOut}) { expect(value.length, equals(16)); for (int r = 0; r < 4; r++) { for (int c = 0; c < 4; c++) { - expect(value[r*4 + c], closeTo(expected[r*4 + c], 1e-10)); + expect(value[r*4 + c], within(from: expected[r*4 + c])); } } } diff --git a/lib/web_ui/test/engine/host_node_test.dart b/lib/web_ui/test/engine/host_node_test.dart index e882d49042ccc..205bdafa9f4a1 100644 --- a/lib/web_ui/test/engine/host_node_test.dart +++ b/lib/web_ui/test/engine/host_node_test.dart @@ -112,6 +112,31 @@ void testMain() { expect(hidesRevealIcons, isFalse); }, skip: isEdge); + test( + 'Attaches styles to hide the autofill overlay for browsers that support it', + () { + final DomElement? style = + hostNode.querySelector('#flt-internals-stylesheet'); + final String vendorPrefix = (isSafari || isFirefox) ? '' : '-webkit-'; + final bool autofillOverlay = hasCssRule(style, + selector: '.transparentTextEditing:${vendorPrefix}autofill', + declaration: 'opacity: 0 !important'); + final bool autofillOverlayHovered = hasCssRule(style, + selector: '.transparentTextEditing:${vendorPrefix}autofill:hover', + declaration: 'opacity: 0 !important'); + final bool autofillOverlayFocused = hasCssRule(style, + selector: '.transparentTextEditing:${vendorPrefix}autofill:focus', + declaration: 'opacity: 0 !important'); + final bool autofillOverlayActive = hasCssRule(style, + selector: '.transparentTextEditing:${vendorPrefix}autofill:active', + declaration: 'opacity: 0 !important'); + + expect(autofillOverlay, isTrue); + expect(autofillOverlayHovered, isTrue); + expect(autofillOverlayFocused, isTrue); + expect(autofillOverlayActive, isTrue); + }, skip: !browserHasAutofillOverlay()); + _runDomTests(hostNode); }); diff --git a/lib/web_ui/test/engine/view_embedder/dimensions_provider/custom_element_dimensions_provider_test.dart b/lib/web_ui/test/engine/view_embedder/dimensions_provider/custom_element_dimensions_provider_test.dart index a891bc0634d05..db7fffb4aedd6 100644 --- a/lib/web_ui/test/engine/view_embedder/dimensions_provider/custom_element_dimensions_provider_test.dart +++ b/lib/web_ui/test/engine/view_embedder/dimensions_provider/custom_element_dimensions_provider_test.dart @@ -110,41 +110,23 @@ void doTests() { }); test('funnels resize events on sizeSource', () async { - final Future event = provider.onResize.first; - final Future> events = provider.onResize.take(3).toList(); - - // The resize observer fires asynchronously, so we wait a little between - // resizes, so the observer has time to fire events separately. - await Future.delayed(const Duration(milliseconds: 100), () { - sizeSource - ..style.width = '100px' - ..style.height = '100px'; - }); + sizeSource + ..style.width = '100px' + ..style.height = '100px'; - await Future.delayed(const Duration(milliseconds: 100), () { - sizeSource - ..style.width = '200px' - ..style.height = '200px'; - }); + expect(await provider.onResize.first, const ui.Size(100, 100)); - await Future.delayed(const Duration(milliseconds: 100), () { - sizeSource - ..style.width = '300px' - ..style.height = '300px'; - }); + sizeSource + ..style.width = '200px' + ..style.height = '200px'; - // Let the DOM settle so the observer reports the last 300x300 mutation... - await Future.delayed(const Duration(milliseconds: 100)); + expect(await provider.onResize.first, const ui.Size(200, 200)); + + sizeSource + ..style.width = '300px' + ..style.height = '300px'; - expect(event, completion(const ui.Size(100, 100))); - expect(events, completes); - expect( - events, - completion(const [ - ui.Size(100, 100), - ui.Size(200, 200), - ui.Size(300, 300), - ])); + expect(await provider.onResize.first, const ui.Size(300, 300)); }); test('closed by onHotRestart', () async { diff --git a/lib/web_ui/test/geometry_test.dart b/lib/web_ui/test/geometry_test.dart index 24150d801cdf4..80df3611c3af8 100644 --- a/lib/web_ui/test/geometry_test.dart +++ b/lib/web_ui/test/geometry_test.dart @@ -13,6 +13,8 @@ import 'package:test/test.dart'; import 'package:ui/ui.dart'; +import 'matchers.dart'; + void main() { internalBootstrapBrowserTest(() => testMain); } @@ -31,34 +33,32 @@ void testMain() { }); test('Offset.fromDirection', () { expect(Offset.fromDirection(0.0, 0.0), const Offset(0.0, 0.0)); - expect(Offset.fromDirection(pi / 2.0).dx, - closeTo(0.0, 1e-12)); // aah, floating point math. i love you so. - expect(Offset.fromDirection(pi / 2.0).dy, 1.0); - expect(Offset.fromDirection(-pi / 2.0).dx, closeTo(0.0, 1e-12)); - expect(Offset.fromDirection(-pi / 2.0).dy, -1.0); + // aah, floating point math. i love you so. + expect(Offset.fromDirection(pi / 2.0), within(from: const Offset(0.0, 1.0))); + expect(Offset.fromDirection(-pi / 2.0), within(from: const Offset(0.0, -1.0))); expect(Offset.fromDirection(0.0), const Offset(1.0, 0.0)); - expect(Offset.fromDirection(pi / 4.0).dx, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(pi / 4.0).dy, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi / 4.0).dx, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi / 4.0).dy, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(pi).dx, -1.0); - expect(Offset.fromDirection(pi).dy, closeTo(0.0, 1e-12)); - expect(Offset.fromDirection(pi * 3.0 / 4.0).dx, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(pi * 3.0 / 4.0).dy, - closeTo(1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi * 3.0 / 4.0).dx, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); - expect(Offset.fromDirection(-pi * 3.0 / 4.0).dy, - closeTo(-1.0 / math.sqrt(2.0), 1e-12)); + expect( + Offset.fromDirection(pi / 4.0), + within(from: Offset(1.0 / math.sqrt(2.0), 1.0 / math.sqrt(2.0))), + ); + expect( + Offset.fromDirection(-pi / 4.0), + within(from: Offset(1.0 / math.sqrt(2.0), -1.0 / math.sqrt(2.0))), + ); + expect(Offset.fromDirection(pi), within(from: const Offset(-1.0, 0.0))); + expect( + Offset.fromDirection(pi * 3.0 / 4.0), + within(from: Offset(-1.0 / math.sqrt(2.0), 1.0 / math.sqrt(2.0))), + ); + expect( + Offset.fromDirection(-pi * 3.0 / 4.0), + within(from: Offset(-1.0 / math.sqrt(2.0), -1.0 / math.sqrt(2.0))), + ); expect(Offset.fromDirection(0.0, 2.0), const Offset(2.0, 0.0)); expect( - Offset.fromDirection(pi / 6, 2.0).dx, closeTo(math.sqrt(3.0), 1e-12)); - expect(Offset.fromDirection(pi / 6, 2.0).dy, closeTo(1.0, 1e-12)); + Offset.fromDirection(pi / 6, 2.0), + within(from: Offset(math.sqrt(3.0), 1.0)), + ); }); test('Size.aspectRatio', () { expect(const Size(0.0, 0.0).aspectRatio, 0.0); diff --git a/lib/web_ui/test/html/canvas_clip_path_golden_test.dart b/lib/web_ui/test/html/canvas_clip_path_golden_test.dart index a4643c3a97359..7242600b361e6 100644 --- a/lib/web_ui/test/html/canvas_clip_path_golden_test.dart +++ b/lib/web_ui/test/html/canvas_clip_path_golden_test.dart @@ -119,6 +119,50 @@ Future testMain() async { await canvasScreenshot(rc, 'image_clipped_by_oval_path', region: const Rect.fromLTWH(0, 0, 600, 800)); }); + + test('Clips with fillType evenOdd', () async { + final engine.RecordingCanvas rc = engine.RecordingCanvas(const Rect.fromLTRB(0, 0, 500, 500)); + rc.save(); + const double testWidth = 400; + const double testHeight = 350; + + // draw RGB test image + rc.drawImageRect(createTestImage(), const Rect.fromLTRB(0, 0, testWidth, testHeight), + const Rect.fromLTWH(0, 0, testWidth, testHeight), engine.SurfacePaint()); + + // draw a clipping path with: + // 1) an outside larger rectangle + // 2) a smaller inner rectangle specified by a path + final Path path = Path(); + path.addRect(const Rect.fromLTWH(0, 0, testWidth, testHeight)); + const double left = 25; + const double top = 30; + const double right = 300; + const double bottom = 250; + path + ..moveTo(left, top) + ..lineTo(right,top) + ..lineTo(right,bottom) + ..lineTo(left, bottom) + ..close(); + path.fillType = PathFillType.evenOdd; + rc.clipPath(path); + + // draw an orange paint path of size testWidth and testHeight + final Path paintPath = Path(); + paintPath.addRect(const Rect.fromLTWH(0, 0, testWidth, testHeight)); + paintPath.close(); + rc.drawPath(paintPath, + engine.SurfacePaint() + ..color = const Color(0xFFFF9800) + ..style = PaintingStyle.fill); + rc.restore(); + + // when fillType is set to evenOdd from the clipping path, expect the inner + // rectangle should clip some of the orange painted portion, revealing the RGB testImage + await canvasScreenshot(rc, 'clipPath_uses_fillType_evenOdd', + region: const Rect.fromLTWH(0, 0, 600, 800)); + }); } engine.HtmlImage createTestImage({int width = 200, int height = 150}) { diff --git a/lib/web_ui/test/lerp_test.dart b/lib/web_ui/test/lerp_test.dart index 2c9d1fc0574c0..65dde6513fbd7 100644 --- a/lib/web_ui/test/lerp_test.dart +++ b/lib/web_ui/test/lerp_test.dart @@ -7,12 +7,7 @@ import 'package:test/test.dart'; import 'package:ui/ui.dart'; -/// The epsilon of tolerable double precision error. -/// -/// This is used in various places in the framework to allow for floating point -/// precision loss in calculations. Differences below this threshold are safe -/// to disregard. -const double precisionErrorTolerance = 1e-10; +import 'matchers.dart'; void main() { internalBootstrapBrowserTest(() => testMain); @@ -31,19 +26,19 @@ void testMain() { }); test('lerpDouble should treat a null input as 0 if the other input is non-null', () { - expect(lerpDouble(null, 10.0, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10.0, null, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(null, 10.0, 0.25), within(from: 2.5)); + expect(lerpDouble(10.0, null, 0.25), within(from: 7.5)); - expect(lerpDouble(null, 10, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10, null, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(null, 10, 0.25), within(from: 2.5)); + expect(lerpDouble(10, null, 0.25), within(from: 7.5)); }); test('lerpDouble should handle interpolation values < 0.0', () { - expect(lerpDouble(0.0, 10.0, -5.0), closeTo(-50.0, precisionErrorTolerance)); - expect(lerpDouble(10.0, 0.0, -5.0), closeTo(60.0, precisionErrorTolerance)); + expect(lerpDouble(0.0, 10.0, -5.0), within(from: -50.0)); + expect(lerpDouble(10.0, 0.0, -5.0), within(from: 60.0)); - expect(lerpDouble(0, 10, -5), closeTo(-50, precisionErrorTolerance)); - expect(lerpDouble(10, 0, -5), closeTo(60, precisionErrorTolerance)); + expect(lerpDouble(0, 10, -5), within(from: -50.0)); + expect(lerpDouble(10, 0, -5), within(from: 60.0)); }); test('lerpDouble should return the start value at 0.0', () { @@ -55,17 +50,17 @@ void testMain() { }); test('lerpDouble should interpolate between two values', () { - expect(lerpDouble(0.0, 10.0, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10.0, 0.0, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(0.0, 10.0, 0.25), within(from: 2.5)); + expect(lerpDouble(10.0, 0.0, 0.25), within(from: 7.5)); - expect(lerpDouble(0, 10, 0.25), closeTo(2.5, precisionErrorTolerance)); - expect(lerpDouble(10, 0, 0.25), closeTo(7.5, precisionErrorTolerance)); + expect(lerpDouble(0, 10, 0.25), within(from: 2.5)); + expect(lerpDouble(10, 0, 0.25), within(from: 7.5)); // Exact answer: 20.0 - 1.0e-29 - expect(lerpDouble(10.0, 1.0e30, 1.0e-29), closeTo(20.0, precisionErrorTolerance)); + expect(lerpDouble(10.0, 1.0e30, 1.0e-29), within(from: 20.0)); // Exact answer: 5.0 + 5.0e29 - expect(lerpDouble(10.0, 1.0e30, 0.5), closeTo(5.0e29, precisionErrorTolerance)); + expect(lerpDouble(10.0, 1.0e30, 0.5), within(from: 5.0e29)); }); test('lerpDouble should return the end value at 1.0', () { @@ -80,11 +75,11 @@ void testMain() { }); test('lerpDouble should handle interpolation values > 1.0', () { - expect(lerpDouble(0.0, 10.0, 5.0), closeTo(50.0, precisionErrorTolerance)); - expect(lerpDouble(10.0, 0.0, 5.0), closeTo(-40.0, precisionErrorTolerance)); + expect(lerpDouble(0.0, 10.0, 5.0), within(from: 50.0)); + expect(lerpDouble(10.0, 0.0, 5.0), within(from: -40.0)); - expect(lerpDouble(0, 10, 5), closeTo(50, precisionErrorTolerance)); - expect(lerpDouble(10, 0, 5), closeTo(-40, precisionErrorTolerance)); + expect(lerpDouble(0, 10, 5), within(from: 50.0)); + expect(lerpDouble(10, 0, 5), within(from: -40.0)); }); test('lerpDouble should return input value in all cases if begin/end are equal', () { diff --git a/lib/web_ui/test/matchers.dart b/lib/web_ui/test/matchers.dart index b754d4b2387e0..df6124d0790d5 100644 --- a/lib/web_ui/test/matchers.dart +++ b/lib/web_ui/test/matchers.dart @@ -15,6 +15,13 @@ import 'package:test/test.dart'; import 'package:ui/src/engine.dart'; import 'package:ui/ui.dart'; +/// The epsilon of tolerable double precision error. +/// +/// This is used in various places in the framework to allow for floating point +/// precision loss in calculations. Differences below this threshold are safe +/// to disregard. +const double precisionErrorTolerance = 1e-10; + /// Enumerates all persisted surfaces in the tree rooted at [root]. /// /// If [root] is `null` returns all surfaces from the last rendered scene. @@ -60,7 +67,7 @@ Iterable enumerateOffsets([PersistedSurface? root]) { /// /// This makes it useful for comparing numbers, [Color]s, [Offset]s and other /// sets of value for which a metric space is defined. -typedef DistanceFunction = num Function(T a, T b); +typedef DistanceFunction = double Function(T a, T b); /// The type of a union of instances of [DistanceFunction] for various types /// T. @@ -73,7 +80,7 @@ typedef DistanceFunction = num Function(T a, T b); /// /// Calling an instance of this type must either be done dynamically, or by /// first casting it to a [DistanceFunction] for some concrete T. -typedef AnyDistanceFunction = num Function(Never a, Never b); +typedef AnyDistanceFunction = double Function(Never a, Never b); const Map _kStandardDistanceFunctions = { @@ -85,7 +92,7 @@ const Map _kStandardDistanceFunctions = Size: _sizeDistance, }; -int _intDistance(int a, int b) => (b - a).abs(); +double _intDistance(int a, int b) => (b - a).abs().toDouble(); double _doubleDistance(double a, double b) => (b - a).abs(); double _offsetDistance(Offset a, Offset b) => (b - a).distance; @@ -131,8 +138,8 @@ double _sizeDistance(Size a, Size b) { /// [double]s and has an optional `epsilon` parameter. /// * [closeTo], which specializes in numbers only. Matcher within({ - required num distance, required T from, + double distance = precisionErrorTolerance, DistanceFunction? distanceFunction, }) { distanceFunction ??= _kStandardDistanceFunctions[T] as DistanceFunction?; @@ -152,7 +159,7 @@ class _IsWithinDistance extends Matcher { final DistanceFunction distanceFunction; final T value; - final num epsilon; + final double epsilon; @override bool matches(Object? object, Map matchState) { @@ -163,7 +170,7 @@ class _IsWithinDistance extends Matcher { return true; } final T test = object; - final num distance = distanceFunction(test, value); + final double distance = distanceFunction(test, value); if (distance < 0) { throw ArgumentError( 'Invalid distance function was used to compare a ${value.runtimeType} ' @@ -421,46 +428,6 @@ void expectHtml(DomElement element, String expectedHtml, expect(actualHtml, expectedHtml); } -/// Tests that [currentHtml] matches [expectedHtml]. -/// -/// The comparison does not consider every minutia of the DOM. By default it -/// tests the element tree structure and non-layout style attributes, and -/// ignores everything else. If you are testing layout specifically, pass the -/// [HtmlComparisonMode.layoutOnly] as the [mode] argument. -/// -/// To keep test HTML strings manageable, you may use short HTML tag names -/// instead of the full names: -/// -/// * is interchangeable with -/// * is interchangeable with -/// * is interchangeable with -/// * is interchangeable with -/// * is interchangeable with -/// * is interchangeable with -/// * is interchangeable with -/// * is interchangeable with -/// -/// To simplify test HTML strings further the elements corresponding to the -/// root view [RenderView], such as (i.e. ), are also stripped -/// out before comparison. -/// -/// Example: -/// -/// If you call [WidgetTester.pumpWidget] that results in HTML -/// `

Hello

`, you don't have to specify -/// `` tags and simply expect `

Hello

`. -void expectPageHtml(String expectedHtml, - {HtmlComparisonMode mode = HtmlComparisonMode.nonLayoutOnly}) { - expectedHtml = canonicalizeHtml(expectedHtml, mode: mode); - final String actualHtml = canonicalizeHtml(currentHtml, mode: mode); - expect(actualHtml, expectedHtml); -} - -/// Currently rendered HTML DOM as an HTML string. -String get currentHtml { - return flutterViewEmbedder.sceneElement?.outerHTML ?? ''; -} - class SceneTester { SceneTester(this.scene); diff --git a/lib/web_ui/test/text/canvas_paragraph_builder_test.dart b/lib/web_ui/test/text/canvas_paragraph_builder_test.dart index b8d92315da7d2..0e10fcb6c6c71 100644 --- a/lib/web_ui/test/text/canvas_paragraph_builder_test.dart +++ b/lib/web_ui/test/text/canvas_paragraph_builder_test.dart @@ -455,6 +455,40 @@ Future testMain() async { ); debugEmulateFlutterTesterEnvironment = true; }); + + // Regression test for https://github.com/flutter/flutter/issues/108431. + // Set dir attribute for RTL fragments in order to let the browser + // handle mirrored characters. + test('Sets "dir" attribute for RTL fragment', () { + final EngineParagraphStyle style = EngineParagraphStyle( + fontSize: 20.0, + textDirection: TextDirection.rtl, + ); + final CanvasParagraphBuilder builder = CanvasParagraphBuilder(style); + + builder.addText('(1)'); + + final CanvasParagraph paragraph = builder.build(); + expect(paragraph.paragraphStyle, style); + expect(paragraph.plainText, '(1)'); + + paragraph.layout(const ParagraphConstraints(width: double.infinity)); + expectOuterHtml( + paragraph, + '' + '' + '(' + '' + '' + '1' + '' + '' + ')' + '' + '', + ignorePositions: true, + ); + }); } const String defaultFontFamily = 'Ahem'; diff --git a/lib/web_ui/test/text/line_breaker_test.dart b/lib/web_ui/test/text/line_breaker_test.dart index 479920271d4ea..275c4de47b60f 100644 --- a/lib/web_ui/test/text/line_breaker_test.dart +++ b/lib/web_ui/test/text/line_breaker_test.dart @@ -421,7 +421,7 @@ void groupForEachFragmenter(GroupBody callback) { () => callback(isV8: false), ); - if (domWindow.Intl.v8BreakIterator != null) { + if (domIntl.v8BreakIterator != null) { group( '$V8LineBreakFragmenter', () => callback(isV8: true), diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 0f819ef9981c1..6e4e3757cefc6 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -412,7 +412,7 @@ void DartIsolate::SetMessageHandlingTaskRunner( } // Updating thread names here does not change the underlying OS thread names. -// Instead, this is just additional metadata for the Observatory to show the +// Instead, this is just additional metadata for the Dart VM Service to show the // thread name of the isolate. bool DartIsolate::UpdateThreadPoolNames() const { // TODO(chinmaygarde): This implementation does not account for multiple @@ -766,7 +766,7 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( const auto& settings = vm_data->GetSettings(); - if (!settings.enable_observatory) { + if (!settings.enable_vm_service) { return nullptr; } @@ -802,8 +802,8 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( tonic::DartState::Scope scope(service_isolate); if (!DartServiceIsolate::Startup( - settings.observatory_host, // server IP address - settings.observatory_port, // server observatory port + settings.vm_service_host, // server IP address + settings.vm_service_port, // server VM service port tonic::DartState::HandleLibraryTag, // embedder library tag handler false, // disable websocket origin check settings.disable_service_auth_codes, // disable VM service auth codes diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index e5f43fd56616a..2a299f3150c2f 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -404,9 +404,9 @@ TEST_F(DartIsolateTest, CanCreateServiceIsolate) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); fml::AutoResetWaitableEvent service_isolate_latch; auto settings = CreateSettingsForFixture(); - settings.enable_observatory = true; - settings.observatory_port = 0; - settings.observatory_host = "127.0.0.1"; + settings.enable_vm_service = true; + settings.vm_service_port = 0; + settings.vm_service_host = "127.0.0.1"; settings.enable_service_port_fallback = true; settings.service_isolate_create_callback = [&service_isolate_latch]() { service_isolate_latch.Signal(); diff --git a/runtime/dart_lifecycle_unittests.cc b/runtime/dart_lifecycle_unittests.cc index d3162905e3ae6..467df37d273af 100644 --- a/runtime/dart_lifecycle_unittests.cc +++ b/runtime/dart_lifecycle_unittests.cc @@ -19,7 +19,7 @@ using DartLifecycleTest = FixtureTest; TEST_F(DartLifecycleTest, CanStartAndShutdownVM) { auto settings = CreateSettingsForFixture(); settings.leak_vm = false; - settings.enable_observatory = false; + settings.enable_vm_service = false; ASSERT_FALSE(DartVMRef::IsInstanceRunning()); { auto vm_ref = DartVMRef::Create(settings); @@ -31,7 +31,7 @@ TEST_F(DartLifecycleTest, CanStartAndShutdownVM) { TEST_F(DartLifecycleTest, CanStartAndShutdownVMOverAndOver) { auto settings = CreateSettingsForFixture(); settings.leak_vm = false; - settings.enable_observatory = false; + settings.enable_vm_service = false; ASSERT_FALSE(DartVMRef::IsInstanceRunning()); auto count = DartVM::GetVMLaunchCount(); for (size_t i = 0; i < 10; i++) { @@ -89,7 +89,7 @@ TEST_F(DartLifecycleTest, DISABLED_ShuttingDownTheVMShutsDownAllIsolates) { auto settings = CreateSettingsForFixture(); settings.leak_vm = false; // Make sure the service protocol launches - settings.enable_observatory = true; + settings.enable_vm_service = true; auto thread_task_runner = CreateNewThread(); diff --git a/runtime/dart_service_isolate.cc b/runtime/dart_service_isolate.cc index 18b51a32a6f1a..9f27e16d323b9 100644 --- a/runtime/dart_service_isolate.cc +++ b/runtime/dart_service_isolate.cc @@ -33,7 +33,7 @@ namespace { static Dart_LibraryTagHandler g_embedder_tag_handler; static tonic::DartLibraryNatives* g_natives; -static std::string g_observatory_uri; +static std::string g_vm_service_uri; Dart_NativeFunction GetNativeFunction(Dart_Handle name, int argument_count, @@ -51,7 +51,7 @@ const uint8_t* GetSymbol(Dart_NativeFunction native_function) { std::mutex DartServiceIsolate::callbacks_mutex_; -std::set> +std::set> DartServiceIsolate::callbacks_; void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) { @@ -63,11 +63,11 @@ void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) { return; } - g_observatory_uri = uri; + g_vm_service_uri = uri; // Collect callbacks to fire in a separate collection and invoke them outside // the lock. - std::vector + std::vector callbacks_to_fire; { std::scoped_lock lock(callbacks_mutex_); @@ -82,13 +82,13 @@ void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) { } DartServiceIsolate::CallbackHandle DartServiceIsolate::AddServerStatusCallback( - const DartServiceIsolate::ObservatoryServerStateCallback& callback) { + const DartServiceIsolate::DartVMServiceServerStateCallback& callback) { if (!callback) { return 0; } auto callback_pointer = - std::make_unique( + std::make_unique( callback); auto handle = reinterpret_cast(callback_pointer.get()); @@ -98,8 +98,8 @@ DartServiceIsolate::CallbackHandle DartServiceIsolate::AddServerStatusCallback( callbacks_.insert(std::move(callback_pointer)); } - if (!g_observatory_uri.empty()) { - callback(g_observatory_uri); + if (!g_vm_service_uri.empty()) { + callback(g_vm_service_uri); } return handle; diff --git a/runtime/dart_service_isolate.h b/runtime/dart_service_isolate.h index 754a963d13693..5078c28a78a83 100644 --- a/runtime/dart_service_isolate.h +++ b/runtime/dart_service_isolate.h @@ -27,11 +27,11 @@ class DartServiceIsolate { using CallbackHandle = ptrdiff_t; //---------------------------------------------------------------------------- - /// A callback made by the Dart VM when the observatory is ready. The argument - /// indicates the observatory URI. + /// A callback made by the Dart VM when the VM Service is ready. The argument + /// indicates the VM Service URI. /// - using ObservatoryServerStateCallback = - std::function; + using DartVMServiceServerStateCallback = + std::function; //---------------------------------------------------------------------------- /// @brief Start the service isolate. This call may only be made in the @@ -68,19 +68,19 @@ class DartServiceIsolate { char** error); //---------------------------------------------------------------------------- - /// @brief Add a callback that will get invoked when the observatory - /// starts up. If the observatory has already started before this + /// @brief Add a callback that will get invoked when the VM Service + /// starts up. If the VM Service has already started before this /// call is made, the callback is invoked immediately. /// /// This method is thread safe. /// - /// @param[in] callback The callback with information about the observatory. + /// @param[in] callback The callback with information about the VM Service. /// /// @return A handle for the callback that can be used later in /// `RemoveServerStatusCallback`. /// [[nodiscard]] static CallbackHandle AddServerStatusCallback( - const ObservatoryServerStateCallback& callback); + const DartVMServiceServerStateCallback& callback); //---------------------------------------------------------------------------- /// @brief Removed a callback previously registered via @@ -101,7 +101,7 @@ class DartServiceIsolate { static void Shutdown(Dart_NativeArguments args); static std::mutex callbacks_mutex_; - static std::set> callbacks_; + static std::set> callbacks_; }; } // namespace flutter diff --git a/runtime/platform_data.h b/runtime/platform_data.h index ca7b683a1e8e6..8b11b34ef6585 100644 --- a/runtime/platform_data.h +++ b/runtime/platform_data.h @@ -14,17 +14,18 @@ namespace flutter { //------------------------------------------------------------------------------ -/// The struct of platform-specific data used for initializing ui.Window. +/// The struct of platform-specific data used for initializing +/// ui.PlatformDispatcher. /// -/// framework may request data from ui.Window before platform is properly -/// configured. Engine this struct to set the desired default value for -/// ui.Window when creating Shell before platform is ready to send the real +/// The framework may request data from ui.PlatformDispatcher before the +/// platform is properly configured. When creating the Shell, the engine sets +/// this struct to default values until the platform is ready to send the real /// data. /// /// See also: /// /// * flutter::Shell::Create, which takes a platform_data to initialize the -/// ui.Window attached to it. +/// ui.PlatformDispatcher attached to it. struct PlatformData { PlatformData(); diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index df47539e188c1..66e0de6140013 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -15,6 +15,8 @@ #include "flutter/shell/common/thread_host.h" #include "flutter/testing/testing.h" +#include "third_party/skia/include/core/SkSurface.h" + #include "gmock/gmock.h" using testing::_; diff --git a/shell/common/shell.h b/shell/common/shell.h index f51edc9f9e343..2ecf71dac6559 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -452,7 +452,7 @@ class Shell final : public PlatformView::Delegate, std::atomic needs_report_timings_{false}; // Whether there's a task scheduled to report the timings to Dart through - // ui.Window.onReportTimings. + // ui.PlatformDispatcher.onReportTimings. bool frame_timings_report_scheduled_ = false; // Vector of FrameTiming::kCount * n timestamps for n frames whose timings diff --git a/shell/common/shell_test_platform_view_vulkan.cc b/shell/common/shell_test_platform_view_vulkan.cc index 051775ae9a58f..a10fa4790ec65 100644 --- a/shell/common/shell_test_platform_view_vulkan.cc +++ b/shell/common/shell_test_platform_view_vulkan.cc @@ -12,6 +12,8 @@ #include "flutter/vulkan/vulkan_skia_proc_table.h" #include "flutter/vulkan/vulkan_utilities.h" +#include "third_party/skia/include/core/SkSurface.h" + #if OS_FUCHSIA #define VULKAN_SO_PATH "libvulkan.so" #elif FML_OS_MACOSX diff --git a/shell/common/switches.cc b/shell/common/switches.cc index 1d518824aa819..1aec89b79b170 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -235,33 +235,55 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { settings.executable_name = command_line.argv0(); } - // Enable Observatory - settings.enable_observatory = + // Enable the VM Service + settings.enable_vm_service = + !command_line.HasOption(FlagForSwitch(Switch::DisableVMService)) && + // TODO(bkonyi): remove once flutter_tools no longer uses this option. + // See https://github.com/dart-lang/sdk/issues/50233 !command_line.HasOption(FlagForSwitch(Switch::DisableObservatory)); - // Enable mDNS Observatory Publication - settings.enable_observatory_publication = !command_line.HasOption( - FlagForSwitch(Switch::DisableObservatoryPublication)); - - // Set Observatory Host - if (command_line.HasOption(FlagForSwitch(Switch::DeviceObservatoryHost))) { + // Enable mDNS VM Service Publication + settings.enable_vm_service_publication = + !command_line.HasOption( + FlagForSwitch(Switch::DisableVMServicePublication)) && + !command_line.HasOption( + FlagForSwitch(Switch::DisableObservatoryPublication)); + + // Set VM Service Host + if (command_line.HasOption(FlagForSwitch(Switch::DeviceVMServiceHost))) { + command_line.GetOptionValue(FlagForSwitch(Switch::DeviceVMServiceHost), + &settings.vm_service_host); + } else if (command_line.HasOption( + FlagForSwitch(Switch::DeviceObservatoryHost))) { + // TODO(bkonyi): remove once flutter_tools no longer uses this option. + // See https://github.com/dart-lang/sdk/issues/50233 command_line.GetOptionValue(FlagForSwitch(Switch::DeviceObservatoryHost), - &settings.observatory_host); + &settings.vm_service_host); } - // Default the observatory port based on --ipv6 if not set. - if (settings.observatory_host.empty()) { - settings.observatory_host = + // Default the VM Service port based on --ipv6 if not set. + if (settings.vm_service_host.empty()) { + settings.vm_service_host = command_line.HasOption(FlagForSwitch(Switch::IPv6)) ? "::1" : "127.0.0.1"; } - // Set Observatory Port - if (command_line.HasOption(FlagForSwitch(Switch::DeviceObservatoryPort))) { + // Set VM Service Port + if (command_line.HasOption(FlagForSwitch(Switch::DeviceVMServicePort))) { + if (!GetSwitchValue(command_line, Switch::DeviceVMServicePort, + &settings.vm_service_port)) { + FML_LOG(INFO) + << "VM Service port specified was malformed. Will default to " + << settings.vm_service_port; + } + } else if (command_line.HasOption( + FlagForSwitch(Switch::DeviceObservatoryPort))) { + // TODO(bkonyi): remove once flutter_tools no longer uses this option. + // See https://github.com/dart-lang/sdk/issues/50233 if (!GetSwitchValue(command_line, Switch::DeviceObservatoryPort, - &settings.observatory_port)) { + &settings.vm_service_port)) { FML_LOG(INFO) - << "Observatory port specified was malformed. Will default to " - << settings.observatory_port; + << "VM Service port specified was malformed. Will default to " + << settings.vm_service_port; } } diff --git a/shell/common/switches.h b/shell/common/switches.h index a6512908cebe4..ce27a02e0fa01 100644 --- a/shell/common/switches.h +++ b/shell/common/switches.h @@ -70,30 +70,58 @@ DEF_SWITCH(DartFlags, "dart-flags", "Flags passed directly to the Dart VM without being interpreted " "by the Flutter shell.") -DEF_SWITCH(DeviceObservatoryHost, - "observatory-host", - "The hostname/IP address on which the Dart Observatory should " +DEF_SWITCH(DeviceVMServiceHost, + "vm-service-host", + "The hostname/IP address on which the Dart VM Service should " "be served. If not set, defaults to 127.0.0.1 or ::1 depending on " "whether --ipv6 is specified.") +// TODO(bkonyi): remove once flutter_tools no longer uses this option. +// See https://github.com/dart-lang/sdk/issues/50233 +DEF_SWITCH( + DeviceObservatoryHost, + "observatory-host", + "(deprecated) The hostname/IP address on which the Dart VM Service should " + "be served. If not set, defaults to 127.0.0.1 or ::1 depending on " + "whether --ipv6 is specified.") +DEF_SWITCH(DeviceVMServicePort, + "vm-service-port", + "A custom Dart VM Service port. The default is to pick a randomly " + "available open port.") +// TODO(bkonyi): remove once flutter_tools no longer uses this option. +// See https://github.com/dart-lang/sdk/issues/50233 DEF_SWITCH(DeviceObservatoryPort, "observatory-port", - "A custom Dart Observatory port. The default is to pick a randomly " + "(deprecated) A custom Dart VM Service port. The default is to pick " + "a randomly " "available open port.") +DEF_SWITCH( + DisableVMService, + "disable-vm-service", + "Disable the Dart VM Service. The Dart VM Service is never available " + "in release mode.") +// TODO(bkonyi): remove once flutter_tools no longer uses this option. +// See https://github.com/dart-lang/sdk/issues/50233 DEF_SWITCH(DisableObservatory, "disable-observatory", - "Disable the Dart Observatory. The observatory is never available " + "(deprecated) Disable the Dart VM Service. The Dart VM Service is " + "never available " "in release mode.") +DEF_SWITCH(DisableVMServicePublication, + "disable-vm-service-publication", + "Disable mDNS Dart VM Service publication.") +// TODO(bkonyi): remove once flutter_tools no longer uses this option. +// See https://github.com/dart-lang/sdk/issues/50233 DEF_SWITCH(DisableObservatoryPublication, "disable-observatory-publication", - "Disable mDNS Dart Observatory publication.") + "(deprecated) Disable mDNS Dart VM Service publication.") DEF_SWITCH(IPv6, "ipv6", - "Bind to the IPv6 localhost address for the Dart Observatory. " - "Ignored if --observatory-host is set.") + "Bind to the IPv6 localhost address for the Dart VM Service. " + "Ignored if --vm-service-host is set.") DEF_SWITCH(EnableDartProfiling, "enable-dart-profiling", "Enable Dart profiling. Profiling information can be viewed from " - "the observatory.") + "Dart / Flutter DevTools.") DEF_SWITCH(EndlessTraceBuffer, "endless-trace-buffer", "Enable an endless trace buffer. The default is a ring buffer. " diff --git a/shell/gpu/gpu_surface_gl_skia.h b/shell/gpu/gpu_surface_gl_skia.h index 9b2cac089f8ed..8e69f1f9cd945 100644 --- a/shell/gpu/gpu_surface_gl_skia.h +++ b/shell/gpu/gpu_surface_gl_skia.h @@ -14,6 +14,8 @@ #include "flutter/fml/macros.h" #include "flutter/fml/memory/weak_ptr.h" #include "flutter/shell/gpu/gpu_surface_gl_delegate.h" + +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { diff --git a/shell/gpu/gpu_surface_software.cc b/shell/gpu/gpu_surface_software.cc index 862cb7d3e9694..f72f2d4f8822b 100644 --- a/shell/gpu/gpu_surface_software.cc +++ b/shell/gpu/gpu_surface_software.cc @@ -5,8 +5,11 @@ #include "flutter/shell/gpu/gpu_surface_software.h" #include + #include "flutter/fml/logging.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { GPUSurfaceSoftware::GPUSurfaceSoftware(GPUSurfaceSoftwareDelegate* delegate, diff --git a/shell/gpu/gpu_surface_vulkan.cc b/shell/gpu/gpu_surface_vulkan.cc index ba8383c1343cf..da2131c4f7cbc 100644 --- a/shell/gpu/gpu_surface_vulkan.cc +++ b/shell/gpu/gpu_surface_vulkan.cc @@ -5,9 +5,11 @@ #include "flutter/shell/gpu/gpu_surface_vulkan.h" #include "flutter/fml/logging.h" -#include "fml/trace_event.h" -#include "include/core/SkColorSpace.h" -#include "include/core/SkSize.h" +#include "flutter/fml/trace_event.h" + +#include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/core/SkSize.h" +#include "third_party/skia/include/core/SkSurface.h" #include "vulkan/vulkan_core.h" namespace flutter { diff --git a/shell/gpu/gpu_surface_vulkan.h b/shell/gpu/gpu_surface_vulkan.h index b281ac8c0f160..c198f7c60e8f4 100644 --- a/shell/gpu/gpu_surface_vulkan.h +++ b/shell/gpu/gpu_surface_vulkan.h @@ -14,7 +14,9 @@ #include "flutter/vulkan/vulkan_backbuffer.h" #include "flutter/vulkan/vulkan_native_surface.h" #include "flutter/vulkan/vulkan_window.h" -#include "include/core/SkRefCnt.h" + +#include "third_party/skia/include/core/SkRefCnt.h" +#include "third_party/skia/include/core/SkSurface.h" namespace flutter { diff --git a/shell/platform/android/android_surface_software.cc b/shell/platform/android/android_surface_software.cc index 164049d9d9bde..fdfc8d9d509ac 100644 --- a/shell/platform/android/android_surface_software.cc +++ b/shell/platform/android/android_surface_software.cc @@ -13,7 +13,9 @@ #include "flutter/fml/trace_event.h" #include "flutter/shell/platform/android/android_shell_holder.h" #include "flutter/shell/platform/android/jni/platform_view_android_jni.h" + #include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkSurface.h" namespace flutter { diff --git a/shell/platform/android/android_surface_software.h b/shell/platform/android/android_surface_software.h index 1ea3fe8637132..38e4c498f3843 100644 --- a/shell/platform/android/android_surface_software.h +++ b/shell/platform/android/android_surface_software.h @@ -12,6 +12,8 @@ #include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "flutter/shell/platform/android/surface/android_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { class AndroidSurfaceSoftware final : public AndroidSurface, diff --git a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc index f05db8e6e8071..76e0115c896de 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc @@ -5,6 +5,7 @@ #define FML_USED_ON_EMBEDDER #include + #include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h" #include "flutter/flow/embedded_views.h" @@ -14,8 +15,10 @@ #include "flutter/shell/platform/android/jni/jni_mock.h" #include "flutter/shell/platform/android/surface/android_surface.h" #include "flutter/shell/platform/android/surface/android_surface_mock.h" + #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { diff --git a/shell/platform/android/flutter_main.cc b/shell/platform/android/flutter_main.cc index bf4930b1f1082..782b373c21d24 100644 --- a/shell/platform/android/flutter_main.cc +++ b/shell/platform/android/flutter_main.cc @@ -59,7 +59,7 @@ fml::jni::ScopedJavaGlobalRef* g_flutter_jni_class = nullptr; } // anonymous namespace FlutterMain::FlutterMain(const flutter::Settings& settings) - : settings_(settings), observatory_uri_callback_() {} + : settings_(settings), vm_service_uri_callback_() {} FlutterMain::~FlutterMain() = default; @@ -100,8 +100,8 @@ void FlutterMain::Init(JNIEnv* env, __android_log_print( ANDROID_LOG_INFO, "Flutter", "ATrace was enabled at startup. Flutter and Dart " - "tracing will be forwarded to systrace and will not show up in the " - "Observatory timeline or Dart DevTools."); + "tracing will be forwarded to systrace and will not show up in " + "Dart DevTools."); } } @@ -164,17 +164,17 @@ void FlutterMain::Init(JNIEnv* env, // longer be a singleton. g_flutter_main.reset(new FlutterMain(settings)); - g_flutter_main->SetupObservatoryUriCallback(env); + g_flutter_main->SetupDartVMServiceUriCallback(env); } -void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) { +void FlutterMain::SetupDartVMServiceUriCallback(JNIEnv* env) { g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef( env, env->FindClass("io/flutter/embedding/engine/FlutterJNI")); if (g_flutter_jni_class->is_null()) { return; } jfieldID uri_field = env->GetStaticFieldID( - g_flutter_jni_class->obj(), "observatoryUri", "Ljava/lang/String;"); + g_flutter_jni_class->obj(), "vmServiceUri", "Ljava/lang/String;"); if (uri_field == nullptr) { return; } @@ -190,7 +190,7 @@ void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) { fml::RefPtr platform_runner = fml::MessageLoop::GetCurrent().GetTaskRunner(); - observatory_uri_callback_ = DartServiceIsolate::AddServerStatusCallback( + vm_service_uri_callback_ = DartServiceIsolate::AddServerStatusCallback( [platform_runner, set_uri](const std::string& uri) { platform_runner->PostTask([uri, set_uri] { set_uri(uri); }); }); diff --git a/shell/platform/android/flutter_main.h b/shell/platform/android/flutter_main.h index b956377c8e295..bc78efce2d46a 100644 --- a/shell/platform/android/flutter_main.h +++ b/shell/platform/android/flutter_main.h @@ -25,7 +25,7 @@ class FlutterMain { private: const flutter::Settings settings_; - DartServiceIsolate::CallbackHandle observatory_uri_callback_; + DartServiceIsolate::CallbackHandle vm_service_uri_callback_; explicit FlutterMain(const flutter::Settings& settings); @@ -38,7 +38,7 @@ class FlutterMain { jstring engineCachesPath, jlong initTimeMillis); - void SetupObservatoryUriCallback(JNIEnv* env); + void SetupDartVMServiceUriCallback(JNIEnv* env); FML_DISALLOW_COPY_AND_ASSIGN(FlutterMain); }; diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 21a9443228156..9883d6efdb88f 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -321,9 +321,16 @@ private static String[] getArgsFromIntent(Intent intent) { if (intent.getBooleanExtra("verbose-logging", false)) { args.add("--verbose-logging"); } - final int observatoryPort = intent.getIntExtra("observatory-port", 0); - if (observatoryPort > 0) { - args.add("--observatory-port=" + Integer.toString(observatoryPort)); + int vmServicePort = intent.getIntExtra("vm-service-port", 0); + if (vmServicePort > 0) { + args.add("--vm-service-port=" + Integer.toString(vmServicePort)); + } else { + // TODO(bkonyi): remove once flutter_tools no longer uses this option. + // See https://github.com/dart-lang/sdk/issues/50233 + vmServicePort = intent.getIntExtra("observatory-port", 0); + if (vmServicePort > 0) { + args.add("--vm-service-port=" + Integer.toString(vmServicePort)); + } } if (intent.getBooleanExtra("endless-trace-buffer", false)) { args.add("--endless-trace-buffer"); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index 56db871f1ef72..d22118d4391b1 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -829,11 +829,13 @@ void onRequestPermissionsResult( void onNewIntent(@NonNull Intent intent) { ensureAlive(); if (flutterEngine != null) { - Log.v(TAG, "Forwarding onNewIntent() to FlutterEngine and sending pushRoute message."); + Log.v( + TAG, + "Forwarding onNewIntent() to FlutterEngine and sending pushRouteInformation message."); flutterEngine.getActivityControlSurface().onNewIntent(intent); String initialRoute = maybeGetInitialRouteFromIntent(intent); if (initialRoute != null && !initialRoute.isEmpty()) { - flutterEngine.getNavigationChannel().pushRoute(initialRoute); + flutterEngine.getNavigationChannel().pushRouteInformation(initialRoute); } } else { Log.w(TAG, "onNewIntent() invoked before FlutterFragment was attached to an Activity."); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index aba6f671deb5d..3a20807bdf1f0 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -215,7 +215,7 @@ public void init( private static float refreshRateFPS = 60.0f; // This is set from native code via JNI. - @Nullable private static String observatoryUri; + @Nullable private static String vmServiceUri; private native boolean nativeGetIsSoftwareRenderingEnabled(); @@ -230,14 +230,28 @@ public boolean getIsSoftwareRenderingEnabled() { } /** - * Observatory URI for the VM instance. + * VM Service URI for the VM instance. * *

Its value is set by the native engine once {@link #init(Context, String[], String, String, * String, long)} is run. */ @Nullable + public static String getVMServiceUri() { + return vmServiceUri; + } + + /** + * VM Service URI for the VM instance. + * + *

Its value is set by the native engine once {@link #init(Context, String[], String, String, + * String, long)} is run. + * + * @deprecated replaced by {@link #getVMServiceUri()}. + */ + @Deprecated + @Nullable public static String getObservatoryUri() { - return observatoryUri; + return vmServiceUri; } /** diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java b/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java index c741f6a3b58e4..49519f1f979ec 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java @@ -54,8 +54,11 @@ public class FlutterShellArgs { public static final String ARG_PURGE_PERSISTENT_CACHE = "--purge-persistent-cache"; public static final String ARG_KEY_VERBOSE_LOGGING = "verbose-logging"; public static final String ARG_VERBOSE_LOGGING = "--verbose-logging"; + public static final String ARG_KEY_VM_SERVICE_PORT = "vm-service-port"; + public static final String ARG_VM_SERVICE_PORT = "--vm-service-port="; + // TODO(bkonyi): remove once flutter_tools no longer uses this option. + // See https://github.com/dart-lang/sdk/issues/50233 public static final String ARG_KEY_OBSERVATORY_PORT = "observatory-port"; - public static final String ARG_OBSERVATORY_PORT = "--observatory-port="; public static final String ARG_KEY_DART_FLAGS = "dart-flags"; public static final String ARG_DART_FLAGS = "--dart-flags"; public static final String ARG_KEY_MSAA_SAMPLES = "msaa-samples"; @@ -76,9 +79,16 @@ public static FlutterShellArgs fromIntent(@NonNull Intent intent) { if (intent.getBooleanExtra(ARG_KEY_START_PAUSED, false)) { args.add(ARG_START_PAUSED); } - final int observatoryPort = intent.getIntExtra(ARG_KEY_OBSERVATORY_PORT, 0); - if (observatoryPort > 0) { - args.add(ARG_OBSERVATORY_PORT + Integer.toString(observatoryPort)); + int vmServicePort = intent.getIntExtra(ARG_KEY_VM_SERVICE_PORT, 0); + if (vmServicePort > 0) { + args.add(ARG_VM_SERVICE_PORT + Integer.toString(vmServicePort)); + } else { + // TODO(bkonyi): remove once flutter_tools no longer uses this option. + // See https://github.com/dart-lang/sdk/issues/50233 + vmServicePort = intent.getIntExtra(ARG_KEY_OBSERVATORY_PORT, 0); + if (vmServicePort > 0) { + args.add(ARG_VM_SERVICE_PORT + Integer.toString(vmServicePort)); + } } if (intent.getBooleanExtra(ARG_KEY_DISABLE_SERVICE_AUTH_CODES, false)) { args.add(ARG_DISABLE_SERVICE_AUTH_CODES); diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java index 87e7e36fe8d9a..36cac70125bf5 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java @@ -11,6 +11,8 @@ import io.flutter.plugin.common.JSONMethodCodec; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; +import java.util.HashMap; +import java.util.Map; /** TODO(mattcarroll): fill in javadoc for NavigationChannel. */ public class NavigationChannel { @@ -43,6 +45,13 @@ public void pushRoute(@NonNull String route) { channel.invokeMethod("pushRoute", route); } + public void pushRouteInformation(@NonNull String route) { + Log.v(TAG, "Sending message to push route information '" + route + "'"); + Map message = new HashMap<>(); + message.put("location", route); + channel.invokeMethod("pushRouteInformation", message); + } + public void popRoute() { Log.v(TAG, "Sending message to pop route."); channel.invokeMethod("popRoute", null); diff --git a/shell/platform/android/io/flutter/view/FlutterNativeView.java b/shell/platform/android/io/flutter/view/FlutterNativeView.java index 190a9ecbb160e..2f027695b5ad3 100644 --- a/shell/platform/android/io/flutter/view/FlutterNativeView.java +++ b/shell/platform/android/io/flutter/view/FlutterNativeView.java @@ -124,8 +124,13 @@ public boolean isApplicationRunning() { return applicationIsRunning; } + @Deprecated public static String getObservatoryUri() { - return FlutterJNI.getObservatoryUri(); + return FlutterJNI.getVMServiceUri(); + } + + public static String getVMServiceUri() { + return FlutterJNI.getVMServiceUri(); } @Override diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java index 45c1c2e2583b3..e120d7791a6d2 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java @@ -726,7 +726,7 @@ public void itSendsdefaultInitialRouteOnStartIfNotDeepLinkingFromIntent() { } @Test - public void itSendsPushRouteMessageWhenOnNewIntent() { + public void itSendsPushRouteInformationMessageWhenOnNewIntent() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); @@ -742,11 +742,11 @@ public void itSendsPushRouteMessageWhenOnNewIntent() { // Verify that the navigation channel was given the push route message. verify(mockFlutterEngine.getNavigationChannel(), times(1)) - .pushRoute("/custom/route?query=test"); + .pushRouteInformation("/custom/route?query=test"); } @Test - public void itDoesNotSendPushRouteMessageWhenOnNewIntentIsNonHierarchicalUri() { + public void itDoesNotSendPushRouteInformationMessageWhenOnNewIntentIsNonHierarchicalUri() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); @@ -764,11 +764,12 @@ public void itDoesNotSendPushRouteMessageWhenOnNewIntentIsNonHierarchicalUri() { delegate.onNewIntent(mockIntent); // Verify that the navigation channel was not given a push route message. - verify(mockFlutterEngine.getNavigationChannel(), times(0)).pushRoute("mailto:test@test.com"); + verify(mockFlutterEngine.getNavigationChannel(), times(0)) + .pushRouteInformation("mailto:test@test.com"); } @Test - public void itSendsPushRouteMessageWhenOnNewIntentWithQueryParameterAndFragment() { + public void itSendsPushRouteInformationMessageWhenOnNewIntentWithQueryParameterAndFragment() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); @@ -785,11 +786,11 @@ public void itSendsPushRouteMessageWhenOnNewIntentWithQueryParameterAndFragment( // Verify that the navigation channel was given the push route message. verify(mockFlutterEngine.getNavigationChannel(), times(1)) - .pushRoute("/custom/route?query=test#fragment"); + .pushRouteInformation("/custom/route?query=test#fragment"); } @Test - public void itSendsPushRouteMessageWhenOnNewIntentWithFragmentNoQueryParameter() { + public void itSendsPushRouteInformationMessageWhenOnNewIntentWithFragmentNoQueryParameter() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); @@ -804,11 +805,12 @@ public void itSendsPushRouteMessageWhenOnNewIntentWithFragmentNoQueryParameter() delegate.onNewIntent(mockIntent); // Verify that the navigation channel was given the push route message. - verify(mockFlutterEngine.getNavigationChannel(), times(1)).pushRoute("/custom/route#fragment"); + verify(mockFlutterEngine.getNavigationChannel(), times(1)) + .pushRouteInformation("/custom/route#fragment"); } @Test - public void itSendsPushRouteMessageWhenOnNewIntentNoQueryParameter() { + public void itSendsPushRouteInformationMessageWhenOnNewIntentNoQueryParameter() { when(mockHost.shouldHandleDeeplinking()).thenReturn(true); // Create the real object that we're testing. FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost); @@ -823,7 +825,8 @@ public void itSendsPushRouteMessageWhenOnNewIntentNoQueryParameter() { delegate.onNewIntent(mockIntent); // Verify that the navigation channel was given the push route message. - verify(mockFlutterEngine.getNavigationChannel(), times(1)).pushRoute("/custom/route"); + verify(mockFlutterEngine.getNavigationChannel(), times(1)) + .pushRouteInformation("/custom/route"); } @Test diff --git a/shell/platform/common/accessibility_bridge.cc b/shell/platform/common/accessibility_bridge.cc index e6b47d4ae6f86..8007460d787e4 100644 --- a/shell/platform/common/accessibility_bridge.cc +++ b/shell/platform/common/accessibility_bridge.cc @@ -78,7 +78,8 @@ void AccessibilityBridge::CommitUpdates() { // entire subtree into a list. We pick another node from the remaining update, // and keep doing so until the update map is empty. We then concatenate the // lists in the reversed order, this guarantees parent updates always come - // before child updates. + // before child updates. If the root is in the update, it is guaranteed to + // be the first node of the last list. std::vector> results; while (!pending_semantics_node_updates_.empty()) { auto begin = pending_semantics_node_updates_.begin(); @@ -95,6 +96,15 @@ void AccessibilityBridge::CommitUpdates() { } } + // The first update must set the tree's root, which is guaranteed to be the + // last list's first node. A tree's root node never changes, though it can be + // modified. + if (!results.empty() && GetRootAsAXNode()->id() == ui::AXNode::kInvalidAXID) { + FML_DCHECK(!results.back().empty()); + + update.root_id = results.back().front().id; + } + tree_->Unserialize(update); pending_semantics_node_updates_.clear(); pending_semantics_custom_action_updates_.clear(); diff --git a/shell/platform/common/accessibility_bridge.h b/shell/platform/common/accessibility_bridge.h index eb913f6b5c7bf..81a6a1a87a7b7 100644 --- a/shell/platform/common/accessibility_bridge.h +++ b/shell/platform/common/accessibility_bridge.h @@ -50,7 +50,9 @@ class AccessibilityBridge //----------------------------------------------------------------------------- /// @brief The ID of the root node in the accessibility tree. In Flutter, - // this is always 0. + /// this is always 0. + // TODO(loicsharma): Remove this as it is incorrect in a multi-view world. + // See: https://github.com/flutter/flutter/issues/119391 static constexpr int32_t kRootNodeId = 0; //------------------------------------------------------------------------------ diff --git a/shell/platform/common/accessibility_bridge_unittests.cc b/shell/platform/common/accessibility_bridge_unittests.cc index 7b5a4924e01c3..3b5f19764a3ff 100644 --- a/shell/platform/common/accessibility_bridge_unittests.cc +++ b/shell/platform/common/accessibility_bridge_unittests.cc @@ -37,7 +37,7 @@ FlutterSemanticsNode CreateSemanticsNode( }; } -TEST(AccessibilityBridgeTest, basicTest) { +TEST(AccessibilityBridgeTest, BasicTest) { std::shared_ptr bridge = std::make_shared(); @@ -66,7 +66,98 @@ TEST(AccessibilityBridgeTest, basicTest) { EXPECT_EQ(child2_node->GetName(), "child 2"); } -TEST(AccessibilityBridgeTest, canFireChildrenChangedCorrectly) { +// Flutter used to assume that the accessibility root had ID 0. +// In a multi-view world, each view has its own accessibility root +// with a globally unique node ID. +TEST(AccessibilityBridgeTest, AccessibilityRootId) { + std::shared_ptr bridge = + std::make_shared(); + + std::vector children{456, 789}; + FlutterSemanticsNode root = CreateSemanticsNode(123, "root", &children); + FlutterSemanticsNode child1 = CreateSemanticsNode(456, "child 1"); + FlutterSemanticsNode child2 = CreateSemanticsNode(789, "child 2"); + + bridge->AddFlutterSemanticsNodeUpdate(&root); + bridge->AddFlutterSemanticsNodeUpdate(&child1); + bridge->AddFlutterSemanticsNodeUpdate(&child2); + bridge->CommitUpdates(); + + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(123).lock(); + auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(456).lock(); + auto child2_node = bridge->GetFlutterPlatformNodeDelegateFromID(789).lock(); + auto fake_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); + + EXPECT_EQ(bridge->GetRootAsAXNode()->id(), 123); + EXPECT_EQ(bridge->RootDelegate()->GetName(), "root"); + + EXPECT_EQ(root_node->GetChildCount(), 2); + EXPECT_EQ(root_node->GetData().child_ids[0], 456); + EXPECT_EQ(root_node->GetData().child_ids[1], 789); + EXPECT_EQ(root_node->GetName(), "root"); + + EXPECT_EQ(child1_node->GetChildCount(), 0); + EXPECT_EQ(child1_node->GetName(), "child 1"); + + EXPECT_EQ(child2_node->GetChildCount(), 0); + EXPECT_EQ(child2_node->GetName(), "child 2"); + + ASSERT_FALSE(fake_delegate); +} + +// Semantic nodes can be added in any order. +TEST(AccessibilityBridgeTest, AddOrder) { + std::shared_ptr bridge = + std::make_shared(); + + std::vector root_children{34, 56}; + std::vector child2_children{78}; + std::vector child3_children{90}; + FlutterSemanticsNode root = CreateSemanticsNode(12, "root", &root_children); + FlutterSemanticsNode child1 = CreateSemanticsNode(34, "child 1"); + FlutterSemanticsNode child2 = + CreateSemanticsNode(56, "child 2", &child2_children); + FlutterSemanticsNode child3 = + CreateSemanticsNode(78, "child 3", &child3_children); + FlutterSemanticsNode child4 = CreateSemanticsNode(90, "child 4"); + + bridge->AddFlutterSemanticsNodeUpdate(&child3); + bridge->AddFlutterSemanticsNodeUpdate(&child2); + bridge->AddFlutterSemanticsNodeUpdate(&root); + bridge->AddFlutterSemanticsNodeUpdate(&child1); + bridge->AddFlutterSemanticsNodeUpdate(&child4); + bridge->CommitUpdates(); + + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(12).lock(); + auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(34).lock(); + auto child2_node = bridge->GetFlutterPlatformNodeDelegateFromID(56).lock(); + auto child3_node = bridge->GetFlutterPlatformNodeDelegateFromID(78).lock(); + auto child4_node = bridge->GetFlutterPlatformNodeDelegateFromID(90).lock(); + + EXPECT_EQ(bridge->GetRootAsAXNode()->id(), 12); + EXPECT_EQ(bridge->RootDelegate()->GetName(), "root"); + + EXPECT_EQ(root_node->GetChildCount(), 2); + EXPECT_EQ(root_node->GetData().child_ids[0], 34); + EXPECT_EQ(root_node->GetData().child_ids[1], 56); + EXPECT_EQ(root_node->GetName(), "root"); + + EXPECT_EQ(child1_node->GetChildCount(), 0); + EXPECT_EQ(child1_node->GetName(), "child 1"); + + EXPECT_EQ(child2_node->GetChildCount(), 1); + EXPECT_EQ(child2_node->GetData().child_ids[0], 78); + EXPECT_EQ(child2_node->GetName(), "child 2"); + + EXPECT_EQ(child3_node->GetChildCount(), 1); + EXPECT_EQ(child3_node->GetData().child_ids[0], 90); + EXPECT_EQ(child3_node->GetName(), "child 3"); + + EXPECT_EQ(child4_node->GetChildCount(), 0); + EXPECT_EQ(child4_node->GetName(), "child 4"); +} + +TEST(AccessibilityBridgeTest, CanFireChildrenChangedCorrectly) { std::shared_ptr bridge = std::make_shared(); @@ -114,7 +205,7 @@ TEST(AccessibilityBridgeTest, canFireChildrenChangedCorrectly) { Contains(ui::AXEventGenerator::Event::SUBTREE_CREATED)); } -TEST(AccessibilityBridgeTest, canRecreateNodeDelegates) { +TEST(AccessibilityBridgeTest, CanRecreateNodeDelegates) { std::shared_ptr bridge = std::make_shared(); @@ -148,7 +239,7 @@ TEST(AccessibilityBridgeTest, canRecreateNodeDelegates) { EXPECT_EQ(new_child1_node->GetName(), "child 1"); } -TEST(AccessibilityBridgeTest, canHandleSelectionChangeCorrectly) { +TEST(AccessibilityBridgeTest, CanHandleSelectionChangeCorrectly) { std::shared_ptr bridge = std::make_shared(); FlutterSemanticsNode root = CreateSemanticsNode(0, "root"); @@ -180,7 +271,7 @@ TEST(AccessibilityBridgeTest, canHandleSelectionChangeCorrectly) { ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED); } -TEST(AccessibilityBridgeTest, doesNotAssignEditableRootToSelectableText) { +TEST(AccessibilityBridgeTest, DoesNotAssignEditableRootToSelectableText) { std::shared_ptr bridge = std::make_shared(); FlutterSemanticsNode root = CreateSemanticsNode(0, "root"); diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 8492a1475e517..7a30a1fb16d03 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -80,6 +80,8 @@ source_set("flutter_framework_source") { "framework/Source/FlutterChannelKeyResponder.mm", "framework/Source/FlutterDartProject.mm", "framework/Source/FlutterDartProject_Internal.h", + "framework/Source/FlutterDartVMServicePublisher.h", + "framework/Source/FlutterDartVMServicePublisher.mm", "framework/Source/FlutterEmbedderKeyResponder.h", "framework/Source/FlutterEmbedderKeyResponder.mm", "framework/Source/FlutterEngine.mm", @@ -90,8 +92,6 @@ source_set("flutter_framework_source") { "framework/Source/FlutterKeySecondaryResponder.h", "framework/Source/FlutterKeyboardManager.h", "framework/Source/FlutterKeyboardManager.mm", - "framework/Source/FlutterObservatoryPublisher.h", - "framework/Source/FlutterObservatoryPublisher.mm", "framework/Source/FlutterOverlayView.h", "framework/Source/FlutterOverlayView.mm", "framework/Source/FlutterPlatformPlugin.h", @@ -187,6 +187,7 @@ source_set("flutter_framework_source") { "//flutter/shell/platform/darwin/common:framework_shared", "//flutter/shell/platform/embedder:embedder_as_internal_library", "//flutter/shell/profiling:profiling", + "//flutter/third_party/spring_animation", "//third_party/skia", ] @@ -301,6 +302,7 @@ shared_library("ios_test_flutter") { "//flutter/shell/platform/darwin/common:framework_shared", "//flutter/shell/platform/embedder:embedder_as_internal_library", "//flutter/shell/platform/embedder:embedder_test_utils", + "//flutter/third_party/spring_animation", "//flutter/third_party/tonic", "//flutter/third_party/txt", "//third_party/ocmock:ocmock_shared", diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h index 57ac4c22d34bf..caf2b3dfd52a0 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h @@ -410,13 +410,23 @@ FLUTTER_DARWIN_EXPORT @property(nonatomic, readonly) FlutterBasicMessageChannel* keyEventChannel; /** - * The `NSURL` of the observatory for the service isolate. + * The depcreated `NSURL` of the Dart VM Service for the service isolate. * * This is only set in debug and profile runtime modes, and only after the - * observatory service is ready. In release mode or before the observatory has + * Dart VM Service is ready. In release mode or before the Dart VM Service has * started, it returns `nil`. */ -@property(nonatomic, readonly, nullable) NSURL* observatoryUrl; +@property(nonatomic, readonly, nullable) + NSURL* observatoryUrl FLUTTER_DEPRECATED("Use vmServiceUrl instead"); + +/** + * The `NSURL` of the Dart VM Service for the service isolate. + * + * This is only set in debug and profile runtime modes, and only after the + * Dart VM Service is ready. In release mode or before the Dart VM Service has + * started, it returns `nil`. + */ +@property(nonatomic, readonly, nullable) NSURL* vmServiceUrl; /** * The `FlutterBinaryMessenger` associated with this FlutterEngine (used for communicating with diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index 9e0c86f8daddd..abc1bd8e6b7e6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -157,8 +157,11 @@ - (BOOL)openURL:(NSURL*)url { if ([url.fragment length] != 0) { fullRoute = [NSString stringWithFormat:@"%@#%@", fullRoute, url.fragment]; } - [flutterViewController.engine.navigationChannel invokeMethod:@"pushRoute" - arguments:fullRoute]; + [flutterViewController.engine.navigationChannel + invokeMethod:@"pushRouteInformation" + arguments:@{ + @"location" : fullRoute, + }]; } }]; return YES; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm index 33b4e423ce3dd..035b726188d1d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm @@ -67,8 +67,8 @@ - (void)testLaunchUrl { openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"] options:@{}]; XCTAssertTrue(result); - OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRoute" - arguments:@"/custom/route?query=test"]); + OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRouteInformation" + arguments:@{@"location" : @"/custom/route?query=test"}]); } - (void)testLaunchUrlWithDeepLinkingNotSet { @@ -104,8 +104,9 @@ - (void)testLaunchUrlWithQueryParameterAndFragment { openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"] options:@{}]; XCTAssertTrue(result); - OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRoute" - arguments:@"/custom/route?query=test#fragment"]); + OCMVerify([self.mockNavigationChannel + invokeMethod:@"pushRouteInformation" + arguments:@{@"location" : @"/custom/route?query=test#fragment"}]); } - (void)testLaunchUrlWithFragmentNoQueryParameter { @@ -117,8 +118,8 @@ - (void)testLaunchUrlWithFragmentNoQueryParameter { openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"] options:@{}]; XCTAssertTrue(result); - OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRoute" - arguments:@"/custom/route#fragment"]); + OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRouteInformation" + arguments:@{@"location" : @"/custom/route#fragment"}]); } - (void)testReleasesWindowOnDealloc { @@ -139,7 +140,7 @@ - (void)testReleasesWindowOnDealloc { #pragma mark - Deep linking -- (void)testUniversalLinkPushRoute { +- (void)testUniversalLinkPushRouteInformation { OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"]) .andReturn(@YES); @@ -151,8 +152,8 @@ - (void)testUniversalLinkPushRoute { restorationHandler:^(NSArray>* __nullable restorableObjects){ }]; XCTAssertTrue(result); - OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRoute" - arguments:@"/custom/route?query=test"]); + OCMVerify([self.mockNavigationChannel invokeMethod:@"pushRouteInformation" + arguments:@{@"location" : @"/custom/route?query=test"}]); } @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h b/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h similarity index 56% rename from shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h rename to shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h index 0c3fe202c6116..398e9f09e5a92 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_FLUTTEROBSERVATORYPUBLISHER_H_ -#define FLUTTER_FLUTTEROBSERVATORYPUBLISHER_H_ +#ifndef FLUTTER_FLUTTERDARTVMSERVICEPUBLISHER_H_ +#define FLUTTER_FLUTTERDARTVMSERVICEPUBLISHER_H_ #import -@interface FlutterObservatoryPublisher : NSObject +@interface FlutterDartVMServicePublisher : NSObject -- (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPublication +- (instancetype)initWithEnableVMServicePublication:(BOOL)enableVMServicePublication NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -18,4 +18,4 @@ @end -#endif // FLUTTER_FLUTTEROBSERVATORYPUBLISHER_H_ +#endif // FLUTTER_FLUTTERDARTVMSERVICEPUBLISHER_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.mm similarity index 59% rename from shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm rename to shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.mm index 9b3c437856c6f..c8083366af5ab 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.mm @@ -4,12 +4,12 @@ #define FML_USED_ON_EMBEDDER -#import "FlutterObservatoryPublisher.h" +#import "FlutterDartVMServicePublisher.h" #if FLUTTER_RELEASE -@implementation FlutterObservatoryPublisher -- (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPublication { +@implementation FlutterDartVMServicePublisher +- (instancetype)initWithEnableVMServicePublication:(BOOL)enableVMServicePublication { return [super init]; } @end @@ -23,9 +23,9 @@ - (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPubl // // When debugging issues with this implementation, the following is helpful: // -// 1) Running `dns-sd -Z _dartobservatory`. This is a built-in macOS tool that +// 1) Running `dns-sd -Z _dartVmService`. This is a built-in macOS tool that // can find advertized observatories using this method. If dns-sd can't find -// it, then the observatory is not getting advertized over any network +// it, then the VM service is not getting advertised over any network // interface that the host machine has access to. // 2) The Python zeroconf package. The dns-sd tool can sometimes see things // that aren't advertizing over a network interface - for example, simulators @@ -45,26 +45,27 @@ - (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPubl #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/runtime/dart_service_isolate.h" -@protocol FlutterObservatoryPublisherDelegate +@protocol FlutterDartVMServicePublisherDelegate - (void)publishServiceProtocolPort:(NSURL*)uri; - (void)stopService; @end -@interface FlutterObservatoryPublisher () +@interface FlutterDartVMServicePublisher () + (NSData*)createTxtData:(NSURL*)url; @property(readonly, class) NSString* serviceName; -@property(readonly) fml::scoped_nsobject> delegate; +@property(readonly) fml::scoped_nsobject> delegate; @property(nonatomic, readwrite) NSURL* url; -@property(readonly) BOOL enableObservatoryPublication; +@property(readonly) BOOL enableVMServicePublication; @end -@interface ObservatoryDNSServiceDelegate : NSObject +@interface DartVMServiceDNSServiceDelegate : NSObject @end -@implementation ObservatoryDNSServiceDelegate { +@implementation DartVMServiceDNSServiceDelegate { DNSServiceRef _dnsServiceRef; + DNSServiceRef _legacyDnsServiceRef; } - (void)stopService { @@ -72,6 +73,10 @@ - (void)stopService { DNSServiceRefDeallocate(_dnsServiceRef); _dnsServiceRef = NULL; } + if (_legacyDnsServiceRef) { + DNSServiceRefDeallocate(_legacyDnsServiceRef); + _legacyDnsServiceRef = NULL; + } } - (void)publishServiceProtocolPort:(NSURL*)url { @@ -83,32 +88,49 @@ - (void)publishServiceProtocolPort:(NSURL*)url { // Physical devices need to request all interfaces. uint32_t interfaceIndex = 0; #endif // TARGET_IPHONE_SIMULATOR - const char* registrationType = "_dartobservatory._tcp"; + const char* registrationType = "_dartVmService._tcp"; + const char* legacyRegistrationType = "_dartobservatory._tcp"; + const char* domain = "local."; // default domain uint16_t port = [[url port] unsignedShortValue]; - NSData* txtData = [FlutterObservatoryPublisher createTxtData:url]; + NSData* txtData = [FlutterDartVMServicePublisher createTxtData:url]; int err = DNSServiceRegister(&_dnsServiceRef, flags, interfaceIndex, - FlutterObservatoryPublisher.serviceName.UTF8String, registrationType, - domain, NULL, htons(port), txtData.length, txtData.bytes, - RegistrationCallback, NULL); - - if (err != 0) { - FML_LOG(ERROR) << "Failed to register observatory port with mDNS with error " << err << "."; - if (@available(iOS 14.0, *)) { - FML_LOG(ERROR) << "On iOS 14+, local network broadcast in apps need to be declared in " - << "the app's Info.plist. Debug and profile Flutter apps and modules host " - << "VM services on the local network to support debugging features such " - << "as hot reload and DevTools. To make your Flutter app or module " - << "attachable and debuggable, add a '" << registrationType << "' value " - << "to the 'NSBonjourServices' key in your Info.plist for the Debug/" - << "Profile configurations. " - << "For more information, see " - << "https://flutter.dev/docs/development/add-to-app/ios/" - "project-setup#local-network-privacy-permissions"; - } - } else { + FlutterDartVMServicePublisher.serviceName.UTF8String, + registrationType, domain, NULL, htons(port), txtData.length, + txtData.bytes, RegistrationCallback, NULL); + + if (err == 0) { DNSServiceSetDispatchQueue(_dnsServiceRef, dispatch_get_main_queue()); + return; + } + + // TODO(bkonyi): remove once flutter_tools no longer looks for the legacy registration type. + // See https://github.com/dart-lang/sdk/issues/50233 + // + // Try to fallback on the legacy registration type. + err = DNSServiceRegister(&_legacyDnsServiceRef, flags, interfaceIndex, + FlutterDartVMServicePublisher.serviceName.UTF8String, + legacyRegistrationType, domain, NULL, htons(port), txtData.length, + txtData.bytes, RegistrationCallback, NULL); + + if (err == 0) { + DNSServiceSetDispatchQueue(_legacyDnsServiceRef, dispatch_get_main_queue()); + return; + } + + FML_LOG(ERROR) << "Failed to register Dart VM Service port with mDNS with error " << err << "."; + if (@available(iOS 14.0, *)) { + FML_LOG(ERROR) << "On iOS 14+, local network broadcast in apps need to be declared in " + << "the app's Info.plist. Debug and profile Flutter apps and modules host " + << "VM services on the local network to support debugging features such " + << "as hot reload and DevTools. To make your Flutter app or module " + << "attachable and debuggable, add a '" << registrationType << "' value " + << "to the 'NSBonjourServices' key in your Info.plist for the Debug/" + << "Profile configurations. " + << "For more information, see " + << "https://flutter.dev/docs/development/add-to-app/ios/" + "project-setup#local-network-privacy-permissions"; } } @@ -120,32 +142,32 @@ static void DNSSD_API RegistrationCallback(DNSServiceRef sdRef, const char* domain, void* context) { if (errorCode == kDNSServiceErr_NoError) { - FML_DLOG(INFO) << "FlutterObservatoryPublisher is ready!"; + FML_DLOG(INFO) << "FlutterDartVMServicePublisher is ready!"; } else if (errorCode == kDNSServiceErr_PolicyDenied) { FML_LOG(ERROR) - << "Could not register as server for FlutterObservatoryPublisher, permission " + << "Could not register as server for FlutterDartVMServicePublisher, permission " << "denied. Check your 'Local Network' permissions for this app in the Privacy section of " << "the system Settings."; } else { - FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your " + FML_LOG(ERROR) << "Could not register as server for FlutterDartVMServicePublisher. Check your " "network settings and relaunch the application."; } } @end -@implementation FlutterObservatoryPublisher { +@implementation FlutterDartVMServicePublisher { flutter::DartServiceIsolate::CallbackHandle _callbackHandle; - std::unique_ptr> _weakFactory; + std::unique_ptr> _weakFactory; } -- (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPublication { +- (instancetype)initWithEnableVMServicePublication:(BOOL)enableVMServicePublication { self = [super init]; NSAssert(self, @"Super must not return null on init."); - _delegate.reset([[ObservatoryDNSServiceDelegate alloc] init]); - _enableObservatoryPublication = enableObservatoryPublication; - _weakFactory = std::make_unique>(self); + _delegate.reset([[DartVMServiceDNSServiceDelegate alloc] init]); + _enableVMServicePublication = enableVMServicePublication; + _weakFactory = std::make_unique>(self); fml::MessageLoop::EnsureInitializedForCurrentThread(); @@ -160,7 +182,7 @@ - (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPubl NSURL* url = [[[NSURL alloc] initWithString:[NSString stringWithUTF8String:uri.c_str()]] autorelease]; weak.get().url = url; - if (weak.get().enableObservatoryPublication) { + if (weak.get().enableVMServicePublication) { [[weak.get() delegate] publishServiceProtocolPort:url]; } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 480b284678614..c4c434ecf18f7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -21,8 +21,8 @@ #import "flutter/shell/platform/darwin/common/command_line.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterIndirectScribbleDelegate.h" -#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" @@ -108,7 +108,7 @@ @implementation FlutterEngine { std::unique_ptr> _weakFactory; fml::WeakPtr _viewController; - fml::scoped_nsobject _publisher; + fml::scoped_nsobject _publisher; std::shared_ptr _platformViewsController; flutter::IOSRenderingAPI _renderingApi; @@ -502,6 +502,10 @@ - (NSURL*)observatoryUrl { return [_publisher.get() url]; } +- (NSURL*)vmServiceUrl { + return [_publisher.get() url]; +} + - (void)resetChannels { _localizationChannel.reset(); _navigationChannel.reset(); @@ -680,13 +684,13 @@ - (void)launchEngine:(NSString*)entrypoint } - (void)setupShell:(std::unique_ptr)shell - withObservatoryPublication:(BOOL)doesObservatoryPublication { + withVMServicePublication:(BOOL)doesVMServicePublication { _shell = std::move(shell); [self setupChannels]; [self onLocaleUpdated:nil]; [self initializeDisplays]; - _publisher.reset([[FlutterObservatoryPublisher alloc] - initWithEnableObservatoryPublication:doesObservatoryPublication]); + _publisher.reset([[FlutterDartVMServicePublisher alloc] + initWithEnableVMServicePublication:doesVMServicePublication]); [self maybeSetupPlatformViewChannels]; _shell->SetGpuAvailability(_isGpuDisabled ? flutter::GpuAvailability::kUnavailable : flutter::GpuAvailability::kAvailable); @@ -816,7 +820,7 @@ - (BOOL)createShell:(NSString*)entrypoint << entrypoint.UTF8String; } else { [self setupShell:std::move(shell) - withObservatoryPublication:settings.enable_observatory_publication]; + withVMServicePublication:settings.enable_vm_service_publication]; if ([FlutterEngine isProfilerEnabled]) { [self startProfiler]; } @@ -1312,7 +1316,7 @@ - (FlutterEngine*)spawnWithEntrypoint:(/*nullable*/ NSString*)entrypoint result->_profiler = _profiler; result->_profiler_metrics = _profiler_metrics; result->_isGpuDisabled = _isGpuDisabled; - [result setupShell:std::move(shell) withObservatoryPublication:NO]; + [result setupShell:std::move(shell) withVMServicePublication:NO]; return [result autorelease]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm index d03781cc482f0..a10922f9da252 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm @@ -210,7 +210,7 @@ - (void)testWaitForFirstFrameTimeout { [timeoutFirstFrame fulfill]; } }]; - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self waitForExpectationsWithTimeout:5 handler:nil]; } - (void)testSpawn { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.mm b/shell/platform/darwin/ios/framework/Source/FlutterView.mm index 7c188be87109d..dcab55d404c34 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.mm @@ -47,6 +47,12 @@ - (instancetype)initWithDelegate:(id)delegate opaque: if (self) { _delegate = delegate; self.layer.opaque = opaque; + + // This line is necessary. CoreAnimation(or UIKit) may take this to do + // something to compute the final frame presented on screen, if we don't set this, + // it will make it take long time for us to take next CAMetalDrawable and will + // cause constant junk during rendering. + self.backgroundColor = UIColor.clearColor; } return self; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index d9ffc2c26d5bd..ced158a9eda07 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -30,6 +30,7 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" #import "flutter/shell/platform/embedder/embedder.h" +#import "flutter/third_party/spring_animation/spring_animation.h" static constexpr int kMicrosecondsPerSecond = 1000 * 1000; static constexpr CGFloat kScrollViewContentSize = 2.0; @@ -65,6 +66,9 @@ @interface FlutterViewController () _scrollView; fml::scoped_nsobject _keyboardAnimationView; + fml::scoped_nsobject _keyboardSpringAnimation; MouseState _mouseState; // Timestamp after which a scroll inertia cancel event should be inferred. NSTimeInterval _scrollInertiaEventStartline; @@ -594,6 +599,10 @@ - (UIView*)keyboardAnimationView { return _keyboardAnimationView.get(); } +- (SpringAnimation*)keyboardSpringAnimation { + return _keyboardSpringAnimation.get(); +} + - (UIScreen*)mainScreenIfViewLoaded { if (@available(iOS 13.0, *)) { if (self.viewIfLoaded == nil) { @@ -1314,13 +1323,14 @@ - (void)keyboardWillBeHidden:(NSNotification*)notification { } - (void)handleKeyboardNotification:(NSNotification*)notification { - // See https:://flutter.dev/go/ios-keyboard-calculating-inset for more details + // See https://flutter.dev/go/ios-keyboard-calculating-inset for more details // on why notifications are used and how things are calculated. if ([self shouldIgnoreKeyboardNotification:notification]) { return; } NSDictionary* info = notification.userInfo; + CGRect beginKeyboardFrame = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; CGRect keyboardFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue]; FlutterKeyboardMode keyboardMode = [self calculateKeyboardAttachMode:notification]; CGFloat calculatedInset = [self calculateKeyboardInset:keyboardFrame keyboardMode:keyboardMode]; @@ -1332,7 +1342,24 @@ - (void)handleKeyboardNotification:(NSNotification*)notification { self.targetViewInsetBottom = calculatedInset; NSTimeInterval duration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; - [self startKeyBoardAnimation:duration]; + + // Flag for simultaneous compounding animation calls. + // This captures animation calls made while the keyboard animation is currently animating. If the + // new animation is in the same direction as the current animation, this flag lets the current + // animation continue with an updated targetViewInsetBottom instead of starting a new keyboard + // animation. This allows for smoother keyboard animation interpolation. + BOOL keyboardWillShow = beginKeyboardFrame.origin.y > keyboardFrame.origin.y; + BOOL keyboardAnimationIsCompounding = + self.keyboardAnimationIsShowing == keyboardWillShow && _keyboardAnimationVSyncClient != nil; + + // Mark keyboard as showing or hiding. + self.keyboardAnimationIsShowing = keyboardWillShow; + + if (!keyboardAnimationIsCompounding) { + [self startKeyBoardAnimation:duration]; + } else if ([self keyboardSpringAnimation]) { + [self keyboardSpringAnimation].toValue = self.targetViewInsetBottom; + } } - (BOOL)shouldIgnoreKeyboardNotification:(NSNotification*)notification { @@ -1494,12 +1521,12 @@ - (CGFloat)calculateKeyboardInset:(CGRect)keyboardFrame keyboardMode:(NSInteger) } - (void)startKeyBoardAnimation:(NSTimeInterval)duration { - // If current physical_view_inset_bottom == targetViewInsetBottom,do nothing. + // If current physical_view_inset_bottom == targetViewInsetBottom, do nothing. if (_viewportMetrics.physical_view_inset_bottom == self.targetViewInsetBottom) { return; } - // When call this method first time, + // When this method is called for the first time, // initialize the keyboardAnimationView to get animation interpolation during animation. if ([self keyboardAnimationView] == nil) { UIView* keyboardAnimationView = [[UIView alloc] init]; @@ -1514,9 +1541,11 @@ - (void)startKeyBoardAnimation:(NSTimeInterval)duration { // Remove running animation when start another animation. [[self keyboardAnimationView].layer removeAllAnimations]; - // Set animation begin value. + // Set animation begin value and DisplayLink tracking values. [self keyboardAnimationView].frame = CGRectMake(0, _viewportMetrics.physical_view_inset_bottom, 0, 0); + self.keyboardAnimationStartTime = fml::TimePoint().Now(); + self.originalViewInsetBottom = _viewportMetrics.physical_view_inset_bottom; // Invalidate old vsync client if old animation is not completed. [self invalidateKeyboardAnimationVSyncClient]; @@ -1527,6 +1556,11 @@ - (void)startKeyBoardAnimation:(NSTimeInterval)duration { animations:^{ // Set end value. [self keyboardAnimationView].frame = CGRectMake(0, self.targetViewInsetBottom, 0, 0); + + // Setup keyboard animation interpolation. + CAAnimation* keyboardAnimation = + [[self keyboardAnimationView].layer animationForKey:@"position"]; + [self setupKeyboardSpringAnimationIfNeeded:keyboardAnimation]; } completion:^(BOOL finished) { if (_keyboardAnimationVSyncClient == currentVsyncClient) { @@ -1540,6 +1574,24 @@ - (void)startKeyBoardAnimation:(NSTimeInterval)duration { }]; } +- (void)setupKeyboardSpringAnimationIfNeeded:(CAAnimation*)keyboardAnimation { + // If keyboard animation is null or not a spring animation, fallback to DisplayLink tracking. + if (keyboardAnimation == nil || ![keyboardAnimation isKindOfClass:[CASpringAnimation class]]) { + _keyboardSpringAnimation.reset(); + return; + } + + // Setup keyboard spring animation details for spring curve animation calculation. + CASpringAnimation* keyboardCASpringAnimation = (CASpringAnimation*)keyboardAnimation; + _keyboardSpringAnimation.reset([[SpringAnimation alloc] + initWithStiffness:keyboardCASpringAnimation.stiffness + damping:keyboardCASpringAnimation.damping + mass:keyboardCASpringAnimation.mass + initialVelocity:keyboardCASpringAnimation.initialVelocity + fromValue:self.originalViewInsetBottom + toValue:self.targetViewInsetBottom]); +} + - (void)setupKeyboardAnimationVsyncClient { auto callback = [weakSelf = [self getWeakPtr]](std::unique_ptr recorder) { @@ -1556,10 +1608,20 @@ - (void)setupKeyboardAnimationVsyncClient { // Ensure the keyboardAnimationView is in view hierarchy when animation running. [flutterViewController.get().view addSubview:[flutterViewController keyboardAnimationView]]; } - if ([flutterViewController keyboardAnimationView].layer.presentationLayer) { - CGFloat value = - [flutterViewController keyboardAnimationView].layer.presentationLayer.frame.origin.y; - flutterViewController.get()->_viewportMetrics.physical_view_inset_bottom = value; + + if ([flutterViewController keyboardSpringAnimation] == nil) { + if (flutterViewController.get().keyboardAnimationView.layer.presentationLayer) { + flutterViewController.get()->_viewportMetrics.physical_view_inset_bottom = + flutterViewController.get() + .keyboardAnimationView.layer.presentationLayer.frame.origin.y; + [flutterViewController updateViewportMetrics]; + } + } else { + fml::TimeDelta timeElapsed = recorder.get()->GetVsyncTargetTime() - + flutterViewController.get().keyboardAnimationStartTime; + + flutterViewController.get()->_viewportMetrics.physical_view_inset_bottom = + [[flutterViewController keyboardSpringAnimation] curveFunction:timeElapsed.ToSecondsF()]; [flutterViewController updateViewportMetrics]; } }; @@ -1913,8 +1975,8 @@ - (BOOL)isAlwaysUse24HourFormat { } // The brightness mode of the platform, e.g., light or dark, expressed as a string that -// is understood by the Flutter framework. See the settings system channel for more -// information. +// is understood by the Flutter framework. See the settings +// system channel for more information. - (NSString*)brightnessMode { if (@available(iOS 13, *)) { UIUserInterfaceStyle style = self.traitCollection.userInterfaceStyle; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 5d3c1c948df18..1461ca0640993 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -17,6 +17,7 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/embedder/embedder.h" +#import "flutter/third_party/spring_animation/spring_animation.h" FLUTTER_ASSERT_ARC @@ -114,6 +115,7 @@ @interface FlutterViewController (Tests) @property(nonatomic, assign) double targetViewInsetBottom; @property(nonatomic, assign) BOOL isKeyboardInOrTransitioningFromBackground; +@property(nonatomic, assign) BOOL keyboardAnimationIsShowing; - (void)createTouchRateCorrectionVSyncClientIfNeeded; - (void)surfaceUpdated:(BOOL)appeared; @@ -133,6 +135,9 @@ - (FlutterKeyboardMode)calculateKeyboardAttachMode:(NSNotification*)notification - (CGFloat)calculateMultitaskingAdjustment:(CGRect)screenRect keyboardFrame:(CGRect)keyboardFrame; - (void)startKeyBoardAnimation:(NSTimeInterval)duration; - (void)setupKeyboardAnimationVsyncClient; +- (UIView*)keyboardAnimationView; +- (SpringAnimation*)keyboardSpringAnimation; +- (void)setupKeyboardSpringAnimationIfNeeded:(CAAnimation*)keyboardAnimation; - (void)ensureViewportMetricsIsCorrect; - (void)invalidateKeyboardAnimationVSyncClient; - (void)addInternalPlugins; @@ -166,6 +171,19 @@ - (void)tearDown { self.messageSent = nil; } +- (id)setupMockMainScreenAndView:(FlutterViewController*)viewControllerMock + viewFrame:(CGRect)viewFrame + convertedFrame:(CGRect)convertedFrame { + OCMStub([viewControllerMock mainScreenIfViewLoaded]).andReturn(UIScreen.mainScreen); + id mockView = OCMClassMock([UIView class]); + OCMStub([mockView frame]).andReturn(viewFrame); + OCMStub([mockView convertRect:viewFrame toCoordinateSpace:[OCMArg any]]) + .andReturn(convertedFrame); + OCMStub([viewControllerMock viewIfLoaded]).andReturn(mockView); + + return mockView; +} + - (void)testViewDidLoadWillInvokeCreateTouchRateCorrectionVSyncClient { FlutterEngine* engine = [[FlutterEngine alloc] init]; [engine runWithEntrypoint:nil]; @@ -190,6 +208,147 @@ - (void)testStartKeyboardAnimationWillInvokeSetupKeyboardAnimationVsyncClient { OCMVerify([viewControllerMock setupKeyboardAnimationVsyncClient]); } +- (void)testStartKeyboardAnimationWillInvokeSetupKeyboardSpringAnimationIfNeeded { + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + FlutterViewController* viewControllerMock = OCMPartialMock(viewController); + viewControllerMock.targetViewInsetBottom = 100; + [viewControllerMock startKeyBoardAnimation:0.25]; + + CAAnimation* keyboardAnimation = + [[viewControllerMock keyboardAnimationView].layer animationForKey:@"position"]; + + OCMVerify([viewControllerMock setupKeyboardSpringAnimationIfNeeded:keyboardAnimation]); +} + +- (void)testSetupKeyboardSpringAnimationIfNeeded { + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + FlutterViewController* viewControllerMock = OCMPartialMock(viewController); + CGRect viewFrame = UIScreen.mainScreen.bounds; + [self setupMockMainScreenAndView:viewControllerMock viewFrame:viewFrame convertedFrame:viewFrame]; + + // Null check. + [viewControllerMock setupKeyboardSpringAnimationIfNeeded:nil]; + SpringAnimation* keyboardSpringAnimation = [viewControllerMock keyboardSpringAnimation]; + XCTAssertTrue(keyboardSpringAnimation == nil); + + // CAAnimation that is not a CASpringAnimation. + CABasicAnimation* nonSpringAnimation = [CABasicAnimation animation]; + nonSpringAnimation.duration = 1.0; + nonSpringAnimation.fromValue = [NSNumber numberWithFloat:0.0]; + nonSpringAnimation.toValue = [NSNumber numberWithFloat:1.0]; + nonSpringAnimation.keyPath = @"position"; + [viewControllerMock setupKeyboardSpringAnimationIfNeeded:nonSpringAnimation]; + keyboardSpringAnimation = [viewControllerMock keyboardSpringAnimation]; + + XCTAssertTrue(keyboardSpringAnimation == nil); + + // CASpringAnimation. + CASpringAnimation* springAnimation = [CASpringAnimation animation]; + springAnimation.mass = 1.0; + springAnimation.stiffness = 100.0; + springAnimation.damping = 10.0; + springAnimation.keyPath = @"position"; + springAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)]; + springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; + [viewControllerMock setupKeyboardSpringAnimationIfNeeded:springAnimation]; + keyboardSpringAnimation = [viewControllerMock keyboardSpringAnimation]; + XCTAssertTrue(keyboardSpringAnimation != nil); +} + +- (void)testKeyboardAnimationIsShowingAndCompounding { + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + FlutterViewController* viewControllerMock = OCMPartialMock(viewController); + CGRect viewFrame = UIScreen.mainScreen.bounds; + [self setupMockMainScreenAndView:viewControllerMock viewFrame:viewFrame convertedFrame:viewFrame]; + + BOOL isLocal = YES; + CGFloat screenHeight = UIScreen.mainScreen.bounds.size.height; + CGFloat screenWidth = UIScreen.mainScreen.bounds.size.height; + + // Start show keyboard animation. + CGRect initialShowKeyboardBeginFrame = CGRectMake(0, screenHeight, screenWidth, 250); + CGRect initialShowKeyboardEndFrame = CGRectMake(0, screenHeight - 250, screenWidth, 500); + NSNotification* fakeNotification = [NSNotification + notificationWithName:UIKeyboardWillChangeFrameNotification + object:nil + userInfo:@{ + @"UIKeyboardFrameBeginUserInfoKey" : @(initialShowKeyboardBeginFrame), + @"UIKeyboardFrameEndUserInfoKey" : @(initialShowKeyboardEndFrame), + @"UIKeyboardAnimationDurationUserInfoKey" : @(0.25), + @"UIKeyboardIsLocalUserInfoKey" : @(isLocal) + }]; + viewControllerMock.targetViewInsetBottom = 0; + [viewControllerMock handleKeyboardNotification:fakeNotification]; + BOOL isShowingAnimation1 = viewControllerMock.keyboardAnimationIsShowing; + XCTAssertTrue(isShowingAnimation1); + + // Start compounding show keyboard animation. + CGRect compoundingShowKeyboardBeginFrame = CGRectMake(0, screenHeight - 250, screenWidth, 250); + CGRect compoundingShowKeyboardEndFrame = CGRectMake(0, screenHeight - 500, screenWidth, 500); + fakeNotification = [NSNotification + notificationWithName:UIKeyboardWillChangeFrameNotification + object:nil + userInfo:@{ + @"UIKeyboardFrameBeginUserInfoKey" : @(compoundingShowKeyboardBeginFrame), + @"UIKeyboardFrameEndUserInfoKey" : @(compoundingShowKeyboardEndFrame), + @"UIKeyboardAnimationDurationUserInfoKey" : @(0.25), + @"UIKeyboardIsLocalUserInfoKey" : @(isLocal) + }]; + + [viewControllerMock handleKeyboardNotification:fakeNotification]; + BOOL isShowingAnimation2 = viewControllerMock.keyboardAnimationIsShowing; + XCTAssertTrue(isShowingAnimation2); + XCTAssertTrue(isShowingAnimation1 == isShowingAnimation2); + + // Start hide keyboard animation. + CGRect initialHideKeyboardBeginFrame = CGRectMake(0, screenHeight - 500, screenWidth, 250); + CGRect initialHideKeyboardEndFrame = CGRectMake(0, screenHeight - 250, screenWidth, 500); + fakeNotification = [NSNotification + notificationWithName:UIKeyboardWillChangeFrameNotification + object:nil + userInfo:@{ + @"UIKeyboardFrameBeginUserInfoKey" : @(initialHideKeyboardBeginFrame), + @"UIKeyboardFrameEndUserInfoKey" : @(initialHideKeyboardEndFrame), + @"UIKeyboardAnimationDurationUserInfoKey" : @(0.25), + @"UIKeyboardIsLocalUserInfoKey" : @(isLocal) + }]; + + [viewControllerMock handleKeyboardNotification:fakeNotification]; + BOOL isShowingAnimation3 = viewControllerMock.keyboardAnimationIsShowing; + XCTAssertFalse(isShowingAnimation3); + XCTAssertTrue(isShowingAnimation2 != isShowingAnimation3); + + // Start compounding hide keyboard animation. + CGRect compoundingHideKeyboardBeginFrame = CGRectMake(0, screenHeight - 250, screenWidth, 250); + CGRect compoundingHideKeyboardEndFrame = CGRectMake(0, screenHeight, screenWidth, 500); + fakeNotification = [NSNotification + notificationWithName:UIKeyboardWillChangeFrameNotification + object:nil + userInfo:@{ + @"UIKeyboardFrameBeginUserInfoKey" : @(compoundingHideKeyboardBeginFrame), + @"UIKeyboardFrameEndUserInfoKey" : @(compoundingHideKeyboardEndFrame), + @"UIKeyboardAnimationDurationUserInfoKey" : @(0.25), + @"UIKeyboardIsLocalUserInfoKey" : @(isLocal) + }]; + + [viewControllerMock handleKeyboardNotification:fakeNotification]; + BOOL isShowingAnimation4 = viewControllerMock.keyboardAnimationIsShowing; + XCTAssertFalse(isShowingAnimation4); + XCTAssertTrue(isShowingAnimation3 == isShowingAnimation4); +} + - (void)testShouldIgnoreKeyboardNotification { FlutterEngine* mockEngine = OCMPartialMock([[FlutterEngine alloc] init]); [mockEngine createShell:@"" libraryURI:@"" initialRoute:nil]; @@ -197,7 +356,8 @@ - (void)testShouldIgnoreKeyboardNotification { nibName:nil bundle:nil]; FlutterViewController* viewControllerMock = OCMPartialMock(viewController); - OCMStub([viewControllerMock mainScreenIfViewLoaded]).andReturn(UIScreen.mainScreen); + CGRect viewFrame = UIScreen.mainScreen.bounds; + [self setupMockMainScreenAndView:viewControllerMock viewFrame:viewFrame convertedFrame:viewFrame]; CGFloat screenWidth = UIScreen.mainScreen.bounds.size.width; CGFloat screenHeight = UIScreen.mainScreen.bounds.size.height; @@ -215,6 +375,7 @@ - (void)testShouldIgnoreKeyboardNotification { @"UIKeyboardAnimationDurationUserInfoKey" : @0.25, @"UIKeyboardIsLocalUserInfoKey" : @(isLocal) }]; + BOOL shouldIgnore = [viewControllerMock shouldIgnoreKeyboardNotification:notification]; XCTAssertTrue(shouldIgnore == NO); @@ -297,12 +458,12 @@ - (void)testCalculateKeyboardAttachMode { bundle:nil]; FlutterViewController* viewControllerMock = OCMPartialMock(viewController); + CGRect viewFrame = UIScreen.mainScreen.bounds; + [self setupMockMainScreenAndView:viewControllerMock viewFrame:viewFrame convertedFrame:viewFrame]; CGFloat screenWidth = UIScreen.mainScreen.bounds.size.width; CGFloat screenHeight = UIScreen.mainScreen.bounds.size.height; - OCMStub([viewControllerMock mainScreenIfViewLoaded]).andReturn(UIScreen.mainScreen); - // hide notification CGRect keyboardFrame = CGRectZero; NSNotification* notification = @@ -421,7 +582,6 @@ - (void)testCalculateMultitaskingAdjustment { nibName:nil bundle:nil]; FlutterViewController* viewControllerMock = OCMPartialMock(viewController); - OCMStub([viewControllerMock mainScreenIfViewLoaded]).andReturn(UIScreen.mainScreen); CGFloat screenWidth = UIScreen.mainScreen.bounds.size.width; CGFloat screenHeight = UIScreen.mainScreen.bounds.size.height; @@ -429,17 +589,14 @@ - (void)testCalculateMultitaskingAdjustment { CGRect viewOrigFrame = CGRectMake(0, 0, 320, screenHeight - 40); CGRect convertedViewFrame = CGRectMake(20, 20, 320, screenHeight - 40); CGRect keyboardFrame = CGRectMake(20, screenHeight - 320, screenWidth, 300); - - id mockView = OCMClassMock([UIView class]); - OCMStub([mockView frame]).andReturn(viewOrigFrame); - OCMStub([mockView convertRect:viewOrigFrame toCoordinateSpace:[OCMArg any]]) - .andReturn(convertedViewFrame); + id mockView = [self setupMockMainScreenAndView:viewControllerMock + viewFrame:viewOrigFrame + convertedFrame:convertedViewFrame]; id mockTraitCollection = OCMClassMock([UITraitCollection class]); OCMStub([mockTraitCollection userInterfaceIdiom]).andReturn(UIUserInterfaceIdiomPad); OCMStub([mockTraitCollection horizontalSizeClass]).andReturn(UIUserInterfaceSizeClassCompact); OCMStub([mockTraitCollection verticalSizeClass]).andReturn(UIUserInterfaceSizeClassRegular); OCMStub([mockView traitCollection]).andReturn(mockTraitCollection); - OCMStub([viewControllerMock viewIfLoaded]).andReturn(mockView); CGFloat adjustment = [viewControllerMock calculateMultitaskingAdjustment:screenRect keyboardFrame:keyboardFrame]; @@ -461,11 +618,9 @@ - (void)testCalculateKeyboardInset { CGRect convertedViewFrame = CGRectMake(20, 20, 320, screenHeight - 40); CGRect keyboardFrame = CGRectMake(20, screenHeight - 320, screenWidth, 300); - id mockView = OCMClassMock([UIView class]); - OCMStub([mockView frame]).andReturn(viewOrigFrame); - OCMStub([mockView convertRect:viewOrigFrame toCoordinateSpace:[OCMArg any]]) - .andReturn(convertedViewFrame); - OCMStub([viewControllerMock viewIfLoaded]).andReturn(mockView); + [self setupMockMainScreenAndView:viewControllerMock + viewFrame:viewOrigFrame + convertedFrame:convertedViewFrame]; CGFloat inset = [viewControllerMock calculateKeyboardInset:keyboardFrame keyboardMode:FlutterKeyboardModeDocked]; @@ -493,11 +648,7 @@ - (void)testHandleKeyboardNotification { @"UIKeyboardIsLocalUserInfoKey" : @(isLocal) }]; FlutterViewController* viewControllerMock = OCMPartialMock(viewController); - OCMStub([viewControllerMock mainScreenIfViewLoaded]).andReturn(UIScreen.mainScreen); - id mockView = OCMClassMock([UIView class]); - OCMStub([mockView frame]).andReturn(viewFrame); - OCMStub([mockView convertRect:viewFrame toCoordinateSpace:[OCMArg any]]).andReturn(viewFrame); - OCMStub([viewControllerMock viewIfLoaded]).andReturn(mockView); + [self setupMockMainScreenAndView:viewControllerMock viewFrame:viewFrame convertedFrame:viewFrame]; viewControllerMock.targetViewInsetBottom = 0; XCTestExpectation* expectation = [self expectationWithDescription:@"update viewport"]; OCMStub([mockEngine updateViewportMetrics:flutter::ViewportMetrics()]) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm index c14bee16a6104..d264933b0bf43 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm @@ -49,4 +49,10 @@ - (void)testFlutterViewEnableSemanticsWhenIsAccessibilityElementIsCalled { XCTAssertTrue(delegate.callbackCalled); } +- (void)testFlutterViewBackgroundColorIsNotNil { + FakeDelegate* delegate = [[FakeDelegate alloc] init]; + FlutterView* view = [[FlutterView alloc] initWithDelegate:delegate opaque:NO]; + XCTAssertNotNil(view.backgroundColor); +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.h b/shell/platform/darwin/ios/framework/Source/SemanticsObject.h index ce9347c7c44e9..f7c611dec2ced 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.h +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.h @@ -65,6 +65,12 @@ constexpr float kScrollExtentMaxForInf = 1000; */ @property(nonatomic, strong) NSArray* children; +/** + * Direct children of this semantics object in hit test order. Each child's `parent` property + * must be equal to this object. + */ +@property(nonatomic, strong) NSArray* childrenInHitTestOrder; + /** * The UIAccessibility that represents this object. * diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index ff4ab7dc94704..bee20b558aac1 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -267,6 +267,7 @@ - (void)privateSetParent:(SemanticsObject*)parent; @implementation SemanticsObject { fml::scoped_nsobject _container; NSMutableArray* _children; + NSMutableArray* _childrenInHitTestOrder; BOOL _inDealloc; } @@ -295,6 +296,7 @@ - (instancetype)initWithBridge:(fml::WeakPtr)br _bridge = bridge; _uid = uid; _children = [[NSMutableArray alloc] init]; + _childrenInHitTestOrder = [[NSMutableArray alloc] init]; } return self; @@ -305,7 +307,10 @@ - (void)dealloc { [child privateSetParent:nil]; } [_children removeAllObjects]; + [_childrenInHitTestOrder removeAllObjects]; [_children release]; + [_childrenInHitTestOrder release]; + _parent = nil; _container.get().semanticsObject = nil; _inDealloc = YES; @@ -325,6 +330,17 @@ - (void)setChildren:(NSArray*)children { } } +- (void)setChildrenInHitTestOrder:(NSArray*)childrenInHitTestOrder { + for (SemanticsObject* child in _childrenInHitTestOrder) { + [child privateSetParent:nil]; + } + [_childrenInHitTestOrder release]; + _childrenInHitTestOrder = [[NSMutableArray alloc] initWithArray:childrenInHitTestOrder]; + for (SemanticsObject* child in _childrenInHitTestOrder) { + [child privateSetParent:self]; + } +} + - (BOOL)hasChildren { return [self.children count] != 0; } @@ -460,6 +476,10 @@ - (BOOL)isAccessibilityElement { return false; } + return [self isFocusable]; +} + +- (bool)isFocusable { // If the node is scrollable AND hidden OR // The node has a label, value, or hint OR // The node has non-scrolling related actions. @@ -517,6 +537,38 @@ - (NSString*)accessibilityLabel { return label; } +- (bool)containsPoint:(CGPoint)point { + // The point is in global coordinates, so use the global rect here. + return CGRectContainsPoint([self globalRect], point); +} + +// Finds the first eligiable semantics object in hit test order. +- (SemanticsObject*)search:(CGPoint)point { + // Search children in hit test order. + for (SemanticsObject* child in [self childrenInHitTestOrder]) { + if ([child containsPoint:point]) { + SemanticsObject* childSearchResult = [child search:point]; + if (childSearchResult != nil) { + return childSearchResult; + } + } + } + + // Check if the current semantic object should be returned. + if ([self containsPoint:point] && [self isFocusable]) { + return self.nativeAccessibility; + } + return nil; +} + +// Overrides apple private method to fix https://github.com/flutter/flutter/issues/113377. +// For overlapping UIAccessibilityElements (e.g. a stack) in IOS, the focus goes to the smallest +// object before IOS 16, but to the top-left object in IOS 16. +// Overrides this method to focus the first eligiable semantics object in hit test order. +- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { + return [self search:point]; +} + - (NSAttributedString*)accessibilityAttributedLabel { NSString* label = [self accessibilityLabel]; if (label.length == 0) { diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm index bd9878772ce19..0446b3d96f698 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm @@ -92,6 +92,11 @@ void AccessibilityObjectDidLoseFocus(int32_t id) override {} @interface SemanticsObjectTest : XCTestCase @end +@interface SemanticsObject (Tests) + +- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event; +@end + @implementation SemanticsObjectTest - (void)testCreate { @@ -114,6 +119,132 @@ - (void)testSetChildren { XCTAssertNil(child.parent); } +- (void)testAccessibilityHitTestFocusAtLeaf { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0]; + SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1]; + SemanticsObject* object2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2]; + SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3]; + object0.children = @[ object1 ]; + object0.childrenInHitTestOrder = @[ object1 ]; + object1.children = @[ object2, object3 ]; + object1.childrenInHitTestOrder = @[ object2, object3 ]; + + flutter::SemanticsNode node0; + node0.id = 0; + node0.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node0.label = "0"; + [object0 setSemanticsNode:&node0]; + + flutter::SemanticsNode node1; + node1.id = 1; + node1.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node1.label = "1"; + [object1 setSemanticsNode:&node1]; + + flutter::SemanticsNode node2; + node2.id = 2; + node2.rect = SkRect::MakeXYWH(0, 0, 100, 100); + node2.label = "2"; + [object2 setSemanticsNode:&node2]; + + flutter::SemanticsNode node3; + node3.id = 3; + node3.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node3.label = "3"; + [object3 setSemanticsNode:&node3]; + + CGPoint point = CGPointMake(10, 10); + id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; + + // Focus to object2 because it's the first object in hit test order + XCTAssertEqual(hitTestResult, object2); +} + +- (void)testAccessibilityHitTestNoFocusableItem { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0]; + SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1]; + SemanticsObject* object2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2]; + SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3]; + object0.children = @[ object1 ]; + object0.childrenInHitTestOrder = @[ object1 ]; + object1.children = @[ object2, object3 ]; + object1.childrenInHitTestOrder = @[ object2, object3 ]; + + flutter::SemanticsNode node0; + node0.id = 0; + node0.rect = SkRect::MakeXYWH(0, 0, 200, 200); + [object0 setSemanticsNode:&node0]; + + flutter::SemanticsNode node1; + node1.id = 1; + node1.rect = SkRect::MakeXYWH(0, 0, 200, 200); + [object1 setSemanticsNode:&node1]; + + flutter::SemanticsNode node2; + node2.id = 2; + node2.rect = SkRect::MakeXYWH(0, 0, 100, 100); + [object2 setSemanticsNode:&node2]; + + flutter::SemanticsNode node3; + node3.id = 3; + node3.rect = SkRect::MakeXYWH(0, 0, 200, 200); + [object3 setSemanticsNode:&node3]; + + CGPoint point = CGPointMake(10, 10); + id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; + + XCTAssertNil(hitTestResult); +} + +- (void)testAccessibilityHitTestOutOfRect { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0]; + SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1]; + SemanticsObject* object2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2]; + SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3]; + object0.children = @[ object1 ]; + object0.childrenInHitTestOrder = @[ object1 ]; + object1.children = @[ object2, object3 ]; + object1.childrenInHitTestOrder = @[ object2, object3 ]; + + flutter::SemanticsNode node0; + node0.id = 0; + node0.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node0.label = "0"; + [object0 setSemanticsNode:&node0]; + + flutter::SemanticsNode node1; + node1.id = 1; + node1.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node1.label = "1"; + [object1 setSemanticsNode:&node1]; + + flutter::SemanticsNode node2; + node2.id = 2; + node2.rect = SkRect::MakeXYWH(0, 0, 100, 100); + node2.label = "2"; + [object2 setSemanticsNode:&node2]; + + flutter::SemanticsNode node3; + node3.id = 3; + node3.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node3.label = "3"; + [object3 setSemanticsNode:&node3]; + + CGPoint point = CGPointMake(300, 300); + id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; + + XCTAssertNil(hitTestResult); +} + - (void)testReplaceChildAtIndex { fml::WeakPtrFactory factory( new flutter::MockAccessibilityBridge()); diff --git a/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm b/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm index 15d3f6df652ba..dda84f9ac158e 100644 --- a/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm +++ b/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm @@ -5,6 +5,7 @@ #import #import +#include "flutter/fml/raster_thread_merger.h" #include "flutter/fml/thread.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" @@ -65,11 +66,11 @@ - (void)testSetCorrectVariableRefreshRates { callback:callback] autorelease]; CADisplayLink* link = [vsyncClient getDisplayLink]; if (@available(iOS 15.0, *)) { - XCTAssertEqual(link.preferredFrameRateRange.maximum, maxFrameRate); - XCTAssertEqual(link.preferredFrameRateRange.preferred, maxFrameRate); - XCTAssertEqual(link.preferredFrameRateRange.minimum, maxFrameRate / 2); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1); } else { - XCTAssertEqual(link.preferredFramesPerSecond, maxFrameRate); + XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1); } [vsyncClient release]; } @@ -88,11 +89,11 @@ - (void)testDoNotSetVariableRefreshRatesIfCADisableMinimumFrameDurationOnPhoneIs callback:callback] autorelease]; CADisplayLink* link = [vsyncClient getDisplayLink]; if (@available(iOS 15.0, *)) { - XCTAssertEqual(link.preferredFrameRateRange.maximum, 0); - XCTAssertEqual(link.preferredFrameRateRange.preferred, 0); - XCTAssertEqual(link.preferredFrameRateRange.minimum, 0); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, 0, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, 0, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, 0, 0.1); } else { - XCTAssertEqual(link.preferredFramesPerSecond, 0); + XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 0, 0.1); } [vsyncClient release]; } @@ -107,11 +108,11 @@ - (void)testDoNotSetVariableRefreshRatesIfCADisableMinimumFrameDurationOnPhoneIs callback:callback] autorelease]; CADisplayLink* link = [vsyncClient getDisplayLink]; if (@available(iOS 15.0, *)) { - XCTAssertEqual(link.preferredFrameRateRange.maximum, 0); - XCTAssertEqual(link.preferredFrameRateRange.preferred, 0); - XCTAssertEqual(link.preferredFrameRateRange.minimum, 0); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, 0, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, 0, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, 0, 0.1); } else { - XCTAssertEqual(link.preferredFramesPerSecond, 0); + XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 0, 0.1); } [vsyncClient release]; } @@ -135,4 +136,57 @@ - (void)testAwaitAndPauseWillWorkCorrectly { [vsyncClient release]; } +- (void)testRefreshRateUpdatedTo80WhenThraedsMerge { + auto platform_thread_task_runner = CreateNewThread("Platform"); + auto raster_thread_task_runner = CreateNewThread("Raster"); + auto ui_thread_task_runner = CreateNewThread("UI"); + auto io_thread_task_runner = CreateNewThread("IO"); + auto task_runners = + flutter::TaskRunners("test", platform_thread_task_runner, raster_thread_task_runner, + ui_thread_task_runner, io_thread_task_runner); + + id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; + double maxFrameRate = 120; + [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; + [[[mockDisplayLinkManager stub] andReturnValue:@(YES)] maxRefreshRateEnabledOnIPhone]; + auto vsync_waiter = flutter::VsyncWaiterIOS(task_runners); + + fml::scoped_nsobject vsyncClient = vsync_waiter.GetVsyncClient(); + CADisplayLink* link = [vsyncClient.get() getDisplayLink]; + + if (@available(iOS 15.0, *)) { + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1); + } else { + XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1); + } + + const auto merger = fml::RasterThreadMerger::CreateOrShareThreadMerger( + nullptr, platform_thread_task_runner->GetTaskQueueId(), + raster_thread_task_runner->GetTaskQueueId()); + + merger->MergeWithLease(5); + vsync_waiter.AwaitVSync(); + + if (@available(iOS 15.0, *)) { + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, 80, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, 80, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, 60, 0.1); + } else { + XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, 80, 0.1); + } + + merger->UnMergeNowIfLastOne(); + vsync_waiter.AwaitVSync(); + + if (@available(iOS 15.0, *)) { + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.maximum, maxFrameRate, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.preferred, maxFrameRate, 0.1); + XCTAssertEqualWithAccuracy(link.preferredFrameRateRange.minimum, maxFrameRate / 2, 0.1); + } else { + XCTAssertEqualWithAccuracy(link.preferredFramesPerSecond, maxFrameRate, 0.1); + } +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index 66f903f7f77b3..a54a4442259ea 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -107,7 +107,14 @@ void PostAccessibilityNotification(UIAccessibilityNotifications notification, SemanticsObject* child = GetOrCreateObject(node.childrenInTraversalOrder[i], nodes); [newChildren addObject:child]; } + NSMutableArray* newChildrenInHitTestOrder = + [[[NSMutableArray alloc] initWithCapacity:newChildCount] autorelease]; + for (NSUInteger i = 0; i < newChildCount; ++i) { + SemanticsObject* child = GetOrCreateObject(node.childrenInHitTestOrder[i], nodes); + [newChildrenInHitTestOrder addObject:child]; + } object.children = newChildren; + object.childrenInHitTestOrder = newChildrenInHitTestOrder; if (!node.customAccessibilityActions.empty()) { NSMutableArray* accessibilityCustomActions = [[[NSMutableArray alloc] init] autorelease]; diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index 4a8a3479288d7..9b978150e01ca 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -399,6 +399,7 @@ - (void)testReplacedSemanticsDoesNotCleanupChildren { node.scrollExtentMax = 100.0; node.scrollPosition = 0.0; parent.childrenInTraversalOrder.push_back(1); + parent.childrenInHitTestOrder.push_back(1); flutter::SemanticsNode child; child.id = 2; @@ -407,6 +408,7 @@ - (void)testReplacedSemanticsDoesNotCleanupChildren { child.value = "value"; child.hint = "hint"; node.childrenInTraversalOrder.push_back(2); + node.childrenInHitTestOrder.push_back(2); nodes[0] = parent; nodes[1] = node; @@ -427,6 +429,7 @@ - (void)testReplacedSemanticsDoesNotCleanupChildren { new_node.scrollExtentMax = 100.0; new_node.scrollPosition = 0.0; new_node.childrenInTraversalOrder.push_back(2); + new_node.childrenInHitTestOrder.push_back(2); new_nodes[1] = new_node; bridge->UpdateSemantics(/*nodes=*/new_nodes, /*actions=*/actions); @@ -489,6 +492,7 @@ - (void)testScrollableSemanticsDeallocated { node.scrollExtentMax = 100.0; node.scrollPosition = 0.0; parent.childrenInTraversalOrder.push_back(1); + parent.childrenInHitTestOrder.push_back(1); nodes[0] = parent; nodes[1] = node; flutter::CustomAccessibilityActionUpdates actions; @@ -556,6 +560,7 @@ - (void)testBridgeReplacesSemanticsNode { node.scrollExtentMax = 100.0; node.scrollPosition = 0.0; parent.childrenInTraversalOrder.push_back(1); + parent.childrenInHitTestOrder.push_back(1); nodes[0] = parent; nodes[1] = node; flutter::CustomAccessibilityActionUpdates actions; diff --git a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h index 14beef5401a9f..36a608db7deca 100644 --- a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h +++ b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h @@ -15,6 +15,13 @@ @interface DisplayLinkManager : NSObject +// Whether the max refresh rate on iPhone Pro-motion devices are enabled. +// This reflects the value of `CADisableMinimumFrameDurationOnPhone` in the +// info.plist file. +// +// Note on iPads that support Pro-motion, the max refresh rate is always enabled. +@property(class, nonatomic, readonly) BOOL maxRefreshRateEnabledOnIPhone; + //------------------------------------------------------------------------------ /// @brief The display refresh rate used for reporting purposes. The engine does not care /// about this for frame scheduling. It is only used by tools for instrumentation. The @@ -51,6 +58,8 @@ - (double)getRefreshRate; +- (void)setMaxRefreshRate:(double)refreshRate; + @end namespace flutter { @@ -64,12 +73,17 @@ class VsyncWaiterIOS final : public VsyncWaiter, public VariableRefreshRateRepor // |VariableRefreshRateReporter| double GetRefreshRate() const override; - private: - fml::scoped_nsobject client_; + // Made public for testing. + fml::scoped_nsobject GetVsyncClient() const; // |VsyncWaiter| + // Made public for testing. void AwaitVSync() override; + private: + fml::scoped_nsobject client_; + double max_refresh_rate_; + FML_DISALLOW_COPY_AND_ASSIGN(VsyncWaiterIOS); }; diff --git a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm index 207205f7288d8..5ed238704cc74 100644 --- a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm +++ b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm @@ -12,8 +12,12 @@ #include "flutter/common/task_runners.h" #include "flutter/fml/logging.h" +#include "flutter/fml/memory/task_runner_checker.h" #include "flutter/fml/trace_event.h" +// When calculating refresh rate diffrence, anything within 0.1 fps is ignored. +const static double kRefreshRateDiffToIgnore = 0.1; + namespace flutter { VsyncWaiterIOS::VsyncWaiterIOS(const flutter::TaskRunners& task_runners) @@ -26,6 +30,7 @@ client_ = fml::scoped_nsobject{[[VSyncClient alloc] initWithTaskRunner:task_runners_.GetUITaskRunner() callback:callback]}; + max_refresh_rate_ = [DisplayLinkManager displayRefreshRate]; } VsyncWaiterIOS::~VsyncWaiterIOS() { @@ -35,6 +40,19 @@ } void VsyncWaiterIOS::AwaitVSync() { + double new_max_refresh_rate = [DisplayLinkManager displayRefreshRate]; + if (fml::TaskRunnerChecker::RunsOnTheSameThread( + task_runners_.GetRasterTaskRunner()->GetTaskQueueId(), + task_runners_.GetPlatformTaskRunner()->GetTaskQueueId())) { + // Pressure tested on iPhone 13 pro, the oldest iPhone that supports refresh rate greater than + // 60fps. A flutter app can handle fast scrolling on 80 fps with 6 PlatformViews in the scene at + // the same time. + new_max_refresh_rate = 80; + } + if (fabs(new_max_refresh_rate - max_refresh_rate_) > kRefreshRateDiffToIgnore) { + max_refresh_rate_ = new_max_refresh_rate; + [client_.get() setMaxRefreshRate:max_refresh_rate_]; + } [client_.get() await]; } @@ -43,6 +61,10 @@ return [client_.get() getRefreshRate]; } +fml::scoped_nsobject VsyncWaiterIOS::GetVsyncClient() const { + return client_; +} + } // namespace flutter @implementation VSyncClient { @@ -64,7 +86,7 @@ - (instancetype)initWithTaskRunner:(fml::RefPtr)task_runner }; display_link_.get().paused = YES; - [self setMaxRefreshRateIfEnabled]; + [self setMaxRefreshRate:[DisplayLinkManager displayRefreshRate]]; task_runner->PostTask([client = [self retain]]() { [client->display_link_.get() addToRunLoop:[NSRunLoop currentRunLoop] @@ -76,15 +98,12 @@ - (instancetype)initWithTaskRunner:(fml::RefPtr)task_runner return self; } -- (void)setMaxRefreshRateIfEnabled { - NSNumber* minimumFrameRateDisabled = - [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CADisableMinimumFrameDurationOnPhone"]; - if (![minimumFrameRateDisabled boolValue]) { +- (void)setMaxRefreshRate:(double)refreshRate { + if (!DisplayLinkManager.maxRefreshRateEnabledOnIPhone) { return; } - double maxFrameRate = fmax([DisplayLinkManager displayRefreshRate], 60); + double maxFrameRate = fmax(refreshRate, 60); double minFrameRate = fmax(maxFrameRate / 2, 60); - if (@available(iOS 15.0, *)) { display_link_.get().preferredFrameRateRange = CAFrameRateRangeMake(minFrameRate, maxFrameRate, maxFrameRate); @@ -170,4 +189,9 @@ - (void)onDisplayLink:(CADisplayLink*)link { // no-op. } ++ (BOOL)maxRefreshRateEnabledOnIPhone { + return [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CADisableMinimumFrameDurationOnPhone"] + boolValue]; +} + @end diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index 2d649bd80a6de..e1ed6b69518c0 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -12,6 +12,8 @@ #import "flutter/shell/platform/darwin/ios/ios_context.h" #import "flutter/shell/platform/darwin/ios/ios_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + @class CALayer; namespace flutter { diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index f60f9e95b0e9a..2e87510cc0885 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -11,6 +11,8 @@ #include "flutter/fml/logging.h" #include "flutter/fml/platform/darwin/cf_utils.h" #include "flutter/fml/trace_event.h" + +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/utils/mac/SkCGUtils.h" namespace flutter { diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h b/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h index 891ae28928a1e..7c7bea715893b 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h @@ -23,7 +23,7 @@ * Some single-view APIs will eventually be replaced by their multi-view * variant. During the deprecation period, the single-view APIs will coexist with * and work with the multi-view APIs as if the other views don't exist. For - * backward compatibility, single-view APIs will always operate the view with + * backward compatibility, single-view APIs will always operate on the view with * this ID. Also, the first view assigned to the engine will also have this ID. */ extern const uint64_t kFlutterDefaultViewId; @@ -32,6 +32,9 @@ extern const uint64_t kFlutterDefaultViewId; /** * Coordinates a single instance of execution of a Flutter engine. + * + * A FlutterEngine can only be attached with one controller from the native + * code. */ FLUTTER_DARWIN_EXPORT @interface FlutterEngine : NSObject @@ -76,10 +79,9 @@ FLUTTER_DARWIN_EXPORT - (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint; /** - * The default `FlutterViewController` associated with this engine, if any. + * The `FlutterViewController` of this engine, if any. * - * The default view always has ID kFlutterDefaultViewId, and is the view - * operated by the APIs that do not have a view ID specified. + * This view is used by legacy APIs that assume a single view. * * Setting this field from nil to a non-nil view controller also updates * the view controller's engine and ID. diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h b/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h index c341f2354dcd9..daedcb8773dae 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h @@ -36,12 +36,18 @@ FLUTTER_DARWIN_EXPORT @property(nonnull, readonly) id textures; /** - * The view displaying Flutter content. May return |nil|, for instance in a headless environment. + * The default view displaying Flutter content. * - * WARNING: If/when multiple Flutter views within the same application are supported (#30701), this - * API will change. + * This method may return |nil|, for instance in a headless environment. + * + * The default view is a special view operated by single-view APIs. + */ +- (nullable NSView*)view; + +/** + * The `NSView` associated with the given view ID, if any. */ -@property(nullable, readonly) NSView* view; +- (nullable NSView*)viewForId:(uint64_t)viewId; /** * Registers |delegate| to receive handleMethodCall:result: callbacks for the given |channel|. diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h b/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h index e4d8df7d4c48d..5979131f7451b 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h @@ -89,7 +89,9 @@ FLUTTER_DARWIN_EXPORT NS_DESIGNATED_INITIALIZER; - (nonnull instancetype)initWithCoder:(nonnull NSCoder*)nibNameOrNil NS_DESIGNATED_INITIALIZER; /** - * Initializes this FlutterViewController with the specified `FlutterEngine`. + * Initializes this FlutterViewController with an existing `FlutterEngine`. + * + * The initialized view controller will add itself to the engine as part of this process. * * This initializer is suitable for both the first Flutter view controller and * the following ones of the app. diff --git a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm index d493da6461719..0100e0b2074e7 100644 --- a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm +++ b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm @@ -32,17 +32,15 @@ void DispatchMacOSNotification(gfx::NativeViewAccessible native_node, } // namespace } // namespace flutter::testing -@interface AccessibilityBridgeTestEngine : FlutterEngine -- (std::shared_ptr) - createAccessibilityBridge:(nonnull FlutterEngine*)engine - viewController:(nonnull FlutterViewController*)viewController; +@interface AccessibilityBridgeTestViewController : FlutterViewController +- (std::shared_ptr)createAccessibilityBridgeWithEngine: + (nonnull FlutterEngine*)engine; @end -@implementation AccessibilityBridgeTestEngine -- (std::shared_ptr) - createAccessibilityBridge:(nonnull FlutterEngine*)engine - viewController:(nonnull FlutterViewController*)viewController { - return std::make_shared(engine, viewController); +@implementation AccessibilityBridgeTestViewController +- (std::shared_ptr)createAccessibilityBridgeWithEngine: + (nonnull FlutterEngine*)engine { + return std::make_shared(engine, self); } @end @@ -56,10 +54,7 @@ @implementation AccessibilityBridgeTestEngine FlutterDartProject* project = [[FlutterDartProject alloc] initWithAssetsPath:fixtures ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; - FlutterEngine* engine = [[AccessibilityBridgeTestEngine alloc] initWithName:@"test" - project:project - allowHeadlessExecution:true]; - return [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + return [[AccessibilityBridgeTestViewController alloc] initWithProject:project]; } } // namespace @@ -76,8 +71,8 @@ @implementation AccessibilityBridgeTestEngine // Setting up bridge so that the AccessibilityBridgeMacDelegateSpy // can query semantics information from. engine.semanticsEnabled = YES; - auto bridge = - std::reinterpret_pointer_cast(engine.accessibilityBridge.lock()); + auto bridge = std::reinterpret_pointer_cast( + viewController.accessibilityBridge.lock()); FlutterSemanticsNode root; root.id = 0; root.flags = static_cast(0); @@ -124,8 +119,8 @@ @implementation AccessibilityBridgeTestEngine // Setting up bridge so that the AccessibilityBridgeMacDelegateSpy // can query semantics information from. engine.semanticsEnabled = YES; - auto bridge = - std::reinterpret_pointer_cast(engine.accessibilityBridge.lock()); + auto bridge = std::reinterpret_pointer_cast( + viewController.accessibilityBridge.lock()); FlutterSemanticsNode root; root.id = 0; root.flags = static_cast(0); @@ -171,8 +166,8 @@ @implementation AccessibilityBridgeTestEngine // Setting up bridge so that the AccessibilityBridgeMacDelegateSpy // can query semantics information from. engine.semanticsEnabled = YES; - auto bridge = - std::reinterpret_pointer_cast(engine.accessibilityBridge.lock()); + auto bridge = std::reinterpret_pointer_cast( + viewController.accessibilityBridge.lock()); FlutterSemanticsNode root; root.id = 0; root.flags = static_cast(0); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm index 74173158d8c59..51b874f47dfbd 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositor.mm @@ -19,7 +19,7 @@ // TODO(dkwingsmt): This class only supports single-view for now. As more // classes are gradually converted to multi-view, it should get the view ID // from somewhere. - FlutterView* view = [view_provider_ getView:kFlutterDefaultViewId]; + FlutterView* view = [view_provider_ viewForId:kFlutterDefaultViewId]; if (!view) { return false; } @@ -37,7 +37,7 @@ bool FlutterCompositor::Present(uint64_t view_id, const FlutterLayer** layers, size_t layers_count) { - FlutterView* view = [view_provider_ getView:view_id]; + FlutterView* view = [view_provider_ viewForId:view_id]; if (!view) { return false; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterCompositorTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterCompositorTest.mm index bd6bf4d57b58b..4005b176aaf24 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterCompositorTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterCompositorTest.mm @@ -11,6 +11,8 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h" #import "flutter/testing/testing.h" +extern const uint64_t kFlutterDefaultViewId; + @interface FlutterViewMockProvider : NSObject { FlutterView* _defaultView; } @@ -30,7 +32,7 @@ - (nonnull instancetype)initWithDefaultView:(nonnull FlutterView*)view { return self; } -- (nullable FlutterView*)getView:(uint64_t)viewId { +- (nullable FlutterView*)viewForId:(uint64_t)viewId { if (viewId == kFlutterDefaultViewId) { return _defaultView; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm index 07a9836f414c7..481b2aab9997c 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm @@ -84,6 +84,29 @@ @interface FlutterEngine () - (nullable FlutterViewController*)viewControllerForId:(uint64_t)viewId; +/** + * An internal method that adds the view controller with the given ID. + * + * This method assigns the controller with the ID, puts the controller into the + * map, and does assertions related to the default view ID. + */ +- (void)registerViewController:(FlutterViewController*)controller forId:(uint64_t)viewId; + +/** + * An internal method that removes the view controller with the given ID. + * + * This method clears the ID of the controller, removes the controller from the + * map. This is an no-op if the view ID is not associated with any view + * controllers. + */ +- (void)deregisterViewControllerForId:(uint64_t)viewId; + +/** + * Shuts down the engine if view requirement is not met, and headless execution + * is not allowed. + */ +- (void)shutDownIfNeeded; + /** * Sends the list of user-preferred locales to the Flutter engine. */ @@ -161,10 +184,18 @@ - (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine } - (NSView*)view { - if (!_flutterEngine.viewController.viewLoaded) { - [_flutterEngine.viewController loadView]; + return [self viewForId:kFlutterDefaultViewId]; +} + +- (NSView*)viewForId:(uint64_t)viewId { + FlutterViewController* controller = [_flutterEngine viewControllerForId:viewId]; + if (controller == nil) { + return nil; } - return _flutterEngine.viewController.flutterView; + if (!controller.viewLoaded) { + [controller loadView]; + } + return controller.flutterView; } - (void)addMethodCallDelegate:(nonnull id)delegate @@ -194,9 +225,6 @@ @implementation FlutterEngine { // The embedding-API-level engine object. FLUTTER_API_SYMBOL(FlutterEngine) _engine; - // The private member for accessibility. - std::shared_ptr _bridge; - // The project being run by this engine. FlutterDartProject* _project; @@ -217,6 +245,11 @@ @implementation FlutterEngine { // when the engine is destroyed. std::unique_ptr _macOSCompositor; + // The information of all views attached to this engine mapped from IDs. + // + // It can't use NSDictionary, because the values need to be weak references. + NSMapTable* _viewControllers; + // FlutterCompositor is copied and used in embedder.cc. FlutterCompositor _compositor; @@ -233,6 +266,8 @@ @implementation FlutterEngine { // A method channel for miscellaneous platform functionality. FlutterMethodChannel* _platformChannel; + + int _nextViewId; } - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project { @@ -252,10 +287,14 @@ - (instancetype)initWithName:(NSString*)labelPrefix _semanticsEnabled = NO; _isResponseValid = [[NSMutableArray alloc] initWithCapacity:1]; [_isResponseValid addObject:@YES]; + // kFlutterDefaultViewId is reserved for the default view. + // All IDs above it are for regular views. + _nextViewId = kFlutterDefaultViewId + 1; _embedderAPI.struct_size = sizeof(FlutterEngineProcTable); FlutterEngineGetProcAddresses(&_embedderAPI); + _viewControllers = [NSMapTable weakToWeakObjectsMapTable]; _renderer = [[FlutterRenderer alloc] initWithFlutterEngine:self]; NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; @@ -287,7 +326,7 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { return NO; } - if (!_allowHeadlessExecution && !_viewController) { + if (!_allowHeadlessExecution && [_viewControllers count] == 0) { NSLog(@"Attempted to run an engine with no view controller without headless mode enabled."); return NO; } @@ -314,8 +353,11 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage; flutterArguments.update_semantics_callback = [](const FlutterSemanticsUpdate* update, void* user_data) { + // TODO(dkwingsmt): This callback only supports single-view, therefore it + // only operates on the default view. To support multi-view, we need a + // way to pass in the ID (probably through FlutterSemanticsUpdate). FlutterEngine* engine = (__bridge FlutterEngine*)user_data; - [engine updateSemantics:update]; + [[engine viewControllerForId:kFlutterDefaultViewId] updateSemantics:update]; }; flutterArguments.custom_dart_entrypoint = entrypoint.UTF8String; flutterArguments.shutdown_dart_vm_when_done = true; @@ -377,7 +419,14 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint { } [self sendUserLocales]; - [self updateWindowMetrics]; + + // Update window metric for all view controllers. + NSEnumerator* viewControllerEnumerator = [_viewControllers objectEnumerator]; + FlutterViewController* nextViewController; + while ((nextViewController = [viewControllerEnumerator nextObject])) { + [self updateWindowMetricsForViewController:nextViewController]; + } + [self updateDisplayConfig]; // Send the initial user settings such as brightness and text scale factor // to the engine. @@ -411,28 +460,59 @@ - (void)loadAOTData:(NSString*)assetsDir { } } +- (void)registerViewController:(FlutterViewController*)controller forId:(uint64_t)viewId { + NSAssert(controller != nil, @"The controller must not be nil."); + NSAssert(![controller attached], + @"The incoming view controller is already attached to an engine."); + NSAssert([_viewControllers objectForKey:@(viewId)] == nil, @"The requested view ID is occupied."); + [controller attachToEngine:self withId:viewId]; + NSAssert(controller.id == viewId, @"Failed to assign view ID."); + [_viewControllers setObject:controller forKey:@(viewId)]; +} + +- (void)deregisterViewControllerForId:(uint64_t)viewId { + FlutterViewController* oldController = [self viewControllerForId:viewId]; + if (oldController != nil) { + [oldController detachFromEngine]; + [_viewControllers removeObjectForKey:@(viewId)]; + } +} + +- (void)shutDownIfNeeded { + if ([_viewControllers count] == 0 && !_allowHeadlessExecution) { + [self shutDownEngine]; + } +} + +- (FlutterViewController*)viewControllerForId:(uint64_t)viewId { + FlutterViewController* controller = [_viewControllers objectForKey:@(viewId)]; + NSAssert(controller == nil || controller.id == viewId, + @"The stored controller has unexpected view ID."); + return controller; +} + - (void)setViewController:(FlutterViewController*)controller { - if (_viewController == controller) { + FlutterViewController* currentController = + [_viewControllers objectForKey:@(kFlutterDefaultViewId)]; + if (currentController == controller) { // From nil to nil, or from non-nil to the same controller. return; } - if (_viewController == nil && controller != nil) { + if (currentController == nil && controller != nil) { // From nil to non-nil. NSAssert(controller.engine == nil, @"Failed to set view controller to the engine: " @"The given FlutterViewController is already attached to an engine %@. " @"If you wanted to create an FlutterViewController and set it to an existing engine, " - @"you should create it with init(engine:, nibName, bundle:) instead.", + @"you should use FlutterViewController#init(engine:, nibName, bundle:) instead.", controller.engine); - _viewController = controller; - [_viewController attachToEngine:self withId:kFlutterDefaultViewId]; - } else if (_viewController != nil && controller == nil) { + [self registerViewController:controller forId:kFlutterDefaultViewId]; + } else if (currentController != nil && controller == nil) { + NSAssert(currentController.id == kFlutterDefaultViewId, + @"The default controller has an unexpected ID %llu", currentController.id); // From non-nil to nil. - [_viewController detachFromEngine]; - _viewController = nil; - if (!_allowHeadlessExecution) { - [self shutDownEngine]; - } + [self deregisterViewControllerForId:kFlutterDefaultViewId]; + [self shutDownIfNeeded]; } else { // From non-nil to a different non-nil view controller. NSAssert(NO, @@ -440,10 +520,14 @@ - (void)setViewController:(FlutterViewController*)controller { @"The engine already has a default view controller %@. " @"If you wanted to make the default view render in a different window, " @"you should attach the current view controller to the window instead.", - _viewController); + [_viewControllers objectForKey:@(kFlutterDefaultViewId)]); } } +- (FlutterViewController*)viewController { + return [self viewControllerForId:kFlutterDefaultViewId]; +} + - (FlutterCompositor*)createFlutterCompositor { _macOSCompositor = std::make_unique( [[FlutterViewEngineProvider alloc] initWithEngine:self], _platformViewController); @@ -488,6 +572,17 @@ - (FlutterCompositor*)createFlutterCompositor { #pragma mark - Framework-internal methods +- (void)addViewController:(FlutterViewController*)controller { + [self registerViewController:controller forId:kFlutterDefaultViewId]; +} + +- (void)removeViewController:(nonnull FlutterViewController*)viewController { + NSAssert([viewController attached] && viewController.engine == self, + @"The given view controller is not associated with this engine."); + [self deregisterViewControllerForId:viewController.id]; + [self shutDownIfNeeded]; +} + - (BOOL)running { return _engine != nullptr; } @@ -543,19 +638,23 @@ - (void)sendInitialSettings { return _embedderAPI; } -- (std::weak_ptr)accessibilityBridge { - return _bridge; -} - - (nonnull NSString*)executableName { return [[[NSProcessInfo processInfo] arguments] firstObject] ?: @"Flutter"; } -- (void)updateWindowMetrics { - if (!_engine || !self.viewController.viewLoaded) { +- (void)updateWindowMetricsForViewController:(FlutterViewController*)viewController { + if (viewController.id != kFlutterDefaultViewId) { + // TODO(dkwingsmt): The embedder API only supports single-view for now. As + // embedder APIs are converted to multi-view, this method should support any + // views. + return; + } + if (!_engine || !viewController || !viewController.viewLoaded) { return; } - NSView* view = self.viewController.flutterView; + NSAssert([self viewControllerForId:viewController.id] == viewController, + @"The provided view controller is not attached to this engine."); + NSView* view = viewController.flutterView; CGRect scaledBounds = [view convertRectToBacking:view.bounds]; CGSize scaledSize = scaledBounds.size; double pixelRatio = view.bounds.size.width == 0 ? 1 : scaledSize.width / view.bounds.size.width; @@ -586,22 +685,15 @@ - (void)setSemanticsEnabled:(BOOL)enabled { return; } _semanticsEnabled = enabled; - // Remove the accessibility children from flutter view before reseting the bridge. - if (!_semanticsEnabled && self.viewController.viewLoaded) { - self.viewController.flutterView.accessibilityChildren = nil; - } - if (!_semanticsEnabled && _bridge) { - _bridge.reset(); - } else if (_semanticsEnabled && !_bridge) { - _bridge = [self createAccessibilityBridge:self viewController:self.viewController]; + + // Update all view controllers' bridges. + NSEnumerator* viewControllerEnumerator = [_viewControllers objectEnumerator]; + FlutterViewController* nextViewController; + while ((nextViewController = [viewControllerEnumerator nextObject])) { + [nextViewController notifySemanticsEnabledChanged]; } - _embedderAPI.UpdateSemanticsEnabled(_engine, _semanticsEnabled); -} -- (std::shared_ptr) - createAccessibilityBridge:(nonnull FlutterEngine*)engine - viewController:(nonnull FlutterViewController*)viewController { - return std::make_shared(engine, _viewController); + _embedderAPI.UpdateSemanticsEnabled(_engine, _semanticsEnabled); } - (void)dispatchSemanticsAction:(FlutterSemanticsAction)action @@ -616,17 +708,6 @@ - (FlutterPlatformViewController*)platformViewController { #pragma mark - Private methods -- (FlutterViewController*)viewControllerForId:(uint64_t)viewId { - // TODO(dkwingsmt): The engine only supports single-view, therefore it - // only processes the default ID. After the engine supports multiple views, - // this method should be able to return the view for any IDs. - NSAssert(viewId == kFlutterDefaultViewId, @"Unexpected view ID %llu", viewId); - if (viewId == kFlutterDefaultViewId) { - return _viewController; - } - return nil; -} - - (void)sendUserLocales { if (!self.running) { return; @@ -690,8 +771,10 @@ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message { } - (void)engineCallbackOnPreEngineRestart { - if (_viewController) { - [_viewController onPreEngineRestart]; + NSEnumerator* viewControllerEnumerator = [_viewControllers objectEnumerator]; + FlutterViewController* nextViewController; + while ((nextViewController = [viewControllerEnumerator nextObject])) { + [nextViewController onPreEngineRestart]; } } @@ -703,7 +786,11 @@ - (void)shutDownEngine { return; } - [self.viewController.flutterView shutdown]; + NSEnumerator* viewControllerEnumerator = [_viewControllers objectEnumerator]; + FlutterViewController* nextViewController; + while ((nextViewController = [viewControllerEnumerator nextObject])) { + [nextViewController.flutterView shutdown]; + } FlutterEngineResult result = _embedderAPI.Deinitialize(_engine); if (result != kSuccess) { @@ -768,7 +855,12 @@ - (void)applicationWillTerminate:(NSNotification*)notification { - (void)onAccessibilityStatusChanged:(NSNotification*)notification { BOOL enabled = [notification.userInfo[kEnhancedUserInterfaceKey] boolValue]; - [self.viewController onAccessibilityStatusChanged:enabled]; + NSEnumerator* viewControllerEnumerator = [_viewControllers objectEnumerator]; + FlutterViewController* nextViewController; + while ((nextViewController = [viewControllerEnumerator nextObject])) { + [nextViewController onAccessibilityStatusChanged:enabled]; + } + self.semanticsEnabled = enabled; } @@ -939,36 +1031,6 @@ - (BOOL)unregisterTextureWithID:(int64_t)textureID { return _embedderAPI.UnregisterExternalTexture(_engine, textureID) == kSuccess; } -- (void)updateSemantics:(const FlutterSemanticsUpdate*)update { - NSAssert(_bridge, @"The accessibility bridge must be initialized."); - for (size_t i = 0; i < update->nodes_count; i++) { - const FlutterSemanticsNode* node = &update->nodes[i]; - _bridge->AddFlutterSemanticsNodeUpdate(node); - } - - for (size_t i = 0; i < update->custom_actions_count; i++) { - const FlutterSemanticsCustomAction* action = &update->custom_actions[i]; - _bridge->AddFlutterSemanticsCustomActionUpdate(action); - } - - _bridge->CommitUpdates(); - - // Accessibility tree can only be used when the view is loaded. - if (!self.viewController.viewLoaded) { - return; - } - // Attaches the accessibility root to the flutter view. - auto root = _bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); - if (root) { - if ([self.viewController.flutterView.accessibilityChildren count] == 0) { - NSAccessibilityElement* native_root = root->GetNativeViewAccessible(); - self.viewController.flutterView.accessibilityChildren = @[ native_root ]; - } - } else { - self.viewController.flutterView.accessibilityChildren = nil; - } -} - #pragma mark - Task runner integration - (void)runTaskOnEmbedder:(FlutterTask)task { diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm index bf8da30fe1df8..d3b2be0406001 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm @@ -348,6 +348,31 @@ - (nonnull NSView*)createWithViewIdentifier:(int64_t)viewId arguments:(nullable EXPECT_EQ(engine.viewController, nil); } +TEST_F(FlutterEngineTest, ProducesAccessibilityTreeWhenAddingViews) { + FlutterEngine* engine = GetFlutterEngine(); + EXPECT_TRUE([engine runWithEntrypoint:@"main"]); + + // Enable the semantics without attaching a view controller. + bool enabled_called = false; + engine.embedderAPI.UpdateSemanticsEnabled = + MOCK_ENGINE_PROC(UpdateSemanticsEnabled, ([&enabled_called](auto engine, bool enabled) { + enabled_called = enabled; + return kSuccess; + })); + engine.semanticsEnabled = YES; + EXPECT_TRUE(enabled_called); + + EXPECT_EQ(engine.viewController, nil); + + // Assign the view controller after enabling semantics + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + engine.viewController = viewController; + + EXPECT_NE(viewController.accessibilityBridge.lock(), nullptr); +} + TEST_F(FlutterEngineTest, NativeCallbacks) { fml::AutoResetWaitableEvent latch; bool latch_called = false; @@ -589,6 +614,69 @@ - (nonnull NSView*)createWithViewIdentifier:(int64_t)viewId arguments:(nullable rasterThread.join(); } +TEST_F(FlutterEngineTest, ManageControllersIfInitiatedByController) { + NSString* fixtures = @(flutter::testing::GetFixturesPath()); + FlutterDartProject* project = [[FlutterDartProject alloc] + initWithAssetsPath:fixtures + ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; + + FlutterEngine* engine; + FlutterViewController* viewController1; + + @autoreleasepool { + // Create FVC1. + viewController1 = [[FlutterViewController alloc] initWithProject:project]; + EXPECT_EQ(viewController1.id, 0ull); + + engine = viewController1.engine; + engine.viewController = nil; + + // Create FVC2 based on the same engine. + FlutterViewController* viewController2 = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + EXPECT_EQ(engine.viewController, viewController2); + } + // FVC2 is deallocated but FVC1 is retained. + + EXPECT_EQ(engine.viewController, nil); + + engine.viewController = viewController1; + EXPECT_EQ(engine.viewController, viewController1); + EXPECT_EQ(viewController1.id, 0ull); +} + +TEST_F(FlutterEngineTest, ManageControllersIfInitiatedByEngine) { + // Don't create the engine with `CreateMockFlutterEngine`, because it adds + // additional references to FlutterViewControllers, which is crucial to this + // test case. + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"io.flutter" + project:nil + allowHeadlessExecution:NO]; + FlutterViewController* viewController1; + + @autoreleasepool { + viewController1 = [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + EXPECT_EQ(viewController1.id, 0ull); + EXPECT_EQ(engine.viewController, viewController1); + + engine.viewController = nil; + + FlutterViewController* viewController2 = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + EXPECT_EQ(viewController2.id, 0ull); + EXPECT_EQ(engine.viewController, viewController2); + } + // FVC2 is deallocated but FVC1 is retained. + + EXPECT_EQ(engine.viewController, nil); + + engine.viewController = viewController1; + EXPECT_EQ(engine.viewController, viewController1); + EXPECT_EQ(viewController1.id, 0ull); +} + } // namespace flutter::testing // NOLINTEND(clang-analyzer-core.StackAddressEscape) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h b/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h index 3181e24077e45..1879cb92dbdab 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h @@ -31,8 +31,6 @@ */ @property(nonatomic) FlutterEngineProcTable& embedderAPI; -@property(nonatomic, readonly) std::weak_ptr accessibilityBridge; - /** * True if the semantics is enabled. The Flutter framework starts sending * semantics update through the embedder as soon as it is set to YES. @@ -50,9 +48,39 @@ @property(nonatomic, readonly, nonnull) NSPasteboard* pasteboard; /** - * Informs the engine that the associated view controller's view size has changed. + * Attach a view controller to the engine as its default controller. + * + * Practically, since FlutterEngine can only be attached with one controller, + * the given controller, if successfully attached, will always have the default + * view ID kFlutterDefaultViewId. + * + * The engine holds a weak reference to the attached view controller. + * + * If the given view controller is already attached to an engine, this call + * throws an assertion. + */ +- (void)addViewController:(nonnull FlutterViewController*)viewController; + +/** + * Dissociate the given view controller from this engine. + * + * Practically, since FlutterEngine can only be attached with one controller, + * the given controller must be the default view controller. + * + * If the view controller is not associated with this engine, this call throws an + * assertion. */ -- (void)updateWindowMetrics; +- (void)removeViewController:(nonnull FlutterViewController*)viewController; + +/** + * The `FlutterViewController` associated with the given view ID, if any. + */ +- (nullable FlutterViewController*)viewControllerForId:(uint64_t)viewId; + +/** + * Informs the engine that the specified view controller's window metrics have changed. + */ +- (void)updateWindowMetricsForViewController:(nonnull FlutterViewController*)viewController; /** * Dispatches the given pointer event data to engine. @@ -94,14 +122,3 @@ withData:(fml::MallocMapping)data; @end - -@interface FlutterEngine (TestMethods) -/* Creates an accessibility bridge with the provided parameters. - * - * By default this method calls AccessibilityBridgeMac's initializer. Exposing - * this method allows unit tests to override in order to capture information. - */ -- (std::shared_ptr) - createAccessibilityBridge:(nonnull FlutterEngine*)engine - viewController:(nonnull FlutterViewController*)viewController; -@end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.mm b/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.mm index 78c18dd0b08e0..ad50476a47675 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterKeyboardManager.mm @@ -57,7 +57,7 @@ @interface FlutterKeyboardManager () /** * The text input plugin set by initialization. */ -@property(nonatomic) id viewDelegate; +@property(nonatomic, weak) id viewDelegate; /** * The primary responders added by addPrimaryResponder. diff --git a/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm index 84372964f9501..276d620da47c6 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMacTest.mm @@ -33,7 +33,7 @@ FlutterViewController* viewController = CreateTestViewController(); FlutterEngine* engine = viewController.engine; engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); // Initialize ax node data. FlutterSemanticsNode root; root.id = 0; @@ -69,7 +69,7 @@ FlutterViewController* viewController = CreateTestViewController(); FlutterEngine* engine = viewController.engine; engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); // Initialize ax node data. FlutterSemanticsNode root; root.id = 0; @@ -111,7 +111,7 @@ FlutterViewController* viewController = CreateTestViewController(); FlutterEngine* engine = viewController.engine; engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); // Initialize ax node data. FlutterSemanticsNode root; root.id = 0; @@ -158,7 +158,7 @@ window.contentView = viewController.view; engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); // Initialize ax node data. FlutterSemanticsNode root; root.id = 0; @@ -233,7 +233,7 @@ window.contentView = viewController.view; engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); // Initialize ax node data. FlutterSemanticsNode root; root.id = 0; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm b/shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm index 007a3cce157a5..d7d2c2fc7d6ac 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm @@ -89,7 +89,7 @@ - (FlutterRendererConfig)createRendererConfig { #pragma mark - Embedder callback implementations. - (FlutterMetalTexture)createTextureForView:(uint64_t)viewId size:(CGSize)size { - FlutterView* view = [_viewProvider getView:viewId]; + FlutterView* view = [_viewProvider viewForId:viewId]; NSAssert(view != nil, @"Can't create texture on a non-existent view 0x%llx.", viewId); if (view == nil) { // FlutterMetalTexture has texture `null`, therefore is discarded. @@ -99,7 +99,7 @@ - (FlutterMetalTexture)createTextureForView:(uint64_t)viewId size:(CGSize)size { } - (BOOL)present:(uint64_t)viewId texture:(const FlutterMetalTexture*)texture { - FlutterView* view = [_viewProvider getView:viewId]; + FlutterView* view = [_viewProvider viewForId:viewId]; if (view == nil) { return NO; } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterRendererTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterRendererTest.mm index 01146e1464c02..46da658efd8e6 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterRendererTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterRendererTest.mm @@ -9,37 +9,54 @@ #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" #include "flutter/testing/testing.h" +@interface RendererTestViewController : FlutterViewController +- (void)loadMockFlutterView:(FlutterView*)mockView; +@end + +@implementation RendererTestViewController { + FlutterView* _mockFlutterView; +} + +- (void)loadMockFlutterView:(FlutterView*)mockView { + _mockFlutterView = mockView; + [self loadView]; +} + +- (nonnull FlutterView*)createFlutterViewWithMTLDevice:(id)device + commandQueue:(id)commandQueue { + return _mockFlutterView; +} +@end + namespace flutter::testing { namespace { // Returns an engine configured for the test fixture resource configuration. -FlutterEngine* CreateTestEngine() { +RendererTestViewController* CreateTestViewController() { NSString* fixtures = @(testing::GetFixturesPath()); FlutterDartProject* project = [[FlutterDartProject alloc] initWithAssetsPath:fixtures ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; - return [[FlutterEngine alloc] initWithName:@"test" project:project allowHeadlessExecution:true]; -} - -void SetEngineDefaultView(FlutterEngine* engine, id flutterView) { - id mockFlutterViewController = OCMClassMock([FlutterViewController class]); - OCMStub([mockFlutterViewController flutterView]).andReturn(flutterView); - [engine setViewController:mockFlutterViewController]; + RendererTestViewController* viewController = + [[RendererTestViewController alloc] initWithProject:project]; + return viewController; } } // namespace TEST(FlutterRenderer, PresentDelegatesToFlutterView) { - FlutterEngine* engine = CreateTestEngine(); - FlutterRenderer* renderer = [[FlutterRenderer alloc] initWithFlutterEngine:engine]; + RendererTestViewController* viewController = CreateTestViewController(); + FlutterEngine* engine = viewController.engine; id viewMock = OCMClassMock([FlutterView class]); - SetEngineDefaultView(engine, viewMock); + [viewController loadMockFlutterView:viewMock]; + FlutterRenderer* renderer = [[FlutterRenderer alloc] initWithFlutterEngine:engine]; id surfaceManagerMock = OCMClassMock([FlutterSurfaceManager class]); OCMStub([viewMock surfaceManager]).andReturn(surfaceManagerMock); @@ -61,11 +78,12 @@ void SetEngineDefaultView(FlutterEngine* engine, id flutterView) { } TEST(FlutterRenderer, TextureReturnedByFlutterView) { - FlutterEngine* engine = CreateTestEngine(); - FlutterRenderer* renderer = [[FlutterRenderer alloc] initWithFlutterEngine:engine]; + RendererTestViewController* viewController = CreateTestViewController(); + FlutterEngine* engine = viewController.engine; id viewMock = OCMClassMock([FlutterView class]); - SetEngineDefaultView(engine, viewMock); + [viewController loadMockFlutterView:viewMock]; + FlutterRenderer* renderer = [[FlutterRenderer alloc] initWithFlutterEngine:engine]; id surfaceManagerMock = OCMClassMock([FlutterSurfaceManager class]); OCMStub([viewMock surfaceManager]).andReturn(surfaceManagerMock); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm index e4d97b5b7d30d..09b7f7a7c232f 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm @@ -20,6 +20,7 @@ static NSString* const kTextInputChannel = @"flutter/textinput"; +#pragma mark - Textinput channel method names // See https://api.flutter.dev/flutter/services/SystemChannels/textInput-constant.html static NSString* const kSetClientMethod = @"TextInput.setClient"; static NSString* const kShowMethod = @"TextInput.show"; @@ -35,14 +36,12 @@ static NSString* const kPerformSelectors = @"TextInputClient.performSelectors"; static NSString* const kMultilineInputType = @"TextInputType.multiline"; -static NSString* const kTextAffinityDownstream = @"TextAffinity.downstream"; -static NSString* const kTextAffinityUpstream = @"TextAffinity.upstream"; - +#pragma mark - TextInputConfiguration field names +static NSString* const kSecureTextEntry = @"obscureText"; static NSString* const kTextInputAction = @"inputAction"; static NSString* const kEnableDeltaModel = @"enableDeltaModel"; static NSString* const kTextInputType = @"inputType"; static NSString* const kTextInputTypeName = @"name"; - static NSString* const kSelectionBaseKey = @"selectionBase"; static NSString* const kSelectionExtentKey = @"selectionExtent"; static NSString* const kSelectionAffinityKey = @"selectionAffinity"; @@ -51,6 +50,17 @@ static NSString* const kComposingExtentKey = @"composingExtent"; static NSString* const kTextKey = @"text"; static NSString* const kTransformKey = @"transform"; +static NSString* const kAssociatedAutofillFields = @"fields"; + +// TextInputConfiguration.autofill and sub-field names +static NSString* const kAutofillProperties = @"autofill"; +static NSString* const kAutofillId = @"uniqueIdentifier"; +static NSString* const kAutofillEditingValue = @"editingValue"; +static NSString* const kAutofillHints = @"hints"; + +// TextAffinity types +static NSString* const kTextAffinityDownstream = @"TextAffinity.downstream"; +static NSString* const kTextAffinityUpstream = @"TextAffinity.upstream"; /** * The affinity of the current cursor position. If the cursor is at a position representing @@ -77,6 +87,54 @@ typedef NS_ENUM(NSUInteger, FlutterTextAffinity) { return flutter::TextRange([base unsignedLongValue], [extent unsignedLongValue]); } +// Returns the autofill hint content type, if specified; otherwise nil. +static NSString* GetAutofillContentType(NSDictionary* autofill) { + NSArray* hints = autofill[kAutofillHints]; + return hints.count > 0 ? hints[0] : nil; +} + +// Returns YES if configuration describes a field for which autocomplete should be enabled for +// the specified TextInputConfiguration. Autocomplete is enabled by default, but will be disabled +// if the field is password-related, or if the configuration contains no autofill settings. +static BOOL EnableAutocompleteForTextInputConfiguration(NSDictionary* configuration) { + // Disable if obscureText is set. + if ([configuration[kSecureTextEntry] boolValue]) { + return NO; + } + + // Disable if autofill properties are not set. + NSDictionary* autofill = configuration[kAutofillProperties]; + if (autofill == nil) { + return NO; + } + + // Disable if autofill properties indicate a username/password. + // See: https://github.com/flutter/flutter/issues/119824 + NSString* contentType = GetAutofillContentType(autofill); + if ([contentType isEqualToString:@"password"] || [contentType isEqualToString:@"username"]) { + return NO; + } + return YES; +} + +// Returns YES if configuration describes a field for which autocomplete should be enabled. +// Autocomplete is enabled by default, but will be disabled if the field is password-related, or if +// the configuration contains no autofill settings. +// +// In the case where the current field is part of an AutofillGroup, the configuration will have +// a fields attribute with a list of TextInputConfigurations, one for each field. In the case where +// any field in the group disables autocomplete, we disable it for all. +static BOOL EnableAutocomplete(NSDictionary* configuration) { + for (NSDictionary* field in configuration[kAssociatedAutofillFields]) { + if (!EnableAutocompleteForTextInputConfiguration(field)) { + return NO; + } + } + + // Check the top-level TextInputConfiguration. + return EnableAutocompleteForTextInputConfiguration(configuration); +} + @interface NSEvent (KeyEquivalentMarker) // Internally marks that the event was received through performKeyEquivalent:. @@ -245,8 +303,9 @@ @implementation FlutterTextInputPlugin { } - (instancetype)initWithViewController:(FlutterViewController*)viewController { - // The view needs a non-zero frame. - self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)]; + // The view needs an empty frame otherwise it is visible on dark background. + // https://github.com/flutter/flutter/issues/118504 + self = [super initWithFrame:NSZeroRect]; if (self != nil) { _flutterViewController = viewController; _channel = [FlutterMethodChannel methodChannelWithName:kTextInputChannel @@ -317,6 +376,8 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { NSDictionary* inputTypeInfo = config[kTextInputType]; _inputType = inputTypeInfo[kTextInputTypeName]; self.textAffinity = kFlutterTextAffinityUpstream; + self.automaticTextCompletionEnabled = EnableAutocomplete(config); + // TODO(cbracken): support text content types https://github.com/flutter/flutter/issues/120252 _activeModel = std::make_unique(); } diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm index 94c095d354d25..3bf1bef6457f9 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputPluginTest.mm @@ -387,6 +387,227 @@ - (bool)testClearClientDuringComposing { return true; } +- (bool)testAutocompleteDisabledWhenAutofillNotSet { + // Set up FlutterTextInputPlugin. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + // Set input client 1. + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + } + ]] + result:^(id){ + }]; + + // Verify autocomplete is disabled. + EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]); + return true; +} + +- (bool)testAutocompleteEnabledWhenAutofillSet { + // Set up FlutterTextInputPlugin. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + // Set input client 1. + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"autofill" : @{ + @"uniqueIdentifier" : @"field1", + @"hints" : @[ @"name" ], + @"editingValue" : @{@"text" : @""}, + } + } + ]] + result:^(id){ + }]; + + // Verify autocomplete is enabled. + EXPECT_TRUE([plugin isAutomaticTextCompletionEnabled]); + return true; +} + +- (bool)testAutocompleteEnabledWhenAutofillSetNoHint { + // Set up FlutterTextInputPlugin. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + // Set input client 1. + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"autofill" : @{ + @"uniqueIdentifier" : @"field1", + @"hints" : @[], + @"editingValue" : @{@"text" : @""}, + } + } + ]] + result:^(id){ + }]; + + // Verify autocomplete is enabled. + EXPECT_TRUE([plugin isAutomaticTextCompletionEnabled]); + return true; +} + +- (bool)testAutocompleteDisabledWhenObscureTextSet { + // Set up FlutterTextInputPlugin. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + // Set input client 1. + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"obscureText" : @YES, + @"autofill" : @{ + @"uniqueIdentifier" : @"field1", + @"hints" : @[ @"name" ], + @"editingValue" : @{@"text" : @""}, + } + } + ]] + result:^(id){ + }]; + + // Verify autocomplete is disabled. + EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]); + return true; +} + +- (bool)testAutocompleteDisabledWhenPasswordAutofillSet { + // Set up FlutterTextInputPlugin. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + // Set input client 1. + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"autofill" : @{ + @"uniqueIdentifier" : @"field1", + @"hints" : @[ @"password" ], + @"editingValue" : @{@"text" : @""}, + } + } + ]] + result:^(id){ + }]; + + // Verify autocomplete is disabled. + EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]); + return true; +} + +- (bool)testAutocompleteDisabledWhenAutofillGroupIncludesPassword { + // Set up FlutterTextInputPlugin. + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + // Set input client 1. + [plugin handleMethodCall:[FlutterMethodCall + methodCallWithMethodName:@"TextInput.setClient" + arguments:@[ + @(1), @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"fields" : @[ + @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"autofill" : @{ + @"uniqueIdentifier" : @"field1", + @"hints" : @[ @"password" ], + @"editingValue" : @{@"text" : @""}, + } + }, + @{ + @"inputAction" : @"action", + @"inputType" : @{@"name" : @"inputName"}, + @"autofill" : @{ + @"uniqueIdentifier" : @"field2", + @"hints" : @[ @"name" ], + @"editingValue" : @{@"text" : @""}, + } + } + ] + } + ]] + result:^(id){ + }]; + + // Verify autocomplete is disabled. + EXPECT_FALSE([plugin isAutomaticTextCompletionEnabled]); + return true; +} + - (bool)testFirstRectForCharacterRange { id engineMock = flutter::testing::CreateMockFlutterEngine(@""); id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); @@ -1354,6 +1575,31 @@ - (bool)testSelectorsAreForwardedToFramework { ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testClearClientDuringComposing]); } +TEST(FlutterTextInputPluginTest, TestAutocompleteDisabledWhenAutofillNotSet) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testAutocompleteDisabledWhenAutofillNotSet]); +} + +TEST(FlutterTextInputPluginTest, TestAutocompleteEnabledWhenAutofillSet) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testAutocompleteEnabledWhenAutofillSet]); +} + +TEST(FlutterTextInputPluginTest, TestAutocompleteEnabledWhenAutofillSetNoHint) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testAutocompleteEnabledWhenAutofillSetNoHint]); +} + +TEST(FlutterTextInputPluginTest, TestAutocompleteDisabledWhenObscureTextSet) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testAutocompleteDisabledWhenObscureTextSet]); +} + +TEST(FlutterTextInputPluginTest, TestAutocompleteDisabledWhenPasswordAutofillSet) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testAutocompleteDisabledWhenPasswordAutofillSet]); +} + +TEST(FlutterTextInputPluginTest, TestAutocompleteDisabledWhenAutofillGroupIncludesPassword) { + ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] + testAutocompleteDisabledWhenAutofillGroupIncludesPassword]); +} + TEST(FlutterTextInputPluginTest, TestFirstRectForCharacterRange) { ASSERT_TRUE([[FlutterInputPluginTestObjc alloc] testFirstRectForCharacterRange]); } @@ -1414,14 +1660,14 @@ - (bool)testSelectorsAreForwardedToFramework { engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); FlutterPlatformNodeDelegateMac delegate(bridge, viewController); ui::AXTree tree; ui::AXNode ax_node(&tree, nullptr, 0, 0); ui::AXNodeData node_data; node_data.SetValue("initial text"); ax_node.SetData(node_data); - delegate.Init(engine.accessibilityBridge, &ax_node); + delegate.Init(viewController.accessibilityBridge, &ax_node); { FlutterTextPlatformNode text_platform_node(&delegate, viewController); @@ -1480,14 +1726,14 @@ - (bool)testSelectorsAreForwardedToFramework { engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); FlutterPlatformNodeDelegateMac delegate(bridge, viewController); ui::AXTree tree; ui::AXNode ax_node(&tree, nullptr, 0, 0); ui::AXNodeData node_data; node_data.SetValue("initial text"); ax_node.SetData(node_data); - delegate.Init(engine.accessibilityBridge, &ax_node); + delegate.Init(viewController.accessibilityBridge, &ax_node); FlutterTextPlatformNode text_platform_node(&delegate, viewController); FlutterTextField* textField = text_platform_node.GetNativeViewAccessible(); @@ -1532,4 +1778,21 @@ - (bool)testSelectorsAreForwardedToFramework { ASSERT_FALSE(window.firstResponder == viewController.textInputPlugin); } +TEST(FlutterTextInputPluginTest, HasZeroSize) { + id engineMock = flutter::testing::CreateMockFlutterEngine(@""); + id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger)); + OCMStub( // NOLINT(google-objc-avoid-throwing-exception) + [engineMock binaryMessenger]) + .andReturn(binaryMessengerMock); + + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + + FlutterTextInputPlugin* plugin = + [[FlutterTextInputPlugin alloc] initWithViewController:viewController]; + + ASSERT_TRUE(NSIsEmptyRect(plugin.frame)); +} + } // namespace flutter::testing diff --git a/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObjectTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObjectTest.mm index 4e4b821a6115d..4555e435d710c 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObjectTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObjectTest.mm @@ -41,14 +41,14 @@ engine.semanticsEnabled = YES; - auto bridge = engine.accessibilityBridge.lock(); + auto bridge = viewController.accessibilityBridge.lock(); FlutterPlatformNodeDelegateMac delegate(bridge, viewController); ui::AXTree tree; ui::AXNode ax_node(&tree, nullptr, 0, 0); ui::AXNodeData node_data; node_data.SetValue("initial text"); ax_node.SetData(node_data); - delegate.Init(engine.accessibilityBridge, &ax_node); + delegate.Init(viewController.accessibilityBridge, &ax_node); // Verify that a FlutterTextField is attached to the view. FlutterTextPlatformNode text_platform_node(&delegate, viewController); id native_accessibility = text_platform_node.GetNativeViewAccessible(); diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index 4d41d066c8fd4..994cc8f468d69 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -287,11 +287,14 @@ @implementation FlutterViewController { // The project to run in this controller's engine. FlutterDartProject* _project; + std::shared_ptr _bridge; + uint64_t _id; } @dynamic id; @dynamic view; +@dynamic accessibilityBridge; /** * Performs initialization that's common between the different init paths. @@ -306,14 +309,16 @@ static void CommonInit(FlutterViewController* controller, FlutterEngine* engine) @"The FlutterViewController is unexpectedly attached to " @"engine %@ before initialization.", controller.engine); - engine.viewController = controller; + [engine addViewController:controller]; NSCAssert(controller.engine != nil, @"The FlutterViewController unexpectedly stays unattached after initialization. " @"In unit tests, this is likely because either the FlutterViewController or " - @"the FlutterEngine is mocked. Please subclass these classes instead."); + @"the FlutterEngine is mocked. Please subclass these classes instead.", + controller.engine, controller.id); controller->_mouseTrackingMode = FlutterMouseTrackingModeInKeyWindow; controller->_textInputPlugin = [[FlutterTextInputPlugin alloc] initWithViewController:controller]; [controller initializeKeyboard]; + [controller notifySemanticsEnabledChanged]; // macOS fires this message when changing IMEs. CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter(); __weak FlutterViewController* weakSelf = controller; @@ -351,11 +356,6 @@ - (instancetype)initWithEngine:(nonnull FlutterEngine*)engine nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle { NSAssert(engine != nil, @"Engine is required"); - NSAssert(engine.viewController == nil, - @"The supplied FlutterEngine is already used with FlutterViewController " - "instance. One instance of the FlutterEngine can only be attached to one " - "FlutterViewController at a time. Set FlutterEngine.viewController " - "to nil before attaching it to another FlutterViewController."); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { @@ -408,7 +408,9 @@ - (void)viewWillDisappear { } - (void)dealloc { - _engine.viewController = nil; + if ([self attached]) { + [_engine removeViewController:self]; + } CFNotificationCenterRef cfCenter = CFNotificationCenterGetDistributedCenter(); CFNotificationCenterRemoveEveryObserver(cfCenter, (__bridge void*)self); } @@ -437,6 +439,26 @@ - (void)onPreEngineRestart { [self initializeKeyboard]; } +- (void)notifySemanticsEnabledChanged { + BOOL mySemanticsEnabled = !!_bridge; + BOOL newSemanticsEnabled = _engine.semanticsEnabled; + if (newSemanticsEnabled == mySemanticsEnabled) { + return; + } + if (newSemanticsEnabled) { + _bridge = [self createAccessibilityBridgeWithEngine:_engine]; + } else { + // Remove the accessibility children from flutter view before resetting the bridge. + _flutterView.accessibilityChildren = nil; + _bridge.reset(); + } + NSAssert(newSemanticsEnabled == !!_bridge, @"Failed to update semantics for the view."); +} + +- (std::weak_ptr)accessibilityBridge { + return _bridge; +} + - (void)attachToEngine:(nonnull FlutterEngine*)engine withId:(uint64_t)viewId { NSAssert(_engine == nil, @"Already attached to an engine %@.", _engine); _engine = engine; @@ -452,6 +474,39 @@ - (BOOL)attached { return _engine != nil; } +- (void)updateSemantics:(const FlutterSemanticsUpdate*)update { + NSAssert(_engine.semanticsEnabled, @"Semantics must be enabled."); + if (!_engine.semanticsEnabled) { + return; + } + for (size_t i = 0; i < update->nodes_count; i++) { + const FlutterSemanticsNode* node = &update->nodes[i]; + _bridge->AddFlutterSemanticsNodeUpdate(node); + } + + for (size_t i = 0; i < update->custom_actions_count; i++) { + const FlutterSemanticsCustomAction* action = &update->custom_actions[i]; + _bridge->AddFlutterSemanticsCustomActionUpdate(action); + } + + _bridge->CommitUpdates(); + + // Accessibility tree can only be used when the view is loaded. + if (!self.viewLoaded) { + return; + } + // Attaches the accessibility root to the flutter view. + auto root = _bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); + if (root) { + if ([self.flutterView.accessibilityChildren count] == 0) { + NSAccessibilityElement* native_root = root->GetNativeViewAccessible(); + self.flutterView.accessibilityChildren = @[ native_root ]; + } + } else { + self.flutterView.accessibilityChildren = nil; + } +} + #pragma mark - Private methods - (BOOL)launchEngine { @@ -526,8 +581,7 @@ - (void)configureTrackingArea { - (void)initializeKeyboard { // TODO(goderbauer): Seperate keyboard/textinput stuff into ViewController specific and Engine // global parts. Move the global parts to FlutterEngine. - __weak FlutterViewController* weakSelf = self; - _keyboardManager = [[FlutterKeyboardManager alloc] initWithViewDelegate:weakSelf]; + _keyboardManager = [[FlutterKeyboardManager alloc] initWithViewDelegate:self]; } - (void)dispatchMouseEvent:(nonnull NSEvent*)event { @@ -713,6 +767,11 @@ - (void)onAccessibilityStatusChanged:(BOOL)enabled { } } +- (std::shared_ptr)createAccessibilityBridgeWithEngine: + (nonnull FlutterEngine*)engine { + return std::make_shared(engine, self); +} + - (nonnull FlutterView*)createFlutterViewWithMTLDevice:(id)device commandQueue:(id)commandQueue { return [[FlutterView alloc] initWithMTLDevice:device @@ -733,7 +792,7 @@ - (void)onKeyboardLayoutChanged { * Responds to view reshape by notifying the engine of the change in dimensions. */ - (void)viewDidReshape:(NSView*)view { - [_engine updateWindowMetrics]; + [_engine updateWindowMetricsForViewController:self]; } #pragma mark - FlutterPluginRegistry diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h b/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h index c60c5354b8d8e..c58602f219667 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h @@ -4,6 +4,8 @@ #import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterViewController.h" +#include + #import "flutter/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMac.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterKeyboardViewDelegate.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.h" @@ -19,6 +21,8 @@ */ @property(nonatomic, readonly, nonnull) FlutterTextInputPlugin* textInputPlugin; +@property(nonatomic, readonly) std::weak_ptr accessibilityBridge; + /** * Returns YES if provided event is being currently redispatched by keyboard manager. */ @@ -38,12 +42,32 @@ */ - (void)detachFromEngine; +/** + * Called by the associated FlutterEngine when FlutterEngine#semanticsEnabled + * has changed. + */ +- (void)notifySemanticsEnabledChanged; + +/** + * Notify from the framework that the semantics for this view needs to be + * updated. + */ +- (void)updateSemantics:(nonnull const FlutterSemanticsUpdate*)update; + @end // Private methods made visible for testing @interface FlutterViewController (TestMethods) - (void)onAccessibilityStatusChanged:(BOOL)enabled; +/* Creates an accessibility bridge with the provided parameters. + * + * By default this method calls AccessibilityBridgeMac's initializer. Exposing + * this method allows unit tests to override. + */ +- (std::shared_ptr)createAccessibilityBridgeWithEngine: + (nonnull FlutterEngine*)engine; + - (nonnull FlutterView*)createFlutterViewWithMTLDevice:(nonnull id)device commandQueue:(nonnull id)commandQueue; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.mm index a063784b5e2c9..95c3aa53e0ee5 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.mm @@ -22,14 +22,8 @@ - (instancetype)initWithEngine:(FlutterEngine*)engine { return self; } -- (nullable FlutterView*)getView:(uint64_t)viewId { - // TODO(dkwingsmt): This class only supports the first view for now. After - // FlutterEngine supports multi-view, it should get the view associated to the - // ID. - if (viewId == kFlutterDefaultViewId) { - return _engine.viewController.flutterView; - } - return nil; +- (nullable FlutterView*)viewForId:(uint64_t)viewId { + return [_engine viewControllerForId:viewId].flutterView; } @end diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProviderTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProviderTest.mm index 6a1aa66b69c59..86c94a70caa60 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProviderTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProviderTest.mm @@ -6,6 +6,7 @@ #import #import +#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.h" @@ -19,23 +20,29 @@ TEST(FlutterViewEngineProviderUnittests, GetViewReturnsTheCorrectView) { FlutterViewEngineProvider* viewProvider; - id mockEngine = OCMClassMock([FlutterEngine class]); + id mockEngine = CreateMockFlutterEngine(@""); __block id mockFlutterViewController; - OCMStub([mockEngine viewController]).andDo(^(NSInvocation* invocation) { - if (mockFlutterViewController != nil) { - [invocation setReturnValue:&mockFlutterViewController]; - } - }); + OCMStub([mockEngine viewControllerForId:0]) + .ignoringNonObjectArgs() + .andDo(^(NSInvocation* invocation) { + uint64_t viewId; + [invocation getArgument:&viewId atIndex:2]; + if (viewId == 0 /* kFlutterDefaultViewId */) { + if (mockFlutterViewController != nil) { + [invocation setReturnValue:&mockFlutterViewController]; + } + } + }); viewProvider = [[FlutterViewEngineProvider alloc] initWithEngine:mockEngine]; // When the view controller is not set, the returned view is nil. - EXPECT_EQ([viewProvider getView:0], nil); + EXPECT_EQ([viewProvider viewForId:0], nil); // When the view controller is set, the returned view is the controller's view. mockFlutterViewController = OCMStrictClassMock([FlutterViewController class]); id mockView = OCMStrictClassMock([FlutterView class]); OCMStub([mockFlutterViewController flutterView]).andReturn(mockView); - EXPECT_EQ([viewProvider getView:0], mockView); + EXPECT_EQ([viewProvider viewForId:0], mockView); } } // namespace flutter::testing diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h b/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h index f873c72266a95..9548b7afab1b8 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewProvider.h @@ -20,6 +20,6 @@ extern const uint64_t kFlutterDefaultViewId; * * Returns nil if the ID is invalid. */ -- (nullable FlutterView*)getView:(uint64_t)id; +- (nullable FlutterView*)viewForId:(uint64_t)id; @end diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 956448c237565..46bd46a7a3f3c 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -19,6 +19,7 @@ #include "flutter/fml/thread.h" #include "third_party/dart/runtime/bin/elf_loader.h" #include "third_party/dart/runtime/include/dart_native_api.h" +#include "third_party/skia/include/core/SkSurface.h" #if !defined(FLUTTER_NO_EXPORT) #if FML_OS_WIN diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index e1a4253becf54..52ca605473542 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -299,8 +299,8 @@ typedef enum { /// /// - all other formats are called packed formats, and the component order /// as specified in the format name refers to the order in the native type. -/// for example, for kRGB565, the R component uses the 5 least significant -/// bits of the uint16_t pixel value. +/// for example, for kFlutterSoftwarePixelFormatRGB565, the R component +/// uses the 5 least significant bits of the uint16_t pixel value. /// /// Each pixel format in this list is documented with an example on how to get /// the color components from the pixel. @@ -316,30 +316,31 @@ typedef enum { /// pixel with 8 bit grayscale value. /// The grayscale value is the luma value calculated from r, g, b /// according to BT.709. (gray = r*0.2126 + g*0.7152 + b*0.0722) - kGray8, + kFlutterSoftwarePixelFormatGray8, /// pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word. /// r = p & 0x3F; g = (p>>5) & 0x3F; b = p>>11; - kRGB565, + kFlutterSoftwarePixelFormatRGB565, /// pixel with 4 bits for alpha, red, green, blue; in 16-bit word. /// r = p & 0xF; g = (p>>4) & 0xF; b = (p>>8) & 0xF; a = p>>12; - kRGBA4444, + kFlutterSoftwarePixelFormatRGBA4444, /// pixel with 8 bits for red, green, blue, alpha. /// r = p[0]; g = p[1]; b = p[2]; a = p[3]; - kRGBA8888, + kFlutterSoftwarePixelFormatRGBA8888, /// pixel with 8 bits for red, green and blue and 8 unused bits. /// r = p[0]; g = p[1]; b = p[2]; - kRGBX8888, + kFlutterSoftwarePixelFormatRGBX8888, /// pixel with 8 bits for blue, green, red and alpha. /// r = p[2]; g = p[1]; b = p[0]; a = p[3]; - kBGRA8888, + kFlutterSoftwarePixelFormatBGRA8888, - /// either kBGRA8888 or kRGBA8888 depending on CPU endianess and OS - kNative32, + /// either kFlutterSoftwarePixelFormatBGRA8888 or + /// kFlutterSoftwarePixelFormatRGBA8888 depending on CPU endianess and OS + kFlutterSoftwarePixelFormatNative32, } FlutterSoftwarePixelFormat; typedef struct { diff --git a/shell/platform/embedder/embedder_render_target.cc b/shell/platform/embedder/embedder_render_target.cc index c9ef521d6302b..5d6d22887c043 100644 --- a/shell/platform/embedder/embedder_render_target.cc +++ b/shell/platform/embedder/embedder_render_target.cc @@ -8,6 +8,8 @@ #include "flutter/fml/logging.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { EmbedderRenderTarget::EmbedderRenderTarget(FlutterBackingStore backing_store, diff --git a/shell/platform/embedder/embedder_surface_metal.h b/shell/platform/embedder/embedder_surface_metal.h index bb4c8579e20e1..d835218103e02 100644 --- a/shell/platform/embedder/embedder_surface_metal.h +++ b/shell/platform/embedder/embedder_surface_metal.h @@ -11,6 +11,8 @@ #include "flutter/shell/platform/embedder/embedder_external_view_embedder.h" #include "flutter/shell/platform/embedder/embedder_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { class EmbedderSurfaceMetal final : public EmbedderSurface, diff --git a/shell/platform/embedder/embedder_surface_software.cc b/shell/platform/embedder/embedder_surface_software.cc index f507e25e66646..1f3735b521951 100644 --- a/shell/platform/embedder/embedder_surface_software.cc +++ b/shell/platform/embedder/embedder_surface_software.cc @@ -7,8 +7,10 @@ #include #include "flutter/fml/trace_event.h" + #include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { diff --git a/shell/platform/embedder/embedder_surface_software.h b/shell/platform/embedder/embedder_surface_software.h index 21c60cfae208e..5d52e63d76528 100644 --- a/shell/platform/embedder/embedder_surface_software.h +++ b/shell/platform/embedder/embedder_surface_software.h @@ -10,6 +10,8 @@ #include "flutter/shell/platform/embedder/embedder_external_view_embedder.h" #include "flutter/shell/platform/embedder/embedder_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { class EmbedderSurfaceSoftware final : public EmbedderSurface, diff --git a/shell/platform/embedder/pixel_formats.cc b/shell/platform/embedder/pixel_formats.cc index a97a9aaceb191..79acbb2e72833 100644 --- a/shell/platform/embedder/pixel_formats.cc +++ b/shell/platform/embedder/pixel_formats.cc @@ -7,19 +7,19 @@ std::optional getSkColorType(FlutterSoftwarePixelFormat pixfmt) { switch (pixfmt) { - case kGray8: + case kFlutterSoftwarePixelFormatGray8: return kGray_8_SkColorType; - case kRGB565: + case kFlutterSoftwarePixelFormatRGB565: return kRGB_565_SkColorType; - case kRGBA4444: + case kFlutterSoftwarePixelFormatRGBA4444: return kARGB_4444_SkColorType; - case kRGBA8888: + case kFlutterSoftwarePixelFormatRGBA8888: return kRGBA_8888_SkColorType; - case kRGBX8888: + case kFlutterSoftwarePixelFormatRGBX8888: return kRGB_888x_SkColorType; - case kBGRA8888: + case kFlutterSoftwarePixelFormatBGRA8888: return kBGRA_8888_SkColorType; - case kNative32: + case kFlutterSoftwarePixelFormatNative32: return kN32_SkColorType; default: FML_LOG(ERROR) << "Invalid software rendering pixel format"; diff --git a/shell/platform/embedder/tests/embedder_assertions.h b/shell/platform/embedder/tests/embedder_assertions.h index 2c267e1392117..9f43aca20bbf9 100644 --- a/shell/platform/embedder/tests/embedder_assertions.h +++ b/shell/platform/embedder/tests/embedder_assertions.h @@ -355,20 +355,20 @@ inline std::string FlutterOpenGLTargetTypeToString( inline std::string FlutterSoftwarePixelFormatToString( FlutterSoftwarePixelFormat pixfmt) { switch (pixfmt) { - case kGray8: - return "kGray8"; - case kRGB565: - return "kRGB565"; - case kRGBA4444: - return "kRGBA4444"; - case kRGBA8888: - return "kRGBA8888"; - case kRGBX8888: - return "kRGBX8888"; - case kBGRA8888: - return "kBGRA8888"; - case kNative32: - return "kNative32"; + case kFlutterSoftwarePixelFormatGray8: + return "kFlutterSoftwarePixelFormatGray8"; + case kFlutterSoftwarePixelFormatRGB565: + return "kFlutterSoftwarePixelFormatRGB565"; + case kFlutterSoftwarePixelFormatRGBA4444: + return "kFlutterSoftwarePixelFormatRGBA4444"; + case kFlutterSoftwarePixelFormatRGBA8888: + return "kFlutterSoftwarePixelFormatRGBA8888"; + case kFlutterSoftwarePixelFormatRGBX8888: + return "kFlutterSoftwarePixelFormatRGBX8888"; + case kFlutterSoftwarePixelFormatBGRA8888: + return "kFlutterSoftwarePixelFormatBGRA8888"; + case kFlutterSoftwarePixelFormatNative32: + return "kFlutterSoftwarePixelFormatNative32"; default: FML_LOG(ERROR) << "Invalid software rendering pixel format"; } diff --git a/shell/platform/embedder/tests/embedder_config_builder.cc b/shell/platform/embedder/tests/embedder_config_builder.cc index 32d5ffa2d1de9..52764b4452ab5 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.cc +++ b/shell/platform/embedder/tests/embedder_config_builder.cc @@ -113,7 +113,7 @@ EmbedderConfigBuilder::EmbedderConfigBuilder( SetSemanticsCallbackHooks(); SetLogMessageCallbackHook(); SetLocalizationCallbackHooks(); - AddCommandLineArgument("--disable-observatory"); + AddCommandLineArgument("--disable-vm-service"); if (preference == InitializationPreference::kSnapshotsInitialize || preference == InitializationPreference::kMultiAOTInitialize) { diff --git a/shell/platform/embedder/tests/embedder_config_builder.h b/shell/platform/embedder/tests/embedder_config_builder.h index 2727c85fdadbd..d3b133c4e402e 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.h +++ b/shell/platform/embedder/tests/embedder_config_builder.h @@ -108,7 +108,8 @@ class EmbedderConfigBuilder { void SetRenderTargetType( EmbedderTestBackingStoreProducer::RenderTargetType type, - FlutterSoftwarePixelFormat software_pixfmt = kNative32); + FlutterSoftwarePixelFormat software_pixfmt = + kFlutterSoftwarePixelFormatNative32); UniqueEngine LaunchEngine() const; diff --git a/shell/platform/embedder/tests/embedder_metal_unittests.mm b/shell/platform/embedder/tests/embedder_metal_unittests.mm index 62b7a43bcc83d..d341cc2d68e09 100644 --- a/shell/platform/embedder/tests/embedder_metal_unittests.mm +++ b/shell/platform/embedder/tests/embedder_metal_unittests.mm @@ -19,6 +19,8 @@ #include "flutter/testing/assertions_skia.h" #include "flutter/testing/testing.h" +#include "third_party/skia/include/core/SkSurface.h" + // CREATE_NATIVE_ENTRY is leaky by design // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape) diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc b/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc index f4357b73b3acd..f2c7175efc501 100644 --- a/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer.cc @@ -36,8 +36,9 @@ EmbedderTestBackingStoreProducer::EmbedderTestBackingStoreProducer( #endif { if (type == RenderTargetType::kSoftwareBuffer && - software_pixfmt_ != kNative32) { - FML_LOG(ERROR) << "Expected pixel format to be the default (kNative32) when" + software_pixfmt_ != kFlutterSoftwarePixelFormatNative32) { + FML_LOG(ERROR) << "Expected pixel format to be the default " + "(kFlutterSoftwarePixelFormatNative32) when" "backing store producer should produce deprecated v1 " "software backing " "stores."; diff --git a/shell/platform/embedder/tests/embedder_test_backingstore_producer.h b/shell/platform/embedder/tests/embedder_test_backingstore_producer.h index aea4b0732d5d6..85c3a53e33acf 100644 --- a/shell/platform/embedder/tests/embedder_test_backingstore_producer.h +++ b/shell/platform/embedder/tests/embedder_test_backingstore_producer.h @@ -9,6 +9,8 @@ #include "flutter/fml/macros.h" #include "flutter/fml/memory/ref_ptr_internal.h" #include "flutter/shell/platform/embedder/embedder.h" + +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" #ifdef SHELL_ENABLE_METAL @@ -38,10 +40,10 @@ class EmbedderTestBackingStoreProducer { kVulkanImage, }; - EmbedderTestBackingStoreProducer( - sk_sp context, - RenderTargetType type, - FlutterSoftwarePixelFormat software_pixfmt = kNative32); + EmbedderTestBackingStoreProducer(sk_sp context, + RenderTargetType type, + FlutterSoftwarePixelFormat software_pixfmt = + kFlutterSoftwarePixelFormatNative32); ~EmbedderTestBackingStoreProducer(); bool Create(const FlutterBackingStoreConfig* config, diff --git a/shell/platform/embedder/tests/embedder_test_context_software.h b/shell/platform/embedder/tests/embedder_test_context_software.h index d4708e91825be..45c9c10ca8e9b 100644 --- a/shell/platform/embedder/tests/embedder_test_context_software.h +++ b/shell/platform/embedder/tests/embedder_test_context_software.h @@ -7,6 +7,8 @@ #include "flutter/shell/platform/embedder/tests/embedder_test_context.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index ebf916f5cd1c2..dd9be015a84e9 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -1635,49 +1635,71 @@ static void expectSoftwareRenderingOutputMatches( matcher); \ } -// Don't test the pixel formats that contain padding (so an X) and the kNative32 -// pixel format here, so we don't add any flakiness. -SW_PIXFMT_TEST_F(RedRGBA565xF800, draw_solid_red, kRGB565, (uint16_t)0xF800); -SW_PIXFMT_TEST_F(RedRGBA4444xF00F, draw_solid_red, kRGBA4444, (uint16_t)0xF00F); +// Don't test the pixel formats that contain padding (so an X) and the +// kFlutterSoftwarePixelFormatNative32 pixel format here, so we don't add any +// flakiness. +SW_PIXFMT_TEST_F(RedRGBA565xF800, + draw_solid_red, + kFlutterSoftwarePixelFormatRGB565, + (uint16_t)0xF800); +SW_PIXFMT_TEST_F(RedRGBA4444xF00F, + draw_solid_red, + kFlutterSoftwarePixelFormatRGBA4444, + (uint16_t)0xF00F); SW_PIXFMT_TEST_F(RedRGBA8888xFFx00x00xFF, draw_solid_red, - kRGBA8888, + kFlutterSoftwarePixelFormatRGBA8888, (std::vector{0xFF, 0x00, 0x00, 0xFF})); SW_PIXFMT_TEST_F(RedBGRA8888x00x00xFFxFF, draw_solid_red, - kBGRA8888, + kFlutterSoftwarePixelFormatBGRA8888, (std::vector{0x00, 0x00, 0xFF, 0xFF})); -SW_PIXFMT_TEST_F(RedGray8x36, draw_solid_red, kGray8, (uint8_t)0x36); +SW_PIXFMT_TEST_F(RedGray8x36, + draw_solid_red, + kFlutterSoftwarePixelFormatGray8, + (uint8_t)0x36); -SW_PIXFMT_TEST_F(GreenRGB565x07E0, draw_solid_green, kRGB565, (uint16_t)0x07E0); +SW_PIXFMT_TEST_F(GreenRGB565x07E0, + draw_solid_green, + kFlutterSoftwarePixelFormatRGB565, + (uint16_t)0x07E0); SW_PIXFMT_TEST_F(GreenRGBA4444x0F0F, draw_solid_green, - kRGBA4444, + kFlutterSoftwarePixelFormatRGBA4444, (uint16_t)0x0F0F); SW_PIXFMT_TEST_F(GreenRGBA8888x00xFFx00xFF, draw_solid_green, - kRGBA8888, + kFlutterSoftwarePixelFormatRGBA8888, (std::vector{0x00, 0xFF, 0x00, 0xFF})); SW_PIXFMT_TEST_F(GreenBGRA8888x00xFFx00xFF, draw_solid_green, - kBGRA8888, + kFlutterSoftwarePixelFormatBGRA8888, (std::vector{0x00, 0xFF, 0x00, 0xFF})); -SW_PIXFMT_TEST_F(GreenGray8xB6, draw_solid_green, kGray8, (uint8_t)0xB6); +SW_PIXFMT_TEST_F(GreenGray8xB6, + draw_solid_green, + kFlutterSoftwarePixelFormatGray8, + (uint8_t)0xB6); -SW_PIXFMT_TEST_F(BlueRGB565x001F, draw_solid_blue, kRGB565, (uint16_t)0x001F); +SW_PIXFMT_TEST_F(BlueRGB565x001F, + draw_solid_blue, + kFlutterSoftwarePixelFormatRGB565, + (uint16_t)0x001F); SW_PIXFMT_TEST_F(BlueRGBA4444x00FF, draw_solid_blue, - kRGBA4444, + kFlutterSoftwarePixelFormatRGBA4444, (uint16_t)0x00FF); SW_PIXFMT_TEST_F(BlueRGBA8888x00x00xFFxFF, draw_solid_blue, - kRGBA8888, + kFlutterSoftwarePixelFormatRGBA8888, (std::vector{0x00, 0x00, 0xFF, 0xFF})); SW_PIXFMT_TEST_F(BlueBGRA8888xFFx00x00xFF, draw_solid_blue, - kBGRA8888, + kFlutterSoftwarePixelFormatBGRA8888, (std::vector{0xFF, 0x00, 0x00, 0xFF})); -SW_PIXFMT_TEST_F(BlueGray8x12, draw_solid_blue, kGray8, (uint8_t)0x12); +SW_PIXFMT_TEST_F(BlueGray8x12, + draw_solid_blue, + kFlutterSoftwarePixelFormatGray8, + (uint8_t)0x12); //------------------------------------------------------------------------------ // Key Data diff --git a/shell/platform/embedder/tests/embedder_unittests_util.cc b/shell/platform/embedder/tests/embedder_unittests_util.cc index 474091922d931..c5efbd8bc9e2e 100644 --- a/shell/platform/embedder/tests/embedder_unittests_util.cc +++ b/shell/platform/embedder/tests/embedder_unittests_util.cc @@ -10,6 +10,8 @@ #include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h" #include "flutter/shell/platform/embedder/tests/embedder_unittests_util.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { namespace testing { diff --git a/shell/platform/fuchsia/dart_runner/service_isolate.cc b/shell/platform/fuchsia/dart_runner/service_isolate.cc index 6c7ca066c673b..d331e96f44af6 100644 --- a/shell/platform/fuchsia/dart_runner/service_isolate.cc +++ b/shell/platform/fuchsia/dart_runner/service_isolate.cc @@ -209,17 +209,17 @@ Dart_Isolate CreateServiceIsolate( } // namespace dart_runner Dart_Handle GetVMServiceAssetsArchiveCallback() { - dart_utils::MappedResource observatory_tar; + dart_utils::MappedResource vm_service_tar; if (!dart_utils::MappedResource::LoadFromNamespace( - nullptr, "/pkg/data/observatory.tar", observatory_tar)) { + nullptr, "/pkg/data/observatory.tar", vm_service_tar)) { FX_LOG(ERROR, LOG_TAG, "Failed to load Observatory assets"); return nullptr; } // TODO(rmacnak): Should we avoid copying the tar? Or does the service // library not hold onto it anyway? return tonic::DartConverter::ToDart( - reinterpret_cast(observatory_tar.address()), - observatory_tar.size()); + reinterpret_cast(vm_service_tar.address()), + vm_service_tar.size()); } } // namespace dart_runner diff --git a/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_aot_runner/dart-aot-runner-integration-test.cc b/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_aot_runner/dart-aot-runner-integration-test.cc index fff8d443e0315..33ec20c2ae462 100644 --- a/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_aot_runner/dart-aot-runner-integration-test.cc +++ b/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_aot_runner/dart-aot-runner-integration-test.cc @@ -99,9 +99,9 @@ TEST_F(RealmBuilderTest, DartRunnerStartsUp) { // Build the Realm with the provided child and protocols auto realm = realm_builder.Build(dispatcher()); - FML_LOG(INFO) << "Realm built: " << realm.GetChildName(); + FML_LOG(INFO) << "Realm built: " << realm.component().GetChildName(); // Connect to the Dart echo server - auto echo = realm.ConnectSync(); + auto echo = realm.component().ConnectSync(); fidl::StringPtr response; // Attempt to ping the Dart echo server for a response echo->EchoString("hello", &response); diff --git a/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_jit_runner/dart-jit-runner-integration-test.cc b/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_jit_runner/dart-jit-runner-integration-test.cc index 0c24533459e11..ea32bb40f441b 100644 --- a/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_jit_runner/dart-jit-runner-integration-test.cc +++ b/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_jit_runner/dart-jit-runner-integration-test.cc @@ -97,9 +97,9 @@ TEST_F(RealmBuilderTest, DartRunnerStartsUp) { // Build the Realm with the provided child and protocols auto realm = realm_builder.Build(dispatcher()); - FML_LOG(INFO) << "Realm built: " << realm.GetChildName(); + FML_LOG(INFO) << "Realm built: " << realm.component().GetChildName(); // Connect to the Dart echo server - auto echo = realm.ConnectSync(); + auto echo = realm.component().ConnectSync(); fidl::StringPtr response; // Attempt to ping the Dart echo server for a response echo->EchoString("hello", &response); diff --git a/shell/platform/fuchsia/flutter/component_v1.cc b/shell/platform/fuchsia/flutter/component_v1.cc index a024974c13b84..b869edbdd97d2 100644 --- a/shell/platform/fuchsia/flutter/component_v1.cc +++ b/shell/platform/fuchsia/flutter/component_v1.cc @@ -217,8 +217,7 @@ ComponentV1::ComponentV1( // Clone and check if client is servicing the directory. directory_ptr_->Clone(fuchsia::io::OpenFlags::DESCRIBE | - fuchsia::io::OpenFlags::RIGHT_READABLE | - fuchsia::io::OpenFlags::RIGHT_WRITABLE, + fuchsia::io::OpenFlags::CLONE_SAME_RIGHTS, cloned_directory_ptr_.NewRequest()); cloned_directory_ptr_.events().OnOpen = [this](zx_status_t status, @@ -234,8 +233,11 @@ ComponentV1::ComponentV1( for (auto& dir_str : other_dirs) { fuchsia::io::DirectoryHandle dir; auto request = dir.NewRequest().TakeChannel(); - auto status = fdio_service_connect_at(directory_ptr_.channel().get(), - dir_str, request.release()); + auto status = fdio_open_at( + directory_ptr_.channel().get(), dir_str, + static_cast(fuchsia::io::OpenFlags::DIRECTORY | + fuchsia::io::OpenFlags::RIGHT_READABLE), + request.release()); if (status == ZX_OK) { outgoing_dir_->AddEntry( dir_str, std::make_unique(dir.TakeChannel())); @@ -363,12 +365,12 @@ ComponentV1::ComponentV1( } #if defined(DART_PRODUCT) - settings_.enable_observatory = false; + settings_.enable_vm_service = false; #else - settings_.enable_observatory = true; + settings_.enable_vm_service = true; // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc. - settings_.observatory_host = "127.0.0.1"; + settings_.vm_service_host = "127.0.0.1"; #endif // Controls whether category "skia" trace events are enabled. diff --git a/shell/platform/fuchsia/flutter/component_v2.cc b/shell/platform/fuchsia/flutter/component_v2.cc index 93504818d8915..9893de69e1765 100644 --- a/shell/platform/fuchsia/flutter/component_v2.cc +++ b/shell/platform/fuchsia/flutter/component_v2.cc @@ -267,8 +267,7 @@ ComponentV2::ComponentV2( // Clone and check if client is servicing the directory. directory_ptr_->Clone(fuchsia::io::OpenFlags::DESCRIBE | - fuchsia::io::OpenFlags::RIGHT_READABLE | - fuchsia::io::OpenFlags::RIGHT_WRITABLE, + fuchsia::io::OpenFlags::CLONE_SAME_RIGHTS, cloned_directory_ptr_.NewRequest()); // Collect our standard set of directories along with directories that are @@ -291,8 +290,11 @@ ComponentV2::ComponentV2( for (auto& dir_str : other_dirs) { fuchsia::io::DirectoryHandle dir; auto request = dir.NewRequest().TakeChannel(); - auto status = fdio_service_connect_at(directory_ptr_.channel().get(), - dir_str.c_str(), request.release()); + auto status = fdio_open_at( + directory_ptr_.channel().get(), dir_str.c_str(), + static_cast(fuchsia::io::OpenFlags::DIRECTORY | + fuchsia::io::OpenFlags::RIGHT_READABLE), + request.release()); if (status == ZX_OK) { outgoing_dir_->AddEntry( dir_str.c_str(), @@ -426,12 +428,12 @@ ComponentV2::ComponentV2( } #if defined(DART_PRODUCT) - settings_.enable_observatory = false; + settings_.enable_vm_service = false; #else - settings_.enable_observatory = true; + settings_.enable_vm_service = true; // TODO(cbracken): pass this in as a param to allow 0.0.0.0, ::1, etc. - settings_.observatory_host = "127.0.0.1"; + settings_.vm_service_host = "127.0.0.1"; #endif // Controls whether category "skia" trace events are enabled. diff --git a/shell/platform/fuchsia/flutter/software_surface.cc b/shell/platform/fuchsia/flutter/software_surface.cc index 307b804d55b5e..b2b4d2fa4d533 100644 --- a/shell/platform/fuchsia/flutter/software_surface.cc +++ b/shell/platform/fuchsia/flutter/software_surface.cc @@ -16,8 +16,10 @@ #include "flutter/fml/trace_event.h" #include "fuchsia/sysmem/cpp/fidl.h" #include "include/core/SkImageInfo.h" + #include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/core/SkSurface.h" #include "../runtime/dart/utils/inlines.h" diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc b/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc index 78ffa88c17327..02b8da8c051a2 100644 --- a/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc +++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc @@ -330,11 +330,13 @@ void FlutterEmbedderTest::LaunchParentViewInRealm( // Instruct Test UI Stack to present parent-view's View. std::optional view_ref_koid; - scene_provider_ = realm_->Connect(); + scene_provider_ = + realm_->component().Connect(); scene_provider_.set_error_handler( [](auto) { FML_LOG(ERROR) << "Error from test scene provider"; }); fuchsia::ui::test::scene::ControllerAttachClientViewRequest request; - request.set_view_provider(realm_->Connect()); + request.set_view_provider( + realm_->component().Connect()); scene_provider_->RegisterViewTreeWatcher(view_tree_watcher_.NewRequest(), []() {}); scene_provider_->AttachClientView( @@ -355,7 +357,7 @@ void FlutterEmbedderTest::LaunchParentViewInRealm( }); FML_LOG(INFO) << "Client view has rendered"; - scenic_ = realm_->Connect(); + scenic_ = realm_->component().Connect(); FML_LOG(INFO) << "Launched parent-view"; } diff --git a/shell/platform/fuchsia/flutter/tests/integration/mouse-input/mouse-input-test.cc b/shell/platform/fuchsia/flutter/tests/integration/mouse-input/mouse-input-test.cc index 42d3d2c4c57d3..170bd0c207e2a 100644 --- a/shell/platform/fuchsia/flutter/tests/integration/mouse-input/mouse-input-test.cc +++ b/shell/platform/fuchsia/flutter/tests/integration/mouse-input/mouse-input-test.cc @@ -171,7 +171,7 @@ class MouseInputTest : public PortableUITest, // Get the display dimensions. FML_LOG(INFO) << "Waiting for scenic display info"; - scenic_ = realm_root()->Connect(); + scenic_ = realm_root()->component().Connect(); scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) { display_width_ = display_info.width_in_px; display_height_ = display_info.height_in_px; @@ -300,7 +300,7 @@ INSTANTIATE_TEST_SUITE_P( "fuchsia-pkg://fuchsia.com/flatland-scene-manager-test-ui-stack#meta/" "test-ui-stack.cm")); -TEST_P(MouseInputTest, FlutterMouseMove) { +TEST_P(MouseInputTest, DISABLED_FlutterMouseMove) { LaunchClient(); SimulateMouseEvent(/* pressed_buttons = */ {}, /* movement_x = */ 1, @@ -322,7 +322,7 @@ TEST_P(MouseInputTest, FlutterMouseMove) { /*component_name=*/"mouse-input-view"); } -TEST_P(MouseInputTest, FlutterMouseDown) { +TEST_P(MouseInputTest, DISABLED_FlutterMouseDown) { LaunchClient(); SimulateMouseEvent( @@ -365,7 +365,7 @@ TEST_P(MouseInputTest, FlutterMouseDown) { /*component_name=*/"mouse-input-view"); } -TEST_P(MouseInputTest, FlutterMouseDownUp) { +TEST_P(MouseInputTest, DISABLED_FlutterMouseDownUp) { LaunchClient(); SimulateMouseEvent( @@ -423,7 +423,7 @@ TEST_P(MouseInputTest, FlutterMouseDownUp) { /*component_name=*/"mouse-input-view"); } -TEST_P(MouseInputTest, FlutterMouseDownMoveUp) { +TEST_P(MouseInputTest, DISABLED_FlutterMouseDownMoveUp) { LaunchClient(); SimulateMouseEvent( @@ -552,7 +552,7 @@ TEST_P(MouseInputTest, DISABLED_FlutterMouseWheelIssue103098) { EXPECT_EQ(event_3.wheel_y_physical_pixel(), 0); } -TEST_P(MouseInputTest, FlutterMouseWheel) { +TEST_P(MouseInputTest, DISABLED_FlutterMouseWheel) { LaunchClient(); double initial_x = static_cast(display_width()) / 2.f + 1; diff --git a/shell/platform/fuchsia/flutter/tests/integration/text-input/text-input-test.cc b/shell/platform/fuchsia/flutter/tests/integration/text-input/text-input-test.cc index b0311fda6f94f..d248cc03c7bf8 100644 --- a/shell/platform/fuchsia/flutter/tests/integration/text-input/text-input-test.cc +++ b/shell/platform/fuchsia/flutter/tests/integration/text-input/text-input-test.cc @@ -145,7 +145,7 @@ class TextInputTest : public PortableUITest, // Get the display dimensions. FML_LOG(INFO) << "Waiting for scenic display info"; - scenic_ = realm_root()->template Connect(); + scenic_ = realm_root()->component().Connect(); scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) { display_width_ = display_info.width_in_px; display_height_ = display_info.height_in_px; diff --git a/shell/platform/fuchsia/flutter/tests/integration/touch-input/touch-input-test.cc b/shell/platform/fuchsia/flutter/tests/integration/touch-input/touch-input-test.cc index e872e92229402..5166cca0cbe07 100644 --- a/shell/platform/fuchsia/flutter/tests/integration/touch-input/touch-input-test.cc +++ b/shell/platform/fuchsia/flutter/tests/integration/touch-input/touch-input-test.cc @@ -226,7 +226,7 @@ class FlutterTapTestBase : public PortableUITest, // Get the display dimensions. FML_LOG(INFO) << "Waiting for scenic display info"; - scenic_ = realm_root()->template Connect(); + scenic_ = realm_root()->component().Connect(); scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) { display_width_ = display_info.width_in_px; display_height_ = display_info.height_in_px; @@ -345,7 +345,7 @@ class FlutterEmbedTapTest : public FlutterTapTestBase { // Get the display dimensions. FML_LOG(INFO) << "Waiting for scenic display info"; - scenic_ = realm_root()->template Connect(); + scenic_ = realm_root()->component().Connect(); scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) { display_width_ = display_info.width_in_px; display_height_ = display_info.height_in_px; diff --git a/shell/platform/fuchsia/flutter/tests/integration/utils/portable_ui_test.cc b/shell/platform/fuchsia/flutter/tests/integration/utils/portable_ui_test.cc index aae6eb5934195..7c07590317b27 100644 --- a/shell/platform/fuchsia/flutter/tests/integration/utils/portable_ui_test.cc +++ b/shell/platform/fuchsia/flutter/tests/integration/utils/portable_ui_test.cc @@ -142,14 +142,16 @@ bool PortableUITest::HasViewConnected(zx_koid_t view_ref_koid) { } void PortableUITest::LaunchClient() { - scene_provider_ = realm_->Connect(); + scene_provider_ = + realm_->component().Connect(); scene_provider_.set_error_handler([](auto) { FML_LOG(ERROR) << "Error from test scene provider: " << &zx_status_get_string; }); fuchsia::ui::test::scene::ControllerAttachClientViewRequest request; - request.set_view_provider(realm_->Connect()); + request.set_view_provider( + realm_->component().Connect()); scene_provider_->RegisterViewTreeWatcher(view_tree_watcher_.NewRequest(), []() {}); scene_provider_->AttachClientView( @@ -214,7 +216,8 @@ void PortableUITest::LaunchClientWithEmbeddedView() { void PortableUITest::RegisterTouchScreen() { FML_LOG(INFO) << "Registering fake touch screen"; - input_registry_ = realm_->Connect(); + input_registry_ = + realm_->component().Connect(); input_registry_.set_error_handler([](auto) { FML_LOG(ERROR) << "Error from input helper: " << &zx_status_get_string; }); @@ -232,7 +235,8 @@ void PortableUITest::RegisterTouchScreen() { void PortableUITest::RegisterMouse() { FML_LOG(INFO) << "Registering fake mouse"; - input_registry_ = realm_->Connect(); + input_registry_ = + realm_->component().Connect(); input_registry_.set_error_handler([](auto) { FML_LOG(ERROR) << "Error from input helper: " << &zx_status_get_string; }); @@ -249,7 +253,8 @@ void PortableUITest::RegisterMouse() { void PortableUITest::RegisterKeyboard() { FML_LOG(INFO) << "Registering fake keyboard"; - input_registry_ = realm_->Connect(); + input_registry_ = + realm_->component().Connect(); input_registry_.set_error_handler([](auto) { FML_LOG(ERROR) << "Error from input helper: " << &zx_status_get_string; }); diff --git a/shell/platform/fuchsia/flutter/vulkan_surface_producer.cc b/shell/platform/fuchsia/flutter/vulkan_surface_producer.cc index 55ccbda9c7ca8..00282c068841d 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface_producer.cc +++ b/shell/platform/fuchsia/flutter/vulkan_surface_producer.cc @@ -14,6 +14,8 @@ #include "flutter/fml/trace_event.h" #include "flutter/vulkan/vulkan_skia_proc_table.h" #include "flutter_vma/flutter_skia_vma.h" + +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrBackendSemaphore.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/vk/GrVkBackendContext.h" diff --git a/shell/platform/glfw/flutter_glfw.cc b/shell/platform/glfw/flutter_glfw.cc index 2509067a7ccc9..d50871bd6f14c 100644 --- a/shell/platform/glfw/flutter_glfw.cc +++ b/shell/platform/glfw/flutter_glfw.cc @@ -673,12 +673,12 @@ UniqueAotDataPtr LoadAotData(const std::filesystem::path& aot_data_path) { << std::endl; return nullptr; } + std::string path_string = aot_data_path.string(); if (!std::filesystem::exists(aot_data_path)) { - std::cerr << "Can't load AOT data from " << aot_data_path.string() - << "; no such file." << std::endl; + std::cerr << "Can't load AOT data from " << path_string << "; no such file." + << std::endl; return nullptr; } - std::string path_string = aot_data_path.u8string(); FlutterEngineAOTDataSource source = {}; source.type = kFlutterEngineAOTDataSourceTypeElfPath; source.elf_path = path_string.c_str(); @@ -757,8 +757,8 @@ static bool RunFlutterEngine( } FlutterProjectArgs args = {}; args.struct_size = sizeof(FlutterProjectArgs); - args.assets_path = assets_path.c_str(); - args.icu_data_path = icu_path.c_str(); + args.assets_path = assets_path.string().c_str(); + args.icu_data_path = icu_path.string().c_str(); args.command_line_argc = static_cast(argv.size()); args.command_line_argv = &argv[0]; args.platform_message_callback = EngineOnFlutterPlatformMessage; diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc index 69fea7ccafe6f..5229d4d9f391f 100644 --- a/shell/platform/linux/fl_view.cc +++ b/shell/platform/linux/fl_view.cc @@ -200,8 +200,17 @@ static void handle_geometry_changed(FlView* self) { self->engine, allocation.width * scale_factor, allocation.height * scale_factor, scale_factor); - fl_renderer_wait_for_frame(self->renderer, allocation.width * scale_factor, - allocation.height * scale_factor); + // Make sure the view has been realized and its size has been allocated before + // waiting for a frame. `fl_view_realize()` and `fl_view_size_allocate()` may + // be called in either order depending on the order in which the window is + // shown and the view is added to a container in the app runner. + // + // Note: `gtk_widget_init()` initializes the size allocation to 1x1. + if (allocation.width > 1 && allocation.height > 1 && + gtk_widget_get_realized(GTK_WIDGET(self))) { + fl_renderer_wait_for_frame(self->renderer, allocation.width * scale_factor, + allocation.height * scale_factor); + } } // Adds a widget to render in this view. @@ -661,6 +670,8 @@ static void fl_view_realize(GtkWidget* widget) { g_warning("Failed to start Flutter engine: %s", error->message); return; } + + handle_geometry_changed(self); } // Implements GtkWidget::get-preferred-width diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index 1f7a850b07135..fcd51e7cddf83 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -122,7 +122,10 @@ source_set("flutter_windows_source") { public_configs = [ ":relative_angle_headers" ] - defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ] + defines = [ + "FLUTTER_ENGINE_NO_PROTOTYPES", + "FLUTTER_ENGINE_USE_UIA", + ] public_deps = [ "//flutter/fml:string_conversion", @@ -227,6 +230,8 @@ executable("flutter_windows_unittests") { public_configs = [ "//flutter:config" ] + defines = [ "FLUTTER_ENGINE_USE_UIA" ] + deps = [ ":flutter_windows_fixtures", ":flutter_windows_headers", diff --git a/shell/platform/windows/client_wrapper/BUILD.gn b/shell/platform/windows/client_wrapper/BUILD.gn index 99b9f0c8b2dd8..88d25d75c97be 100644 --- a/shell/platform/windows/client_wrapper/BUILD.gn +++ b/shell/platform/windows/client_wrapper/BUILD.gn @@ -120,24 +120,26 @@ zip_bundle("client_wrapper_archive") { "//flutter/shell/platform/common/client_wrapper:client_wrapper", ] tmp_files = [] - foreach(source, client_wrapper_file_archive_list) { + foreach(source_file, client_wrapper_file_archive_list) { tmp_files += [ { - source = "//flutter/shell/platform/common/client_wrapper/$source" - destination = "cpp_client_wrapper/$source" + source = "//flutter/shell/platform/common/client_wrapper/$source_file" + destination = "cpp_client_wrapper/$source_file" }, ] } # Windows specific source code files - foreach(source, win_client_wrapper_file_archive_list) { + foreach(source_file, win_client_wrapper_file_archive_list) { tmp_files += [ { - source = "//flutter/shell/platform/windows/client_wrapper/$source" - destination = "cpp_client_wrapper/$source" + source = "//flutter/shell/platform/windows/client_wrapper/$source_file" + destination = "cpp_client_wrapper/$source_file" }, ] } + + # Headers headers = core_cpp_client_wrapper_includes + core_cpp_client_wrapper_internal_headers foreach(header, headers) { @@ -150,5 +152,18 @@ zip_bundle("client_wrapper_archive") { }, ] } + + # Wrapper includes + foreach(header, _wrapper_includes) { + rebased_path = + rebase_path("//flutter/shell/platform/windows/client_wrapper/$header", + "//flutter/shell/platform/windows/client_wrapper") + tmp_files += [ + { + source = header + destination = "cpp_client_wrapper/$rebased_path" + }, + ] + } files = tmp_files } diff --git a/shell/platform/windows/flutter_window_unittests.cc b/shell/platform/windows/flutter_window_unittests.cc index 99c612db87671..15b79db02b627 100644 --- a/shell/platform/windows/flutter_window_unittests.cc +++ b/shell/platform/windows/flutter_window_unittests.cc @@ -2,25 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/shell/platform/common/json_message_codec.h" -#include "flutter/shell/platform/embedder/embedder.h" -#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" -#include "flutter/shell/platform/windows/flutter_windows_engine.h" -#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h" -#include "flutter/shell/platform/windows/keyboard_key_handler.h" -#include "flutter/shell/platform/windows/testing/engine_modifier.h" #include "flutter/shell/platform/windows/testing/flutter_window_test.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h" -#include "flutter/shell/platform/windows/testing/test_keyboard.h" -#include "flutter/shell/platform/windows/text_input_plugin.h" -#include "flutter/shell/platform/windows/text_input_plugin_delegate.h" +#include "flutter/shell/platform/windows/testing/wm_builders.h" #include "gmock/gmock.h" #include "gtest/gtest.h" -#include - using testing::_; using testing::Invoke; using testing::Return; @@ -31,74 +20,6 @@ namespace testing { namespace { static constexpr int32_t kDefaultPointerDeviceId = 0; -// A key event handler that can be spied on while it forwards calls to the real -// key event handler. -class SpyKeyboardKeyHandler : public KeyboardHandlerBase { - public: - SpyKeyboardKeyHandler(flutter::BinaryMessenger* messenger) { - real_implementation_ = std::make_unique(); - real_implementation_->AddDelegate( - std::make_unique(messenger)); - ON_CALL(*this, KeyboardHook(_, _, _, _, _, _, _)) - .WillByDefault(Invoke(real_implementation_.get(), - &KeyboardKeyHandler::KeyboardHook)); - ON_CALL(*this, SyncModifiersIfNeeded(_)) - .WillByDefault(Invoke(real_implementation_.get(), - &KeyboardKeyHandler::SyncModifiersIfNeeded)); - } - - MOCK_METHOD7(KeyboardHook, - void(int key, - int scancode, - int action, - char32_t character, - bool extended, - bool was_down, - KeyEventCallback callback)); - - MOCK_METHOD1(SyncModifiersIfNeeded, void(int modifiers_state)); - - private: - std::unique_ptr real_implementation_; -}; - -// A text input plugin that can be spied on while it forwards calls to the real -// text input plugin. -class SpyTextInputPlugin : public TextInputPlugin, - public TextInputPluginDelegate { - public: - SpyTextInputPlugin(flutter::BinaryMessenger* messenger) - : TextInputPlugin(messenger, this) { - real_implementation_ = std::make_unique(messenger, this); - ON_CALL(*this, KeyboardHook(_, _, _, _, _, _)) - .WillByDefault( - Invoke(real_implementation_.get(), &TextInputPlugin::KeyboardHook)); - ON_CALL(*this, TextHook(_)) - .WillByDefault( - Invoke(real_implementation_.get(), &TextInputPlugin::TextHook)); - } - - MOCK_METHOD6(KeyboardHook, - void(int key, - int scancode, - int action, - char32_t character, - bool extended, - bool was_down)); - MOCK_METHOD1(TextHook, void(const std::u16string& text)); - MOCK_METHOD0(ComposeBeginHook, void()); - MOCK_METHOD0(ComposeCommitHook, void()); - MOCK_METHOD0(ComposeEndHook, void()); - MOCK_METHOD2(ComposeChangeHook, - void(const std::u16string& text, int cursor_pos)); - - virtual void OnCursorRectUpdated(const Rect& rect) {} - virtual void OnResetImeComposing() {} - - private: - std::unique_ptr real_implementation_; -}; - class MockFlutterWindow : public FlutterWindow { public: MockFlutterWindow() : FlutterWindow(800, 600) { @@ -154,68 +75,16 @@ class MockFlutterWindow : public FlutterWindow { } }; -// A FlutterWindowsView that overrides the RegisterKeyboardHandlers function -// to register the keyboard hook handlers that can be spied upon. -class TestFlutterWindowsView : public FlutterWindowsView { +class MockFlutterWindowsView : public FlutterWindowsView { public: - TestFlutterWindowsView(std::unique_ptr window_binding) + MockFlutterWindowsView(std::unique_ptr window_binding) : FlutterWindowsView(std::move(window_binding)) {} - ~TestFlutterWindowsView() {} - - SpyKeyboardKeyHandler* key_event_handler; - SpyTextInputPlugin* text_input_plugin; + ~MockFlutterWindowsView() {} MOCK_METHOD2(NotifyWinEventWrapper, void(ui::AXPlatformNodeWin*, ax::mojom::Event)); - - protected: - std::unique_ptr CreateKeyboardKeyHandler( - flutter::BinaryMessenger* messenger, - flutter::KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state, - KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan) - override { - auto spy_key_event_handler = - std::make_unique(messenger); - key_event_handler = spy_key_event_handler.get(); - return spy_key_event_handler; - } - - std::unique_ptr CreateTextInputPlugin( - flutter::BinaryMessenger* messenger) override { - auto spy_key_event_handler = - std::make_unique(messenger); - text_input_plugin = spy_key_event_handler.get(); - return spy_key_event_handler; - } }; -// The static value to return as the "handled" value from the framework for key -// events. Individual tests set this to change the framework response that the -// test engine simulates. -static bool test_response = false; - -// Returns an engine instance configured with dummy project path values, and -// overridden methods for sending platform messages, so that the engine can -// respond as if the framework were connected. -std::unique_ptr GetTestEngine() { - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = L"C:\\foo\\flutter_assets"; - properties.icu_data_path = L"C:\\foo\\icudtl.dat"; - properties.aot_library_path = L"C:\\foo\\aot.so"; - FlutterProjectBundle project(properties); - auto engine = std::make_unique(project); - - EngineModifier modifier(engine.get()); - auto key_response_controller = std::make_shared(); - key_response_controller->SetChannelResponse( - [](MockKeyResponseController::ResponseCallback callback) { - callback(test_response); - }); - MockEmbedderApiForKeyboard(modifier, key_response_controller); - - return engine; -} - } // namespace TEST(FlutterWindowTest, CreateDestroy) { @@ -419,7 +288,7 @@ TEST(FlutterWindowTest, AlertNode) { ON_CALL(*win32window, GetPlatformWindow()).WillByDefault(Return(nullptr)); ON_CALL(*win32window, GetAxFragmentRootDelegate()) .WillByDefault(Return(nullptr)); - TestFlutterWindowsView view(std::move(win32window)); + MockFlutterWindowsView view(std::move(win32window)); std::wstring message = L"Test alert"; EXPECT_CALL(view, NotifyWinEventWrapper(_, ax::mojom::Event::kAlert)) .Times(1); diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 8a9f3f760074c..f0aab9220ea43 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -668,6 +668,7 @@ void FlutterWindowsEngine::UpdateHighContrastEnabled(bool enabled) { ~FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast; } UpdateAccessibilityFeatures(static_cast(flags)); + settings_plugin_->UpdateHighContrastMode(enabled); } int FlutterWindowsEngine::EnabledAccessibilityFeatures() const { diff --git a/shell/platform/windows/flutter_windows_view_unittests.cc b/shell/platform/windows/flutter_windows_view_unittests.cc index 259b82baef983..b356b562d7f34 100644 --- a/shell/platform/windows/flutter_windows_view_unittests.cc +++ b/shell/platform/windows/flutter_windows_view_unittests.cc @@ -116,38 +116,6 @@ TEST(FlutterWindowsViewTest, KeySequence) { key_event_logs.clear(); } -TEST(FlutterWindowsViewTest, RestartClearsKeyboardState) { - std::unique_ptr engine = GetTestEngine(); - - auto window_binding_handler = - std::make_unique<::testing::NiceMock>(); - FlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(std::move(engine)); - - test_response = false; - - // Receives a KeyA down. Events are dispatched and decided unhandled. Now the - // keyboard key handler is waiting for the redispatched event. - view.OnKey(kVirtualKeyA, kScanCodeKeyA, WM_KEYDOWN, 'a', false, false, - [](bool handled) {}); - EXPECT_EQ(key_event_logs.size(), 2); - EXPECT_EQ(key_event_logs[0], kKeyEventFromEmbedder); - EXPECT_EQ(key_event_logs[1], kKeyEventFromChannel); - key_event_logs.clear(); - - // Resets state so that the keyboard key handler is no longer waiting. - view.OnPreEngineRestart(); - - // Receives another KeyA down. If the state had not been cleared, this event - // will be considered the redispatched event and ignored. - view.OnKey(kVirtualKeyA, kScanCodeKeyA, WM_KEYDOWN, 'a', false, false, - [](bool handled) {}); - EXPECT_EQ(key_event_logs.size(), 2); - EXPECT_EQ(key_event_logs[0], kKeyEventFromEmbedder); - EXPECT_EQ(key_event_logs[1], kKeyEventFromChannel); - key_event_logs.clear(); -} - TEST(FlutterWindowsViewTest, EnableSemantics) { std::unique_ptr engine = GetTestEngine(); EngineModifier modifier(engine.get()); @@ -198,10 +166,7 @@ TEST(FlutterWindowsView, AddSemanticsNodeUpdate) { bridge->CommitUpdates(); // Look up the root windows node delegate. - auto node_delegate = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); ASSERT_TRUE(node_delegate); EXPECT_EQ(node_delegate->GetChildCount(), 0); @@ -317,10 +282,7 @@ TEST(FlutterWindowsView, AddSemanticsNodeUpdateWithChildren) { bridge->CommitUpdates(); // Look up the root windows node delegate. - auto node_delegate = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); ASSERT_TRUE(node_delegate); EXPECT_EQ(node_delegate->GetChildCount(), 2); @@ -666,10 +628,7 @@ TEST(FlutterWindowsViewTest, CheckboxNativeState) { bridge->CommitUpdates(); { - auto root_node = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kCheckBox); EXPECT_EQ(root_node->GetData().GetCheckedState(), ax::mojom::CheckedState::kTrue); @@ -707,10 +666,7 @@ TEST(FlutterWindowsViewTest, CheckboxNativeState) { bridge->CommitUpdates(); { - auto root_node = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kCheckBox); EXPECT_EQ(root_node->GetData().GetCheckedState(), ax::mojom::CheckedState::kFalse); @@ -749,10 +705,7 @@ TEST(FlutterWindowsViewTest, CheckboxNativeState) { bridge->CommitUpdates(); { - auto root_node = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kCheckBox); EXPECT_EQ(root_node->GetData().GetCheckedState(), ax::mojom::CheckedState::kMixed); @@ -821,10 +774,7 @@ TEST(FlutterWindowsViewTest, SwitchNativeState) { bridge->CommitUpdates(); { - auto root_node = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kToggleButton); EXPECT_EQ(root_node->GetData().GetCheckedState(), ax::mojom::CheckedState::kTrue); @@ -872,10 +822,7 @@ TEST(FlutterWindowsViewTest, SwitchNativeState) { bridge->CommitUpdates(); { - auto root_node = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kToggleButton); EXPECT_EQ(root_node->GetData().GetCheckedState(), ax::mojom::CheckedState::kFalse); @@ -942,18 +889,13 @@ TEST(FlutterWindowsViewTest, TooltipNodeData) { bridge->AddFlutterSemanticsNodeUpdate(&root); bridge->CommitUpdates(); - auto root_node = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) - .lock(); + auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); std::string tooltip = root_node->GetData().GetStringAttribute( ax::mojom::StringAttribute::kTooltip); EXPECT_EQ(tooltip, "tooltip"); // Check that MSAA name contains the tooltip. - IAccessible* native_view = bridge - ->GetFlutterPlatformNodeDelegateFromID( - AccessibilityBridge::kRootNodeId) + IAccessible* native_view = bridge->GetFlutterPlatformNodeDelegateFromID(0) .lock() ->GetNativeViewAccessible(); VARIANT varchild = {.vt = VT_I4, .lVal = CHILDID_SELF}; diff --git a/shell/platform/windows/keyboard_unittests.cc b/shell/platform/windows/keyboard_unittests.cc index 30aeb3192a766..62f7b21bb8d45 100644 --- a/shell/platform/windows/keyboard_unittests.cc +++ b/shell/platform/windows/keyboard_unittests.cc @@ -13,8 +13,10 @@ #include "flutter/shell/platform/windows/keyboard_key_handler.h" #include "flutter/shell/platform/windows/keyboard_manager.h" #include "flutter/shell/platform/windows/testing/engine_modifier.h" +#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/test_keyboard.h" +#include "flutter/shell/platform/windows/testing/windows_test.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -414,7 +416,7 @@ class KeyboardTester { using ResponseHandler = std::function; - explicit KeyboardTester() + explicit KeyboardTester(WindowsTestContext& context) : callback_handler_(RespondValue(false)), map_virtual_key_layout_(LayoutDefault) { view_ = std::make_unique( @@ -434,9 +436,9 @@ class KeyboardTester { virtual_key, extended ? MAPVK_VK_TO_VSC_EX : MAPVK_VK_TO_VSC); }); view_->SetEngine(GetTestEngine( - [&callback_handler = callback_handler_]( - const FlutterKeyEvent* event, - MockKeyResponseController::ResponseCallback callback) { + context, [&callback_handler = callback_handler_]( + const FlutterKeyEvent* event, + MockKeyResponseController::ResponseCallback callback) { FlutterKeyEvent clone_event = *event; clone_event.character = event->character == nullptr ? nullptr @@ -497,15 +499,12 @@ class KeyboardTester { // Returns an engine instance configured with dummy project path values, and // overridden methods for sending platform messages, so that the engine can // respond as if the framework were connected. - static std::unique_ptr GetTestEngine( + std::unique_ptr GetTestEngine( + WindowsTestContext& context, MockKeyResponseController::EmbedderCallbackHandler embedder_callback_handler) { - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = L"C:\\foo\\flutter_assets"; - properties.icu_data_path = L"C:\\foo\\icudtl.dat"; - properties.aot_library_path = L"C:\\foo\\aot.so"; - FlutterProjectBundle project(properties); - auto engine = std::make_unique(project); + FlutterWindowsEngineBuilder builder{context}; + auto engine = builder.Build(); EngineModifier modifier(engine.get()); @@ -539,6 +538,8 @@ class KeyboardTester { } }; +class KeyboardTest : public WindowsTest {}; + } // namespace // Define compound `expect` in macros. If they're defined in functions, the @@ -556,8 +557,8 @@ class KeyboardTester { EXPECT_EQ(_key_call.type, KeyCall::kKeyCallTextMethodCall); \ EXPECT_STREQ(_key_call.text_method_call.c_str(), json_string); -TEST(KeyboardTest, LowerCaseAHandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, LowerCaseAHandled) { + KeyboardTester tester{GetContext()}; tester.Responding(true); // US Keyboard layout @@ -587,8 +588,8 @@ TEST(KeyboardTest, LowerCaseAHandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -TEST(KeyboardTest, LowerCaseAUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, LowerCaseAUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -619,8 +620,8 @@ TEST(KeyboardTest, LowerCaseAUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, ArrowLeftHandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, ArrowLeftHandled) { + KeyboardTester tester{GetContext()}; tester.Responding(true); // US Keyboard layout @@ -649,8 +650,8 @@ TEST(KeyboardTest, ArrowLeftHandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -TEST(KeyboardTest, ArrowLeftUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, ArrowLeftUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -679,8 +680,8 @@ TEST(KeyboardTest, ArrowLeftUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, ShiftLeftUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, ShiftLeftUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -723,8 +724,8 @@ TEST(KeyboardTest, ShiftLeftUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, ShiftRightUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, ShiftRightUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -756,8 +757,8 @@ TEST(KeyboardTest, ShiftRightUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, CtrlLeftUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, CtrlLeftUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -789,8 +790,8 @@ TEST(KeyboardTest, CtrlLeftUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, CtrlRightUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, CtrlRightUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -822,8 +823,8 @@ TEST(KeyboardTest, CtrlRightUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, AltLeftUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, AltLeftUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -855,8 +856,8 @@ TEST(KeyboardTest, AltLeftUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -TEST(KeyboardTest, AltRightUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, AltRightUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -889,8 +890,8 @@ TEST(KeyboardTest, AltRightUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -TEST(KeyboardTest, MetaLeftUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, MetaLeftUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -920,8 +921,8 @@ TEST(KeyboardTest, MetaLeftUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, MetaRightUnhandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, MetaRightUnhandled) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -952,10 +953,70 @@ TEST(KeyboardTest, MetaRightUnhandled) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } +// Press and hold A. This should generate a repeat event. +TEST_F(KeyboardTest, RepeatA) { + KeyboardTester tester{GetContext()}; + tester.Responding(true); + + // Press A + tester.InjectKeyboardChanges(std::vector{ + WmKeyDownInfo{kVirtualKeyA, kScanCodeKeyA, kNotExtended, kWasUp}.Build( + kWmResultZero), + WmCharInfo{'a', kScanCodeKeyA, kNotExtended, kWasUp}.Build( + kWmResultZero)}); + + // Hold A + tester.InjectKeyboardChanges(std::vector{ + WmKeyDownInfo{kVirtualKeyA, kScanCodeKeyA, kNotExtended, kWasDown}.Build( + kWmResultZero), + WmCharInfo{'a', kScanCodeKeyA, kNotExtended, kWasDown}.Build( + kWmResultZero)}); + + EXPECT_EQ(key_calls.size(), 2); + EXPECT_CALL_IS_EVENT(key_calls[0], kFlutterKeyEventTypeDown, kPhysicalKeyA, + kLogicalKeyA, "a", kNotSynthesized); + EXPECT_CALL_IS_EVENT(key_calls[1], kFlutterKeyEventTypeRepeat, kPhysicalKeyA, + kLogicalKeyA, "a", kNotSynthesized); + EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); +} + +// Press A, hot restart the engine, and hold A. +// This should reset the keyboard's state and generate +// two separate key down events. +TEST_F(KeyboardTest, RestartClearsKeyboardState) { + KeyboardTester tester{GetContext()}; + tester.Responding(true); + + // Press A + tester.InjectKeyboardChanges(std::vector{ + WmKeyDownInfo{kVirtualKeyA, kScanCodeKeyA, kNotExtended, kWasUp}.Build( + kWmResultZero), + WmCharInfo{'a', kScanCodeKeyA, kNotExtended, kWasUp}.Build( + kWmResultZero)}); + + // Send the "hot restart" signal. This should reset the keyboard's state. + tester.GetView().OnPreEngineRestart(); + + // Hold A. Notice the message declares the key is already down, however, the + // the keyboard does not send a repeat event as its state was reset. + tester.InjectKeyboardChanges(std::vector{ + WmKeyDownInfo{kVirtualKeyA, kScanCodeKeyA, kNotExtended, kWasDown}.Build( + kWmResultZero), + WmCharInfo{'a', kScanCodeKeyA, kNotExtended, kWasDown}.Build( + kWmResultZero)}); + + EXPECT_EQ(key_calls.size(), 2); + EXPECT_CALL_IS_EVENT(key_calls[0], kFlutterKeyEventTypeDown, kPhysicalKeyA, + kLogicalKeyA, "a", kNotSynthesized); + EXPECT_CALL_IS_EVENT(key_calls[1], kFlutterKeyEventTypeDown, kPhysicalKeyA, + kLogicalKeyA, "a", kNotSynthesized); + EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); +} + // Press Shift-A. This is special because Win32 gives 'A' as character for the // KeyA press. -TEST(KeyboardTest, ShiftLeftKeyA) { - KeyboardTester tester; +TEST_F(KeyboardTest, ShiftLeftKeyA) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -1013,8 +1074,8 @@ TEST(KeyboardTest, ShiftLeftKeyA) { // Press Ctrl-A. This is special because Win32 gives 0x01 as character for the // KeyA press. -TEST(KeyboardTest, CtrlLeftKeyA) { - KeyboardTester tester; +TEST_F(KeyboardTest, CtrlLeftKeyA) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -1071,8 +1132,8 @@ TEST(KeyboardTest, CtrlLeftKeyA) { } // Press Ctrl-1. This is special because it yields no WM_CHAR for the 1. -TEST(KeyboardTest, CtrlLeftDigit1) { - KeyboardTester tester; +TEST_F(KeyboardTest, CtrlLeftDigit1) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -1128,8 +1189,8 @@ TEST(KeyboardTest, CtrlLeftDigit1) { // Press 1 on a French keyboard. This is special because it yields WM_CHAR // with char_code '&'. -TEST(KeyboardTest, Digit1OnFrenchLayout) { - KeyboardTester tester; +TEST_F(KeyboardTest, Digit1OnFrenchLayout) { + KeyboardTester tester{GetContext()}; tester.Responding(false); tester.SetLayout(LayoutFrench); @@ -1161,8 +1222,8 @@ TEST(KeyboardTest, Digit1OnFrenchLayout) { } // This tests AltGr-Q on a German keyboard, which should print '@'. -TEST(KeyboardTest, AltGrModifiedKey) { - KeyboardTester tester; +TEST_F(KeyboardTest, AltGrModifiedKey) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // German Keyboard layout @@ -1247,8 +1308,8 @@ TEST(KeyboardTest, AltGrModifiedKey) { // // This is because pressing AltGr alone causes Win32 to send a fake "CtrlLeft // down" event first (see |IsKeyDownAltRight| for detailed explanation). -TEST(KeyboardTest, AltGrTwice) { - KeyboardTester tester; +TEST_F(KeyboardTest, AltGrTwice) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // 1. AltGr down. @@ -1348,8 +1409,8 @@ TEST(KeyboardTest, AltGrTwice) { // This tests dead key ^ then E on a French keyboard, which should be combined // into ê. -TEST(KeyboardTest, DeadKeyThatCombines) { - KeyboardTester tester; +TEST_F(KeyboardTest, DeadKeyThatCombines) { + KeyboardTester tester{GetContext()}; tester.Responding(false); tester.SetLayout(LayoutFrench); @@ -1411,8 +1472,8 @@ TEST(KeyboardTest, DeadKeyThatCombines) { // // It is different from French AZERTY because the character that the ^ key is // mapped to does not contain the dead key character somehow. -TEST(KeyboardTest, DeadKeyWithoutDeadMaskThatCombines) { - KeyboardTester tester; +TEST_F(KeyboardTest, DeadKeyWithoutDeadMaskThatCombines) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // Press ShiftLeft @@ -1491,8 +1552,8 @@ TEST(KeyboardTest, DeadKeyWithoutDeadMaskThatCombines) { // This tests dead key ^ then & (US: 1) on a French keyboard, which do not // combine and should output "^&". -TEST(KeyboardTest, DeadKeyThatDoesNotCombine) { - KeyboardTester tester; +TEST_F(KeyboardTest, DeadKeyThatDoesNotCombine) { + KeyboardTester tester{GetContext()}; tester.Responding(false); tester.SetLayout(LayoutFrench); @@ -1560,8 +1621,8 @@ TEST(KeyboardTest, DeadKeyThatDoesNotCombine) { // This tests dead key `, then dead key `, then e. // // It should output ``e, instead of `è. -TEST(KeyboardTest, DeadKeyTwiceThenLetter) { - KeyboardTester tester; +TEST_F(KeyboardTest, DeadKeyTwiceThenLetter) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US INTL layout. @@ -1642,8 +1703,8 @@ TEST(KeyboardTest, DeadKeyTwiceThenLetter) { } // This tests when the resulting character needs to be combined with surrogates. -TEST(KeyboardTest, MultibyteCharacter) { - KeyboardTester tester; +TEST_F(KeyboardTest, MultibyteCharacter) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // Gothic Keyboard layout. (We need a layout that yields non-BMP characters @@ -1679,8 +1740,8 @@ TEST(KeyboardTest, MultibyteCharacter) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 1); } -TEST(KeyboardTest, SynthesizeModifiers) { - KeyboardTester tester; +TEST_F(KeyboardTest, SynthesizeModifiers) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // Two dummy events used to trigger synthesization. @@ -1907,8 +1968,8 @@ TEST(KeyboardTest, SynthesizeModifiers) { // any events. // // Regression test for https://github.com/flutter/flutter/issues/95888 . -TEST(KeyboardTest, ImeExtendedEventsAreIgnored) { - KeyboardTester tester; +TEST_F(KeyboardTest, ImeExtendedEventsAreIgnored) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout. @@ -1935,8 +1996,8 @@ TEST(KeyboardTest, ImeExtendedEventsAreIgnored) { // Regression test for https://github.com/flutter/flutter/issues/104169. These // are real messages recorded when pressing Shift-2 using Microsoft Pinyin IME // on Win 10 Enterprise, which crashed the app before the fix. -TEST(KeyboardTest, UpOnlyImeEventsAreCorrectlyHandled) { - KeyboardTester tester; +TEST_F(KeyboardTest, UpOnlyImeEventsAreCorrectlyHandled) { + KeyboardTester tester{GetContext()}; tester.Responding(true); // US Keyboard layout. @@ -1973,8 +2034,8 @@ TEST(KeyboardTest, UpOnlyImeEventsAreCorrectlyHandled) { // arrive earlier than the framework response, and if the 2nd event has an // identical hash as the one waiting for response, an earlier implementation // will crash upon the response. -TEST(KeyboardTest, SlowFrameworkResponse) { - KeyboardTester tester; +TEST_F(KeyboardTest, SlowFrameworkResponse) { + KeyboardTester tester{GetContext()}; std::vector recorded_callbacks; @@ -2036,9 +2097,8 @@ TEST(KeyboardTest, SlowFrameworkResponse) { // KeyA down, KeyA up, (down event responded with false), KeyA down, KeyA up, // // The code must not take the 2nd real key down events as a redispatched event. -TEST(KeyboardTest, SlowFrameworkResponseForIdenticalEvents) { - KeyboardTester tester; - +TEST_F(KeyboardTest, SlowFrameworkResponseForIdenticalEvents) { + KeyboardTester tester{GetContext()}; std::vector recorded_callbacks; // Store callbacks to manually call them. @@ -2113,8 +2173,8 @@ TEST(KeyboardTest, SlowFrameworkResponseForIdenticalEvents) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -TEST(KeyboardTest, TextInputSubmit) { - KeyboardTester tester; +TEST_F(KeyboardTest, TextInputSubmit) { + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -2181,7 +2241,7 @@ TEST(KeyboardTest, TextInputSubmit) { clear_key_calls(); } -TEST(KeyboardTest, VietnameseTelexAddDiacriticWithFastResponse) { +TEST_F(KeyboardTest, VietnameseTelexAddDiacriticWithFastResponse) { // In this test, the user presses the folloing keys: // // Key Current text @@ -2191,7 +2251,7 @@ TEST(KeyboardTest, VietnameseTelexAddDiacriticWithFastResponse) { // // And the Backspace event is responded immediately. - KeyboardTester tester; + KeyboardTester tester{GetContext()}; tester.Responding(false); // US Keyboard layout @@ -2263,8 +2323,9 @@ TEST(KeyboardTest, VietnameseTelexAddDiacriticWithFastResponse) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -void VietnameseTelexAddDiacriticWithSlowResponse(bool backspace_response) { - // In this test, the user presses the folloing keys: +void VietnameseTelexAddDiacriticWithSlowResponse(WindowsTestContext& context, + bool backspace_response) { + // In this test, the user presses the following keys: // // Key Current text // =========================== @@ -2273,7 +2334,7 @@ void VietnameseTelexAddDiacriticWithSlowResponse(bool backspace_response) { // // And the Backspace down event is responded slowly with `backspace_response`. - KeyboardTester tester; + KeyboardTester tester{context}; tester.Responding(false); // US Keyboard layout @@ -2368,18 +2429,18 @@ void VietnameseTelexAddDiacriticWithSlowResponse(bool backspace_response) { EXPECT_EQ(tester.RedispatchedMessageCountAndClear(), 0); } -TEST(KeyboardTest, VietnameseTelexAddDiacriticWithSlowFalseResponse) { - VietnameseTelexAddDiacriticWithSlowResponse(false); +TEST_F(KeyboardTest, VietnameseTelexAddDiacriticWithSlowFalseResponse) { + VietnameseTelexAddDiacriticWithSlowResponse(GetContext(), false); } -TEST(KeyboardTest, VietnameseTelexAddDiacriticWithSlowTrueResponse) { - VietnameseTelexAddDiacriticWithSlowResponse(true); +TEST_F(KeyboardTest, VietnameseTelexAddDiacriticWithSlowTrueResponse) { + VietnameseTelexAddDiacriticWithSlowResponse(GetContext(), true); } // Ensure that the scancode-less key events issued by Narrator // when toggling caps lock don't violate assert statements. -TEST(KeyboardTest, DoubleCapsLock) { - KeyboardTester tester; +TEST_F(KeyboardTest, DoubleCapsLock) { + KeyboardTester tester{GetContext()}; tester.Responding(false); tester.InjectKeyboardChanges(std::vector{ diff --git a/shell/platform/windows/settings_plugin.cc b/shell/platform/windows/settings_plugin.cc index 2754516e108be..094184703a030 100644 --- a/shell/platform/windows/settings_plugin.cc +++ b/shell/platform/windows/settings_plugin.cc @@ -26,6 +26,32 @@ constexpr wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; constexpr wchar_t kGetTextScaleFactorRegKey[] = L"Software\\Microsoft\\Accessibility"; constexpr wchar_t kGetTextScaleFactorRegValue[] = L"TextScaleFactor"; + +// Return an approximation of the apparent luminance of a given color. +int GetLuminance(DWORD color) { + int r = GetRValue(color); + int g = GetGValue(color); + int b = GetBValue(color); + return (r + r + r + b + (g << 2)) >> 3; +} + +// Return kLight if light mode for apps is selected, otherwise return kDark. +SettingsPlugin::PlatformBrightness GetThemeBrightness() { + DWORD use_light_theme; + DWORD use_light_theme_size = sizeof(use_light_theme); + LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, + nullptr, &use_light_theme, &use_light_theme_size); + + if (result == 0) { + return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight + : SettingsPlugin::PlatformBrightness::kDark; + } else { + // The current OS does not support dark mode. (Older Windows 10 or before + // Windows 10) + return SettingsPlugin::PlatformBrightness::kLight; + } +} } // namespace SettingsPlugin::SettingsPlugin(BinaryMessenger* messenger, @@ -103,19 +129,13 @@ float SettingsPlugin::GetTextScaleFactor() { } SettingsPlugin::PlatformBrightness SettingsPlugin::GetPreferredBrightness() { - DWORD use_light_theme; - DWORD use_light_theme_size = sizeof(use_light_theme); - LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, - nullptr, &use_light_theme, &use_light_theme_size); - - if (result == 0) { - return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight - : SettingsPlugin::PlatformBrightness::kDark; + if (is_high_contrast_) { + DWORD window_color = GetSysColor(COLOR_WINDOW); + int luminance = GetLuminance(window_color); + return luminance >= 127 ? SettingsPlugin::PlatformBrightness::kLight + : SettingsPlugin::PlatformBrightness::kDark; } else { - // The current OS does not support dark mode. (Older Windows 10 or before - // Windows 10) - return SettingsPlugin::PlatformBrightness::kLight; + return GetThemeBrightness(); } } @@ -146,4 +166,9 @@ void SettingsPlugin::WatchTextScaleFactorChanged() { text_scale_factor_changed_watcher_->GetHandle(), TRUE); } +void SettingsPlugin::UpdateHighContrastMode(bool is_high_contrast) { + is_high_contrast_ = is_high_contrast; + SendSettings(); +} + } // namespace flutter diff --git a/shell/platform/windows/settings_plugin.h b/shell/platform/windows/settings_plugin.h index 2c663fc048212..dbd770fa5bd6f 100644 --- a/shell/platform/windows/settings_plugin.h +++ b/shell/platform/windows/settings_plugin.h @@ -23,6 +23,8 @@ namespace flutter { // These are typically set in the control panel. class SettingsPlugin { public: + enum struct PlatformBrightness { kDark, kLight }; + explicit SettingsPlugin(BinaryMessenger* messenger, TaskRunner* task_runner); virtual ~SettingsPlugin(); @@ -37,9 +39,10 @@ class SettingsPlugin { // this automatically. virtual void StopWatching(); - protected: - enum struct PlatformBrightness { kDark, kLight }; + // Update the high contrast status of the system. + virtual void UpdateHighContrastMode(bool is_high_contrast); + protected: // Returns `true` if the user uses 24 hour time. virtual bool GetAlwaysUse24HourFormat(); @@ -55,6 +58,8 @@ class SettingsPlugin { // Starts watching text scale factor changes. virtual void WatchTextScaleFactorChanged(); + bool is_high_contrast_ = false; + private: std::unique_ptr> channel_; diff --git a/shell/platform/windows/settings_plugin_unittests.cc b/shell/platform/windows/settings_plugin_unittests.cc index 2380f46017014..2ca1711c8faf4 100644 --- a/shell/platform/windows/settings_plugin_unittests.cc +++ b/shell/platform/windows/settings_plugin_unittests.cc @@ -21,6 +21,8 @@ class MockSettingsPlugin : public SettingsPlugin { virtual ~MockSettingsPlugin() = default; + bool is_high_contrast() { return is_high_contrast_; } + // |SettingsPlugin| MOCK_METHOD0(GetAlwaysUse24HourFormat, bool()); MOCK_METHOD0(GetTextScaleFactor, float()); @@ -70,5 +72,24 @@ TEST(SettingsPluginTest, StartWatchingStartsWatchingChanges) { settings_plugin.StartWatching(); } +TEST(SettingsPluginTest, HighContrastModeHonored) { + int times = 0; + TestBinaryMessenger messenger( + [×](const std::string& channel, const uint8_t* message, + size_t message_size, BinaryReply reply) { + ASSERT_EQ(channel, "flutter/settings"); + times++; + }); + ::testing::NiceMock settings_plugin(&messenger, nullptr); + + settings_plugin.UpdateHighContrastMode(true); + EXPECT_TRUE(settings_plugin.is_high_contrast()); + + settings_plugin.UpdateHighContrastMode(false); + EXPECT_FALSE(settings_plugin.is_high_contrast()); + + EXPECT_EQ(times, 2); +} + } // namespace testing } // namespace flutter diff --git a/shell/platform/windows/testing/mock_window.h b/shell/platform/windows/testing/mock_window.h index f25732ee63617..22429cf32a18f 100644 --- a/shell/platform/windows/testing/mock_window.h +++ b/shell/platform/windows/testing/mock_window.h @@ -67,6 +67,8 @@ class MockWindow : public Window { MOCK_METHOD0(GetAxFragmentRootDelegate, ui::AXFragmentRootDelegateWin*()); + MOCK_METHOD3(OnGetObject, LRESULT(UINT, WPARAM, LPARAM)); + void CallOnImeComposition(UINT const message, WPARAM const wparam, LPARAM const lparam); diff --git a/shell/platform/windows/window.h b/shell/platform/windows/window.h index 1ad35e68e2b86..632e140979575 100644 --- a/shell/platform/windows/window.h +++ b/shell/platform/windows/window.h @@ -141,9 +141,9 @@ class Window : public KeyboardManager::WindowDelegate { // // The primary use of this function is to supply Windows with wrapped // semantics objects for use by Windows accessibility. - LRESULT OnGetObject(UINT const message, - WPARAM const wparam, - LPARAM const lparam); + virtual LRESULT OnGetObject(UINT const message, + WPARAM const wparam, + LPARAM const lparam); // Called when IME composing begins. virtual void OnComposeBegin() = 0; diff --git a/shell/platform/windows/window_unittests.cc b/shell/platform/windows/window_unittests.cc index 82fbede827fe2..251ef3f217f1f 100644 --- a/shell/platform/windows/window_unittests.cc +++ b/shell/platform/windows/window_unittests.cc @@ -360,5 +360,23 @@ TEST(MockWindow, UnknownPointerTypeSkipsDirectManipulation) { window.InjectWindowMessage(DM_POINTERHITTEST, MAKEWPARAM(pointer_id, 0), 0); } +// Test that the root UIA object is queried by WM_GETOBJECT. +TEST(MockWindow, GetObjectUia) { + MockWindow window; + bool uia_called = false; + ON_CALL(window, OnGetObject) + .WillByDefault(Invoke([&uia_called](UINT msg, WPARAM wpar, LPARAM lpar) { +#ifdef FLUTTER_ENGINE_USE_UIA + uia_called = true; +#endif // FLUTTER_ENGINE_USE_UIA + return static_cast(0); + })); + EXPECT_CALL(window, OnGetObject).Times(1); + + window.InjectWindowMessage(WM_GETOBJECT, 0, UiaRootObjectId); + + EXPECT_TRUE(uia_called); +} + } // namespace testing } // namespace flutter diff --git a/shell/profiling/sampling_profiler.cc b/shell/profiling/sampling_profiler.cc index c6058b76cd4c7..4b5e8d44b7997 100644 --- a/shell/profiling/sampling_profiler.cc +++ b/shell/profiling/sampling_profiler.cc @@ -33,7 +33,7 @@ void SamplingProfiler::Start() { << num_samples_per_sec_; double delay_between_samples = 1.0 / num_samples_per_sec_; auto task_delay = fml::TimeDelta::FromSecondsF(delay_between_samples); - UpdateObservatoryThreadName(); + UpdateDartVMServiceThreadName(); is_running_ = true; SampleRepeatedly(task_delay); } @@ -88,7 +88,7 @@ void SamplingProfiler::SampleRepeatedly(fml::TimeDelta task_delay) const { task_delay); } -void SamplingProfiler::UpdateObservatoryThreadName() const { +void SamplingProfiler::UpdateDartVMServiceThreadName() const { FML_CHECK(profiler_task_runner_); profiler_task_runner_->PostTask( diff --git a/shell/profiling/sampling_profiler.h b/shell/profiling/sampling_profiler.h index d68f88a643d3e..1385613503494 100644 --- a/shell/profiling/sampling_profiler.h +++ b/shell/profiling/sampling_profiler.h @@ -76,7 +76,7 @@ using Sampler = std::function; * @brief a Sampling Profiler that runs peridically and calls the `Sampler` * which servers as a value function to gather various profiling metrics as * represented by `ProfileSample`. These profiling metrics are then posted to - * the observatory timeline. + * the Dart VM Service timeline. * */ class SamplingProfiler { @@ -84,7 +84,7 @@ class SamplingProfiler { /** * @brief Construct a new Sampling Profiler object * - * @param thread_label observatory prefix to be set for the profiling task + * @param thread_label Dart VM Service prefix to be set for the profiling task * runner. * @param profiler_task_runner the task runner to service sampling requests. * @param sampler the value function to collect the profiling metrics. @@ -121,10 +121,10 @@ class SamplingProfiler { /** * @brief This doesn't update the underlying OS thread name for the thread * backing `profiler_task_runner_`. Instead, this is just additional metadata - * for the Observatory to show the thread name of the isolate. + * for the VM Service to show the thread name of the isolate. * */ - void UpdateObservatoryThreadName() const; + void UpdateDartVMServiceThreadName() const; FML_DISALLOW_COPY_AND_ASSIGN(SamplingProfiler); }; diff --git a/shell/testing/observatory/launcher.dart b/shell/testing/observatory/launcher.dart index 2603e359c4b0e..0b4e91e3a5140 100644 --- a/shell/testing/observatory/launcher.dart +++ b/shell/testing/observatory/launcher.dart @@ -2,25 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -library observatory_sky_shell_launcher; - import 'dart:async'; import 'dart:convert'; import 'dart:io'; class ShellProcess { - final Completer _observatoryUriCompleter = Completer(); + final Completer _vmServiceUriCompleter = Completer(); final Process _process; ShellProcess(this._process) { - // Scan stdout and scrape the Observatory Uri. + // Scan stdout and scrape the VM Service Uri. _process.stdout .transform(utf8.decoder) .transform(const LineSplitter()) .listen((String line) { final uri = _extractVMServiceUri(line); if (uri != null) { - _observatoryUriCompleter.complete(uri); + _vmServiceUriCompleter.complete(uri); } }); } @@ -29,13 +27,13 @@ class ShellProcess { return _process.kill(); } - Future waitForObservatory() async { - return _observatoryUriCompleter.future; + Future waitForVMService() async { + return _vmServiceUriCompleter.future; } Uri? _extractVMServiceUri(String str) { final listeningMessageRegExp = RegExp( - r'(?:Observatory|The Dart VM service is) listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)', + r'The Dart VM service is listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)', ); final match = listeningMessageRegExp.firstMatch(str); if (match != null) { @@ -47,7 +45,7 @@ class ShellProcess { class ShellLauncher { final List args = [ - '--observatory-port=0', + '--vm-service-port=0', '--non-interactive', '--run-forever', '--disable-service-auth-codes', diff --git a/shell/testing/observatory/service_client.dart b/shell/testing/observatory/service_client.dart index 160a17795468a..8d52c6ef1ca27 100644 --- a/shell/testing/observatory/service_client.dart +++ b/shell/testing/observatory/service_client.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -library observatory_sky_shell_service_client; - import 'dart:async'; import 'dart:convert'; import 'dart:io'; diff --git a/shell/testing/observatory/test.dart b/shell/testing/observatory/test.dart index a351c444e69d9..ad944dfb74210 100644 --- a/shell/testing/observatory/test.dart +++ b/shell/testing/observatory/test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This is a minimal dependency heart beat test for Observatory. +// This is a minimal dependency heart beat test for the Dart VM Service. import 'dart:async'; import 'dart:convert'; @@ -170,14 +170,14 @@ Future runTests(ShellLauncher launcher, List tests) async { if (process == null) { return false; } - final Uri uri = await process.waitForObservatory(); + final Uri uri = await process.waitForVMService(); try { for (int i = 0; i < tests.length; i++) { print('Executing test ${i + 1}/${tests.length}'); await tests[i](uri); } } catch (e, st) { - print('Observatory test failure: $e\n$st'); + print('Dart VM Service test failure: $e\n$st'); exitCode = -1; } await process.kill(); diff --git a/shell/testing/tester_main.cc b/shell/testing/tester_main.cc index 443e22b3a5b93..efe40884101cd 100644 --- a/shell/testing/tester_main.cc +++ b/shell/testing/tester_main.cc @@ -24,8 +24,10 @@ #include "flutter/shell/common/switches.h" #include "flutter/shell/common/thread_host.h" #include "flutter/shell/gpu/gpu_surface_software.h" + #include "third_party/dart/runtime/include/bin/dart_io_api.h" #include "third_party/dart/runtime/include/dart_api.h" +#include "third_party/skia/include/core/SkSurface.h" #if defined(FML_OS_WIN) #include diff --git a/sky/packages/sky_engine/LICENSE b/sky/packages/sky_engine/LICENSE index a93a3bfbd3754..8b982520eb014 100644 --- a/sky/packages/sky_engine/LICENSE +++ b/sky/packages/sky_engine/LICENSE @@ -245,6 +245,7 @@ fuchsia-vulkan fuchsia_sdk glslang khronos +perfetto shaderc spirv-cross txt @@ -449,6 +450,196 @@ 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. +-------------------------------------------------------------------------------- +perfetto + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright (c) 2017, The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + 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. @@ -25091,6 +25282,38 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- +skia + +Copyright 2012 Google LLC + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- angle Copyright 2012 The ANGLE Project Authors. All rights reserved. @@ -25388,6 +25611,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- accessibility engine +spring_animation tonic txt web_unicode @@ -27794,6 +28018,38 @@ skia Copyright 2023 Google LLC +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +skia + +Copyright 2023 The Android Open Source Project + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/testing/dart/fragment_shader_test.dart b/testing/dart/fragment_shader_test.dart index 7ce3edbe389b6..e97eb5128f6e5 100644 --- a/testing/dart/fragment_shader_test.dart +++ b/testing/dart/fragment_shader_test.dart @@ -332,34 +332,6 @@ void main() async { shader.dispose(); }); - // This test can't rely on actual pixels rendered since it needs to run on a - // metal shader on iOS. instead parse the source code. - test('impellerc orders samplers in metal shader according to declaration and not usage', () async { - if (!Platform.isMacOS) { - return; - } - final Directory directory = shaderDirectory('iplr-remap'); - final String data = readAsStringLossy(File(path.join(directory.path, 'shader_with_samplers.frag.iplr'))); - - const String expected = 'texture2d textureA [[texture(0)]],' - ' texture2d textureB [[texture(1)]]'; - - expect(data, contains(expected)); - }); - - test('impellerc orders samplers in metal shader according to declaration and not usage in glow', () async { - if (!Platform.isMacOS) { - return; - } - final Directory directory = shaderDirectory('iplr-remap'); - final String data = readAsStringLossy(File(path.join(directory.path, 'glow_shader.frag.iplr'))); - - const String expected = 'texture2d tInput [[texture(0)]], texture2d tNoise [[texture(1)]], ' - 'sampler tInputSmplr [[sampler(0)]], sampler tNoiseSmplr [[sampler(1)]]'; - - expect(data, contains(expected)); - }); - // Test all supported GLSL ops. See lib/spirv/lib/src/constants.dart final Map iplrSupportedGLSLOpShaders = await _loadShaderAssets( path.join('supported_glsl_op_shaders', 'iplr'), diff --git a/testing/dart/observatory/shader_reload_test.dart b/testing/dart/observatory/shader_reload_test.dart index ca4981e4b64fb..ff2280ed271f0 100644 --- a/testing/dart/observatory/shader_reload_test.dart +++ b/testing/dart/observatory/shader_reload_test.dart @@ -23,7 +23,7 @@ void main() { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); + fail('This test must not be run with --disable-vm-service.'); } vmService = await vmServiceConnectUri( diff --git a/testing/dart/observatory/skp_test.dart b/testing/dart/observatory/skp_test.dart index 0303702c7a3f5..00c7235b2fb0a 100644 --- a/testing/dart/observatory/skp_test.dart +++ b/testing/dart/observatory/skp_test.dart @@ -17,7 +17,7 @@ void main() { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); + fail('This test must not be run with --disable-vm-service.'); } final vms.VmService vmService = await vmServiceConnectUri( diff --git a/testing/dart/observatory/tracing_test.dart b/testing/dart/observatory/tracing_test.dart index 3257a8ef06e3c..6f709bf64084e 100644 --- a/testing/dart/observatory/tracing_test.dart +++ b/testing/dart/observatory/tracing_test.dart @@ -15,7 +15,7 @@ void main() { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); + fail('This test must not be run with --disable-vm-service.'); } final vms.VmService vmService = await vmServiceConnectUri( diff --git a/testing/dart/observatory/vmservice_methods_test.dart b/testing/dart/observatory/vmservice_methods_test.dart index 6fe14f0d5e697..e74caac65b692 100644 --- a/testing/dart/observatory/vmservice_methods_test.dart +++ b/testing/dart/observatory/vmservice_methods_test.dart @@ -18,7 +18,7 @@ void main() { try { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); + fail('This test must not be run with --disable-vm-service.'); } vmService = await vmServiceConnectUri( @@ -47,7 +47,7 @@ void main() { try { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); + fail('This test must not be run with --disable-vm-service.'); } vmService = await vmServiceConnectUri( @@ -71,7 +71,7 @@ void main() { final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); + fail('This test must not be run with --disable-vm-service.'); } final Completer completer = Completer(); diff --git a/testing/dart_fixture.cc b/testing/dart_fixture.cc index 9fe8a5c5b0fc9..7c765dcb105a5 100644 --- a/testing/dart_fixture.cc +++ b/testing/dart_fixture.cc @@ -35,7 +35,7 @@ Settings DartFixture::CreateSettingsForFixture() { settings.isolate_create_callback = [this]() { native_resolver_->SetNativeResolverForIsolate(); }; - settings.enable_observatory = false; + settings.enable_vm_service = false; SetSnapshotsAndAssets(settings); return settings; } diff --git a/testing/ios/IosUnitTests/Tests/FlutterEngineConfig.xcconfig b/testing/ios/IosUnitTests/Tests/FlutterEngineConfig.xcconfig index 8d3437a336fb1..fd5201bd71c5e 100644 --- a/testing/ios/IosUnitTests/Tests/FlutterEngineConfig.xcconfig +++ b/testing/ios/IosUnitTests/Tests/FlutterEngineConfig.xcconfig @@ -1 +1,2 @@ -FLUTTER_ENGINE=ios_debug_sim_unopt +FLUTTER_ENGINE[arch=x86_64]=ios_debug_sim_unopt +FLUTTER_ENGINE[arch=arm64]=ios_debug_sim_unopt_arm64 diff --git a/testing/run_tests.py b/testing/run_tests.py index 875b0ef88ccfb..c198d2f69879a 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -33,6 +33,7 @@ FONT_SUBSET_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'tools', 'font-subset') FML_UNITTESTS_FILTER = '--gtest_filter=-*TimeSensitiveTest*' +ENCODING = 'UTF-8' def print_divider(char='='): @@ -393,6 +394,7 @@ def make_test(name, flags=None, extra_env=None): # The accessibility library only supports Mac and Windows. make_test('accessibility_unittests'), make_test('flutter_channels_unittests'), + make_test('spring_animation_unittests'), ] if is_linux(): @@ -598,6 +600,11 @@ def ensure_ios_tests_are_built(ios_out_dir): def assert_expected_xcode_version(): """Checks that the user has a version of Xcode installed""" version_output = subprocess.check_output(['xcodebuild', '-version']) + # TODO ricardoamador: remove this check when python 2 is deprecated. + version_output = version_output if isinstance( + version_output, str + ) else version_output.decode(ENCODING) + version_output = version_output.strip() match = re.match(r'Xcode (\d+)', version_output) message = 'Xcode must be installed to run the iOS embedding unit tests' assert match, message diff --git a/testing/scenario_app/run_ios_tests.sh b/testing/scenario_app/run_ios_tests.sh index 74b32a0d233ca..bd0a6f84bd720 100755 --- a/testing/scenario_app/run_ios_tests.sh +++ b/testing/scenario_app/run_ios_tests.sh @@ -27,7 +27,11 @@ function follow_links() ( SCRIPT_DIR=$(follow_links "$(dirname -- "${BASH_SOURCE[0]}")") SRC_DIR="$(cd "$SCRIPT_DIR/../../.."; pwd -P)" -FLUTTER_ENGINE="ios_debug_sim_unopt" +if uname -m | grep "arm64"; then + FLUTTER_ENGINE="ios_debug_sim_unopt_arm64" +else + FLUTTER_ENGINE="ios_debug_sim_unopt" +fi if [[ $# -eq 1 ]]; then FLUTTER_ENGINE="$1" diff --git a/testing/test_gl_surface.h b/testing/test_gl_surface.h index b5c7632b58e43..32bd732f2c8b9 100644 --- a/testing/test_gl_surface.h +++ b/testing/test_gl_surface.h @@ -8,6 +8,8 @@ #include #include "flutter/fml/macros.h" + +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { diff --git a/testing/test_metal_surface.cc b/testing/test_metal_surface.cc index 162c0a9ef7837..15578b819133f 100644 --- a/testing/test_metal_surface.cc +++ b/testing/test_metal_surface.cc @@ -7,6 +7,8 @@ #include "flutter/fml/logging.h" #include "flutter/testing/test_metal_surface_impl.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { bool TestMetalSurface::PlatformSupportsMetal() { diff --git a/testing/test_metal_surface_impl.h b/testing/test_metal_surface_impl.h index 12185a46c5f11..fb96891e930ae 100644 --- a/testing/test_metal_surface_impl.h +++ b/testing/test_metal_surface_impl.h @@ -9,6 +9,8 @@ #include "flutter/testing/test_metal_context.h" #include "flutter/testing/test_metal_surface.h" +#include "third_party/skia/include/core/SkSurface.h" + namespace flutter { class TestMetalSurfaceImpl : public TestMetalSurface { diff --git a/testing/test_vulkan_surface.h b/testing/test_vulkan_surface.h index 4dce92fe725f8..e9c7ed8d27d07 100644 --- a/testing/test_vulkan_surface.h +++ b/testing/test_vulkan_surface.h @@ -10,6 +10,7 @@ #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkSize.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { diff --git a/third_party/accessibility/ax/platform/ax_platform_node_win.cc b/third_party/accessibility/ax/platform/ax_platform_node_win.cc index fcc7b8b3b6486..68bf57733fce2 100644 --- a/third_party/accessibility/ax/platform/ax_platform_node_win.cc +++ b/third_party/accessibility/ax/platform/ax_platform_node_win.cc @@ -5266,7 +5266,6 @@ std::optional AXPlatformNodeWin::MojoEventToUIAEvent( } } -// static std::optional AXPlatformNodeWin::MojoEventToUIAProperty( ax::mojom::Event event) { switch (event) { @@ -5281,6 +5280,11 @@ std::optional AXPlatformNodeWin::MojoEventToUIAProperty( case ax::mojom::Event::kSelectionAdd: case ax::mojom::Event::kSelectionRemove: return UIA_SelectionItemIsSelectedPropertyId; + case ax::mojom::Event::kValueChanged: + if (SupportsToggle(GetData().role)) { + return UIA_ToggleToggleStatePropertyId; + } + return std::nullopt; default: return std::nullopt; } diff --git a/third_party/accessibility/ax/platform/ax_platform_node_win.h b/third_party/accessibility/ax/platform/ax_platform_node_win.h index 1a00db956ef2d..0f5924e228536 100644 --- a/third_party/accessibility/ax/platform/ax_platform_node_win.h +++ b/third_party/accessibility/ax/platform/ax_platform_node_win.h @@ -470,8 +470,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2")) static std::optional MojoEventToUIAEvent(ax::mojom::Event event); // Convert a mojo event to a UIA property id. Exposed for testing. - static std::optional MojoEventToUIAProperty( - ax::mojom::Event event); + std::optional MojoEventToUIAProperty(ax::mojom::Event event); // |AXPlatformNodeBase| bool IsDescendantOf(AXPlatformNode* ancestor) const override; diff --git a/third_party/accessibility/ax/platform/ax_platform_node_win_unittest.cc b/third_party/accessibility/ax/platform/ax_platform_node_win_unittest.cc index 9c872969037d7..8f0b94d62f98e 100644 --- a/third_party/accessibility/ax/platform/ax_platform_node_win_unittest.cc +++ b/third_party/accessibility/ax/platform/ax_platform_node_win_unittest.cc @@ -4674,4 +4674,20 @@ TEST_F(AXPlatformNodeWinTest, IScrollProviderSetScrollPercent) { EXPECT_EQ(y_scroll_percent, 34); } +TEST_F(AXPlatformNodeWinTest, MojoEventToUIAPropertyTest) { + AXNodeData root; + root.id = 1; + root.role = ax::mojom::Role::kCheckBox; + root.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState, + static_cast(ax::mojom::CheckedState::kMixed)); + + Init(root); + + ComPtr platform_node = + QueryInterfaceFromNode(GetRootAsAXNode()); + EXPECT_EQ( + platform_node->MojoEventToUIAProperty(ax::mojom::Event::kValueChanged), + UIA_ToggleToggleStatePropertyId); +} + } // namespace ui diff --git a/third_party/canvaskit/BUILD.gn b/third_party/canvaskit/BUILD.gn index 45ab6a223da00..429af65e42c24 100644 --- a/third_party/canvaskit/BUILD.gn +++ b/third_party/canvaskit/BUILD.gn @@ -26,6 +26,7 @@ if (build_canvaskit_chromium) { extra_toolchain_args = { skia_use_icu = false skia_use_client_icu = true + skia_icu_bidi_third_party_dir = "//flutter/third_party/canvaskit/icu_bidi" } } diff --git a/third_party/canvaskit/icu_bidi/BUILD.gn b/third_party/canvaskit/icu_bidi/BUILD.gn new file mode 100644 index 0000000000000..79628ef6755ea --- /dev/null +++ b/third_party/canvaskit/icu_bidi/BUILD.gn @@ -0,0 +1,53 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +public_include_dirs = [ + "//third_party/icu/source/common", + "//third_party/icu/source/i18n", +] + +config("icu_bidi_public") { + include_dirs = public_include_dirs + defines = [ + "U_USING_ICU_NAMESPACE=0", + "U_DISABLE_RENAMING=0", + "U_HAVE_LIB_SUFFIX=1", + "U_LIB_SUFFIX_C_NAME=_skia", + "U_DISABLE_VERSION_SUFFIX=1", + "SK_USING_THIRD_PARTY_ICU", + ] + cflags = [] + + foreach(dir, include_dirs) { + cflags += [ + "-isystem", + rebase_path(dir), + ] + } +} + +static_library("icu_bidi") { + defines = [ + "U_COMMON_IMPLEMENTATION", + "U_STATIC_IMPLEMENTATION", + "U_I18N_IMPLEMENTATION", + ] + sources = [ + "//third_party/icu/source/common/cmemory.cpp", + "//third_party/icu/source/common/cstring.cpp", + "//third_party/icu/source/common/ubidi.cpp", + "//third_party/icu/source/common/ubidi_props.cpp", + "//third_party/icu/source/common/ubidiln.cpp", + "//third_party/icu/source/common/ubidiwrt.cpp", + "//third_party/icu/source/common/uchar.cpp", + "//third_party/icu/source/common/udataswp.cpp", + "//third_party/icu/source/common/uinvchar.cpp", + "//third_party/icu/source/common/ustring.cpp", + "//third_party/icu/source/common/ustrtrns.cpp", + "//third_party/icu/source/common/utf_impl.cpp", + "//third_party/icu/source/common/utrie2.cpp", + ] + public_configs = [ ":icu_bidi_public" ] + cflags = [ "-w" ] +} diff --git a/third_party/spring_animation/BUILD.gn b/third_party/spring_animation/BUILD.gn new file mode 100644 index 0000000000000..32a6a128b5b16 --- /dev/null +++ b/third_party/spring_animation/BUILD.gn @@ -0,0 +1,33 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if (is_ios || is_mac) { + import("//flutter/common/config.gni") + import("//flutter/testing/testing.gni") + + source_set("spring_animation") { + sources = [ + "spring_animation.h", + "spring_animation.mm", + ] + public_configs = [ "//flutter:config" ] + } + + if (enable_unittests) { + test_fixtures("spring_animation_fixtures") { + fixtures = [] + } + + executable("spring_animation_unittests") { + testonly = true + sources = [ "SpringAnimationTest.mm" ] + deps = [ + ":spring_animation", + ":spring_animation_fixtures", + "//flutter/testing", + ] + public_configs = [ "//flutter:config" ] + } + } +} diff --git a/third_party/spring_animation/Libraries/Animated/animations/SpringAnimation.js b/third_party/spring_animation/Libraries/Animated/animations/SpringAnimation.js deleted file mode 100644 index 69101dab030e8..0000000000000 --- a/third_party/spring_animation/Libraries/Animated/animations/SpringAnimation.js +++ /dev/null @@ -1,370 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - * @format - */ - -'use strict'; - -import type {PlatformConfig} from '../AnimatedPlatformConfig'; -import type AnimatedInterpolation from '../nodes/AnimatedInterpolation'; -import type AnimatedValue from '../nodes/AnimatedValue'; -import type AnimatedValueXY from '../nodes/AnimatedValueXY'; -import type {AnimationConfig, EndCallback} from './Animation'; - -import NativeAnimatedHelper from '../NativeAnimatedHelper'; -import AnimatedColor from '../nodes/AnimatedColor'; -import * as SpringConfig from '../SpringConfig'; -import Animation from './Animation'; -import invariant from 'invariant'; - -export type SpringAnimationConfig = { - ...AnimationConfig, - toValue: - | number - | AnimatedValue - | { - x: number, - y: number, - ... - } - | AnimatedValueXY - | { - r: number, - g: number, - b: number, - a: number, - ... - } - | AnimatedColor - | AnimatedInterpolation, - overshootClamping?: boolean, - restDisplacementThreshold?: number, - restSpeedThreshold?: number, - velocity?: - | number - | { - x: number, - y: number, - ... - }, - bounciness?: number, - speed?: number, - tension?: number, - friction?: number, - stiffness?: number, - damping?: number, - mass?: number, - delay?: number, -}; - -export type SpringAnimationConfigSingle = { - ...AnimationConfig, - toValue: number, - overshootClamping?: boolean, - restDisplacementThreshold?: number, - restSpeedThreshold?: number, - velocity?: number, - bounciness?: number, - speed?: number, - tension?: number, - friction?: number, - stiffness?: number, - damping?: number, - mass?: number, - delay?: number, -}; - -export default class SpringAnimation extends Animation { - _overshootClamping: boolean; - _restDisplacementThreshold: number; - _restSpeedThreshold: number; - _lastVelocity: number; - _startPosition: number; - _lastPosition: number; - _fromValue: number; - _toValue: number; - _stiffness: number; - _damping: number; - _mass: number; - _initialVelocity: number; - _delay: number; - _timeout: any; - _startTime: number; - _lastTime: number; - _frameTime: number; - _onUpdate: (value: number) => void; - _animationFrame: any; - _useNativeDriver: boolean; - _platformConfig: ?PlatformConfig; - - constructor(config: SpringAnimationConfigSingle) { - super(); - - this._overshootClamping = config.overshootClamping ?? false; - this._restDisplacementThreshold = config.restDisplacementThreshold ?? 0.001; - this._restSpeedThreshold = config.restSpeedThreshold ?? 0.001; - this._initialVelocity = config.velocity ?? 0; - this._lastVelocity = config.velocity ?? 0; - this._toValue = config.toValue; - this._delay = config.delay ?? 0; - this._useNativeDriver = NativeAnimatedHelper.shouldUseNativeDriver(config); - this._platformConfig = config.platformConfig; - this.__isInteraction = config.isInteraction ?? !this._useNativeDriver; - this.__iterations = config.iterations ?? 1; - - if ( - config.stiffness !== undefined || - config.damping !== undefined || - config.mass !== undefined - ) { - invariant( - config.bounciness === undefined && - config.speed === undefined && - config.tension === undefined && - config.friction === undefined, - 'You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one', - ); - this._stiffness = config.stiffness ?? 100; - this._damping = config.damping ?? 10; - this._mass = config.mass ?? 1; - } else if (config.bounciness !== undefined || config.speed !== undefined) { - // Convert the origami bounciness/speed values to stiffness/damping - // We assume mass is 1. - invariant( - config.tension === undefined && - config.friction === undefined && - config.stiffness === undefined && - config.damping === undefined && - config.mass === undefined, - 'You can define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one', - ); - const springConfig = SpringConfig.fromBouncinessAndSpeed( - config.bounciness ?? 8, - config.speed ?? 12, - ); - this._stiffness = springConfig.stiffness; - this._damping = springConfig.damping; - this._mass = 1; - } else { - // Convert the origami tension/friction values to stiffness/damping - // We assume mass is 1. - const springConfig = SpringConfig.fromOrigamiTensionAndFriction( - config.tension ?? 40, - config.friction ?? 7, - ); - this._stiffness = springConfig.stiffness; - this._damping = springConfig.damping; - this._mass = 1; - } - - invariant(this._stiffness > 0, 'Stiffness value must be greater than 0'); - invariant(this._damping > 0, 'Damping value must be greater than 0'); - invariant(this._mass > 0, 'Mass value must be greater than 0'); - } - - __getNativeAnimationConfig(): {| - damping: number, - initialVelocity: number, - iterations: number, - mass: number, - platformConfig: ?PlatformConfig, - overshootClamping: boolean, - restDisplacementThreshold: number, - restSpeedThreshold: number, - stiffness: number, - toValue: any, - type: $TEMPORARY$string<'spring'>, - |} { - return { - type: 'spring', - overshootClamping: this._overshootClamping, - restDisplacementThreshold: this._restDisplacementThreshold, - restSpeedThreshold: this._restSpeedThreshold, - stiffness: this._stiffness, - damping: this._damping, - mass: this._mass, - initialVelocity: this._initialVelocity ?? this._lastVelocity, - toValue: this._toValue, - iterations: this.__iterations, - platformConfig: this._platformConfig, - }; - } - - start( - fromValue: number, - onUpdate: (value: number) => void, - onEnd: ?EndCallback, - previousAnimation: ?Animation, - animatedValue: AnimatedValue, - ): void { - this.__active = true; - this._startPosition = fromValue; - this._lastPosition = this._startPosition; - - this._onUpdate = onUpdate; - this.__onEnd = onEnd; - this._lastTime = Date.now(); - this._frameTime = 0.0; - - if (previousAnimation instanceof SpringAnimation) { - const internalState = previousAnimation.getInternalState(); - this._lastPosition = internalState.lastPosition; - this._lastVelocity = internalState.lastVelocity; - // Set the initial velocity to the last velocity - this._initialVelocity = this._lastVelocity; - this._lastTime = internalState.lastTime; - } - - const start = () => { - if (this._useNativeDriver) { - this.__startNativeAnimation(animatedValue); - } else { - this.onUpdate(); - } - }; - - // If this._delay is more than 0, we start after the timeout. - if (this._delay) { - this._timeout = setTimeout(start, this._delay); - } else { - start(); - } - } - - getInternalState(): Object { - return { - lastPosition: this._lastPosition, - lastVelocity: this._lastVelocity, - lastTime: this._lastTime, - }; - } - - /** - * This spring model is based off of a damped harmonic oscillator - * (https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). - * - * We use the closed form of the second order differential equation: - * - * x'' + (2ζ⍵_0)x' + ⍵^2x = 0 - * - * where - * ⍵_0 = √(k / m) (undamped angular frequency of the oscillator), - * ζ = c / 2√mk (damping ratio), - * c = damping constant - * k = stiffness - * m = mass - * - * The derivation of the closed form is described in detail here: - * http://planetmath.org/sites/default/files/texpdf/39745.pdf - * - * This algorithm happens to match the algorithm used by CASpringAnimation, - * a QuartzCore (iOS) API that creates spring animations. - */ - onUpdate(): void { - // If for some reason we lost a lot of frames (e.g. process large payload or - // stopped in the debugger), we only advance by 4 frames worth of - // computation and will continue on the next frame. It's better to have it - // running at faster speed than jumping to the end. - const MAX_STEPS = 64; - let now = Date.now(); - if (now > this._lastTime + MAX_STEPS) { - now = this._lastTime + MAX_STEPS; - } - - const deltaTime = (now - this._lastTime) / 1000; - this._frameTime += deltaTime; - - const c: number = this._damping; - const m: number = this._mass; - const k: number = this._stiffness; - const v0: number = -this._initialVelocity; - - const zeta = c / (2 * Math.sqrt(k * m)); // damping ratio - const omega0 = Math.sqrt(k / m); // undamped angular frequency of the oscillator (rad/ms) - const omega1 = omega0 * Math.sqrt(1.0 - zeta * zeta); // exponential decay - const x0 = this._toValue - this._startPosition; // calculate the oscillation from x0 = 1 to x = 0 - - let position = 0.0; - let velocity = 0.0; - const t = this._frameTime; - if (zeta < 1) { - // Under damped - const envelope = Math.exp(-zeta * omega0 * t); - position = - this._toValue - - envelope * - (((v0 + zeta * omega0 * x0) / omega1) * Math.sin(omega1 * t) + - x0 * Math.cos(omega1 * t)); - // This looks crazy -- it's actually just the derivative of the - // oscillation function - velocity = - zeta * - omega0 * - envelope * - ((Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0)) / omega1 + - x0 * Math.cos(omega1 * t)) - - envelope * - (Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0) - - omega1 * x0 * Math.sin(omega1 * t)); - } else { - // Critically damped - const envelope = Math.exp(-omega0 * t); - position = this._toValue - envelope * (x0 + (v0 + omega0 * x0) * t); - velocity = - envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0)); - } - - this._lastTime = now; - this._lastPosition = position; - this._lastVelocity = velocity; - - this._onUpdate(position); - if (!this.__active) { - // a listener might have stopped us in _onUpdate - return; - } - - // Conditions for stopping the spring animation - let isOvershooting = false; - if (this._overshootClamping && this._stiffness !== 0) { - if (this._startPosition < this._toValue) { - isOvershooting = position > this._toValue; - } else { - isOvershooting = position < this._toValue; - } - } - const isVelocity = Math.abs(velocity) <= this._restSpeedThreshold; - let isDisplacement = true; - if (this._stiffness !== 0) { - isDisplacement = - Math.abs(this._toValue - position) <= this._restDisplacementThreshold; - } - - if (isOvershooting || (isVelocity && isDisplacement)) { - if (this._stiffness !== 0) { - // Ensure that we end up with a round value - this._lastPosition = this._toValue; - this._lastVelocity = 0; - this._onUpdate(this._toValue); - } - - this.__debouncedOnEnd({finished: true}); - return; - } - // $FlowFixMe[method-unbinding] added when improving typing for this parameters - this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); - } - - stop(): void { - super.stop(); - this.__active = false; - clearTimeout(this._timeout); - global.cancelAnimationFrame(this._animationFrame); - this.__debouncedOnEnd({finished: false}); - } -} diff --git a/third_party/spring_animation/SpringAnimationTest.mm b/third_party/spring_animation/SpringAnimationTest.mm new file mode 100644 index 0000000000000..110594093d222 --- /dev/null +++ b/third_party/spring_animation/SpringAnimationTest.mm @@ -0,0 +1,65 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#import "flutter/third_party/spring_animation/spring_animation.h" +#include "gtest/gtest.h" + +TEST(SpringAnimationTest, CanInitializeCorrectly) { + SpringAnimation* animation = [[SpringAnimation alloc] initWithStiffness:1000 + damping:500 + mass:3 + initialVelocity:0 + fromValue:0 + toValue:1000]; + ASSERT_TRUE(animation.stiffness == 1000); + ASSERT_TRUE(animation.damping == 500); + ASSERT_TRUE(animation.mass == 3); + ASSERT_TRUE(animation.initialVelocity == 0); + ASSERT_TRUE(animation.fromValue == 0); + ASSERT_TRUE(animation.toValue == 1000); +} + +TEST(SpringAnimationTest, CurveFunctionCanWorkCorrectly) { + // Here is the keyboard curve config on iOS platform. + SpringAnimation* animation = [[SpringAnimation alloc] initWithStiffness:1000 + damping:500 + mass:3 + initialVelocity:0 + fromValue:0 + toValue:1000]; + const double accuracy = 1.0; + const double startTime = 0; + const double endTime = 0.6; + + const double startValue = [animation curveFunction:startTime]; + ASSERT_TRUE(fabs(startValue - animation.fromValue) < accuracy); + const double toValue = [animation curveFunction:endTime]; + ASSERT_TRUE(fabs(toValue - animation.toValue) < accuracy); +} + +TEST(SpringAnimationTest, CanUpdatePositionValuesAndCalculateCorrectly) { + SpringAnimation* animation = [[SpringAnimation alloc] initWithStiffness:1000 + damping:500 + mass:3 + initialVelocity:0 + fromValue:0 + toValue:1000]; + const double startTime = 0; + const double endTime = 0.6; + + const double startValue1 = [animation curveFunction:startTime]; + const double toValue1 = [animation curveFunction:endTime]; + + animation.fromValue = 10; + animation.toValue = 800; + + ASSERT_TRUE(animation.fromValue == 10); + ASSERT_TRUE(animation.toValue == 800); + + const double startValue2 = [animation curveFunction:startTime]; + const double toValue2 = [animation curveFunction:endTime]; + ASSERT_TRUE(startValue2 > startValue1); + ASSERT_TRUE(toValue2 < toValue1); +} diff --git a/third_party/spring_animation/spring_animation.h b/third_party/spring_animation/spring_animation.h new file mode 100644 index 0000000000000..9d200af90e8a1 --- /dev/null +++ b/third_party/spring_animation/spring_animation.h @@ -0,0 +1,43 @@ +// +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. +// +// @flow +// @format +// + +#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_SPRING_ANIMATION_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_SPRING_ANIMATION_H_ + +#include + +// This simplified spring model is based off of a damped harmonic oscillator. +// See: +// https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator +// +// This models the closed form of the second order differential equation which +// happens to match the algorithm used by CASpringAnimation, a QuartzCore (iOS) +// API that creates spring animations. +@interface SpringAnimation : NSObject + +- (instancetype)initWithStiffness:(double)stiffness + damping:(double)damping + mass:(double)mass + initialVelocity:(double)initialVelocity + fromValue:(double)fromValue + toValue:(double)toValue; + +- (double)curveFunction:(double)t; + +@property(nonatomic, assign, readonly) double stiffness; +@property(nonatomic, assign, readonly) double damping; +@property(nonatomic, assign, readonly) double mass; +@property(nonatomic, assign, readonly) double initialVelocity; +@property(nonatomic, assign) double fromValue; +@property(nonatomic, assign) double toValue; + +@end + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_SPRING_ANIMATION_H_ diff --git a/third_party/spring_animation/spring_animation.mm b/third_party/spring_animation/spring_animation.mm new file mode 100644 index 0000000000000..60016293a9f5d --- /dev/null +++ b/third_party/spring_animation/spring_animation.mm @@ -0,0 +1,67 @@ +// +// Copyright (c) Meta Platforms, Inc. and affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. +// +// @flow +// @format +// + +#import "spring_animation.h" + +#include + +@interface SpringAnimation () + +@property(nonatomic, assign) double zeta; +@property(nonatomic, assign) double omega0; +@property(nonatomic, assign) double omega1; +@property(nonatomic, assign) double v0; + +@end + +// Spring code adapted from React Native's Animation Library, see: +// https://github.com/facebook/react-native/blob/main/Libraries/Animated/animations/SpringAnimation.js +@implementation SpringAnimation +- (instancetype)initWithStiffness:(double)stiffness + damping:(double)damping + mass:(double)mass + initialVelocity:(double)initialVelocity + fromValue:(double)fromValue + toValue:(double)toValue { + self = [super init]; + if (self) { + _stiffness = stiffness; + _damping = damping; + _mass = mass; + _initialVelocity = initialVelocity; + _fromValue = fromValue; + _toValue = toValue; + + _zeta = _damping / (2 * sqrt(_stiffness * _mass)); // Damping ratio. + _omega0 = sqrt(_stiffness / _mass); // Undamped angular frequency of the oscillator. + _omega1 = _omega0 * sqrt(1.0 - _zeta * _zeta); // Exponential decay. + _v0 = -_initialVelocity; + } + return self; +} + +- (double)curveFunction:(double)t { + const double x0 = _toValue - _fromValue; + + double y; + if (_zeta < 1) { + // Under damped. + const double envelope = exp(-_zeta * _omega0 * t); + y = _toValue - envelope * (((_v0 + _zeta * _omega0 * x0) / _omega1) * sin(_omega1 * t) + + x0 * cos(_omega1 * t)); + } else { + // Critically damped. + const double envelope = exp(-_omega0 * t); + y = _toValue - envelope * (x0 + (_v0 + _omega0 * x0) * t); + } + + return y; +} +@end diff --git a/tools/cipd/malioc/.gitignore b/tools/cipd/malioc/.gitignore new file mode 100644 index 0000000000000..5a658f14ebc7c --- /dev/null +++ b/tools/cipd/malioc/.gitignore @@ -0,0 +1,2 @@ +# Don't accidentally check in the Arm Tools. +arm-tools/ diff --git a/tools/cipd/malioc/README.md b/tools/cipd/malioc/README.md new file mode 100644 index 0000000000000..bfa6bfb748a4f --- /dev/null +++ b/tools/cipd/malioc/README.md @@ -0,0 +1,22 @@ +# Updating malioc + +Flutter uses `malioc` from the Arm Mobile Studio to statically analyze +Impeller's shaders. See `impeller/tools/malioc_diff.py` for more information +about that. + +The files in this directory are instructions for updating the `flutter_internal` +CIPD package that CI uses to obtain `malioc`. + +## Steps + +1. Download the Arm Mobile Studio from [Arm](https://developer.arm.com/Tools%20and%20Software/Arm%20Mobile%20Studio) +2. Extract the `.zip` archive into a directory called `arm-tools` sibling to + this file. +3. Check that the `arm-tools` directory contains a child directory + `mali_offline_compiler`. If it instead contains a child directory which + is something like `Arm_Mobile_Studio_2022.4`, then copy the contents of that + directory to `arm-tools` instead. +4. Run the `generate.sh` script in this directory. +5. Verify that the file appears [here](https://chrome-infra-packages.appspot.com/p/flutter_internal/tools). +6. Update `.ci.yaml` to refer to the new version tag echoed by `generate.sh`. +7. Delete the `arm-tools` directory diff --git a/tools/cipd/malioc/cipd.yaml b/tools/cipd/malioc/cipd.yaml new file mode 100644 index 0000000000000..47f70db8ef05a --- /dev/null +++ b/tools/cipd/malioc/cipd.yaml @@ -0,0 +1,5 @@ +package: flutter_internal/tools/arm-tools +description: Tools for analyzing shaders +install_mode: copy +data: + - dir: arm-tools diff --git a/tools/cipd/malioc/generate.sh b/tools/cipd/malioc/generate.sh new file mode 100755 index 0000000000000..a9d63f4183264 --- /dev/null +++ b/tools/cipd/malioc/generate.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -e + +version_tag=`date +%Y-%m-%dT%T%z` + +cipd create --pkg-def cipd.yaml -tag last_updated:"$version_tag" diff --git a/tools/fuchsia/build_fuchsia_artifacts.py b/tools/fuchsia/build_fuchsia_artifacts.py index fe5dff51f9dcc..f3954b28d560b 100755 --- a/tools/fuchsia/build_fuchsia_artifacts.py +++ b/tools/fuchsia/build_fuchsia_artifacts.py @@ -254,6 +254,8 @@ def CheckCIPDPackageExists(package_name, tag): tag, ] stdout = subprocess.check_output(command) + # TODO ricardoamador: remove this check when python 2 is deprecated. + stdout = stdout if isinstance(stdout, str) else stdout.decode('UTF-8') match = re.search(r'No matching instances\.', stdout) if match: return False diff --git a/tools/fuchsia/fuchsia_archive.gni b/tools/fuchsia/fuchsia_archive.gni index a30d392c526e9..5606565987a90 100644 --- a/tools/fuchsia/fuchsia_archive.gni +++ b/tools/fuchsia/fuchsia_archive.gni @@ -105,8 +105,14 @@ template("_fuchsia_archive") { } foreach(lib, pkg.libraries) { + output_path = "" + + if (defined(lib.output_path)) { + output_path = lib.output_path + } + copy_sources += [ "${lib.path}/${lib.name}" ] - copy_outputs += [ "$far_base_dir/lib/${lib.name}" ] + copy_outputs += [ "$far_base_dir/lib/${output_path}${lib.name}" ] } pkg_dir_deps = pkg.deps diff --git a/tools/fuchsia/fuchsia_libs.gni b/tools/fuchsia/fuchsia_libs.gni index 08f34a71e622f..2458e4e617d29 100644 --- a/tools/fuchsia/fuchsia_libs.gni +++ b/tools/fuchsia/fuchsia_libs.gni @@ -59,6 +59,7 @@ common_libs = [ { name = "ld.so.1" path = rebase_path("$sysroot_dist_lib/$ld_so_path") + output_path = ld_so_path }, ] diff --git a/tools/fuchsia/merge_and_upload_debug_symbols.py b/tools/fuchsia/merge_and_upload_debug_symbols.py index 6e1038ed7ce1f..6005b6dcfc8ae 100755 --- a/tools/fuchsia/merge_and_upload_debug_symbols.py +++ b/tools/fuchsia/merge_and_upload_debug_symbols.py @@ -64,6 +64,7 @@ def CheckCIPDPackageExists(package_name, tag): tag, ] stdout = subprocess.check_output(command) + stdout = stdout if isinstance(stdout, str) else stdout.decode('UTF-8') match = re.search(r'No matching instances\.', stdout) if match: return False diff --git a/tools/gn b/tools/gn index 2a4b3b973faae..9215fd6d835c3 100755 --- a/tools/gn +++ b/tools/gn @@ -342,23 +342,22 @@ def to_gn_args(args): gn_args['host_cpu'] = 'x86' gn_args['current_cpu'] = 'x86' - if is_host_build(args) and gn_args['host_os'] == 'mac': - # macOS host builds (whether x64 or arm64) must currently be built under - # Rosetta on Apple Silicon Macs. - # TODO(cbracken): https://github.com/flutter/flutter/issues/103386 + # When building binaries to run on a macOS host (like gen_snapshot), always + # use the clang_x64 toolchain, which will run under Rosetta. This is done for + # two reasons: + # 1. goma currently only supports the clang_x64 toolchain. + # 2. gen_snapshot cannot crossbuild from arm64 to x64. Its host architecture + # must be x64 to target x64. + # TODO(cbracken): https://github.com/flutter/flutter/issues/103386 + if get_host_os() == 'mac' and not args.force_mac_arm64: gn_args['host_cpu'] = 'x64' + if is_host_build(args) and gn_args['host_os'] == 'mac': # macOS unit tests include Vulkan headers which reference Metal types # introduced in macOS 10.14. gn_args['mac_sdk_min'] = '10.14' gn_args['mac_deployment_target'] = '10.14.0' - # macOS target builds (whether x64 or arm64) must currently be built under - # Rosetta on Apple Silicon Macs. - # TODO(cbracken): https://github.com/flutter/flutter/issues/103386 - if 'target_os' in gn_args and gn_args['target_os'] == 'mac': - gn_args['host_cpu'] = 'x64' - if gn_args['target_os'] == 'ios': gn_args['use_ios_simulator'] = args.simulator elif get_host_os() == 'mac': @@ -662,9 +661,7 @@ def to_gn_wasm_args(args, gn_args): # than forced to true, once the recipes are updated. # https://github.com/flutter/flutter/issues/113303 gn_args['build_canvaskit'] = True - # TODO(mdebbar): Read this from an input argument. - # https://github.com/flutter/flutter/issues/118744 - gn_args['build_canvaskit_chromium'] = False + gn_args['build_canvaskit_chromium'] = args.build_canvaskit_chromium gn_args['flutter_build_web_sdk'] = True @@ -731,6 +728,13 @@ def parse_args(args): parser.add_argument( '--mac-cpu', type=str, choices=['x64', 'arm64'], default='x64' ) + parser.add_argument( + '--force-mac-arm64', + action='store_true', + default=False, + help='Force use of the clang_arm64 toolchain on an arm64 mac host when ' + 'building host binaries.' + ) parser.add_argument('--simulator', action='store_true', default=False) parser.add_argument( '--linux', dest='target_os', action='store_const', const='linux' @@ -885,6 +889,14 @@ def parse_args(args): '--no-build-canvaskit', dest='build_canvaskit', action='store_false' ) + parser.add_argument( + '--build-canvaskit-chromium', + default=False, + dest='build_canvaskit_chromium', + action='store_true', + help='build the Chromium variant of CanvasKit from sources' + ) + parser.add_argument( '--ide', default='', @@ -1044,6 +1056,7 @@ def main(argv): elif sys.platform.startswith('win'): # On Windows, generate a Visual Studio project. command.append('--ide=vs') + command.append('--ninja-executable=ninja') command.append('--export-compile-commands=default') diff --git a/tools/licenses/lib/paths.dart b/tools/licenses/lib/paths.dart index 18a02134c9159..5e136a1107322 100644 --- a/tools/licenses/lib/paths.dart +++ b/tools/licenses/lib/paths.dart @@ -132,6 +132,17 @@ final Set skippedPaths = { r'third_party/libwebp/webp_js', r'third_party/libxml', // dependency of the testing system that we don't actually use r'third_party/ocmock', // only used for tests + r'third_party/perfetto/debian', // contains nothing that ends up in the binary executable + r'third_party/perfetto/infra', // contains nothing that ends up in the binary executable + r'third_party/perfetto/protos', // contains nothing that ends up in the binary executable + r'third_party/perfetto/python/perfetto/trace_processor', // contains nothing that ends up in the binary executable + r'third_party/perfetto/src/ipc', // contains nothing that ends up in the binary executable + r'third_party/perfetto/src/profiling/memory', // contains nothing that ends up in the binary executable + r'third_party/perfetto/src/tools', // contains nothing that ends up in the binary executable + r'third_party/perfetto/src/trace_processor', // contains nothing that ends up in the binary executable + r'third_party/perfetto/src/traced', // contains nothing that ends up in the binary executable + r'third_party/perfetto/src/tracing', // contains nothing that ends up in the binary executable + r'third_party/protobuf', // build-time dependency only r'third_party/pkg/archive', // contains nothing that ends up in the binary executable r'third_party/pkg/equatable', r'third_party/pkg/file', diff --git a/vulkan/vulkan_swapchain.cc b/vulkan/vulkan_swapchain.cc index cb8a28fa6b656..e6d5b780c27e0 100644 --- a/vulkan/vulkan_swapchain.cc +++ b/vulkan/vulkan_swapchain.cc @@ -7,6 +7,7 @@ #include "flutter/vulkan/procs/vulkan_proc_table.h" #include "third_party/skia/include/core/SkColorSpace.h" +#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" #include "third_party/skia/include/gpu/vk/GrVkTypes.h" diff --git a/vulkan/vulkan_window.cc b/vulkan/vulkan_window.cc index a7067fff3f907..f7f51dce9e738 100644 --- a/vulkan/vulkan_window.cc +++ b/vulkan/vulkan_window.cc @@ -11,13 +11,15 @@ #include "flutter/flutter_vma/flutter_skia_vma.h" #include "flutter/vulkan/vulkan_skia_proc_table.h" -#include "third_party/skia/include/gpu/GrDirectContext.h" #include "vulkan_application.h" #include "vulkan_device.h" #include "vulkan_native_surface.h" #include "vulkan_surface.h" #include "vulkan_swapchain.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" + namespace vulkan { VulkanWindow::VulkanWindow(fml::RefPtr proc_table,