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
345 changes: 295 additions & 50 deletions flow/display_list.cc

Large diffs are not rendered by default.

468 changes: 447 additions & 21 deletions flow/display_list.h

Large diffs are not rendered by default.

155 changes: 29 additions & 126 deletions flow/display_list_canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ void DisplayListCanvasRecorder::willSave() {
SkCanvas::SaveLayerStrategy DisplayListCanvasRecorder::getSaveLayerStrategy(
const SaveLayerRec& rec) {
if (rec.fPaint) {
RecordPaintAttributes(rec.fPaint, DrawType::kSaveLayerOpType);
builder_->setAttributesFromPaint(*rec.fPaint, kSaveLayerWithPaintFlags);
builder_->saveLayer(rec.fBounds, true);
} else {
builder_->saveLayer(rec.fBounds, false);
Expand All @@ -273,49 +273,62 @@ void DisplayListCanvasRecorder::didRestore() {
}

void DisplayListCanvasRecorder::onDrawPaint(const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kFillOpType);
builder_->setAttributesFromPaint(paint, kDrawPaintFlags);
builder_->drawPaint();
}
void DisplayListCanvasRecorder::onDrawRect(const SkRect& rect,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawRectFlags);
builder_->drawRect(rect);
}
void DisplayListCanvasRecorder::onDrawRRect(const SkRRect& rrect,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawRRectFlags);
builder_->drawRRect(rrect);
}
void DisplayListCanvasRecorder::onDrawDRRect(const SkRRect& outer,
const SkRRect& inner,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawDRRectFlags);
builder_->drawDRRect(outer, inner);
}
void DisplayListCanvasRecorder::onDrawOval(const SkRect& rect,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawOvalFlags);
builder_->drawOval(rect);
}
void DisplayListCanvasRecorder::onDrawArc(const SkRect& rect,
SkScalar startAngle,
SkScalar sweepAngle,
bool useCenter,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint,
useCenter //
? kDrawArcWithCenterFlags
: kDrawArcNoCenterFlags);
builder_->drawArc(rect, startAngle, sweepAngle, useCenter);
}
void DisplayListCanvasRecorder::onDrawPath(const SkPath& path,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawPathFlags);
builder_->drawPath(path);
}

