Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
#
Expand Down Expand Up @@ -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',

Expand Down Expand Up @@ -659,7 +662,7 @@ hooks = [
'pattern': '.',
'condition': 'download_windows_deps',
'action': [
'python',
'python3',
'src/build/win/generate_winrt_headers.py',
]
}
Expand Down
2 changes: 2 additions & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions flow/layers/container_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_) {
Expand Down
3 changes: 2 additions & 1 deletion flow/layers/layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
16 changes: 16 additions & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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();

Expand Down
1 change: 1 addition & 0 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
return;
}
context->has_platform_view = true;
set_subtree_has_platform_view(true);
std::unique_ptr<EmbeddedViewParams> params =
std::make_unique<EmbeddedViewParams>(matrix, size_,
context->mutators_stack);
Expand Down
55 changes: 55 additions & 0 deletions flow/layers/platform_view_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<MockCanvas::DrawCall>());
}

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<PlatformViewLayer>(layer_offset, layer_size, view_id);
auto child_clip_layer =
std::make_shared<ClipRectLayer>(child_clip, Clip::hardEdge);
auto parent_clip_layer =
std::make_shared<ClipRectLayer>(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
45 changes: 45 additions & 0 deletions flow/testing/mock_embedder.cc
Original file line number Diff line number Diff line change
@@ -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<fml::RasterThreadMerger> raster_thread_merger) {}

// |ExternalViewEmbedder|
void MockViewEmbedder::PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<EmbeddedViewParams> params) {}

// |ExternalViewEmbedder|
std::vector<SkCanvas*> MockViewEmbedder::GetCurrentCanvases() {
return std::vector<SkCanvas*>({});
}

// |ExternalViewEmbedder|
SkCanvas* MockViewEmbedder::CompositeEmbeddedView(int view_id) {
return nullptr;
}

} // namespace testing
} // namespace flutter
47 changes: 47 additions & 0 deletions flow/testing/mock_embedder.h
Original file line number Diff line number Diff line change
@@ -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<fml::RasterThreadMerger> raster_thread_merger) override;

// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(
int view_id,
std::unique_ptr<EmbeddedViewParams> params) override;

// |ExternalViewEmbedder|
std::vector<SkCanvas*> GetCurrentCanvases() override;

// |ExternalViewEmbedder|
SkCanvas* CompositeEmbeddedView(int view_id) override;
};

} // namespace testing
} // namespace flutter

#endif // FLOW_TESTING_MOCK_EMBEDDER_H_