diff --git a/DEPS b/DEPS index 04ca09c87143c..9d9b8158c679c 100644 --- a/DEPS +++ b/DEPS @@ -14,7 +14,7 @@ vars = { 'flutter_git': 'https://flutter.googlesource.com', 'skia_git': 'https://skia.googlesource.com', 'llvm_git': 'https://llvm.googlesource.com', - 'skia_revision': 'a2e2eb29249226baaa3b84f06ba3970fd21258d8', + 'skia_revision': 'ca108745b1de1ce366393013c441abc8012794f5', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. @@ -56,7 +56,7 @@ 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': 'b81b344a194ffedb8b775fe9e006ef3dd51ce573', + 'dart_revision': '183b9e21b706a72c3c5997157459b67d1d66199a', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py @@ -66,7 +66,7 @@ vars = { 'dart_browser_launcher_rev': 'fa98c77e7a2fee21a4ad3528dd79da0f4df6bd0f', 'dart_clock_rev': '6e43768a0b135a0d36fc886907b70c4bf27117e6', 'dart_collection_rev': '0c1f829c29da1d63488be774f430b2035a565d6f', - 'dart_devtools_rev': '6390e5ddf69c836c530256891405e0cb3319b604', + 'dart_devtools_rev': '25053ae4af8f162188388c6f3786e03349652e51', 'dart_libprotobuf_rev': '24487dd1045c7f3d64a21f38a3f0c06cc4cf2edb', 'dart_perfetto_rev': '13ce0c9e13b0940d2476cd0cff2301708a9a2e2b', 'dart_protobuf_gn_rev': 'ca669f79945418f6229e4fef89b666b2a88cbb10', @@ -258,7 +258,7 @@ vars = { # The version / instance id of the cipd:chromium/fuchsia/gn-sdk which will be # used altogether with fuchsia-sdk to generate gn based build rules. - 'fuchsia_gn_sdk_version': 'OKGFjciA5Vd0TQks4ow7-ppfxy_Y6v5hSjjn2w6LWjwC', + 'fuchsia_gn_sdk_version': 'ALNKvSVWQSpw1uxPyh6OvWHf878FzEm6nvVEyTB8H-8C', } gclient_gn_args_file = 'src/flutter/third_party/dart/build/config/gclient_args.gni' @@ -350,7 +350,7 @@ deps = { Var('chromium_git') + '/external/github.com/WebAssembly/binaryen.git@9ce4b8a47b15c324b170f7572829532b7e5bfe47', 'src/flutter/third_party/dart/third_party/devtools': - {'dep_type': 'cipd', 'packages': [{'package': 'dart/third_party/flutter/devtools', 'version': 'git_revision:6390e5ddf69c836c530256891405e0cb3319b604'}]}, + {'dep_type': 'cipd', 'packages': [{'package': 'dart/third_party/flutter/devtools', 'version': 'git_revision:25053ae4af8f162188388c6f3786e03349652e51'}]}, 'src/flutter/third_party/dart/third_party/pkg/args': Var('dart_git') + '/args.git@1a24d614423e7861ae2e341bfb19050959cef0cd', diff --git a/ci/licenses_golden/licenses_dart b/ci/licenses_golden/licenses_dart index e5f68edb791d8..d802661c7e150 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: fe7a1b28fc5b53de956ae51eb38dd156 +Signature: a15ad53ef1d04fd5a04ee85dd04724b1 ==================================================================================================== LIBRARY: dart @@ -4785,7 +4785,7 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. -You may obtain a copy of this library's Source Code Form from: https://dart.googlesource.com/sdk/+/b81b344a194ffedb8b775fe9e006ef3dd51ce573 +You may obtain a copy of this library's Source Code Form from: https://dart.googlesource.com/sdk/+/b519f85c3076454c4629206dfc07afecf2271f37 /third_party/fallback_root_certificates/ ==================================================================================================== diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 7a8baeeff3fcb..092515d1e40e7 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 1ded87af9824a96c85637a7eeebbf8b8 +Signature: 36f9a4aa48517b97d1c84e5d710a42f5 ==================================================================================================== LIBRARY: etc1 diff --git a/display_list/dl_op_records.h b/display_list/dl_op_records.h index 2b5210abcbd51..3cd38e23d12b9 100644 --- a/display_list/dl_op_records.h +++ b/display_list/dl_op_records.h @@ -790,6 +790,7 @@ struct DrawImageRectOp final : DrawOpBase { #define DEFINE_DRAW_IMAGE_NINE_OP(name, render_with_attributes) \ struct name##Op final : DrawOpBase { \ static constexpr auto kType = DisplayListOpType::k##name; \ + static constexpr uint32_t kDepthInc = 9; \ \ name##Op(const sk_sp& image, \ const SkIRect& center, \ diff --git a/display_list/testing/dl_test_snippets.cc b/display_list/testing/dl_test_snippets.cc index 9dfadf47a71e5..d3ffa455082af 100644 --- a/display_list/testing/dl_test_snippets.cc +++ b/display_list/testing/dl_test_snippets.cc @@ -835,37 +835,37 @@ std::vector CreateAllRenderingOps() { }}, {"DrawImageNine", { - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, DlFilterMode::kNearest, true); }}, - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { r.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, DlFilterMode::kNearest, false); }}, - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, DlFilterMode::kLinear, false); }}, - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { r.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, - {1, 48, 1, + {1, 48, 9, [](DlOpReceiver& r) { auto dl_image = DlImage::Make(TestSkImage); r.drawImageNine(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80}, diff --git a/docs/contributing/Compiling-the-engine.md b/docs/contributing/Compiling-the-engine.md index f209d34afad93..e970754857e2d 100644 --- a/docs/contributing/Compiling-the-engine.md +++ b/docs/contributing/Compiling-the-engine.md @@ -60,7 +60,7 @@ Run the following steps, from the `src` directory created in [Setting up the Eng > 💡 **TIP**: When developing on a Mac with ARM (M CPU), prefer `host_debug_unopt_arm64`. > > You can continue to use `host_debug_unopt` (required for Intel Macs), but the engine will be run under Rosetta -> which may be slower. See [Developing with Flutter on Apple Silicon](../../platforms/desktop/macos/Developing-with-Flutter-on-Apple-Silicon.md) +> which may be slower. See [Developing with Flutter on Apple Silicon](https://github.com/flutter/flutter/blob/master/docs/platforms/desktop/macos/Developing-with-Flutter-on-Apple-Silicon.md) > for more information. 4. Build your executables @@ -80,11 +80,11 @@ If you're going to be debugging crashes in the engine, make sure you add `android/AndroidManifest.xml` file for the Flutter app you are using to test the engine. -See [The flutter tool](../../tool/README.md) for instructions on how to use the `flutter` tool with a local engine. +See [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) for instructions on how to use the `flutter` tool with a local engine. You will typically use the `android_debug_unopt` build to debug the engine on a device, and `android_debug_unopt_x64` to debug in on a simulator. Modifying dart sources in the engine will require adding a `dependency_override` section in you app's `pubspec.yaml` as detailed -[here](../../tool/README.md#using-a-locally-built-engine-with-the-flutter-tool). +[here](https://github.com/flutter/flutter/blob/master/docs/tool/README.md#using-a-locally-built-engine-with-the-flutter-tool). Note that if you use particular android or ios engine build, you will need to have corresponding host build available next to it: if you use `android_debug_unopt`, you should have built `host_debug_unopt`, @@ -133,11 +133,11 @@ Run the following steps, from the `src` directory created in the steps above: 5. `ninja -C out/ios_debug_unopt && ninja -C out/host_debug_unopt` to build all artifacts (use `out/ios_debug_sim_unopt` for Simulator). -See [The flutter tool](../../tool/README.md) for instructions on how to use the `flutter` tool with a local engine. +See [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) for instructions on how to use the `flutter` tool with a local engine. You will typically use the `ios_debug_unopt` build to debug the engine on a device, and `ios_debug_sim_unopt` to debug in on a simulator. Modifying dart sources in the engine will require adding a `dependency_override` section in you app's `pubspec.yaml` as detailed -[here](../../tool/README.md#using-a-locally-built-engine-with-the-flutter-tool). +[here](https://github.com/flutter/flutter/blob/master/docs/tool/README.md#using-a-locally-built-engine-with-the-flutter-tool). See also [instructions for debugging the engine in a Flutter app in Xcode](../Debugging-the-engine.md#debugging-ios-builds-with-xcode). @@ -155,10 +155,10 @@ These steps build the desktop embedding, and the engine used by `flutter test` o 4. `ninja -C out/host_debug_unopt` to build a desktop unoptimized binary. * If you skipped `--unoptimized`, use `ninja -C out/host_debug` instead. -See [The flutter tool](../../tool/README.md) for instructions on how to use the `flutter` tool with a local engine. +See [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) for instructions on how to use the `flutter` tool with a local engine. You will typically use the `host_debug_unopt` build in this setup. Modifying dart sources in the engine will require adding a `dependency_override` section in you app's `pubspec.yaml` as detailed -[here](../../tool/README.md#using-a-locally-built-engine-with-the-flutter-tool). +[here](https://github.com/flutter/flutter/blob/master/docs/tool/README.md#using-a-locally-built-engine-with-the-flutter-tool). ## Compiling for Windows diff --git a/docs/contributing/Setting-up-the-Engine-development-environment.md b/docs/contributing/Setting-up-the-Engine-development-environment.md index c4b7c7c0de451..3935239be0a19 100644 --- a/docs/contributing/Setting-up-the-Engine-development-environment.md +++ b/docs/contributing/Setting-up-the-Engine-development-environment.md @@ -91,8 +91,8 @@ gclient sync ## Next steps: * [Compiling the engine](Compiling-the-engine.md) explains how to actually get builds, now that you have the code. - * [The flutter tool](../../tool/README.md) has a section explaining how to use custom engine builds. - * [Signing commits](../../contributing/Signing-commits.md), to configure your environment to securely sign your commits. + * [The flutter tool](https://github.com/flutter/flutter/blob/master/docs/tool/README.md) has a section explaining how to use custom engine builds. + * [Signing commits](https://github.com/flutter/flutter/blob/master/docs/contributing/Signing-commits.md), to configure your environment to securely sign your commits. ## Editor autocomplete support diff --git a/docs/testing/Testing-the-engine.md b/docs/testing/Testing-the-engine.md index 4426f805736d5..aba1ad8d39092 100644 --- a/docs/testing/Testing-the-engine.md +++ b/docs/testing/Testing-the-engine.md @@ -329,7 +329,7 @@ Xcode and hit CMD+U. Dart unit tests are executed during pre-submit on our CI system when submitting PRs to the `flutter/engine` repository. -_See also: [Flutter Test Fonts](../../contributing/testing/Flutter-Test-Fonts.md)_ +_See also: [Flutter Test Fonts](https://github.com/flutter/flutter/blob/master/docs/contributing/testing/Flutter-Test-Fonts.md)_ ### Framework tests diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index ff10379c8ca21..74a031f09e6d8 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -177,6 +177,9 @@ class Canvas { Picture EndRecordingAsPicture(); + uint64_t GetOpDepth() const { return current_depth_; } + uint64_t GetMaxOpDepth() const { return transform_stack_.back().clip_depth; } + protected: std::deque transform_stack_; std::optional initial_cull_rect_; diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index 8513835d98586..90ab30dc7cd0b 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -19,7 +19,7 @@ namespace impeller { /// Approximately the same size as the max frames in flight. -static const constexpr size_t kHostBufferArenaSize = 3u; +static const constexpr size_t kHostBufferArenaSize = 4u; /// The host buffer class manages one more 1024 Kb blocks of device buffer /// allocations. diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc index 888f46bd393f0..2c63029cd3480 100644 --- a/impeller/display_list/dl_dispatcher.cc +++ b/impeller/display_list/dl_dispatcher.cc @@ -36,6 +36,81 @@ namespace impeller { +#if EXPERIMENTAL_CANVAS && !defined(NDEBUG) +#define USE_DEPTH_WATCHER true +#else // EXPERIMENTAL_CANVAS && !defined(NDEBUG) +#define USE_DEPTH_WATCHER false +#endif // EXPERIMENTAL_CANVAS && !defined(NDEBUG) + +#if USE_DEPTH_WATCHER + +// Invoke this macro at the top of any DlOpReceiver dispatch function +// using a number indicating the maximum depth that the operation is +// expected to consume in the Canvas. Most rendering ops consume 1 +// except for DrawImageNine that currently consumes 1 per section (i.e. 9). +// Attribute, clip and transform ops do not consume depth but this +// macro can still be used with an argument of 0 to verify that expectation. +// +// The watchdog object allocated here will automatically double-check +// the depth usage at any exit point to the function, or any other +// point at which it falls out of scope. +#define AUTO_DEPTH_WATCHER(d) \ + DepthWatcher _watcher(__FILE__, __LINE__, GetCanvas(), d) + +// While the AUTO_DEPTH_WATCHER macro will check the depth usage at +// any exit point from the dispatch function, sometimes the dispatch +// functions are somewhat compounded and result in multiple Canvas +// calls. +// +// Invoke this macro at any key points in the middle of a dispatch +// function to verify that you still haven't exceeded the maximum +// allowed depth. This is especially useful if the function does +// an implicit save/restore where the restore call might assert the +// depth constraints in a function in Canvas that can't be as easily +// traced back to a given dispatch function as these macros can. +#define AUTO_DEPTH_CHECK() _watcher.check(__FILE__, __LINE__) + +// Helper class, use the AUTO_DEPTH_WATCHER macros to access it +struct DepthWatcher { + DepthWatcher(const std::string& file, + int line, + const impeller::Canvas& canvas, + int allowed) + : file_(file), + line_(line), + canvas_(canvas), + allowed_(allowed), + old_depth_(canvas.GetOpDepth()), + old_max_(canvas.GetMaxOpDepth()) {} + + ~DepthWatcher() { check(file_, line_); } + + void check(const std::string& file, int line) { + FML_CHECK(canvas_.GetOpDepth() <= (old_depth_ + allowed_) && + canvas_.GetOpDepth() <= old_max_) + << std::endl + << "from " << file << ":" << line << std::endl + << "old/allowed/current/max = " << old_depth_ << "/" << allowed_ << "/" + << canvas_.GetOpDepth() << "/" << old_max_; + } + + private: + const std::string file_; + const int line_; + + const impeller::Canvas& canvas_; + const uint64_t allowed_; + const uint64_t old_depth_; + const uint64_t old_max_; +}; + +#else // USE_DEPTH_WATCHER + +#define AUTO_DEPTH_WATCHER(d) +#define AUTO_DEPTH_CHECK() + +#endif // USE_DEPTH_WATCHER + #define UNIMPLEMENTED \ FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__; @@ -171,6 +246,8 @@ static Matrix ToMatrix(const SkMatrix& m) { // |flutter::DlOpReceiver| void DlDispatcherBase::setAntiAlias(bool aa) { + AUTO_DEPTH_WATCHER(0u); + // Nothing to do because AA is implicit. } @@ -189,26 +266,36 @@ static Paint::Style ToStyle(flutter::DlDrawStyle style) { // |flutter::DlOpReceiver| void DlDispatcherBase::setDrawStyle(flutter::DlDrawStyle style) { + AUTO_DEPTH_WATCHER(0u); + paint_.style = ToStyle(style); } // |flutter::DlOpReceiver| void DlDispatcherBase::setColor(flutter::DlColor color) { + AUTO_DEPTH_WATCHER(0u); + paint_.color = skia_conversions::ToColor(color); } // |flutter::DlOpReceiver| void DlDispatcherBase::setStrokeWidth(SkScalar width) { + AUTO_DEPTH_WATCHER(0u); + paint_.stroke_width = width; } // |flutter::DlOpReceiver| void DlDispatcherBase::setStrokeMiter(SkScalar limit) { + AUTO_DEPTH_WATCHER(0u); + paint_.stroke_miter = limit; } // |flutter::DlOpReceiver| void DlDispatcherBase::setStrokeCap(flutter::DlStrokeCap cap) { + AUTO_DEPTH_WATCHER(0u); + switch (cap) { case flutter::DlStrokeCap::kButt: paint_.stroke_cap = Cap::kButt; @@ -224,6 +311,8 @@ void DlDispatcherBase::setStrokeCap(flutter::DlStrokeCap cap) { // |flutter::DlOpReceiver| void DlDispatcherBase::setStrokeJoin(flutter::DlStrokeJoin join) { + AUTO_DEPTH_WATCHER(0u); + switch (join) { case flutter::DlStrokeJoin::kMiter: paint_.stroke_join = Join::kMiter; @@ -274,6 +363,8 @@ static std::optional ToColorSourceType( // |flutter::DlOpReceiver| void DlDispatcherBase::setColorSource(const flutter::DlColorSource* source) { + AUTO_DEPTH_WATCHER(0u); + if (!source) { paint_.color_source = ColorSource::MakeColor(); return; @@ -460,16 +551,22 @@ static std::shared_ptr ToColorFilter( // |flutter::DlOpReceiver| void DlDispatcherBase::setColorFilter(const flutter::DlColorFilter* filter) { + AUTO_DEPTH_WATCHER(0u); + paint_.color_filter = ToColorFilter(filter); } // |flutter::DlOpReceiver| void DlDispatcherBase::setInvertColors(bool invert) { + AUTO_DEPTH_WATCHER(0u); + paint_.invert_colors = invert; } // |flutter::DlOpReceiver| void DlDispatcherBase::setBlendMode(flutter::DlBlendMode dl_mode) { + AUTO_DEPTH_WATCHER(0u); + paint_.blend_mode = ToBlendMode(dl_mode); } @@ -488,6 +585,8 @@ static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style) { // |flutter::DlOpReceiver| void DlDispatcherBase::setMaskFilter(const flutter::DlMaskFilter* filter) { + AUTO_DEPTH_WATCHER(0u); + // Needs https://github.com/flutter/flutter/issues/95434 if (filter == nullptr) { paint_.mask_blur_descriptor = std::nullopt; @@ -599,11 +698,15 @@ static std::shared_ptr ToImageFilter( // |flutter::DlOpReceiver| void DlDispatcherBase::setImageFilter(const flutter::DlImageFilter* filter) { + AUTO_DEPTH_WATCHER(0u); + paint_.image_filter = ToImageFilter(filter); } // |flutter::DlOpReceiver| void DlDispatcherBase::save(uint32_t total_content_depth) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().Save(total_content_depth); } @@ -613,6 +716,8 @@ void DlDispatcherBase::saveLayer(const SkRect& bounds, uint32_t total_content_depth, flutter::DlBlendMode max_content_mode, const flutter::DlImageFilter* backdrop) { + AUTO_DEPTH_WATCHER(1u); + auto paint = options.renders_with_attributes() ? paint_ : Paint{}; auto promise = options.content_is_clipped() ? ContentBoundsPromise::kMayClipContents @@ -643,21 +748,29 @@ void DlDispatcherBase::restore() { // |flutter::DlOpReceiver| void DlDispatcherBase::translate(SkScalar tx, SkScalar ty) { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().Translate({tx, ty, 0.0}); } // |flutter::DlOpReceiver| void DlDispatcherBase::scale(SkScalar sx, SkScalar sy) { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().Scale({sx, sy, 1.0}); } // |flutter::DlOpReceiver| void DlDispatcherBase::rotate(SkScalar degrees) { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().Rotate(Degrees{degrees}); } // |flutter::DlOpReceiver| void DlDispatcherBase::skew(SkScalar sx, SkScalar sy) { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().Skew(sx, sy); } @@ -668,6 +781,8 @@ void DlDispatcherBase::transform2DAffine(SkScalar mxx, SkScalar myx, SkScalar myy, SkScalar myt) { + AUTO_DEPTH_WATCHER(0u); + // clang-format off transformFullPerspective( mxx, mxy, 0, mxt, @@ -695,6 +810,8 @@ void DlDispatcherBase::transformFullPerspective(SkScalar mxx, SkScalar mwy, SkScalar mwz, SkScalar mwt) { + AUTO_DEPTH_WATCHER(0u); + // The order of arguments is row-major but Impeller matrices are // column-major. // clang-format off @@ -710,6 +827,8 @@ void DlDispatcherBase::transformFullPerspective(SkScalar mxx, // |flutter::DlOpReceiver| void DlDispatcherBase::transformReset() { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().ResetTransform(); GetCanvas().Transform(initial_matrix_); } @@ -728,6 +847,8 @@ static Entity::ClipOperation ToClipOperation( void DlDispatcherBase::clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().ClipRect(skia_conversions::ToRect(rect), ToClipOperation(clip_op)); } @@ -736,6 +857,8 @@ void DlDispatcherBase::clipRect(const SkRect& rect, void DlDispatcherBase::clipOval(const SkRect& bounds, ClipOp clip_op, bool is_aa) { + AUTO_DEPTH_WATCHER(0u); + GetCanvas().ClipOval(skia_conversions::ToRect(bounds), ToClipOperation(clip_op)); } @@ -744,6 +867,8 @@ void DlDispatcherBase::clipOval(const SkRect& bounds, void DlDispatcherBase::clipRRect(const SkRRect& rrect, ClipOp sk_op, bool is_aa) { + AUTO_DEPTH_WATCHER(0u); + auto clip_op = ToClipOperation(sk_op); if (rrect.isRect()) { GetCanvas().ClipRect(skia_conversions::ToRect(rrect.rect()), clip_op); @@ -774,6 +899,8 @@ const Path& DlDispatcherBase::GetOrCachePath(const CacheablePath& cache) { void DlDispatcherBase::clipPath(const CacheablePath& cache, ClipOp sk_op, bool is_aa) { + AUTO_DEPTH_WATCHER(0u); + auto clip_op = ToClipOperation(sk_op); SkRect rect; @@ -796,6 +923,8 @@ void DlDispatcherBase::clipPath(const CacheablePath& cache, // |flutter::DlOpReceiver| void DlDispatcherBase::drawColor(flutter::DlColor color, flutter::DlBlendMode dl_mode) { + AUTO_DEPTH_WATCHER(1u); + Paint paint; paint.color = skia_conversions::ToColor(color); paint.blend_mode = ToBlendMode(dl_mode); @@ -804,11 +933,15 @@ void DlDispatcherBase::drawColor(flutter::DlColor color, // |flutter::DlOpReceiver| void DlDispatcherBase::drawPaint() { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawPaint(paint_); } // |flutter::DlOpReceiver| void DlDispatcherBase::drawLine(const SkPoint& p0, const SkPoint& p1) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawLine(skia_conversions::ToPoint(p0), skia_conversions::ToPoint(p1), paint_); } @@ -817,6 +950,8 @@ void DlDispatcherBase::drawDashedLine(const DlPoint& p0, const DlPoint& p1, DlScalar on_length, DlScalar off_length) { + AUTO_DEPTH_WATCHER(1u); + Scalar length = p0.GetDistance(p1); // Reasons to defer to regular DrawLine: // length is non-positive - drawLine will draw appropriate "dot" @@ -854,21 +989,29 @@ void DlDispatcherBase::drawDashedLine(const DlPoint& p0, // |flutter::DlOpReceiver| void DlDispatcherBase::drawRect(const SkRect& rect) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawRect(skia_conversions::ToRect(rect), paint_); } // |flutter::DlOpReceiver| void DlDispatcherBase::drawOval(const SkRect& bounds) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawOval(skia_conversions::ToRect(bounds), paint_); } // |flutter::DlOpReceiver| void DlDispatcherBase::drawCircle(const SkPoint& center, SkScalar radius) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawCircle(skia_conversions::ToPoint(center), radius, paint_); } // |flutter::DlOpReceiver| void DlDispatcherBase::drawRRect(const SkRRect& rrect) { + AUTO_DEPTH_WATCHER(1u); + if (skia_conversions::IsNearlySimpleRRect(rrect)) { GetCanvas().DrawRRect(skia_conversions::ToRect(rrect.rect()), skia_conversions::ToSize(rrect.getSimpleRadii()), @@ -880,6 +1023,8 @@ void DlDispatcherBase::drawRRect(const SkRRect& rrect) { // |flutter::DlOpReceiver| void DlDispatcherBase::drawDRRect(const SkRRect& outer, const SkRRect& inner) { + AUTO_DEPTH_WATCHER(1u); + PathBuilder builder; builder.AddPath(skia_conversions::ToPath(outer)); builder.AddPath(skia_conversions::ToPath(inner)); @@ -893,6 +1038,8 @@ void DlDispatcherBase::drawPath(const SkPath& path) { // |flutter::DlOpReceiver| void DlDispatcherBase::drawPath(const CacheablePath& cache) { + AUTO_DEPTH_WATCHER(1u); + SimplifyOrDrawPath(GetCanvas(), cache, paint_); } @@ -929,6 +1076,8 @@ void DlDispatcherBase::drawArc(const SkRect& oval_bounds, SkScalar start_degrees, SkScalar sweep_degrees, bool use_center) { + AUTO_DEPTH_WATCHER(1u); + PathBuilder builder; builder.AddArc(skia_conversions::ToRect(oval_bounds), Degrees(start_degrees), Degrees(sweep_degrees), use_center); @@ -939,6 +1088,8 @@ void DlDispatcherBase::drawArc(const SkRect& oval_bounds, void DlDispatcherBase::drawPoints(PointMode mode, uint32_t count, const SkPoint points[]) { + AUTO_DEPTH_WATCHER(1u); + Paint paint = paint_; paint.style = Paint::Style::kStroke; switch (mode) { @@ -977,6 +1128,8 @@ void DlDispatcherBase::drawPoints(PointMode mode, void DlDispatcherBase::drawVertices( const std::shared_ptr& vertices, flutter::DlBlendMode dl_mode) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawVertices(MakeVertices(vertices), ToBlendMode(dl_mode), paint_); } @@ -986,6 +1139,8 @@ void DlDispatcherBase::drawImage(const sk_sp image, const SkPoint point, flutter::DlImageSampling sampling, bool render_with_attributes) { + AUTO_DEPTH_WATCHER(1u); + if (!image) { return; } @@ -1017,6 +1172,8 @@ void DlDispatcherBase::drawImageRect( flutter::DlImageSampling sampling, bool render_with_attributes, SrcRectConstraint constraint = SrcRectConstraint::kFast) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawImageRect(image->impeller_texture(), // image skia_conversions::ToRect(src), // source rect skia_conversions::ToRect(dst), // destination rect @@ -1031,6 +1188,8 @@ void DlDispatcherBase::drawImageNine(const sk_sp image, const SkRect& dst, flutter::DlFilterMode filter, bool render_with_attributes) { + AUTO_DEPTH_WATCHER(9u); + NinePatchConverter converter = {}; converter.DrawNinePatch( image->impeller_texture(), @@ -1049,6 +1208,8 @@ void DlDispatcherBase::drawAtlas(const sk_sp atlas, flutter::DlImageSampling sampling, const SkRect* cull_rect, bool render_with_attributes) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawAtlas( atlas->impeller_texture(), skia_conversions::ToRSXForms(xform, count), skia_conversions::ToRects(tex, count), ToColors(colors, count), @@ -1060,6 +1221,8 @@ void DlDispatcherBase::drawAtlas(const sk_sp atlas, void DlDispatcherBase::drawDisplayList( const sk_sp display_list, SkScalar opacity) { + AUTO_DEPTH_WATCHER(display_list->total_depth()); + // Save all values that must remain untouched after the operation. Paint saved_paint = paint_; Matrix saved_initial_matrix = initial_matrix_; @@ -1113,6 +1276,7 @@ void DlDispatcherBase::drawDisplayList( // Restore all saved state back to what it was before we interpreted // the display_list + AUTO_DEPTH_CHECK(); GetCanvas().RestoreToCount(restore_count); initial_matrix_ = saved_initial_matrix; paint_ = saved_paint; @@ -1132,6 +1296,8 @@ void DlDispatcherBase::drawTextFrame( const std::shared_ptr& text_frame, SkScalar x, SkScalar y) { + AUTO_DEPTH_WATCHER(1u); + GetCanvas().DrawTextFrame(text_frame, // impeller::Point{x, y}, // paint_ // @@ -1153,6 +1319,8 @@ void DlDispatcherBase::drawShadow(const CacheablePath& cache, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) { + AUTO_DEPTH_WATCHER(1u); + Color spot_color = skia_conversions::ToColor(color); spot_color.alpha *= 0.25; @@ -1202,6 +1370,7 @@ void DlDispatcherBase::drawShadow(const CacheablePath& cache, Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y))); SimplifyOrDrawPath(GetCanvas(), cache, paint); + AUTO_DEPTH_CHECK(); GetCanvas().Restore(); } diff --git a/impeller/docs/android_validation_layers.md b/impeller/docs/android_validation_layers.md index ae32076c686d8..b3406cc6f3f54 100644 --- a/impeller/docs/android_validation_layers.md +++ b/impeller/docs/android_validation_layers.md @@ -17,7 +17,8 @@ flutter/tools/gn \ ``` Then adding the following field to the -`android/app/src/main/AndroidManifest.xml` will turn them on: +`android/app/src/main/AndroidManifest.xml` under the `` tag will turn +them on: ```xml Reset(); EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u); + buffer->Reset(); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 3u); + buffer->Reset(); EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); } @@ -131,7 +134,7 @@ TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) { EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); // Reset until we get back to this frame. - for (auto i = 0; i < 3; i++) { + for (auto i = 0; i < 4; i++) { buffer->Reset(); } @@ -141,7 +144,7 @@ TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) { // Now when we reset, the buffer should get dropped. // Reset until we get back to this frame. - for (auto i = 0; i < 3; i++) { + for (auto i = 0; i < 4; i++) { buffer->Reset(); } diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 0a0973ba0ad01..fa2711c1e6376 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -157,18 +157,8 @@ void ContextVK::Setup(Settings settings) { auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER; dispatcher.init(settings.proc_address_callback); - // Enable Vulkan validation if either: - // 1. The user has explicitly enabled it. - // 2. We are in a combination of debug mode, and running on Android. - // (It's possible 2 is overly conservative and we can simplify this) - auto enable_validation = settings.enable_validation; - -#if defined(FML_OS_ANDROID) && !defined(NDEBUG) - enable_validation = true; -#endif - auto caps = std::shared_ptr(new CapabilitiesVK( - enable_validation, settings.fatal_missing_validations)); + settings.enable_validation, settings.fatal_missing_validations)); if (!caps->IsValid()) { VALIDATION_LOG << "Could not determine device capabilities."; diff --git a/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc index 81af3055d2b06..5c865ba722de9 100644 --- a/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc @@ -15,6 +15,7 @@ #include "impeller/renderer/backend/vulkan/swapchain/surface_vk.h" #include "impeller/toolkit/android/surface_transaction.h" #include "impeller/toolkit/android/surface_transaction_stats.h" +#include "vulkan/vulkan_to_string.hpp" namespace impeller { @@ -111,20 +112,21 @@ std::unique_ptr AHBSwapchainImplVK::AcquireNextDrawable() { return nullptr; } - auto context = transients_->GetContext().lock(); - if (context) { - ContextVK::Cast(*context).GetGPUTracer()->MarkFrameStart(); - } - // Ask the GPU to wait for the render ready semaphore to be signaled before // performing rendering operations. if (!SubmitWaitForRenderReady(pool_entry.render_ready_fence, pool_entry.texture)) { - VALIDATION_LOG << "Could not submit a command to the GPU to wait on render " - "readiness."; + VALIDATION_LOG << "Could wait on render ready fence."; return nullptr; } +#if IMPELLER_DEBUG + auto context = transients_->GetContext().lock(); + if (context) { + ContextVK::Cast(*context).GetGPUTracer()->MarkFrameStart(); + } +#endif // IMPELLER_DEBUG + auto surface = SurfaceVK::WrapSwapchainImage( transients_, pool_entry.texture, [signaler = auto_sema_signaler, weak = weak_from_this(), @@ -154,10 +156,12 @@ bool AHBSwapchainImplVK::Present( return false; } +#if IMPELLER_DEBUG auto context = transients_->GetContext().lock(); if (context) { ContextVK::Cast(*context).GetGPUTracer()->MarkFrameEnd(); } +#endif // IMPELLER_DEBUG if (!texture) { return false; @@ -308,8 +312,8 @@ bool AHBSwapchainImplVK::SubmitWaitForRenderReady( ); if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) { - VALIDATION_LOG << "Fence waiter encountered an unexpected error. Tearing " - "down the waiter thread."; + VALIDATION_LOG << "Encountered error while waiting on swapchain image: " + << vk::to_string(result); return false; } diff --git a/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc index 8be88832bb470..fa6564e43fa44 100644 --- a/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_impl_vk.cc @@ -20,11 +20,6 @@ namespace impeller { static constexpr size_t kMaxFramesInFlight = 3u; -// Number of frames to poll for orientation changes. For example `1u` means -// that the orientation will be polled every frame, while `2u` means that the -// orientation will be polled every other frame. -static constexpr size_t kPollFramesForOrientation = 1u; - struct KHRFrameSynchronizerVK { vk::UniqueFence acquire; vk::UniqueSemaphore render_ready; @@ -334,11 +329,15 @@ KHRSwapchainImplVK::AcquireResult KHRSwapchainImplVK::AcquireNextDrawable() { //---------------------------------------------------------------------------- /// Get the next image index. /// + /// @bug Non-infinite timeouts are not supported on some older Android + /// devices and the only indication we get is log spam which serves to + /// add confusion. Just use an infinite timeout instead of being + /// defensive. auto [acq_result, index] = context.GetDevice().acquireNextImageKHR( - *swapchain_, // swapchain - 1'000'000'000, // timeout (ns) 1000ms - *sync->render_ready, // signal semaphore - nullptr // fence + *swapchain_, // swapchain + std::numeric_limits::max(), // timeout (ns) + *sync->render_ready, // signal semaphore + nullptr // fence ); switch (acq_result) { diff --git a/sky/packages/sky_engine/LICENSE b/sky/packages/sky_engine/LICENSE index 1e9c13ed42e29..e86a1672a4ee8 100644 --- a/sky/packages/sky_engine/LICENSE +++ b/sky/packages/sky_engine/LICENSE @@ -32054,7 +32054,7 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. -You may obtain a copy of this library's Source Code Form from: https://dart.googlesource.com/sdk/+/b81b344a194ffedb8b775fe9e006ef3dd51ce573 +You may obtain a copy of this library's Source Code Form from: https://dart.googlesource.com/sdk/+/183b9e21b706a72c3c5997157459b67d1d66199a /third_party/fallback_root_certificates/ --------------------------------------------------------------------------------