Make SkPaintFilterCanvas paints no longer COW.

The two existing external users of SkPaintFilterCanvas always end up
making a copy of the paint when the canvas is in use. As a result, the
extra overhead of doing COW is being wasted. In general, it seems easier
for users to optimize by simply not using the filter canvas when it
won't be making any changes. Also, no users are using the 'Type'.

After users are updated to this new API, the old onFilter can be
removed.

Change-Id: Iee1ce3cd22bce8c00664de078375b105abd7c866
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/149806
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Ben Wagner 2018-08-27 18:11:57 -04:00 committed by Skia Commit-Bot
parent 532d6c57c1
commit f55fa0d0cf
5 changed files with 86 additions and 91 deletions

View File

@ -27,23 +27,7 @@ public:
SkPaintFilterCanvas(SkCanvas* canvas);
enum Type {
kPaint_Type,
kPoint_Type,
kArc_Type,
kBitmap_Type,
kRect_Type,
kRRect_Type,
kDRRect_Type,
kOval_Type,
kPath_Type,
kPicture_Type,
kDrawable_Type,
kText_Type,
kTextBlob_Type,
kVertices_Type,
kPatch_Type,
kTypeCount
};
// Forwarded to the wrapped canvas.
@ -54,9 +38,11 @@ public:
}
protected:
/** DEPRECATED */
virtual bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const;
/**
* Called with the paint that will be used to draw the specified type.
* The implementation may modify the paint as they wish (using SkTCopyOnFirstWrite::writable).
* The implementation may modify the paint as they wish.
*
* The result bool is used to determine whether the draw op is to be
* executed (true) or skipped (false).
@ -65,7 +51,7 @@ protected:
* To also filter encapsulated paints (e.g. SkPicture, SkTextBlob), clients may need to
* override the relevant methods (i.e. drawPicture, drawTextBlob).
*/
virtual bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const = 0;
virtual bool onFilter(SkPaint& paint) const;
void onDrawPaint(const SkPaint&) override;
void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;

View File

