Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a86ef94

Browse files
authored
Dynamically determine whether to use offscreen surface based on need (#13976)
Only use an offscreen surface on iOS if a layer which reads back from the destination surface, such as BackdropFilter, is present.
1 parent 4bdd15c commit a86ef94

33 files changed

+386
-36
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ FILE: ../../../flutter/flow/layers/layer.cc
4646
FILE: ../../../flutter/flow/layers/layer.h
4747
FILE: ../../../flutter/flow/layers/layer_tree.cc
4848
FILE: ../../../flutter/flow/layers/layer_tree.h
49+
FILE: ../../../flutter/flow/layers/layer_unittests.cc
4950
FILE: ../../../flutter/flow/layers/opacity_layer.cc
5051
FILE: ../../../flutter/flow/layers/opacity_layer.h
5152
FILE: ../../../flutter/flow/layers/performance_overlay_layer.cc

flow/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ executable("flow_unittests") {
109109
"flow_run_all_unittests.cc",
110110
"flow_test_utils.cc",
111111
"flow_test_utils.h",
112+
"layers/layer_unittests.cc",
112113
"layers/performance_overlay_layer_unittests.cc",
113114
"layers/physical_shape_layer_unittests.cc",
114115
"matrix_decomposition_unittests.cc",

flow/layers/backdrop_filter_layer.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
namespace flutter {
88

99
BackdropFilterLayer::BackdropFilterLayer(sk_sp<SkImageFilter> filter)
10-
: filter_(std::move(filter)) {}
10+
: filter_(std::move(filter)) {
11+
set_layer_reads_surface(filter_.get() != nullptr);
12+
}
1113

1214
BackdropFilterLayer::~BackdropFilterLayer() = default;
1315

flow/layers/clip_path_layer.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace flutter {
1515
ClipPathLayer::ClipPathLayer(const SkPath& clip_path, Clip clip_behavior)
1616
: clip_path_(clip_path), clip_behavior_(clip_behavior) {
1717
FML_DCHECK(clip_behavior != Clip::none);
18+
set_renders_to_save_layer(clip_behavior == Clip::antiAliasWithSaveLayer);
1819
}
1920

2021
ClipPathLayer::~ClipPathLayer() = default;

flow/layers/clip_rect_layer.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace flutter {
99
ClipRectLayer::ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior)
1010
: clip_rect_(clip_rect), clip_behavior_(clip_behavior) {
1111
FML_DCHECK(clip_behavior != Clip::none);
12+
set_renders_to_save_layer(clip_behavior == Clip::antiAliasWithSaveLayer);
1213
}
1314

1415
ClipRectLayer::~ClipRectLayer() = default;

flow/layers/clip_rrect_layer.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace flutter {
99
ClipRRectLayer::ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior)
1010
: clip_rrect_(clip_rrect), clip_behavior_(clip_behavior) {
1111
FML_DCHECK(clip_behavior != Clip::none);
12+
set_renders_to_save_layer(clip_behavior == Clip::antiAliasWithSaveLayer);
1213
}
1314

1415
ClipRRectLayer::~ClipRRectLayer() = default;

flow/layers/color_filter_layer.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
namespace flutter {
88

99
ColorFilterLayer::ColorFilterLayer(sk_sp<SkColorFilter> filter)
10-
: filter_(std::move(filter)) {}
10+
: filter_(std::move(filter)) {
11+
set_renders_to_save_layer(true);
12+
}
1113

1214
ColorFilterLayer::~ColorFilterLayer() = default;
1315

flow/layers/container_layer.cc

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,46 @@
66

77
namespace flutter {
88

9-
ContainerLayer::ContainerLayer() {}
9+
ContainerLayer::ContainerLayer()
10+
: child_needs_screen_readback_(false), renders_to_save_layer_(false) {}
1011

1112
ContainerLayer::~ContainerLayer() = default;
1213

1314
void ContainerLayer::Add(std::shared_ptr<Layer> layer) {
14-
layer->set_parent(this);
15+
Layer* the_layer = layer.get();
16+
the_layer->set_parent(this);
1517
layers_.push_back(std::move(layer));
18+
if (the_layer->tree_reads_surface()) {
19+
NotifyChildReadback(the_layer);
20+
}
21+
}
22+
23+
void ContainerLayer::ClearChildren() {
24+
layers_.clear();
25+
if (child_needs_screen_readback_) {
26+
child_needs_screen_readback_ = false;
27+
UpdateTreeReadsSurface();
28+
}
29+
}
30+
31+
void ContainerLayer::set_renders_to_save_layer(bool value) {
32+
if (renders_to_save_layer_ != value) {
33+
renders_to_save_layer_ = value;
34+
UpdateTreeReadsSurface();
35+
}
36+
}
37+
38+
void ContainerLayer::NotifyChildReadback(const Layer* layer) {
39+
if (child_needs_screen_readback_ || !layer->tree_reads_surface()) {
40+
return;
41+
}
42+
child_needs_screen_readback_ = true;
43+
UpdateTreeReadsSurface();
44+
}
45+
46+
bool ContainerLayer::ComputeTreeReadsSurface() const {
47+
return layer_reads_surface() ||
48+
(!renders_to_save_layer_ && child_needs_screen_readback_);
1649
}
1750

1851
void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {

flow/layers/container_layer.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,43 @@ class ContainerLayer : public Layer {
2525

2626
const std::vector<std::shared_ptr<Layer>>& layers() const { return layers_; }
2727

28+
// Called when the layer, which must be a child of this container,
29+
// changes its tree_reads_surface() result from false to true.
30+
void NotifyChildReadback(const Layer* layer);
31+
2832
protected:
2933
void PrerollChildren(PrerollContext* context,
3034
const SkMatrix& child_matrix,
3135
SkRect* child_paint_bounds);
3236
void PaintChildren(PaintContext& context) const;
3337

38+
virtual bool ComputeTreeReadsSurface() const override;
39+
3440
#if defined(OS_FUCHSIA)
3541
void UpdateSceneChildren(SceneUpdateContext& context);
3642
#endif // defined(OS_FUCHSIA)
3743

44+
// Specify whether or not the container has its children render
45+
// to a SaveLayer which will prevent many rendering anomalies
46+
// from propagating to the parent - such as if the children
47+
// read back from the surface on which they render, or if the
48+
// children perform non-associative rendering. Those children
49+
// will now be performing those operations on the SaveLayer
50+
// rather than the layer that this container renders onto.
51+
void set_renders_to_save_layer(bool value);
52+
3853
// For OpacityLayer to restructure to have a single child.
39-
void ClearChildren() { layers_.clear(); }
54+
void ClearChildren();
4055

4156
private:
4257
std::vector<std::shared_ptr<Layer>> layers_;
4358

59+
// child_needs_screen_readback_ is maintained even if the
60+
// renders_to_save_layer_ property is set in case both
61+
// parameters are dynamically and independently determined.
62+
bool child_needs_screen_readback_;
63+
bool renders_to_save_layer_;
64+
4465
FML_DISALLOW_COPY_AND_ASSIGN(ContainerLayer);
4566
};
4667

flow/layers/layer.cc

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
#include "flutter/flow/layers/layer.h"
6+
#include "flutter/flow/layers/container_layer.h"
67

78
#include "flutter/flow/paint_utils.h"
89
#include "third_party/skia/include/core/SkColorFilter.h"
@@ -13,7 +14,9 @@ Layer::Layer()
1314
: parent_(nullptr),
1415
needs_system_composite_(false),
1516
paint_bounds_(SkRect::MakeEmpty()),
16-
unique_id_(NextUniqueID()) {}
17+
unique_id_(NextUniqueID()),
18+
tree_reads_surface_(false),
19+
layer_reads_surface_(false) {}
1720

1821
Layer::~Layer() = default;
1922

@@ -26,6 +29,28 @@ uint64_t Layer::NextUniqueID() {
2629
return id;
2730
}
2831

32+
void Layer::set_layer_reads_surface(bool value) {
33+
if (layer_reads_surface_ != value) {
34+
layer_reads_surface_ = value;
35+
UpdateTreeReadsSurface();
36+
}
37+
}
38+
39+
bool Layer::ComputeTreeReadsSurface() const {
40+
return layer_reads_surface_;
41+
}
42+
43+
void Layer::UpdateTreeReadsSurface() {
44+
bool new_tree_reads_surface = ComputeTreeReadsSurface();
45+
46+
if (tree_reads_surface_ != new_tree_reads_surface) {
47+
tree_reads_surface_ = new_tree_reads_surface;
48+
if (parent_ != nullptr) {
49+
parent_->NotifyChildReadback(this);
50+
}
51+
}
52+
}
53+
2954
void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {}
3055

3156
#if defined(OS_FUCHSIA)

0 commit comments

Comments
 (0)