diff --git a/DEPS b/DEPS index c6dbd15c26c0b..ae1ec76d92030 100644 --- a/DEPS +++ b/DEPS @@ -35,7 +35,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS. # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '5cae07b3980f4684d3d477457c307a67235adf99', + 'dart_revision': '4511eb2a779a612d9d6b2012123575013e0aef12', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py @@ -96,7 +96,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + '33358ba597f875f6646522fd4ea86c1b31404d77', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + '7137efc8964bd91fa13e69af2cd3d1e13007d065', # Fuchsia compatibility # @@ -341,6 +341,9 @@ deps = { 'src/third_party/colorama/src': Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8', + 'src/third_party/expat': + Var('flutter_git') + '/third_party/expat' + '@' + '1441fc5252746e53b285d15be7e65e4cd74d97eb', + 'src/third_party/freetype2': Var('flutter_git') + '/third_party/freetype2' + '@' + '1f03c1b2d7f2ae832a4fbe9d12bd96c3c15bbece', @@ -659,7 +662,7 @@ hooks = [ 'pattern': '.', 'condition': 'download_windows_deps', 'action': [ - 'python', + 'python3', 'src/build/win/generate_winrt_headers.py', ] } diff --git a/flow/BUILD.gn b/flow/BUILD.gn index ebb8873d26e45..e112594570c3e 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -112,6 +112,8 @@ if (enable_unittests) { "testing/gl_context_switch_test.cc", "testing/gl_context_switch_test.h", "testing/layer_test.h", + "testing/mock_embedder.cc", + "testing/mock_embedder.h", "testing/mock_layer.cc", "testing/mock_layer.h", "testing/mock_raster_cache.cc", diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index 35aef14590140..925f6154e77d3 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -161,6 +161,7 @@ void ContainerLayer::PrerollChildren(PrerollContext* context, context->has_platform_view = child_has_platform_view; context->has_texture_layer = child_has_texture_layer; + set_subtree_has_platform_view(child_has_platform_view); #if defined(LEGACY_FUCHSIA_EMBEDDER) if (child_layer_exists_below_) { diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index a81607b2982df..c04c0756528e4 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -13,7 +13,8 @@ Layer::Layer() : paint_bounds_(SkRect::MakeEmpty()), unique_id_(NextUniqueID()), original_layer_id_(unique_id_), - needs_system_composite_(false) {} + needs_system_composite_(false), + subtree_has_platform_view_(false) {} Layer::~Layer() = default; diff --git a/flow/layers/layer.h b/flow/layers/layer.h index fa2674105cb8f..c3a38a9089500 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -202,6 +202,11 @@ class Layer { needs_system_composite_ = value; } + bool subtree_has_platform_view() const { return subtree_has_platform_view_; } + void set_subtree_has_platform_view(bool value) { + subtree_has_platform_view_ = value; + } + // Returns the paint bounds in the layer's local coordinate system // as determined during Preroll(). The bounds should include any // transform, clip or distortions performed by the layer itself, @@ -229,6 +234,16 @@ class Layer { // Determines if the Paint() method is necessary based on the properties // of the indicated PaintContext object. bool needs_painting(PaintContext& context) const { + if (subtree_has_platform_view_) { + // Workaround for the iOS embedder. The iOS embedder expects that + // if we preroll it, then we will later call its Paint() method. + // Now that we preroll all layers without any culling, we may + // call its Preroll() without calling its Paint(). For now, we + // will not perform paint culling on any subtree that has a + // platform view. + // See https://github.com/flutter/flutter/issues/81419 + return true; + } // Workaround for Skia bug (quickReject does not reject empty bounds). // https://bugs.chromium.org/p/skia/issues/detail?id=10951 if (paint_bounds_.isEmpty()) { @@ -264,6 +279,7 @@ class Layer { uint64_t unique_id_; uint64_t original_layer_id_; bool needs_system_composite_; + bool subtree_has_platform_view_; static uint64_t NextUniqueID(); diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 0971f93db777e..d846c401a143e 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -27,6 +27,7 @@ void PlatformViewLayer::Preroll(PrerollContext* context, return; } context->has_platform_view = true; + set_subtree_has_platform_view(true); std::unique_ptr params = std::make_unique(matrix, size_, context->mutators_stack); diff --git a/flow/layers/platform_view_layer_unittests.cc b/flow/layers/platform_view_layer_unittests.cc index 5387abc7b7ed3..56b90dd1b3dd3 100644 --- a/flow/layers/platform_view_layer_unittests.cc +++ b/flow/layers/platform_view_layer_unittests.cc @@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "flutter/flow/layers/clip_rect_layer.h" #include "flutter/flow/layers/platform_view_layer.h" #include "flutter/flow/testing/layer_test.h" +#include "flutter/flow/testing/mock_embedder.h" #include "flutter/flow/testing/mock_layer.h" #include "flutter/fml/macros.h" #include "flutter/testing/mock_canvas.h" @@ -32,11 +34,64 @@ TEST_F(PlatformViewLayerTest, NullViewEmbedderDoesntPrerollCompositeOrPaint) { #else EXPECT_FALSE(layer->needs_system_composite()); #endif // LEGACY_FUCHSIA_EMBEDDER + EXPECT_FALSE(layer->subtree_has_platform_view()); layer->Paint(paint_context()); EXPECT_EQ(paint_context().leaf_nodes_canvas, &mock_canvas()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector()); } +TEST_F(PlatformViewLayerTest, ClippedPlatformViewPrerollsAndPaintsNothing) { + const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); + const SkSize layer_size = SkSize::Make(8.0f, 8.0f); + const SkRect child_clip = SkRect::MakeLTRB(20.0f, 20.0f, 40.0f, 40.0f); + const SkRect parent_clip = SkRect::MakeLTRB(50.0f, 50.0f, 80.0f, 80.0f); + const int64_t view_id = 0; + auto layer = + std::make_shared(layer_offset, layer_size, view_id); + auto child_clip_layer = + std::make_shared(child_clip, Clip::hardEdge); + auto parent_clip_layer = + std::make_shared(parent_clip, Clip::hardEdge); + parent_clip_layer->Add(child_clip_layer); + child_clip_layer->Add(layer); + + auto embedder = MockViewEmbedder(); + preroll_context()->view_embedder = &embedder; + + parent_clip_layer->Preroll(preroll_context(), SkMatrix()); + EXPECT_TRUE(preroll_context()->has_platform_view); + EXPECT_EQ(layer->paint_bounds(), + SkRect::MakeSize(layer_size) + .makeOffset(layer_offset.fX, layer_offset.fY)); + EXPECT_TRUE(layer->needs_painting(paint_context())); + EXPECT_TRUE(child_clip_layer->needs_painting(paint_context())); + EXPECT_TRUE(parent_clip_layer->needs_painting(paint_context())); +#if defined(LEGACY_FUCHSIA_EMBEDDER) + EXPECT_TRUE(layer->needs_system_composite()); +#else + EXPECT_FALSE(layer->needs_system_composite()); +#endif // LEGACY_FUCHSIA_EMBEDDER + EXPECT_TRUE(layer->subtree_has_platform_view()); + EXPECT_TRUE(child_clip_layer->subtree_has_platform_view()); + EXPECT_TRUE(parent_clip_layer->subtree_has_platform_view()); + + parent_clip_layer->Paint(paint_context()); + EXPECT_EQ(paint_context().leaf_nodes_canvas, &mock_canvas()); + EXPECT_EQ( + mock_canvas().draw_calls(), + std::vector( + {MockCanvas::DrawCall{0, MockCanvas::SaveData{1}}, + MockCanvas::DrawCall{ + 1, MockCanvas::ClipRectData{parent_clip, SkClipOp::kIntersect, + MockCanvas::kHard_ClipEdgeStyle}}, + MockCanvas::DrawCall{1, MockCanvas::SaveData{2}}, + MockCanvas::DrawCall{ + 2, MockCanvas::ClipRectData{child_clip, SkClipOp::kIntersect, + MockCanvas::kHard_ClipEdgeStyle}}, + MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, + MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}})); +} + } // namespace testing } // namespace flutter diff --git a/flow/testing/mock_embedder.cc b/flow/testing/mock_embedder.cc new file mode 100644 index 0000000000000..11d34ee80beda --- /dev/null +++ b/flow/testing/mock_embedder.cc @@ -0,0 +1,45 @@ +// 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 "flutter/flow/testing/mock_embedder.h" + +namespace flutter { +namespace testing { + +MockViewEmbedder::MockViewEmbedder() = default; + +MockViewEmbedder::~MockViewEmbedder() = default; + +// |ExternalViewEmbedder| +SkCanvas* MockViewEmbedder::GetRootCanvas() { + return nullptr; +} + +// |ExternalViewEmbedder| +void MockViewEmbedder::CancelFrame() {} + +// |ExternalViewEmbedder| +void MockViewEmbedder::BeginFrame( + SkISize frame_size, + GrDirectContext* context, + double device_pixel_ratio, + fml::RefPtr raster_thread_merger) {} + +// |ExternalViewEmbedder| +void MockViewEmbedder::PrerollCompositeEmbeddedView( + int view_id, + std::unique_ptr params) {} + +// |ExternalViewEmbedder| +std::vector MockViewEmbedder::GetCurrentCanvases() { + return std::vector({}); +} + +// |ExternalViewEmbedder| +SkCanvas* MockViewEmbedder::CompositeEmbeddedView(int view_id) { + return nullptr; +} + +} // namespace testing +} // namespace flutter diff --git a/flow/testing/mock_embedder.h b/flow/testing/mock_embedder.h new file mode 100644 index 0000000000000..2de6ddb51c7b7 --- /dev/null +++ b/flow/testing/mock_embedder.h @@ -0,0 +1,47 @@ +// 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. + +#ifndef FLOW_TESTING_MOCK_EMBEDDER_H_ +#define FLOW_TESTING_MOCK_EMBEDDER_H_ + +#include "flutter/flow/embedded_views.h" + +namespace flutter { +namespace testing { + +class MockViewEmbedder : public ExternalViewEmbedder { + public: + MockViewEmbedder(); + + ~MockViewEmbedder(); + + // |ExternalViewEmbedder| + SkCanvas* GetRootCanvas() override; + + // |ExternalViewEmbedder| + void CancelFrame() override; + + // |ExternalViewEmbedder| + void BeginFrame( + SkISize frame_size, + GrDirectContext* context, + double device_pixel_ratio, + fml::RefPtr raster_thread_merger) override; + + // |ExternalViewEmbedder| + void PrerollCompositeEmbeddedView( + int view_id, + std::unique_ptr params) override; + + // |ExternalViewEmbedder| + std::vector GetCurrentCanvases() override; + + // |ExternalViewEmbedder| + SkCanvas* CompositeEmbeddedView(int view_id) override; +}; + +} // namespace testing +} // namespace flutter + +#endif // FLOW_TESTING_MOCK_EMBEDDER_H_