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
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ vars = {

# WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY
# See `lib/web_ui/README.md` for how to roll CanvasKit to a new version.
'canvaskit_cipd_instance': '8MSYGWVWzrTJIoVL00ZquruZs-weuwLBy1kt1AawJiIC',
'canvaskit_cipd_instance': '4PosNKiHa3EaBK4alMD4idrKYxAk0I0QiRVDDQplhOYC',

# Do not download the Emscripten SDK by default.
# This prevents us from downloading the Emscripten toolchain for builds
Expand Down
70 changes: 58 additions & 12 deletions display_list/display_list_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ sk_sp<DisplayList> DisplayListBuilder::Build() {

DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect)
: cull_rect_(cull_rect) {
layer_stack_.emplace_back();
layer_stack_.emplace_back(SkM44(), cull_rect);
current_layer_ = &layer_stack_.back();
}

Expand Down Expand Up @@ -415,7 +415,7 @@ void DisplayListBuilder::setAttributesFromPaint(

void DisplayListBuilder::save() {
Push<SaveOp>(0, 1);
layer_stack_.emplace_back();
layer_stack_.emplace_back(current_layer_);
current_layer_ = &layer_stack_.back();
}
void DisplayListBuilder::restore() {
Expand Down Expand Up @@ -476,7 +476,7 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
: Push<SaveLayerOp>(0, 1, options);
}
CheckLayerOpacityCompatibility(options.renders_with_attributes());
layer_stack_.emplace_back(save_layer_offset, true);
layer_stack_.emplace_back(current_layer_, save_layer_offset, true);
current_layer_ = &layer_stack_.back();
if (options.renders_with_attributes()) {
// |current_opacity_compatibility_| does not take an ImageFilter into
Expand Down Expand Up @@ -505,23 +505,27 @@ void DisplayListBuilder::translate(SkScalar tx, SkScalar ty) {
if (SkScalarIsFinite(tx) && SkScalarIsFinite(ty) &&
(tx != 0.0 || ty != 0.0)) {
Push<TranslateOp>(0, 1, tx, ty);
current_layer_->matrix.preTranslate(tx, ty);
}
}
void DisplayListBuilder::scale(SkScalar sx, SkScalar sy) {
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
(sx != 1.0 || sy != 1.0)) {
Push<ScaleOp>(0, 1, sx, sy);
current_layer_->matrix.preScale(sx, sy);
}
}
void DisplayListBuilder::rotate(SkScalar degrees) {
if (SkScalarMod(degrees, 360.0) != 0.0) {
Push<RotateOp>(0, 1, degrees);
current_layer_->matrix.preConcat(SkMatrix::RotateDeg(degrees));
}
}
void DisplayListBuilder::skew(SkScalar sx, SkScalar sy) {
if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) &&
(sx != 0.0 || sy != 0.0)) {
Push<SkewOp>(0, 1, sx, sy);
current_layer_->matrix.preConcat(SkMatrix::Skew(sx, sy));
}
}