@ -14,23 +14,37 @@
class SkPaintFilterCanvas::AutoPaintFilter {
public:
AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint* paint)
: fPaint(paint) {
fShouldDraw = canvas->onFilter(&fPaint, type);
AutoPaintFilter(const SkPaintFilterCanvas* canvas, const SkPaint* paint)
: fPaint(paint ? *paint : SkPaint()) {
fShouldDraw = canvas->onFilter(fPaint);
}
AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint& paint)
: AutoPaintFilter(canvas, type, &paint) { }
AutoPaintFilter(const SkPaintFilterCanvas* canvas, const SkPaint& paint)
: AutoPaintFilter(canvas, &paint) { }
const SkPaint* paint() const { return fPaint; }
const SkPaint& paint() const { return fPaint; }
bool shouldDraw() const { return fShouldDraw; }
private:
SkTCopyOnFirstWrite<SkPaint> fPaint;
bool fShouldDraw;
SkPaint fPaint;
bool fShouldDraw;
};
bool SkPaintFilterCanvas::onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const {
SK_ABORT("Not reached");
return false;
}
bool SkPaintFilterCanvas::onFilter(SkPaint& paint) const {
SkTCopyOnFirstWrite<SkPaint> p(paint);
bool shouldDraw = this->onFilter(&p, kPicture_Type);
if (p.get() != &paint) {
paint = *p;
}
return shouldDraw;
}
SkPaintFilterCanvas::SkPaintFilterCanvas(SkCanvas *canvas)
: SkCanvasVirtualEnforcer<SkNWayCanvas>(canvas->imageInfo().width(),
canvas->imageInfo().height()) {
@ -43,159 +57,159 @@ SkPaintFilterCanvas::SkPaintFilterCanvas(SkCanvas *canvas)
}
void SkPaintFilterCanvas::onDrawPaint(const SkPaint& paint) {
AutoPaintFilter apf(this, kPaint_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawPaint(*apf.paint());
this->SkNWayCanvas::onDrawPaint(apf.paint());
}
}
void SkPaintFilterCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
const SkPaint& paint) {
AutoPaintFilter apf(this, kPoint_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawPoints(mode, count, pts, *apf.paint());
this->SkNWayCanvas::onDrawPoints(mode, count, pts, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
AutoPaintFilter apf(this, kRect_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawRect(rect, *apf.paint());
this->SkNWayCanvas::onDrawRect(rect, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
AutoPaintFilter apf(this, kRRect_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawRRect(rrect, *apf.paint());
this->SkNWayCanvas::onDrawRRect(rrect, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
const SkPaint& paint) {
AutoPaintFilter apf(this, kDRRect_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawDRRect(outer, inner, *apf.paint());
this->SkNWayCanvas::onDrawDRRect(outer, inner, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
AutoPaintFilter apf(this, kPath_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawRegion(region, *apf.paint());
this->SkNWayCanvas::onDrawRegion(region, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
AutoPaintFilter apf(this, kOval_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawOval(rect, *apf.paint());
this->SkNWayCanvas::onDrawOval(rect, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
bool useCenter, const SkPaint& paint) {
AutoPaintFilter apf(this, kArc_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawArc(rect, startAngle, sweepAngle, useCenter, *apf.paint());
this->SkNWayCanvas::onDrawArc(rect, startAngle, sweepAngle, useCenter, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
AutoPaintFilter apf(this, kPath_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawPath(path, *apf.paint());
this->SkNWayCanvas::onDrawPath(path, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawBitmap(bm, left, top, apf.paint());
this->SkNWayCanvas::onDrawBitmap(bm, left, top, &apf.paint());
}
}
void SkPaintFilterCanvas::onDrawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint constraint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawBitmapRect(bm, src, dst, apf.paint(), constraint);
this->SkNWayCanvas::onDrawBitmapRect(bm, src, dst, &apf.paint(), constraint);
}
}
void SkPaintFilterCanvas::onDrawBitmapNine(const SkBitmap& bm, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawBitmapNine(bm, center, dst, apf.paint());
this->SkNWayCanvas::onDrawBitmapNine(bm, center, dst, &apf.paint());
}
}
void SkPaintFilterCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawBitmapLattice(bitmap, lattice, dst, apf.paint());
this->SkNWayCanvas::onDrawBitmapLattice(bitmap, lattice, dst, &apf.paint());
}
}
void SkPaintFilterCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawImage(image, left, top, apf.paint());
this->SkNWayCanvas::onDrawImage(image, left, top, &apf.paint());
}
}
void SkPaintFilterCanvas::onDrawImageRect(const SkImage* image, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
SrcRectConstraint constraint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawImageRect(image, src, dst, apf.paint(), constraint);
this->SkNWayCanvas::onDrawImageRect(image, src, dst, &apf.paint(), constraint);
}
}
void SkPaintFilterCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawImageNine(image, center, dst, apf.paint());
this->SkNWayCanvas::onDrawImageNine(image, center, dst, &apf.paint());
}
}
void SkPaintFilterCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawImageLattice(image, lattice, dst, apf.paint());
this->SkNWayCanvas::onDrawImageLattice(image, lattice, dst, &apf.paint());
}
}
void SkPaintFilterCanvas::onDrawVerticesObject(const SkVertices* vertices,
const SkVertices::Bone bones[], int boneCount,
SkBlendMode bmode, const SkPaint& paint) {
AutoPaintFilter apf(this, kVertices_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawVerticesObject(vertices, bones, boneCount, bmode, *apf.paint());
this->SkNWayCanvas::onDrawVerticesObject(vertices, bones, boneCount, bmode, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawPatch(const SkPoint cubics[], const SkColor colors[],
const SkPoint texCoords[], SkBlendMode bmode,
const SkPaint& paint) {
AutoPaintFilter apf(this, kPatch_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, *apf.paint());
this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* m,
const SkPaint* paint) {
AutoPaintFilter apf(this, kPicture_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawPicture(picture, m, apf.paint());
this->SkNWayCanvas::onDrawPicture(picture, m, &apf.paint());
}
}
@ -203,7 +217,7 @@ void SkPaintFilterCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* m
// There is no paint to filter in this case, but we can still filter on type.
// Subclasses need to unroll the drawable explicity (by overriding this method) in
// order to actually filter nested content.
AutoPaintFilter apf(this, kDrawable_Type, nullptr);
AutoPaintFilter apf(this, nullptr);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawDrawable(drawable, matrix);
}
@ -211,18 +225,18 @@ void SkPaintFilterCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* m
void SkPaintFilterCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
AutoPaintFilter apf(this, kTextBlob_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawTextBlob(blob, x, y, *apf.paint());
this->SkNWayCanvas::onDrawTextBlob(blob, x, y, apf.paint());
}
}
void SkPaintFilterCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[],
const SkRect tex[], const SkColor colors[], int count,
SkBlendMode bmode, const SkRect* cull, const SkPaint* paint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawAtlas(image, xform, tex, colors, count, bmode, cull, apf.paint());
this->SkNWayCanvas::onDrawAtlas(image, xform, tex, colors, count, bmode, cull, &apf.paint());
}
}
@ -239,10 +253,10 @@ void SkPaintFilterCanvas::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint cli
SkPaint paint;
paint.setColor(color);
paint.setBlendMode(mode);
AutoPaintFilter apf(this, kRect_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, apf.paint()->getColor(),
apf.paint()->getBlendMode());
this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, apf.paint().getColor(),
apf.paint().getBlendMode());
}
}
@ -250,10 +264,10 @@ void SkPaintFilterCanvas::onDrawEdgeAAImageSet(const ImageSetEntry set[], int co
const SkPoint dstClips[],
const SkMatrix preViewMatrices[],
const SkPaint* paint, SrcRectConstraint constraint) {
AutoPaintFilter apf(this, kBitmap_Type, paint);
AutoPaintFilter apf(this, paint);
if (apf.shouldDraw()) {
this->SkNWayCanvas::onDrawEdgeAAImageSet(
set, count, dstClips, preViewMatrices, apf.paint(), constraint);
set, count, dstClips, preViewMatrices, &apf.paint(), constraint);
}
}

