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

Use DisplayListMatrixClipTracker in DisplayListBuilder #38349

Merged
merged 9 commits into from
Dec 20, 2022
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
99 changes: 30 additions & 69 deletions display_list/display_list_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,15 @@ sk_sp<DisplayList> DisplayListBuilder::Build() {
}

DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect,
bool prepare_rtree) {
bool prepare_rtree)
: tracker_(cull_rect, SkMatrix::I()) {
if (prepare_rtree) {
accumulator_ = std::make_unique<RTreeBoundsAccumulator>();
} else {
accumulator_ = std::make_unique<RectBoundsAccumulator>();
}

// isEmpty protects us against NaN as we normalize any empty cull rects
SkRect cull = cull_rect.isEmpty() ? SkRect::MakeEmpty() : cull_rect;
layer_stack_.emplace_back(SkM44(), SkMatrix::I(), cull);
layer_stack_.emplace_back();
current_layer_ = &layer_stack_.back();
}

Expand Down Expand Up @@ -440,9 +439,10 @@ void DisplayListBuilder::checkForDeferredSave() {
}

void DisplayListBuilder::save() {
layer_stack_.emplace_back(current_layer_);
layer_stack_.emplace_back();
current_layer_ = &layer_stack_.back();
current_layer_->has_deferred_save_op_ = true;
tracker_.save();
accumulator()->save();
}

Expand All @@ -455,6 +455,7 @@ void DisplayListBuilder::restore() {
// on the stack.
LayerInfo layer_info = layer_stack_.back();

tracker_.restore();
layer_stack_.pop_back();
current_layer_ = &layer_stack_.back();
bool is_unbounded = layer_info.is_unbounded();
Expand All @@ -463,7 +464,7 @@ void DisplayListBuilder::restore() {
// current accumulator and adjust it as required based on the filter.
std::shared_ptr<const DlImageFilter> filter = layer_info.filter();
if (filter) {
const SkRect* clip = &current_layer_->clip_bounds();
const SkRect clip = tracker_.device_cull_rect();
if (!accumulator()->restore(
[filter = filter, matrix = getTransform()](const SkRect& input,
SkRect& output) {
Expand All @@ -473,7 +474,7 @@ void DisplayListBuilder::restore() {
output.set(output_bounds);
return ret;
},
clip)) {
&clip)) {
is_unbounded = true;
}
} else {
Expand Down Expand Up @@ -544,11 +545,12 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
// We will fill the clip of the outer layer when we restore
AccumulateUnbounded();
}
layer_stack_.emplace_back(current_layer_, save_layer_offset, true,
layer_stack_.emplace_back(save_layer_offset, true,
current_.getImageFilter());
} else {
layer_stack_.emplace_back(current_layer_, save_layer_offset, true, nullptr);
layer_stack_.emplace_back(save_layer_offset, true, nullptr);
}
tracker_.save();
accumulator()->save();
current_layer_ = &layer_stack_.back();
if (options.renders_with_attributes()) {
Expand All @@ -566,7 +568,7 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
// use them as the temporary layer bounds during rendering the layer, so
// we set them as if a clip operation were performed.
if (bounds) {
intersect(*bounds);
tracker_.clipRect(*bounds, SkClipOp::kIntersect, false);
}
if (backdrop) {
// A backdrop will affect up to the entire surface, bounded by the clip
Expand All @@ -590,34 +592,30 @@ void DisplayListBuilder::translate(SkScalar tx, SkScalar ty) {
(tx != 0.0 || ty != 0.0)) {
checkForDeferredSave();
Push<TranslateOp>(0, 1, tx, ty);
current_layer_->matrix().preTranslate(tx, ty);
current_layer_->update_matrix33();
tracker_.translate(tx, ty);
}
}
void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) {
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
(sx != 1.0 || sy != 1.0)) {
checkForDeferredSave();
Push<ScaleOp>(0, 1, sx, sy);
current_layer_->matrix().preScale(sx, sy);
current_layer_->update_matrix33();
tracker_.scale(sx, sy);
}
}
void DisplayListBuilder::rotate(SkScalar degrees) {
if (SkScalarMod(degrees, 360.0) != 0.0) {
checkForDeferredSave();
Push<RotateOp>(0, 1, degrees);
current_layer_->matrix().preConcat(SkMatrix::RotateDeg(degrees));
current_layer_->update_matrix33();
tracker_.rotate(degrees);
}
}
void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) {
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
(sx != 0.0 || sy != 0.0)) {
checkForDeferredSave();
Push<SkewOp>(0, 1, sx, sy);
current_layer_->matrix().preConcat(SkMatrix::Skew(sx, sy));
current_layer_->update_matrix33();
tracker_.skew(sx, sy);
}
}