Expand All @@ -539,6 +543,10 @@ 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));
}
}
// full 4x4 transform in row major order
Expand All @@ -562,11 +570,16 @@ 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));
}
}
// clang-format on
void DisplayListBuilder::transformReset() {
Push<TransformResetOp>(0, 0);
current_layer_->matrix.setIdentity();
}
void DisplayListBuilder::transform(const SkMatrix* matrix) {
if (matrix != nullptr) {
Expand All @@ -586,19 +599,35 @@ void DisplayListBuilder::transform(const SkM44* m44) {
void DisplayListBuilder::clipRect(const SkRect& rect,
SkClipOp clip_op,
bool is_aa) {
clip_op == SkClipOp::kIntersect //
? Push<ClipIntersectRectOp>(0, 1, rect, is_aa)
: Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectRectOp>(0, 1, rect, is_aa);
if (!current_layer_->clip_bounds.intersect(rect)) {
current_layer_->clip_bounds.setEmpty();
}
break;
case SkClipOp::kDifference:
Push<ClipDifferenceRectOp>(0, 1, rect, is_aa);
break;
}
}
void DisplayListBuilder::clipRRect(const SkRRect& rrect,
SkClipOp clip_op,
bool is_aa) {
if (rrect.isRect()) {
clipRect(rrect.rect(), clip_op, is_aa);
} else {
clip_op == SkClipOp::kIntersect //
? Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa)
: Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa);
if (!current_layer_->clip_bounds.intersect(rrect.getBounds())) {
current_layer_->clip_bounds.setEmpty();
}
break;
case SkClipOp::kDifference:
Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa);
break;
}
}
}
void DisplayListBuilder::clipPath(const SkPath& path,
Expand All @@ -621,9 +650,26 @@ void DisplayListBuilder::clipPath(const SkPath& path,
return;
}
}
clip_op == SkClipOp::kIntersect //
? Push<ClipIntersectPathOp>(0, 1, path, is_aa)
: Push<ClipDifferencePathOp>(0, 1, path, is_aa);
switch (clip_op) {
case SkClipOp::kIntersect:
Push<ClipIntersectPathOp>(0, 1, path, is_aa);
if (!current_layer_->clip_bounds.intersect(path.getBounds())) {
current_layer_->clip_bounds.setEmpty();
}
break;
case SkClipOp::kDifference:
Push<ClipDifferencePathOp>(0, 1, path, is_aa);
break;
}
}
SkRect DisplayListBuilder::getLocalClipBounds() {
SkM44 inverse;
if (current_layer_->matrix.invert(&inverse)) {
SkRect devBounds;
current_layer_->clip_bounds.roundOut(&devBounds);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why roundOut?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clip_bounds are sub-pixel accurate, but the actual pixels touched will be rounded out to a whole pixel which means any rendering op that touches any of these pixels might leak through into the resulting rendering since we don't actually do geometric clipping, so they must be accounted for in the returned bounds for culling analysis and they must be accounted for before the inverse transform is applied in the next line.

return inverse.asM33().mapRect(devBounds);
}
return kMaxCullRect_;
}

void DisplayListBuilder::drawPaint() {
Expand Down
38 changes: 36 additions & 2 deletions display_list/display_list_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,28 @@ class DisplayListBuilder final : public virtual Dispatcher,
void transform(const SkMatrix& matrix) { transform(&matrix); }
void transform(const SkM44& matrix44) { transform(&matrix44); }

/// Returns the 4x4 full perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkM44 getTransformFullPerspective() { return current_layer_->matrix; }
/// Returns the 3x3 partial perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkMatrix getTransform() { return current_layer_->matrix.asM33(); }

void clipRect(const SkRect& rect, SkClipOp clip_op, bool is_aa) override;
void clipRRect(const SkRRect& rrect, SkClipOp clip_op, bool is_aa) override;
void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override;

/// 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; }
/// 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();

void drawPaint() override;
void drawPaint(const DlPaint& paint);
void drawColor(DlColor color, DlBlendMode mode) override;
Expand Down Expand Up @@ -350,11 +368,24 @@ class DisplayListBuilder final : public virtual Dispatcher,
}

struct LayerInfo {
LayerInfo(size_t save_layer_offset = 0, bool has_layer = false)
LayerInfo(const SkM44& matrix,
const SkRect& clip_bounds,
size_t save_layer_offset = 0,
bool has_layer = false)
: save_layer_offset(save_layer_offset),
has_layer(has_layer),
cannot_inherit_opacity(false),
has_compatible_op(false) {}
has_compatible_op(false),
matrix(matrix),
clip_bounds(clip_bounds) {}

LayerInfo(const LayerInfo* current_layer,
size_t save_layer_offset = 0,
bool has_layer = false)
: LayerInfo(current_layer->matrix,
current_layer->clip_bounds,
save_layer_offset,
has_layer) {}

// The offset into the memory buffer where the saveLayer DLOp record
// for this saveLayer() call is placed. This may be needed if the
Expand All @@ -368,6 +399,9 @@ class DisplayListBuilder final : public virtual Dispatcher,
bool cannot_inherit_opacity;
bool has_compatible_op;

SkM44 matrix;
SkRect clip_bounds;

bool is_group_opacity_compatible() const { return !cannot_inherit_opacity; }

void mark_incompatible() { cannot_inherit_opacity = true; }
Expand Down
Loading