Add drawRegion() API to SkCanvas
This will allow us to optimize for the RectGrid macrobench.
Currently, SkiaGL is much slower than OpenGL.
SkiaGL 12 items/s
OpenGL 160 items/s
This contains everything except for the fast implementation on GPU.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2277053002
Review-Url: https://codereview.chromium.org/2277053002
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 8f9a576..4cf40e9 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2250,6 +2250,26 @@
}
}
+void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
+ SkRect storage;
+ SkRect regionRect = SkRect::Make(region.getBounds());
+ const SkRect* bounds = nullptr;
+ if (paint.canComputeFastBounds()) {
+ if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
+ return;
+ }
+ bounds = ®ionRect;
+ }
+
+ LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
+
+ while (iter.next()) {
+ iter.fDevice->drawRegion(iter, region, looper.paint());
+ }
+
+ LOOPER_END
+}
+
void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
SkRect storage;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 1f3bd61..8a9fa96 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -73,6 +73,29 @@
return geo;
}
+static inline bool is_int(float x) {
+ return x == (float) sk_float_round2int(x);
+}
+
+void SkBaseDevice::drawRegion(const SkDraw& draw, const SkRegion& region, const SkPaint& paint) {
+ bool isNonTranslate = draw.fMatrix->getType() & ~(SkMatrix::kTranslate_Mask);
+ bool complexPaint = paint.getStyle() != SkPaint::kFill_Style || paint.getMaskFilter() ||
+ paint.getPathEffect();
+ bool antiAlias = paint.isAntiAlias() && (!is_int(draw.fMatrix->getTranslateX()) ||
+ !is_int(draw.fMatrix->getTranslateY()));
+ if (isNonTranslate || complexPaint || antiAlias) {
+ SkPath path;
+ region.getBoundaryPath(&path);
+ return this->drawPath(draw, path, paint, nullptr, false);
+ }
+
+ SkRegion::Iterator it(region);
+ while (!it.done()) {
+ this->drawRect(draw, SkRect::Make(it.rect()), paint);
+ it.next();
+ }
+}
+
void SkBaseDevice::drawArc(const SkDraw& draw, const SkRect& oval, SkScalar startAngle,
SkScalar sweepAngle, bool useCenter, const SkPaint& paint) {
SkPath path;
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index d94e139..af4f5c2 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -54,8 +54,8 @@
M(Save) M(Restore) M(SaveLayer) \
M(Concat) M(SetMatrix) M(Translate) M(TranslateZ) \
M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \
- M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawOval) M(DrawArc) M(DrawRRect) \
- M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \
+ M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawRegion) M(DrawOval) M(DrawArc) \
+ M(DrawRRect) M(DrawDRRect) M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) \
M(DrawShadowedPicture) \
M(DrawImage) M(DrawImageNine) M(DrawImageRect) M(DrawImageLattice) \
M(DrawText) M(DrawPosText) M(DrawPosTextH) \
@@ -189,6 +189,13 @@
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) { c->drawRect(rect, paint); }
};
+ struct DrawRegion final : Op {
+ static const auto kType = Type::DrawRegion;
+ DrawRegion(const SkRegion& region, const SkPaint& paint) : region(region), paint(paint) {}
+ SkRegion region;
+ SkPaint paint;
+ void draw(SkCanvas* c, const SkMatrix&) { c->drawRegion(region, paint); }
+ };
struct DrawOval final : Op {
static const auto kType = Type::DrawOval;
DrawOval(const SkRect& oval, const SkPaint& paint) : oval(oval), paint(paint) {}
@@ -592,6 +599,9 @@
void SkLiteDL::drawRect(const SkRect& rect, const SkPaint& paint) {
this->push<DrawRect>(0, rect, paint);
}
+void SkLiteDL::drawRegion(const SkRegion& region, const SkPaint& paint) {
+ this->push<DrawRegion>(0, region, paint);
+}
void SkLiteDL::drawOval(const SkRect& oval, const SkPaint& paint) {
this->push<DrawOval>(0, oval, paint);
}
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 4f28486..1549576 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -40,6 +40,7 @@
void drawPaint (const SkPaint&);
void drawPath (const SkPath&, const SkPaint&);
void drawRect (const SkRect&, const SkPaint&);
+ void drawRegion(const SkRegion&, const SkPaint&);
void drawOval (const SkRect&, const SkPaint&);
void drawArc (const SkRect&, SkScalar, SkScalar, bool, const SkPaint&);
void drawRRect (const SkRRect&, const SkPaint&);
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index 42218ac..262cdda 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -55,6 +55,9 @@
void SkLiteRecorder::onDrawRect(const SkRect& rect, const SkPaint& paint) {
fDL->drawRect(rect, paint);
}
+void SkLiteRecorder::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
+ fDL->drawRegion(region, paint);
+}
void SkLiteRecorder::onDrawOval(const SkRect& oval, const SkPaint& paint) {
fDL->drawOval(oval, paint);
}
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index c4e80cd..a1a273c 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -33,9 +33,10 @@
void onClipRegion(const SkRegion&, SkRegion::Op) override;
void onDrawPaint (const SkPaint&) override;
- void onDrawPath (const SkPath&, const SkPaint&) override;
- void onDrawRect (const SkRect&, const SkPaint&) override;
- void onDrawOval (const SkRect&, const SkPaint&) override;
+ void onDrawPath (const SkPath&, const SkPaint&) override;
+ void onDrawRect (const SkRect&, const SkPaint&) override;
+ void onDrawRegion(const SkRegion&, const SkPaint&) override;
+ void onDrawOval (const SkRect&, const SkPaint&) override;
void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
void onDrawRRect (const SkRRect&, const SkPaint&) override;
void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index a5c607d..acd2d82 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -93,8 +93,9 @@
DRAW_SHADOWED_PICTURE_LIGHTS,
DRAW_IMAGE_LATTICE,
DRAW_ARC,
+ DRAW_REGION,
- LAST_DRAWTYPE_ENUM = DRAW_ARC
+ LAST_DRAWTYPE_ENUM = DRAW_REGION
};
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 611b556..3df6422 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -469,6 +469,14 @@
canvas->drawRect(rect, *paint);
}
} break;
+ case DRAW_REGION: {
+ const SkPaint* paint = fPictureData->getPaint(reader);
+ SkRegion region;
+ reader->readRegion(®ion);
+ if (paint) {
+ canvas->drawRegion(region, *paint);
+ }
+ } break;
case DRAW_RRECT: {
const SkPaint* paint = fPictureData->getPaint(reader);
SkRRect rrect;
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index c461bfb..d771699 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -451,6 +451,16 @@
this->validate(initialOffset, size);
}
+void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
+ // op + paint index + region
+ size_t regionBytes = region.writeToMemory(nullptr);
+ size_t size = 2 * kUInt32Size + regionBytes;
+ size_t initialOffset = this->addDraw(DRAW_REGION, &size);
+ this->addPaint(paint);
+ fWriter.writeRegion(region);
+ this->validate(initialOffset, size);
+}
+
void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
// op + paint index + rrect
size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 5601d2a..ac8058b 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -186,6 +186,7 @@
void onDrawPaint(const SkPaint&) override;
void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
void onDrawRect(const SkRect&, const SkPaint&) override;
+ void onDrawRegion(const SkRegion&, const SkPaint&) override;
void onDrawOval(const SkRect&, const SkPaint&) override;
void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
void onDrawRRect(const SkRRect&, const SkPaint&) override;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 5b4bc6a..6545586 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -128,6 +128,7 @@
DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
DRAW(DrawRect, drawRect(r.rect, r.paint));
+DRAW(DrawRegion, drawRegion(r.region, r.paint));
DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
DRAW(DrawTextBlob, drawTextBlob(r.blob.get(), r.x, r.y, r.paint));
DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.paint));
@@ -413,6 +414,10 @@
Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw.
Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); }
+ Bounds bounds(const DrawRegion& op) const {
+ SkRect rect = SkRect::Make(op.region.getBounds());
+ return this->adjustAndMap(rect, &op.paint);
+ }
Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); }
// Tighter arc bounds?
Bounds bounds(const DrawArc& op) const { return this->adjustAndMap(op.oval, &op.paint); }
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 214b075..840e19b 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -145,6 +145,10 @@
APPEND(DrawRect, paint, rect);
}
+void SkRecorder::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
+ APPEND(DrawRegion, paint, region);
+}
+
void SkRecorder::onDrawOval(const SkRect& oval, const SkPaint& paint) {
APPEND(DrawOval, paint, oval);
}
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 6892894..3ab958b 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -105,6 +105,7 @@
void onDrawPaint(const SkPaint&) override;
void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
void onDrawRect(const SkRect&, const SkPaint&) override;
+ void onDrawRegion(const SkRegion&, const SkPaint&) override;
void onDrawOval(const SkRect&, const SkPaint&) override;
void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
void onDrawRRect(const SkRRect&, const SkPaint&) override;