diff options
author | Stan Iliev <stani@google.com> | 2017-12-11 13:01:58 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-12-11 18:26:18 +0000 |
commit | ca8c0953e8da1def5e6c12dde6d4368b4bf16077 (patch) | |
tree | c7c0dabde70dbebfedba579f6f9d803652201943 /src/core | |
parent | 51493ee8488e29499a1a0a678a50aeca44ebf718 (diff) |
Implement a fast path for solid color lattice rectangle
Add a flag that hints, which lattice rectangles are solid colors.
Draw solid rectangles and 1x1 rectangles with drawRect.
Test: Measured performance of a ninepatch drawn by HWUI
Bug: b/69796044
Change-Id: Ib3b00ca608da42fa9f2d2038cc126a978421ec7c
Reviewed-on: https://skia-review.googlesource.com/79821
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkDevice.cpp | 20 | ||||
-rw-r--r-- | src/core/SkLatticeIter.cpp | 32 | ||||
-rw-r--r-- | src/core/SkLatticeIter.h | 10 | ||||
-rw-r--r-- | src/core/SkLiteDL.cpp | 16 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 7 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 10 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 3 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 5 | ||||
-rw-r--r-- | src/core/SkRecords.h | 3 |
9 files changed, 78 insertions, 28 deletions
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 5d5c9dae73..85136722b5 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -223,8 +223,24 @@ void SkBaseDevice::drawImageLattice(const SkImage* image, SkLatticeIter iter(lattice, dst); SkRect srcR, dstR; - while (iter.next(&srcR, &dstR)) { - this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint); + SkColor c; + bool isFixedColor = false; + const SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); + + while (iter.next(&srcR, &dstR, &isFixedColor, &c)) { + if (isFixedColor || (srcR.width() <= 1.0f && srcR.height() <= 1.0f && + image->readPixels(info, &c, 4, srcR.fLeft, srcR.fTop))) { + // Fast draw with drawRect, if this is a patch containing a single color + // or if this is a patch containing a single pixel. + if (0 != c || !paint.isSrcOver()) { + SkPaint paintCopy(paint); + int alpha = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); + paintCopy.setColor(SkColorSetA(c, alpha)); + this->drawRect(dstR, paintCopy); + } + } else { + this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint); + } } } diff --git a/src/core/SkLatticeIter.cpp b/src/core/SkLatticeIter.cpp index 9b2a279f2e..551982ec20 100644 --- a/src/core/SkLatticeIter.cpp +++ b/src/core/SkLatticeIter.cpp @@ -166,16 +166,19 @@ SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst fNumRectsInLattice = (xCount + 1) * (yCount + 1); fNumRectsToDraw = fNumRectsInLattice; - if (lattice.fFlags) { - fFlags.push_back_n(fNumRectsInLattice); + if (lattice.fRectTypes) { + fRectTypes.push_back_n(fNumRectsInLattice); + fColors.push_back_n(fNumRectsInLattice); - const SkCanvas::Lattice::Flags* flags = lattice.fFlags; + const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes; + const SkColor* colors = lattice.fColors; bool hasPadRow = (yCount != origYCount); bool hasPadCol = (xCount != origXCount); if (hasPadRow) { // The first row of rects are all empty, skip the first row of flags. flags += origXCount + 1; + colors += origXCount + 1; } int i = 0; @@ -184,17 +187,20 @@ SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst if (0 == x && hasPadCol) { // The first column of rects are all empty. Skip a rect. flags++; + colors++; continue; } - fFlags[i] = *flags; + fRectTypes[i] = *flags; + fColors[i] = *colors; flags++; + colors++; i++; } } - for (int j = 0; j < fFlags.count(); j++) { - if (SkCanvas::Lattice::kTransparent_Flags == fFlags[j]) { + for (int j = 0; j < fRectTypes.count(); j++) { + if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) { fNumRectsToDraw--; } } @@ -248,7 +254,7 @@ SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) fNumRectsToDraw = 9; } -bool SkLatticeIter::next(SkRect* src, SkRect* dst) { +bool SkLatticeIter::next(SkRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) { int currRect = fCurrX + fCurrY * (fSrcX.count() - 1); if (currRect == fNumRectsInLattice) { return false; @@ -264,12 +270,20 @@ bool SkLatticeIter::next(SkRect* src, SkRect* dst) { fCurrY += 1; } - if (fFlags.count() > 0 && SkToBool(SkCanvas::Lattice::kTransparent_Flags & fFlags[currRect])) { - return this->next(src, dst); + if (fRectTypes.count() > 0 + && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) { + return this->next(src, dst, isFixedColor, fixedColor); } src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]); dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]); + if (isFixedColor && fixedColor) { + *isFixedColor = fRectTypes.count() > 0 + && SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]); + if (*isFixedColor) { + *fixedColor = fColors[currRect]; + } + } return true; } diff --git a/src/core/SkLatticeIter.h b/src/core/SkLatticeIter.h index aad39824d5..08cdd5a965 100644 --- a/src/core/SkLatticeIter.h +++ b/src/core/SkLatticeIter.h @@ -30,9 +30,12 @@ public: SkLatticeIter(int imageWidth, int imageHeight, const SkIRect& center, const SkRect& dst); /** - * While it returns true, use src/dst to draw the image/bitmap + * While it returns true, use src/dst to draw the image/bitmap. Optional parameters + * isFixedColor and fixedColor specify if the rectangle is filled with a fixed color. + * If (*isFixedColor) is true, then (*fixedColor) contains the rectangle color. */ - bool next(SkRect* src, SkRect* dst); + bool next(SkRect* src, SkRect* dst, bool* isFixedColor = nullptr, + SkColor* fixedColor = nullptr); /** * Apply a matrix to the dst points. @@ -51,7 +54,8 @@ private: SkTArray<SkScalar> fSrcY; SkTArray<SkScalar> fDstX; SkTArray<SkScalar> fDstY; - SkTArray<SkCanvas::Lattice::Flags> fFlags; + SkTArray<SkCanvas::Lattice::RectType> fRectTypes; + SkTArray<SkColor> fColors; int fCurrX; int fCurrY; diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp index ab5cce3e94..ed23acffe0 100644 --- a/src/core/SkLiteDL.cpp +++ b/src/core/SkLiteDL.cpp @@ -330,9 +330,13 @@ namespace { void draw(SkCanvas* c, const SkMatrix&) const { auto xdivs = pod<int>(this, 0), ydivs = pod<int>(this, xs*sizeof(int)); + auto colors = (0 == fs) ? nullptr : + pod<SkColor>(this, (xs+ys)*sizeof(int)); auto flags = (0 == fs) ? nullptr : - pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int)); - c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src}, dst, &paint); + pod<SkCanvas::Lattice::RectType>(this, (xs+ys)*sizeof(int)+ + fs*sizeof(SkColor)); + c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys, &src, colors}, dst, + &paint); } }; @@ -619,14 +623,16 @@ void SkLiteDL::drawImageRect(sk_sp<const SkImage> image, const SkRect* src, cons void SkLiteDL::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice, const SkRect& dst, const SkPaint* paint) { int xs = lattice.fXCount, ys = lattice.fYCount; - int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0; - size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags); + int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0; + size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType) + + fs * sizeof(SkColor); SkASSERT(lattice.fBounds); void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds, dst, paint); copy_v(pod, lattice.fXDivs, xs, lattice.fYDivs, ys, - lattice.fFlags, fs); + lattice.fColors, fs, + lattice.fRectTypes, fs); } void SkLiteDL::drawText(const void* text, size_t bytes, diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index f9f390ef5a..071e6b3650 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -351,8 +351,11 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader, lattice.fYCount = reader->readInt(); lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t)); int flagCount = reader->readInt(); - lattice.fFlags = (0 == flagCount) ? nullptr : (const SkCanvas::Lattice::Flags*) - reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags))); + lattice.fRectTypes = (0 == flagCount) ? nullptr : + (const SkCanvas::Lattice::RectType*) + reader->skip(SkAlign4(flagCount * sizeof(SkCanvas::Lattice::RectType))); + lattice.fColors = (0 == flagCount) ? nullptr : (const SkColor*) + reader->skip(SkAlign4(flagCount * sizeof(SkColor))); SkIRect src; reader->readIRect(&src); lattice.fBounds = &src; diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 3700e3b330..8a7b5cfa50 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -550,9 +550,12 @@ void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, const SkPaint* paint) { // xCount + xDivs + yCount+ yDivs - int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1); + int flagCount = (nullptr == lattice.fRectTypes) ? 0 : + (lattice.fXCount + 1) * (lattice.fYCount + 1); size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size + - SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect); + SkAlign4(flagCount * sizeof(SkCanvas::Lattice::RectType)) + + SkAlign4(flagCount * sizeof(SkColor)) + + sizeof(SkIRect); // op + paint index + image index + lattice + dst rect size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst); @@ -564,7 +567,8 @@ void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& la this->addInt(lattice.fYCount); fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size); this->addInt(flagCount); - fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags)); + fWriter.writePad(lattice.fRectTypes, flagCount * sizeof(SkCanvas::Lattice::RectType)); + fWriter.writePad(lattice.fColors, flagCount * sizeof(SkColor)); SkASSERT(lattice.fBounds); this->addIRect(*lattice.fBounds); this->addRect(dst); diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 56bde16726..89eb8a751a 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -101,7 +101,8 @@ template <> void Draw::draw(const DrawImageLattice& r) { lattice.fXDivs = r.xDivs; lattice.fYCount = r.yCount; lattice.fYDivs = r.yDivs; - lattice.fFlags = (0 == r.flagCount) ? nullptr : r.flags; + lattice.fRectTypes = (0 == r.flagCount) ? nullptr : r.flags; + lattice.fColors = (0 == r.flagCount) ? nullptr : r.colors; lattice.fBounds = &r.src; fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint); } diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 3d53e9384e..9374b60264 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -238,12 +238,13 @@ void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center, void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst, const SkPaint* paint) { - int flagCount = lattice.fFlags ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0; + int flagCount = lattice.fRectTypes ? (lattice.fXCount + 1) * (lattice.fYCount + 1) : 0; SkASSERT(lattice.fBounds); APPEND(DrawImageLattice, this->copy(paint), sk_ref_sp(image), lattice.fXCount, this->copy(lattice.fXDivs, lattice.fXCount), lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount), - flagCount, this->copy(lattice.fFlags, flagCount), *lattice.fBounds, dst); + flagCount, this->copy(lattice.fRectTypes, flagCount), + this->copy(lattice.fColors, flagCount), *lattice.fBounds, dst); } void SkRecorder::onDrawText(const void* text, size_t byteLength, diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h index bbac4452ca..f1e70b6c88 100644 --- a/src/core/SkRecords.h +++ b/src/core/SkRecords.h @@ -256,7 +256,8 @@ RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, int yCount; PODArray<int> yDivs; int flagCount; - PODArray<SkCanvas::Lattice::Flags> flags; + PODArray<SkCanvas::Lattice::RectType> flags; + PODArray<SkColor> colors; SkIRect src; SkRect dst); RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag, |