Expand All @@ -636,11 +634,8 @@ void DisplayListBuilder::transform2DAffine(
Push<Transform2DAffineOp>(0, 1,
mxx, mxy, mxt,
myx, myy, myt);
current_layer_->matrix().preConcat(SkM44(mxx, mxy, 0, mxt,
myx, myy, 0, myt,
0, 0, 1, 0,
0, 0, 0, 1));
current_layer_->update_matrix33();
tracker_.transform2DAffine(mxx, mxy, mxt,
myx, myy, myt);
}
}
// full 4x4 transform in row major order
Expand All @@ -665,19 +660,17 @@ void DisplayListBuilder::transformFullPerspective(
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt);
current_layer_->matrix().preConcat(SkM44(mxx, mxy, mxz, mxt,
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt));
current_layer_->update_matrix33();
tracker_.transformFullPerspective(mxx, mxy, mxz, mxt,
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt);
}
}
// clang-format on
void DisplayListBuilder::transformReset() {
checkForDeferredSave();
Push<TransformResetOp>(0, 0);
current_layer_->matrix().setIdentity();
current_layer_->update_matrix33();
tracker_.setIdentity();
}
void DisplayListBuilder::transform(const SkMatrix* matrix) {
if (matrix != nullptr) {
Expand All @@ -704,12 +697,12 @@ void DisplayListBuilder::clipRect(const SkRect& rect,
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectRectOp>(0, 1, rect, is_aa);
intersect(rect);
break;
case SkClipOp::kDifference:
Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
break;
}
tracker_.clipRect(rect, clip_op, is_aa);
}
void DisplayListBuilder::clipRRect(const SkRRect& rrect,
SkClipOp clip_op,
Expand All @@ -721,12 +714,12 @@ void DisplayListBuilder::clipRRect(const SkRRect& rrect,
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa);
intersect(rrect.getBounds());
break;
case SkClipOp::kDifference:
Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
break;
}
tracker_.clipRRect(rrect, clip_op, is_aa);
}
}
void DisplayListBuilder::clipPath(const SkPath& path,
Expand All @@ -753,48 +746,16 @@ void DisplayListBuilder::clipPath(const SkPath& path,
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectPathOp>(0, 1, path, is_aa);
if (!path.isInverseFillType()) {
intersect(path.getBounds());
}
break;
case SkClipOp::kDifference:
Push<ClipDifferencePathOp>(0, 1, path, is_aa);
// Map "kDifference of inverse path" to "kIntersect of the original path".
if (path.isInverseFillType()) {
intersect(path.getBounds());
}
break;
}
}
void DisplayListBuilder::intersect(const SkRect& rect) {
SkRect dev_clip_bounds = getTransform().mapRect(rect);
if (!current_layer_->clip_bounds().intersect(dev_clip_bounds)) {
current_layer_->clip_bounds().setEmpty();
}
}
SkRect DisplayListBuilder::getLocalClipBounds() {
SkM44 inverse;
if (current_layer_->matrix().invert(&inverse)) {
SkRect dev_bounds;
current_layer_->clip_bounds().roundOut(&dev_bounds);
return inverse.asM33().mapRect(dev_bounds);
}
return kMaxCullRect;
tracker_.clipPath(path, clip_op, is_aa);
}

bool DisplayListBuilder::quickReject(const SkRect& bounds) const {
if (bounds.isEmpty()) {
return true;
}
SkMatrix matrix = getTransform();
// We don't need the inverse, but this method tells us if the matrix
// is singular in which case we can reject all rendering.
if (!matrix.invert(nullptr)) {
return true;
}
SkRect dev_bounds;
matrix.mapRect(bounds).roundOut(&dev_bounds);
return !current_layer_->clip_bounds().intersects(dev_bounds);
return tracker_.content_culled(bounds);
}

void DisplayListBuilder::drawPaint() {
Expand Down Expand Up @@ -1357,7 +1318,7 @@ bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds,
}

void DisplayListBuilder::AccumulateUnbounded() {
accumulator()->accumulate(current_layer_->clip_bounds());
accumulator()->accumulate(tracker_.device_cull_rect());
}

