aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2016-08-25 13:54:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-25 13:54:30 -0700
commit44df651ebefc284acc2f66425dff3ea0b0e14b36 (patch)
tree324bcf1b278ed44e168f0a6c548fd9a194014b6c
parent4d866dfc46bc381da1761d05ce8b5a3bb0cd7f00 (diff)
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
-rw-r--r--gm/drawregion.cpp54
-rw-r--r--gm/drawregionmodes.cpp78
-rw-r--r--include/core/SkCanvas.h9
-rw-r--r--include/core/SkDevice.h2
-rw-r--r--include/private/SkRecords.h4
-rw-r--r--src/core/SkCanvas.cpp20
-rw-r--r--src/core/SkDevice.cpp23
-rw-r--r--src/core/SkLiteDL.cpp14
-rw-r--r--src/core/SkLiteDL.h1
-rw-r--r--src/core/SkLiteRecorder.cpp3
-rw-r--r--src/core/SkLiteRecorder.h7
-rw-r--r--src/core/SkPictureFlat.h3
-rw-r--r--src/core/SkPicturePlayback.cpp8
-rw-r--r--src/core/SkPictureRecord.cpp10
-rw-r--r--src/core/SkPictureRecord.h1
-rw-r--r--src/core/SkRecordDraw.cpp5
-rw-r--r--src/core/SkRecorder.cpp4
-rw-r--r--src/core/SkRecorder.h1
18 files changed, 241 insertions, 6 deletions
diff --git a/gm/drawregion.cpp b/gm/drawregion.cpp
new file mode 100644
index 0000000000..1e9d6c55e2
--- /dev/null
+++ b/gm/drawregion.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+
+/**
+ * This is very similar to the RectGrid macrobench in Android.
+ */
+class DrawRegionGM : public skiagm::GM {
+public:
+ DrawRegionGM() {}
+
+protected:
+ SkString onShortName() override {
+ return SkString("drawregion");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(500, 500);
+ }
+
+ bool runAsBench() const override {
+ return true;
+ }
+
+ void onOnceBeforeDraw() override {
+ for (int x = 50; x < 250; x+=2) {
+ for (int y = 50; y < 250; y+=2) {
+ fRegion.op(x, y, x + 1, y + 1, SkRegion::kUnion_Op);
+ }
+ }
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(0xFFFF00FF);
+ canvas->drawRect(SkRect::MakeLTRB(50.0f, 50.0f, 250.0f, 250.0f), paint);
+
+ paint.setColor(0xFF00FFFF);
+ canvas->drawRegion(fRegion, paint);
+ }
+
+ SkRegion fRegion;
+
+private:
+ typedef skiagm::GM INHERITED;
+};
+DEF_GM( return new DrawRegionGM; )
diff --git a/gm/drawregionmodes.cpp b/gm/drawregionmodes.cpp
new file mode 100644
index 0000000000..be1c2d20e0
--- /dev/null
+++ b/gm/drawregionmodes.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkDashPathEffect.h"
+#include "SkGradientShader.h"
+#include "SkImageFilter.h"
+
+class DrawRegionModesGM : public skiagm::GM {
+public:
+ DrawRegionModesGM() {}
+
+protected:
+ SkString onShortName() override {
+ return SkString("drawregionmodes");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(375, 500);
+ }
+
+ void onOnceBeforeDraw() override {
+ fRegion.op( 50, 50, 100, 100, SkRegion::kUnion_Op);
+ fRegion.op( 50, 100, 150, 150, SkRegion::kUnion_Op);
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ canvas->clear(SK_ColorGREEN);
+
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(0xFFFF0000);
+ paint.setAntiAlias(true);
+
+ canvas->translate(-50.0f, 75.0f);
+ canvas->rotate(-45.0f);
+ canvas->drawRegion(fRegion, paint);
+
+ canvas->translate(125.0f, 125.0f);
+ paint.setImageFilter(SkImageFilter::MakeBlur(5.0f, 5.0f, nullptr, nullptr));
+ canvas->drawRegion(fRegion, paint);
+
+ canvas->translate(-125.0f, 125.0f);
+ paint.setImageFilter(nullptr);
+ SkRect occluder = SkRect::MakeEmpty();
+ paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 5.0f, occluder, 0));
+ canvas->drawRegion(fRegion, paint);
+
+ canvas->translate(-125.0f, -125.0f);
+ paint.setMaskFilter(nullptr);
+ paint.setStyle(SkPaint::kStroke_Style);
+ float intervals[] = { 5.0f, 5.0f };
+ paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
+ canvas->drawRegion(fRegion, paint);
+
+ canvas->setMatrix(SkMatrix::I());
+ canvas->translate(100, 325);
+ paint.setPathEffect(nullptr);
+ paint.setStyle(SkPaint::kFill_Style);
+ SkPoint points[] = { SkPoint::Make(50.0f, 50.0f), SkPoint::Make(150.0f, 150.0f) };
+ SkColor colors[] = { SK_ColorBLUE, SK_ColorYELLOW };
+ paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 2,
+ SkShader::kClamp_TileMode));
+ canvas->drawRegion(fRegion, paint);
+ }
+
+ SkRegion fRegion;
+
+private:
+ typedef skiagm::GM INHERITED;
+};
+DEF_GM( return new DrawRegionModesGM; )
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index bc3b25dc1b..780af107af 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -703,6 +703,14 @@ public:
void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
SkScalar bottom, const SkPaint& paint);
+ /** Draw the outline of the specified region using the specified paint.
+ @param region The region to be drawn
+ @param paint The paint used to draw the region
+ */
+ void drawRegion(const SkRegion& region, const SkPaint& paint) {
+ this->onDrawRegion(region, paint);
+ }
+
/** Draw the specified oval using the specified paint. The oval will be
filled or framed based on the Style in the paint.
@param oval The rectangle bounds of the oval to be drawn
@@ -1412,6 +1420,7 @@ protected:
virtual void onDrawPaint(const SkPaint&);
virtual void onDrawRect(const SkRect&, const SkPaint&);
+ virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
virtual void onDrawOval(const SkRect&, const SkPaint&);
virtual void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
const SkPaint&);
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 44b8791386..3d5d43b8dd 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -159,6 +159,8 @@ protected:
const SkPoint[], const SkPaint& paint) = 0;
virtual void drawRect(const SkDraw&, const SkRect& r,
const SkPaint& paint) = 0;
+ virtual void drawRegion(const SkDraw&, const SkRegion& r,
+ const SkPaint& paint);
virtual void drawOval(const SkDraw&, const SkRect& oval,
const SkPaint& paint) = 0;
/** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h
index 637a2ef68c..09961ce04a 100644
--- a/include/private/SkRecords.h
+++ b/include/private/SkRecords.h
@@ -75,6 +75,7 @@ namespace SkRecords {
M(DrawTextRSXform) \
M(DrawRRect) \
M(DrawRect) \
+ M(DrawRegion) \
M(DrawTextBlob) \
M(DrawAtlas) \
M(DrawVertices) \
@@ -292,6 +293,9 @@ RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag,
RECORD(DrawRect, kDraw_Tag|kHasPaint_Tag,
SkPaint paint;
SkRect rect);
+RECORD(DrawRegion, kDraw_Tag|kHasPaint_Tag,
+ SkPaint paint;
+ SkRegion region);
RECORD(DrawText, kDraw_Tag|kHasText_Tag|kHasPaint_Tag,
SkPaint paint;
PODArray<char> text;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 8f9a576761..4cf40e9c5a 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2250,6 +2250,26 @@ void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
}
}
+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 = &regionRect;
+ }
+
+ 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 1f3bd613c1..8a9fa96926 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -73,6 +73,29 @@ SkPixelGeometry SkBaseDevice::CreateInfo::AdjustGeometry(const SkImageInfo& info
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 d94e1399d6..af4f5c2dbd 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -54,8 +54,8 @@ namespace {
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 @@ namespace {
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::drawPath(const SkPath& path, const SkPaint& paint) {
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 4f28486840..1549576442 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -40,6 +40,7 @@ public:
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 42218acd93..262cdda610 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -55,6 +55,9 @@ void SkLiteRecorder::onDrawPath(const SkPath& path, const SkPaint& paint) {
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 c4e80cd246..a1a273c039 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -33,9 +33,10 @@ public:
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 a5c607dbf6..acd2d822b4 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -93,8 +93,9 @@ enum DrawType {
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 611b556cc0..3df64227a6 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -469,6 +469,14 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->drawRect(rect, *paint);
}
} break;
+ case DRAW_REGION: {
+ const SkPaint* paint = fPictureData->getPaint(reader);
+ SkRegion region;
+ reader->readRegion(&region);
+ 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 c461bfbbac..d771699880 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -451,6 +451,16 @@ void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
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 5601d2ac08..ac8058b31e 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -186,6 +186,7 @@ protected:
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 5b4bc6af6c..6545586499 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -128,6 +128,7 @@ DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
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 @@ private:
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 214b075ce7..840e19b90d 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -145,6 +145,10 @@ void SkRecorder::onDrawRect(const SkRect& rect, const SkPaint& paint) {
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 6892894927..3ab958b56d 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -105,6 +105,7 @@ public:
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;