void DisplayListCanvasRecorder::onDrawPoints(SkCanvas::PointMode mode,
size_t count,
const SkPoint pts[],
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kStrokeOpType);
switch (mode) {
case SkCanvas::kPoints_PointMode:
builder_->setAttributesFromPaint(paint, kDrawPointsAsPointsFlags);
break;
case SkCanvas::kLines_PointMode:
builder_->setAttributesFromPaint(paint, kDrawPointsAsLinesFlags);
break;
case SkCanvas::kPolygon_PointMode:
builder_->setAttributesFromPaint(paint, kDrawPointsAsPolygonFlags);
break;
}
if (mode == SkCanvas::PointMode::kLines_PointMode && count == 2) {
builder_->drawLine(pts[0], pts[1]);
} else {
Expand All @@ -330,7 +343,7 @@ void DisplayListCanvasRecorder::onDrawPoints(SkCanvas::PointMode mode,
void DisplayListCanvasRecorder::onDrawVerticesObject(const SkVertices* vertices,
SkBlendMode mode,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawVerticesFlags);
builder_->drawVertices(sk_ref_sp(vertices), mode);
}

Expand All @@ -340,7 +353,7 @@ void DisplayListCanvasRecorder::onDrawImage2(const SkImage* image,
const SkSamplingOptions& sampling,
const SkPaint* paint) {
if (paint != nullptr) {
RecordPaintAttributes(paint, DrawType::kImageOpType);
builder_->setAttributesFromPaint(*paint, kDrawImageWithPaintFlags);
}
builder_->drawImage(sk_ref_sp(image), SkPoint::Make(dx, dy), sampling,
paint != nullptr);
Expand All @@ -353,7 +366,7 @@ void DisplayListCanvasRecorder::onDrawImageRect2(
const SkPaint* paint,
SrcRectConstraint constraint) {
if (paint != nullptr) {
RecordPaintAttributes(paint, DrawType::kImageRectOpType);
builder_->setAttributesFromPaint(*paint, kDrawImageRectWithPaintFlags);
}
builder_->drawImageRect(sk_ref_sp(image), src, dst, sampling,
paint != nullptr, constraint);
Expand All @@ -370,7 +383,7 @@ void DisplayListCanvasRecorder::onDrawImageLattice2(const SkImage* image,
if (*paint == default_paint) {
paint = nullptr;
} else {
RecordPaintAttributes(paint, DrawType::kImageOpType);
builder_->setAttributesFromPaint(*paint, kDrawImageLatticeWithPaintFlags);
}
}
builder_->drawImageLattice(sk_ref_sp(image), lattice, dst, filter,
Expand All @@ -386,7 +399,7 @@ void DisplayListCanvasRecorder::onDrawAtlas2(const SkImage* image,
const SkRect* cull,
const SkPaint* paint) {
if (paint != nullptr) {
RecordPaintAttributes(paint, DrawType::kImageOpType);
builder_->setAttributesFromPaint(*paint, kDrawAtlasWithPaintFlags);
}
builder_->drawAtlas(sk_ref_sp(image), xform, src, colors, count, mode,
sampling, cull, paint != nullptr);
Expand All @@ -396,7 +409,7 @@ void DisplayListCanvasRecorder::onDrawTextBlob(const SkTextBlob* blob,
SkScalar x,
SkScalar y,
const SkPaint& paint) {
RecordPaintAttributes(&paint, DrawType::kDrawOpType);
builder_->setAttributesFromPaint(paint, kDrawTextBlobFlags);
builder_->drawTextBlob(sk_ref_sp(blob), x, y);
}
void DisplayListCanvasRecorder::onDrawShadowRec(const SkPath& path,
Expand All @@ -411,119 +424,9 @@ void DisplayListCanvasRecorder::onDrawPicture(const SkPicture* picture,
const SkMatrix* matrix,
const SkPaint* paint) {
if (paint != nullptr) {
RecordPaintAttributes(paint, DrawType::kSaveLayerOpType);
builder_->setAttributesFromPaint(*paint, kDrawPictureWithPaintFlags);
}
builder_->drawPicture(sk_ref_sp(picture), matrix, paint != nullptr);
}

void DisplayListCanvasRecorder::RecordPaintAttributes(const SkPaint* paint,
DrawType type) {
int dataNeeded;
switch (type) {
case DrawType::kDrawOpType:
dataNeeded = kDrawMask_;
break;
case DrawType::kFillOpType:
dataNeeded = kPaintMask_;
break;
case DrawType::kStrokeOpType:
dataNeeded = kStrokeMask_;
break;
case DrawType::kImageOpType:
dataNeeded = kImageMask_;
break;
case DrawType::kImageRectOpType:
dataNeeded = kImageRectMask_;
break;
case DrawType::kSaveLayerOpType:
dataNeeded = kSaveLayerMask_;
break;
default:
FML_DCHECK(false);
return;
}
if (paint == nullptr) {
paint = new SkPaint();
}
if ((dataNeeded & kAaNeeded_) != 0 && current_aa_ != paint->isAntiAlias()) {
builder_->setAntiAlias(current_aa_ = paint->isAntiAlias());
}
if ((dataNeeded & kDitherNeeded_) != 0 &&
current_dither_ != paint->isDither()) {
builder_->setDither(current_dither_ = paint->isDither());
}
if ((dataNeeded & kColorNeeded_) != 0 &&
current_color_ != paint->getColor()) {
builder_->setColor(current_color_ = paint->getColor());
}
if ((dataNeeded & kBlendNeeded_)) {
skstd::optional<SkBlendMode> mode_optional = paint->asBlendMode();
if (mode_optional) {
SkBlendMode mode = mode_optional.value();
if (current_blender_ || current_blend_ != mode) {
builder_->setBlendMode(current_blend_ = mode);
current_blender_ = nullptr;
}
} else {
if (current_blender_.get() != paint->getBlender()) {
builder_->setBlender(current_blender_ = sk_ref_sp(paint->getBlender()));
}
}
}
// invert colors is a Flutter::Paint thing, not an SkPaint thing
// if ((dataNeeded & invertColorsNeeded_) != 0 &&
// currentInvertColors_ != paint->???) {
// currentInvertColors_ = paint->invertColors;
// addOp_(currentInvertColors_
// ? _CanvasOp.setInvertColors
// : _CanvasOp.clearInvertColors, 0);
// }
if ((dataNeeded & kPaintStyleNeeded_) != 0) {
if (current_style_ != paint->getStyle()) {
builder_->setStyle(current_style_ = paint->getStyle());
}
if (current_style_ == SkPaint::Style::kStroke_Style) {
dataNeeded |= kStrokeStyleNeeded_;
}
}
if ((dataNeeded & kStrokeStyleNeeded_) != 0) {
if (current_stroke_width_ != paint->getStrokeWidth()) {
builder_->setStrokeWidth(current_stroke_width_ = paint->getStrokeWidth());
}
if (current_cap_ != paint->getStrokeCap()) {
builder_->setStrokeCap(current_cap_ = paint->getStrokeCap());
}
if (current_join_ != paint->getStrokeJoin()) {
builder_->setStrokeJoin(current_join_ = paint->getStrokeJoin());
}
if (current_miter_limit_ != paint->getStrokeMiter()) {
builder_->setStrokeMiter(current_miter_limit_ = paint->getStrokeMiter());
}
}
if ((dataNeeded & kShaderNeeded_) != 0 &&
current_shader_.get() != paint->getShader()) {
builder_->setShader(current_shader_ = sk_ref_sp(paint->getShader()));
}
if ((dataNeeded & kColorFilterNeeded_) != 0 &&
current_color_filter_.get() != paint->getColorFilter()) {
builder_->setColorFilter(current_color_filter_ =
sk_ref_sp(paint->getColorFilter()));
}
if ((dataNeeded & kImageFilterNeeded_) != 0 &&
current_image_filter_.get() != paint->getImageFilter()) {
builder_->setImageFilter(current_image_filter_ =
sk_ref_sp(paint->getImageFilter()));
}
if ((dataNeeded & kPathEffectNeeded_) != 0 &&
current_path_effect_.get() != paint->getPathEffect()) {
builder_->setPathEffect(current_path_effect_ =
sk_ref_sp(paint->getPathEffect()));
}
if ((dataNeeded & kMaskFilterNeeded_) != 0 &&
current_mask_filter_.get() != paint->getMaskFilter()) {
builder_->setMaskFilter(current_mask_filter_ =
sk_ref_sp(paint->getMaskFilter()));
}
}

} // namespace flutter
81 changes: 5 additions & 76 deletions flow/display_list_canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override;
// clang-format on

void clipRect(const SkRect& rect, SkClipOp clip_op, bool isAA) override;
void clipRRect(const SkRRect& rrect, SkClipOp clip_op, bool isAA) override;
void clipPath(const SkPath& path, SkClipOp clip_op, bool isAA) override;
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;

void drawPaint() override;
void drawColor(SkColor color, SkBlendMode mode) override;
Expand Down Expand Up @@ -120,7 +120,8 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
// Receives all methods on SkCanvas and sends them to a DisplayListBuilder
class DisplayListCanvasRecorder
: public SkCanvasVirtualEnforcer<SkNoDrawCanvas>,
public SkRefCnt {
public SkRefCnt,
DisplayListOpFlags {
public:
DisplayListCanvasRecorder(const SkRect& bounds);

Expand Down Expand Up @@ -233,80 +234,8 @@ class DisplayListCanvasRecorder
const SkMatrix* matrix,
const SkPaint* paint) override;

enum class DrawType {
// The operation will be an image operation
kImageOpType,
// The operation will be an imageRect operation
kImageRectOpType,
// The operation will be a fill or stroke depending on the paint.style
kDrawOpType,
// The operation will be a fill (ignoring paint.style)
kFillOpType,
// The operation will be a stroke (ignoring paint.style)
kStrokeOpType,
// The operation will be a saveLayer with a paint object
kSaveLayerOpType,
};

void RecordPaintAttributes(const SkPaint* paint, DrawType type);

private:
sk_sp<DisplayListBuilder> builder_;

// Mask bits for the various attributes that might be needed for a given
// operation.
// clang-format off
static constexpr int kAaNeeded_ = 1 << 0;
static constexpr int kColorNeeded_ = 1 << 1;
static constexpr int kBlendNeeded_ = 1 << 2;
static constexpr int kInvertColorsNeeded_ = 1 << 3;
static constexpr int kPaintStyleNeeded_ = 1 << 4;
static constexpr int kStrokeStyleNeeded_ = 1 << 5;
static constexpr int kShaderNeeded_ = 1 << 6;
static constexpr int kColorFilterNeeded_ = 1 << 7;
static constexpr int kImageFilterNeeded_ = 1 << 8;
static constexpr int kPathEffectNeeded_ = 1 << 9;
static constexpr int kMaskFilterNeeded_ = 1 << 10;
static constexpr int kDitherNeeded_ = 1 << 11;
// clang-format on

// Combinations of the above mask bits that are common to typical "draw"
// calls.
// Note that the strokeStyle_ is handled conditionally depending on whether
// the paintStyle_ attribute value is synchronized. It can also be manually
// specified for operations that will be always stroking, like [drawLine].
static constexpr int kPaintMask_ = kAaNeeded_ | kColorNeeded_ |
kBlendNeeded_ | kInvertColorsNeeded_ |
kColorFilterNeeded_ | kShaderNeeded_ |
kDitherNeeded_ | kImageFilterNeeded_;
static constexpr int kDrawMask_ = kPaintMask_ | kPaintStyleNeeded_ |
kMaskFilterNeeded_ | kPathEffectNeeded_;
static constexpr int kStrokeMask_ = kPaintMask_ | kStrokeStyleNeeded_ |
kMaskFilterNeeded_ | kPathEffectNeeded_;
static constexpr int kImageMask_ = kColorNeeded_ | kBlendNeeded_ |
kInvertColorsNeeded_ |
kColorFilterNeeded_ | kDitherNeeded_ |
kImageFilterNeeded_ | kMaskFilterNeeded_;
static constexpr int kImageRectMask_ = kImageMask_ | kAaNeeded_;
static constexpr int kSaveLayerMask_ =
kColorNeeded_ | kBlendNeeded_ | kInvertColorsNeeded_ |
kColorFilterNeeded_ | kImageFilterNeeded_;

bool current_aa_ = false;
bool current_dither_ = false;
SkColor current_color_ = 0xFF000000;
SkBlendMode current_blend_ = SkBlendMode::kSrcOver;
SkPaint::Style current_style_ = SkPaint::Style::kFill_Style;
SkScalar current_stroke_width_ = 0.0;
SkScalar current_miter_limit_ = 4.0;
SkPaint::Cap current_cap_ = SkPaint::Cap::kButt_Cap;
SkPaint::Join current_join_ = SkPaint::Join::kMiter_Join;
sk_sp<SkBlender> current_blender_;
sk_sp<SkShader> current_shader_;
sk_sp<SkColorFilter> current_color_filter_;
sk_sp<SkImageFilter> current_image_filter_;
sk_sp<SkPathEffect> current_path_effect_;
sk_sp<SkMaskFilter> current_mask_filter_;
};

} // namespace flutter
Expand Down
Loading