void DisplayListBuilder::AccumulateOpBounds(SkRect& bounds,
Expand All @@ -1369,8 +1330,8 @@ void DisplayListBuilder::AccumulateOpBounds(SkRect& bounds,
}
}
void DisplayListBuilder::AccumulateBounds(SkRect& bounds) {
getTransform().mapRect(&bounds);
if (bounds.intersect(current_layer_->clip_bounds())) {
tracker_.mapRect(&bounds);
if (bounds.intersect(tracker_.device_cull_rect())) {
accumulator()->accumulate(bounds);
}
}
Expand Down
37 changes: 7 additions & 30 deletions display_list/display_list_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_flags.h"
#include "flutter/display_list/display_list_image.h"
#include "flutter/display_list/display_list_matrix_clip_tracker.h"
#include "flutter/display_list/display_list_paint.h"
#include "flutter/display_list/display_list_path_effect.h"
#include "flutter/display_list/display_list_sampling_options.h"
Expand Down Expand Up @@ -210,11 +211,11 @@ class DisplayListBuilder final : public virtual Dispatcher,
/// Returns the 4x4 full perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkM44 getTransformFullPerspective() const { return current_layer_->matrix(); }
SkM44 getTransformFullPerspective() const { return tracker_.matrix_4x4(); }
/// Returns the 3x3 partial perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkMatrix getTransform() const { return current_layer_->matrix33(); }
SkMatrix getTransform() const { return tracker_.matrix_3x3(); }

void clipRect(const SkRect& rect, SkClipOp clip_op, bool is_aa) override;
void clipRRect(const SkRRect& rrect, SkClipOp clip_op, bool is_aa) override;
Expand All @@ -223,11 +224,11 @@ class DisplayListBuilder final : public virtual Dispatcher,
/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will
/// be rendered.
SkRect getDestinationClipBounds() { return current_layer_->clip_bounds(); }
SkRect getDestinationClipBounds() { return tracker_.device_cull_rect(); }
/// Conservative estimate of the bounds of all outstanding clip operations
/// transformed into the local coordinate space in which currently
/// recorded rendering operations are interpreted.
SkRect getLocalClipBounds();
SkRect getLocalClipBounds() { return tracker_.local_cull_rect(); }

/// Return true iff the supplied bounds are easily shown to be outside
/// of the current clip bounds. This method may conservatively return
Expand Down Expand Up @@ -386,33 +387,16 @@ class DisplayListBuilder final : public virtual Dispatcher,

class LayerInfo {
public:
explicit LayerInfo(const SkM44& matrix,
const SkMatrix& matrix33,
const SkRect& clip_bounds,
size_t save_layer_offset = 0,
explicit LayerInfo(size_t save_layer_offset = 0,
bool has_layer = false,
std::shared_ptr<const DlImageFilter> filter = nullptr)
: save_layer_offset_(save_layer_offset),
has_layer_(has_layer),
cannot_inherit_opacity_(false),
has_compatible_op_(false),
matrix_(matrix),
matrix33_(matrix33),
clip_bounds_(clip_bounds),
filter_(filter),
is_unbounded_(false) {}

explicit LayerInfo(const LayerInfo* current_layer,
size_t save_layer_offset = 0,
bool has_layer = false,
std::shared_ptr<const DlImageFilter> filter = nullptr)
: LayerInfo(current_layer->matrix_,
current_layer->matrix33_,
current_layer->clip_bounds_,
save_layer_offset,
has_layer,
filter) {}

// The offset into the memory buffer where the saveLayer DLOp record
// for this saveLayer() call is placed. This may be needed if the
// eventual restore() call has discovered important information about
Expand All @@ -424,11 +408,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
bool has_layer() const { return has_layer_; }
bool cannot_inherit_opacity() const { return cannot_inherit_opacity_; }
bool has_compatible_op() const { return cannot_inherit_opacity_; }
SkM44& matrix() { return matrix_; }
SkMatrix& matrix33() { return matrix33_; }
SkRect& clip_bounds() { return clip_bounds_; }

void update_matrix33() { matrix33_ = matrix_.asM33(); }

bool is_group_opacity_compatible() const {
return !cannot_inherit_opacity_;
Expand Down Expand Up @@ -486,9 +465,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
bool has_layer_;
bool cannot_inherit_opacity_;
bool has_compatible_op_;
SkM44 matrix_;
SkMatrix matrix33_;
SkRect clip_bounds_;
std::shared_ptr<const DlImageFilter> filter_;
bool is_unbounded_;
bool has_deferred_save_op_ = false;
Expand All @@ -498,6 +474,7 @@ class DisplayListBuilder final : public virtual Dispatcher,

std::vector<LayerInfo> layer_stack_;
LayerInfo* current_layer_;
DisplayListMatrixClipTracker tracker_;
std::unique_ptr<BoundsAccumulator> accumulator_;
BoundsAccumulator* accumulator() { return accumulator_.get(); }

Expand Down
Loading