Skip to content

Commit

Permalink
Dynamically determine whether to use offscreen surface based on need (f…
Browse files Browse the repository at this point in the history
…lutter#13976)

Only use an offscreen surface on iOS if a layer which reads back from the destination surface, such as BackdropFilter, is present.
  • Loading branch information
flar committed Nov 27, 2019
1 parent 4bdd15c commit a86ef94
Show file tree
Hide file tree
Showing 33 changed files with 386 additions and 36 deletions.
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ FILE: ../../../flutter/flow/layers/layer.cc
FILE: ../../../flutter/flow/layers/layer.h
FILE: ../../../flutter/flow/layers/layer_tree.cc
FILE: ../../../flutter/flow/layers/layer_tree.h
FILE: ../../../flutter/flow/layers/layer_unittests.cc
FILE: ../../../flutter/flow/layers/opacity_layer.cc
FILE: ../../../flutter/flow/layers/opacity_layer.h
FILE: ../../../flutter/flow/layers/performance_overlay_layer.cc
Expand Down
1 change: 1 addition & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ executable("flow_unittests") {
"flow_run_all_unittests.cc",
"flow_test_utils.cc",
"flow_test_utils.h",
"layers/layer_unittests.cc",
"layers/performance_overlay_layer_unittests.cc",
"layers/physical_shape_layer_unittests.cc",
"matrix_decomposition_unittests.cc",
Expand Down
4 changes: 3 additions & 1 deletion flow/layers/backdrop_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
namespace flutter {

BackdropFilterLayer::BackdropFilterLayer(sk_sp<SkImageFilter> filter)
: filter_(std::move(filter)) {}
: filter_(std::move(filter)) {
set_layer_reads_surface(filter_.get() != nullptr);
}

BackdropFilterLayer::~BackdropFilterLayer() = default;

Expand Down
1 change: 1 addition & 0 deletions flow/layers/clip_path_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace flutter {
ClipPathLayer::ClipPathLayer(const SkPath& clip_path, Clip clip_behavior)
: clip_path_(clip_path), clip_behavior_(clip_behavior) {
FML_DCHECK(clip_behavior != Clip::none);
set_renders_to_save_layer(clip_behavior == Clip::antiAliasWithSaveLayer);
}

ClipPathLayer::~ClipPathLayer() = default;
Expand Down
1 change: 1 addition & 0 deletions flow/layers/clip_rect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace flutter {
ClipRectLayer::ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior)
: clip_rect_(clip_rect), clip_behavior_(clip_behavior) {
FML_DCHECK(clip_behavior != Clip::none);
set_renders_to_save_layer(clip_behavior == Clip::antiAliasWithSaveLayer);
}

ClipRectLayer::~ClipRectLayer() = default;
Expand Down
1 change: 1 addition & 0 deletions flow/layers/clip_rrect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace flutter {
ClipRRectLayer::ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior)
: clip_rrect_(clip_rrect), clip_behavior_(clip_behavior) {
FML_DCHECK(clip_behavior != Clip::none);
set_renders_to_save_layer(clip_behavior == Clip::antiAliasWithSaveLayer);
}

ClipRRectLayer::~ClipRRectLayer() = default;
Expand Down
4 changes: 3 additions & 1 deletion flow/layers/color_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
namespace flutter {

ColorFilterLayer::ColorFilterLayer(sk_sp<SkColorFilter> filter)
: filter_(std::move(filter)) {}
: filter_(std::move(filter)) {
set_renders_to_save_layer(true);
}

ColorFilterLayer::~ColorFilterLayer() = default;

Expand Down
37 changes: 35 additions & 2 deletions flow/layers/container_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,46 @@

namespace flutter {

ContainerLayer::ContainerLayer() {}
ContainerLayer::ContainerLayer()
: child_needs_screen_readback_(false), renders_to_save_layer_(false) {}

ContainerLayer::~ContainerLayer() = default;

void ContainerLayer::Add(std::shared_ptr<Layer> layer) {
layer->set_parent(this);
Layer* the_layer = layer.get();
the_layer->set_parent(this);
layers_.push_back(std::move(layer));
if (the_layer->tree_reads_surface()) {
NotifyChildReadback(the_layer);
}
}

void ContainerLayer::ClearChildren() {
layers_.clear();
if (child_needs_screen_readback_) {
child_needs_screen_readback_ = false;
UpdateTreeReadsSurface();
}
}

void ContainerLayer::set_renders_to_save_layer(bool value) {
if (renders_to_save_layer_ != value) {
renders_to_save_layer_ = value;
UpdateTreeReadsSurface();
}
}

void ContainerLayer::NotifyChildReadback(const Layer* layer) {
if (child_needs_screen_readback_ || !layer->tree_reads_surface()) {
return;
}
child_needs_screen_readback_ = true;
UpdateTreeReadsSurface();
}

bool ContainerLayer::ComputeTreeReadsSurface() const {
return layer_reads_surface() ||
(!renders_to_save_layer_ && child_needs_screen_readback_);
}

void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
Expand Down
23 changes: 22 additions & 1 deletion flow/layers/container_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,43 @@ class ContainerLayer : public Layer {

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

// Called when the layer, which must be a child of this container,
// changes its tree_reads_surface() result from false to true.
void NotifyChildReadback(const Layer* layer);

protected:
void PrerollChildren(PrerollContext* context,
const SkMatrix& child_matrix,
SkRect* child_paint_bounds);
void PaintChildren(PaintContext& context) const;

virtual bool ComputeTreeReadsSurface() const override;

#if defined(OS_FUCHSIA)
void UpdateSceneChildren(SceneUpdateContext& context);
#endif // defined(OS_FUCHSIA)

// Specify whether or not the container has its children render
// to a SaveLayer which will prevent many rendering anomalies
// from propagating to the parent - such as if the children
// read back from the surface on which they render, or if the
// children perform non-associative rendering. Those children
// will now be performing those operations on the SaveLayer
// rather than the layer that this container renders onto.
void set_renders_to_save_layer(bool value);

// For OpacityLayer to restructure to have a single child.
void ClearChildren() { layers_.clear(); }
void ClearChildren();

private:
std::vector<std::shared_ptr<Layer>> layers_;

// child_needs_screen_readback_ is maintained even if the
// renders_to_save_layer_ property is set in case both
// parameters are dynamically and independently determined.
bool child_needs_screen_readback_;
bool renders_to_save_layer_;

FML_DISALLOW_COPY_AND_ASSIGN(ContainerLayer);
};

Expand Down
27 changes: 26 additions & 1 deletion flow/layers/layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#include "flutter/flow/layers/layer.h"
#include "flutter/flow/layers/container_layer.h"

#include "flutter/flow/paint_utils.h"
#include "third_party/skia/include/core/SkColorFilter.h"
Expand All @@ -13,7 +14,9 @@ Layer::Layer()
: parent_(nullptr),
needs_system_composite_(false),
paint_bounds_(SkRect::MakeEmpty()),
unique_id_(NextUniqueID()) {}
unique_id_(NextUniqueID()),
tree_reads_surface_(false),
layer_reads_surface_(false) {}

Layer::~Layer() = default;

Expand All @@ -26,6 +29,28 @@ uint64_t Layer::NextUniqueID() {
return id;
}

void Layer::set_layer_reads_surface(bool value) {
if (layer_reads_surface_ != value) {
layer_reads_surface_ = value;
UpdateTreeReadsSurface();
}
}

bool Layer::ComputeTreeReadsSurface() const {
return layer_reads_surface_;
}

void Layer::UpdateTreeReadsSurface() {
bool new_tree_reads_surface = ComputeTreeReadsSurface();

if (tree_reads_surface_ != new_tree_reads_surface) {
tree_reads_surface_ = new_tree_reads_surface;
if (parent_ != nullptr) {
parent_->NotifyChildReadback(this);
}
}
}

void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {}

#if defined(OS_FUCHSIA)
Expand Down
33 changes: 33 additions & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,47 @@ class Layer {

bool needs_painting() const { return !paint_bounds_.isEmpty(); }

// True iff the layer, or some descendant of the layer, performs an
// operation which depends on (i.e. must read back from) the surface
// on which it is rendered in any way beyond the functionality of
// BlendMode. This value has no setter as it is computed from other
// flags and properties on the layer.
// For an example see |BackdropFilterLayer|.
//
// See |UpdateTreeReadsSurface|
// See |set_layer_reads_surface|
// See |ContainerLayer::set_renders_to_save_layer|
// See |ContainerLayer::NotifyChildReadback|
bool tree_reads_surface() const { return tree_reads_surface_; }

uint64_t unique_id() const { return unique_id_; }

protected:
// Compute a new value for tree_reads_surface_ from all of the various
// properties of this layer.
// Used by |UpdateTreeReadsSurface|
virtual bool ComputeTreeReadsSurface() const;

// Update the tree_reads_surface_ value and propagate changes to
// ancestors if needed.
// Uses |ComputeTreeReadsSurface|
void UpdateTreeReadsSurface();

// True iff the layer itself (not a child or other descendant) performs
// an operation which reads from the surface on which it is rendered.
bool layer_reads_surface() const { return layer_reads_surface_; }

void set_layer_reads_surface(bool value);

private:
ContainerLayer* parent_;
bool needs_system_composite_;
SkRect paint_bounds_;
uint64_t unique_id_;

bool tree_reads_surface_;
bool layer_reads_surface_;

static uint64_t NextUniqueID();

FML_DISALLOW_COPY_AND_ASSIGN(Layer);
Expand Down
4 changes: 4 additions & 0 deletions flow/layers/layer_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class LayerTree {
root_layer_ = std::move(root_layer);
}

bool root_needs_screen_readback() const {
return root_layer_ && root_layer_->tree_reads_surface();
}

const SkISize& frame_size() const { return frame_size_; }

void set_frame_size(const SkISize& frame_size) { frame_size_ = frame_size; }
Expand Down
Loading

0 comments on commit a86ef94

Please sign in to comment.