diff options
author | msarett <msarett@google.com> | 2016-08-25 13:54:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-08-25 13:54:30 -0700 |
commit | 44df651ebefc284acc2f66425dff3ea0b0e14b36 (patch) | |
tree | 324bcf1b278ed44e168f0a6c548fd9a194014b6c | |
parent | 4d866dfc46bc381da1761d05ce8b5a3bb0cd7f00 (diff) | |
download | platform_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.cpp | 54 | ||||
-rw-r--r-- | gm/drawregionmodes.cpp | 78 | ||||
-rw-r--r-- | include/core/SkCanvas.h | 9 | ||||
-rw-r--r-- | include/core/SkDevice.h | 2 | ||||
-rw-r--r-- | include/private/SkRecords.h | 4 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 20 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 23 | ||||
-rw-r--r-- | src/core/SkLiteDL.cpp | 14 | ||||
-rw-r--r-- | src/core/SkLiteDL.h | 1 | ||||
-rw-r--r-- | src/core/SkLiteRecorder.cpp | 3 | ||||
-rw-r--r-- | src/core/SkLiteRecorder.h | 7 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 3 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 8 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 10 | ||||
-rw-r--r-- | src/core/SkPictureRecord.h | 1 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 5 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 4 | ||||
-rw-r--r-- | src/core/SkRecorder.h | 1 |
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 = ®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 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(®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 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; |