Skip to content

Commit

Permalink
Call DisplayList builder methods directly from dart canvas (flutter#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
flar committed Nov 16, 2021
1 parent df46b79 commit 1a816e8
Show file tree
Hide file tree
Showing 13 changed files with 3,665 additions and 2,027 deletions.
348 changes: 297 additions & 51 deletions flow/display_list.cc

Large diffs are not rendered by default.

476 changes: 455 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

0 comments on commit 1a816e8

Please sign in to comment.