aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Stan Iliev <stani@google.com>2017-12-11 13:01:58 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-11 18:26:18 +0000
commitca8c0953e8da1def5e6c12dde6d4368b4bf16077 (patch)
treec7c0dabde70dbebfedba579f6f9d803652201943 /src/core
parent51493ee8488e29499a1a0a678a50aeca44ebf718 (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.cpp20
-rw-r--r--src/core/SkLatticeIter.cpp32
-rw-r--r--src/core/SkLatticeIter.h10
-rw-r--r--src/core/SkLiteDL.cpp16
-rw-r--r--src/core/SkPicturePlayback.cpp7
-rw-r--r--src/core/SkPictureRecord.cpp10
-rw-r--r--src/core/SkRecordDraw.cpp3
-rw-r--r--src/core/SkRecorder.cpp5
-rw-r--r--src/core/SkRecords.h3
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,