aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormsarett <msarett@google.com>2016-08-25 13:54:30 -0700
committerCommit bot <commit-bot@chromium.org>2016-08-25 13:54:30 -0700
commit44df651ebefc284acc2f66425dff3ea0b0e14b36 (patch)
tree324bcf1b278ed44e168f0a6c548fd9a194014b6c
parent4d866dfc46bc381da1761d05ce8b5a3bb0cd7f00 (diff)
downloadplatform_external_skqp-44df651ebefc284acc2f66425dff3ea0b0e14b36.tar.gz
platform_external_skqp-44df651ebefc284acc2f66425dff3ea0b0e14b36.tar.bz2
platform_external_skqp-44df651ebefc284acc2f66425dff3ea0b0e14b36.zip
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;