View File

@ -682,7 +682,7 @@ public:
MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }
protected:
bool onFilter(SkTCopyOnFirstWrite<SkPaint>*, Type) const override { return true; }
bool onFilter(SkPaint&) const override { return true; }
private:
typedef SkPaintFilterCanvas INHERITED;

View File

@ -31,13 +31,11 @@ public:
: INHERITED(canvas), fOverdrawViz(overdrawViz) {}
protected:
bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
if (*paint) {
if (fOverdrawViz) {
paint->writable()->setColor(SK_ColorRED);
paint->writable()->setAlpha(0x08);
paint->writable()->setBlendMode(SkBlendMode::kSrcOver);
}
bool onFilter(SkPaint& paint) const override {
if (fOverdrawViz) {
paint.setColor(SK_ColorRED);
paint.setAlpha(0x08);
paint.setBlendMode(SkBlendMode::kSrcOver);
}
return true;
}

View File

@ -1162,18 +1162,15 @@ public:
return true;
}
bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
if (*paint == nullptr) {
return true;
}
bool onFilter(SkPaint& paint) const override {
if (fPaintOverrides->fAntiAlias) {
paint->writable()->setAntiAlias(fPaint->isAntiAlias());
paint.setAntiAlias(fPaint->isAntiAlias());
}
if (fPaintOverrides->fDither) {
paint->writable()->setDither(fPaint->isDither());
paint.setDither(fPaint->isDither());
}
if (fPaintOverrides->fFilterQuality) {
paint->writable()->setFilterQuality(fPaint->getFilterQuality());
paint.setFilterQuality(fPaint->getFilterQuality());
}
return true;
}