aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2016-09-02 11:24:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-02 11:24:30 -0700
commit0764efe6a9ae65ad83992f614f57ca9db5b1f191 (patch)
tree0093acd4cd619336ccd5f6b06748e9928af438ef
parent005327b9ddbf0bb2890c7d563b3d9a8ea8a284f6 (diff)
Add option to skip rects to drawImageLattice()
HWUI skips transparent rects when drawing. When skia draws using bilerp, we will blend transparent rects with neighboring rects and might draw a bit of a smudge. This CL adds the option to skip rects, allowing us to have compatible behavior with the framework. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2305433002 Review-Url: https://codereview.chromium.org/2305433002
-rw-r--r--bench/DrawLatticeBench.cpp1
-rw-r--r--gm/lattice.cpp10
-rw-r--r--include/core/SkCanvas.h30
-rw-r--r--include/private/SkRecords.h2
-rw-r--r--src/core/SkLatticeIter.cpp88
-rw-r--r--src/core/SkLatticeIter.h11
-rw-r--r--src/core/SkLiteDL.cpp26
-rw-r--r--src/core/SkPicturePlayback.cpp3
-rw-r--r--src/core/SkPictureRecord.cpp6
-rw-r--r--src/core/SkRecordDraw.cpp1
-rw-r--r--src/core/SkRecorder.cpp4
-rw-r--r--src/gpu/batches/GrNinePatch.cpp4
12 files changed, 131 insertions, 55 deletions
diff --git a/bench/DrawLatticeBench.cpp b/bench/DrawLatticeBench.cpp
index 9c4d31a099..19d549f297 100644
--- a/bench/DrawLatticeBench.cpp
+++ b/bench/DrawLatticeBench.cpp
@@ -21,6 +21,7 @@ public:
fLattice.fXCount = xCount;
fLattice.fYDivs = yDivs;
fLattice.fYCount = yCount;
+ fLattice.fFlags = nullptr;
fName = SkStringPrintf("DrawLattice_%s", desc);
}
diff --git a/gm/lattice.cpp b/gm/lattice.cpp
index 63de2a66b4..919fb3588e 100644
--- a/gm/lattice.cpp
+++ b/gm/lattice.cpp
@@ -113,6 +113,7 @@ protected:
lattice.fXDivs = xDivs + 1;
lattice.fYCount = 4;
lattice.fYDivs = yDivs + 1;
+ lattice.fFlags = nullptr;
for (int iy = 0; iy < 2; ++iy) {
for (int ix = 0; ix < 2; ++ix) {
@@ -130,6 +131,15 @@ protected:
lattice.fYCount = 5;
lattice.fYDivs = yDivs;
+ // Let's skip a few rects.
+ SkCanvas::Lattice::Flags flags[36];
+ sk_bzero(flags, 36 * sizeof(SkCanvas::Lattice::Flags));
+ flags[4] = SkCanvas::Lattice::kTransparent_Flags;
+ flags[9] = SkCanvas::Lattice::kTransparent_Flags;
+ flags[12] = SkCanvas::Lattice::kTransparent_Flags;
+ flags[19] = SkCanvas::Lattice::kTransparent_Flags;
+ lattice.fFlags = flags;
+
canvas->translate(400, 0);
for (int iy = 0; iy < 2; ++iy) {
for (int ix = 0; ix < 2; ++ix) {
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index acf0ad2a54..d28d0f1898 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -934,21 +934,35 @@ public:
* Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
*/
struct Lattice {
+ enum Flags : uint8_t {
+ // If set, indicates that we should not draw corresponding rect.
+ kTransparent_Flags = 1 << 0,
+ };
+
// An array of x-coordinates that divide the bitmap vertically.
- // These must be unique, increasing, and in the set [0, width].
+ // These must be unique, increasing, and in the set [0, width).
// Does not have ownership.
- const int* fXDivs;
-
- // The number of fXDivs.
- int fXCount;
+ const int* fXDivs;
// An array of y-coordinates that divide the bitmap horizontally.
- // These must be unique, increasing, and in the set [0, height].
+ // These must be unique, increasing, and in the set [0, height).
// Does not have ownership.
- const int* fYDivs;
+ const int* fYDivs;
+
+ // If non-null, the length of this array must be equal to
+ // (fXCount + 1) * (fYCount + 1). Note that we allow the first rect
+ // in each direction to empty (divs[0] = 0). In this case, the
+ // caller still must specify a flag (as a placeholder) for these
+ // empty rects.
+ // The flags correspond to the rects in the lattice, first moving
+ // left to right and then top to bottom.
+ const Flags* fFlags;
+
+ // The number of fXDivs.
+ int fXCount;
// The number of fYDivs.
- int fYCount;
+ int fYCount;
};
/**
diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h
index 09961ce04a..2800a96b56 100644
--- a/include/private/SkRecords.h
+++ b/include/private/SkRecords.h
@@ -242,6 +242,8 @@ RECORD(DrawImageLattice, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
PODArray<int> xDivs;
int yCount;
PODArray<int> yDivs;
+ int flagCount;
+ PODArray<SkCanvas::Lattice::Flags> flags;
SkRect dst);
RECORD(DrawImageRect, kDraw_Tag|kHasImage_Tag|kHasPaint_Tag,
Optional<SkPaint> paint;
diff --git a/src/core/SkLatticeIter.cpp b/src/core/SkLatticeIter.cpp
index ba6ac97a5b..38ef2828bd 100644
--- a/src/core/SkLatticeIter.cpp
+++ b/src/core/SkLatticeIter.cpp
@@ -12,13 +12,9 @@
* Divs must be in increasing order with no duplicates.
*/
static bool valid_divs(const int* divs, int count, int len) {
- if (count <= 0) {
- return false;
- }
-
int prev = -1;
for (int i = 0; i < count; i++) {
- if (prev >= divs[i] || divs[i] > len) {
+ if (prev >= divs[i] || divs[i] >= len) {
return false;
}
}
@@ -27,6 +23,12 @@ static bool valid_divs(const int* divs, int count, int len) {
}
bool SkLatticeIter::Valid(int width, int height, const SkCanvas::Lattice& lattice) {
+ bool zeroXDivs = lattice.fXCount <= 0 || (1 == lattice.fXCount && 0 == lattice.fXDivs[0]);
+ bool zeroYDivs = lattice.fYCount <= 0 || (1 == lattice.fYCount && 0 == lattice.fYDivs[0]);
+ if (zeroXDivs && zeroYDivs) {
+ return false;
+ }
+
return valid_divs(lattice.fXDivs, lattice.fXCount, width) &&
valid_divs(lattice.fYDivs, lattice.fYCount, height);
}
@@ -104,9 +106,9 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
const SkRect& dst)
{
const int* xDivs = lattice.fXDivs;
- int xCount = lattice.fXCount;
+ const int origXCount = lattice.fXCount;
const int* yDivs = lattice.fYDivs;
- int yCount = lattice.fYCount;
+ const int origYCount = lattice.fYCount;
// In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
// If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
@@ -117,15 +119,16 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
// As we move left to right across the image, alternating patches will be "fixed" or
// "scalable" in the x-direction. Similarly, as move top to bottom, alternating
// patches will be "fixed" or "scalable" in the y-direction.
- SkASSERT(xCount > 0 && yCount > 0);
- bool xIsScalable = (0 == xDivs[0]);
+ int xCount = origXCount;
+ int yCount = origYCount;
+ bool xIsScalable = (xCount > 0 && 0 == xDivs[0]);
if (xIsScalable) {
// Once we've decided that the first patch is "scalable", we don't need the
// xDiv. It is always implied that we start at zero.
xDivs++;
xCount--;
}
- bool yIsScalable = (0 == yDivs[0]);
+ bool yIsScalable = (yCount > 0 && 0 == yDivs[0]);
if (yIsScalable) {
// Once we've decided that the first patch is "scalable", we don't need the
// yDiv. It is always implied that we start at zero.
@@ -133,14 +136,6 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
yCount--;
}
- // We never need the final xDiv/yDiv if it is equal to the width/height. This is implied.
- if (xCount > 0 && srcWidth == xDivs[xCount - 1]) {
- xCount--;
- }
- if (yCount > 0 && srcHeight == yDivs[yCount - 1]) {
- yCount--;
- }
-
// Count "scalable" and "fixed" pixels in each dimension.
int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, srcWidth);
int xCountFixed = srcWidth - xCountScalable;
@@ -158,8 +153,42 @@ SkLatticeIter::SkLatticeIter(int srcWidth, int srcHeight, const SkCanvas::Lattic
dst.fTop, dst.fBottom, yIsScalable);
fCurrX = fCurrY = 0;
- fDone = false;
- fNumRects = (xCount + 1) * (yCount + 1);
+ fNumRectsInLattice = (xCount + 1) * (yCount + 1);
+ fNumRectsToDraw = fNumRectsInLattice;
+
+ if (lattice.fFlags) {
+ fFlags.push_back_n(fNumRectsInLattice);
+
+ const SkCanvas::Lattice::Flags* flags = lattice.fFlags;
+
+ 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;
+ }
+
+ int i = 0;
+ for (int y = 0; y < yCount + 1; y++) {
+ for (int x = 0; x < origXCount + 1; x++) {
+ if (0 == x && hasPadCol) {
+ // The first column of rects are all empty. Skip a rect.
+ flags++;
+ continue;
+ }
+
+ fFlags[i] = *flags;
+ flags++;
+ i++;
+ }
+ }
+
+ for (int j = 0; j < fFlags.count(); j++) {
+ if (SkCanvas::Lattice::kTransparent_Flags == fFlags[j]) {
+ fNumRectsToDraw--;
+ }
+ }
+ }
}
bool SkLatticeIter::Valid(int width, int height, const SkIRect& center) {
@@ -205,12 +234,13 @@ SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst)
}
fCurrX = fCurrY = 0;
- fDone = false;
- fNumRects = 9;
+ fNumRectsInLattice = 9;
+ fNumRectsToDraw = 9;
}
bool SkLatticeIter::next(SkRect* src, SkRect* dst) {
- if (fDone) {
+ int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
+ if (currRect == fNumRectsInLattice) {
return false;
}
@@ -219,15 +249,17 @@ bool SkLatticeIter::next(SkRect* src, SkRect* dst) {
SkASSERT(x >= 0 && x < fSrcX.count() - 1);
SkASSERT(y >= 0 && y < fSrcY.count() - 1);
- 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 (fSrcX.count() - 1 == ++fCurrX) {
fCurrX = 0;
fCurrY += 1;
- if (fCurrY >= fSrcY.count() - 1) {
- fDone = true;
- }
}
+
+ if (fFlags.count() > 0 && SkToBool(SkCanvas::Lattice::kTransparent_Flags & fFlags[currRect])) {
+ return this->next(src, dst);
+ }
+
+ src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
+ dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
return true;
}
diff --git a/src/core/SkLatticeIter.h b/src/core/SkLatticeIter.h
index 192b6c5b54..deb2fe95eb 100644
--- a/src/core/SkLatticeIter.h
+++ b/src/core/SkLatticeIter.h
@@ -41,10 +41,10 @@ public:
void mapDstScaleTranslate(const SkMatrix& matrix);
/**
- * Returns the total number of rects that will be drawn.
+ * Returns the number of rects that will actually be drawn.
*/
- int numRects() const {
- return fNumRects;
+ int numRectsToDraw() const {
+ return fNumRectsToDraw;
}
private:
@@ -52,11 +52,12 @@ private:
SkTArray<SkScalar> fSrcY;
SkTArray<SkScalar> fDstX;
SkTArray<SkScalar> fDstY;
+ SkTArray<SkCanvas::Lattice::Flags> fFlags;
int fCurrX;
int fCurrY;
- bool fDone;
- int fNumRects;
+ int fNumRectsInLattice;
+ int fNumRectsToDraw;
};
#endif
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index eaa5a79626..8c8abb1cc3 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -352,19 +352,21 @@ namespace {
};
struct DrawImageLattice final : Op {
static const auto kType = Type::DrawImageLattice;
- DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys,
+ DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs,
const SkRect& dst, const SkPaint* paint)
- : image(std::move(image)), xs(xs), ys(ys), dst(dst) {
+ : image(std::move(image)), xs(xs), ys(ys), fs(fs), dst(dst) {
if (paint) { this->paint = *paint; }
}
sk_sp<const SkImage> image;
- int xs, ys;
+ int xs, ys, fs;
SkRect dst;
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) {
auto xdivs = pod<int>(this, 0),
ydivs = pod<int>(this, xs*sizeof(int));
- c->drawImageLattice(image.get(), {xdivs, xs, ydivs, ys}, dst, &paint);
+ auto flags = (0 == fs) ? nullptr :
+ pod<SkCanvas::Lattice::Flags>(this, (xs+ys)*sizeof(int));
+ c->drawImageLattice(image.get(), {xdivs, ydivs, flags, xs, ys}, dst, &paint);
}
};
@@ -665,11 +667,13 @@ void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRec
void SkLiteDL::drawBitmapLattice(const SkBitmap& bm, const SkCanvas::Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
int xs = lattice.fXCount, ys = lattice.fYCount;
- size_t bytes = (xs + ys) * sizeof(int);
- void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, dst,
+ int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0;
+ size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags);
+ void* pod = this->push<DrawImageLattice>(bytes, SkImage::MakeFromBitmap(bm), xs, ys, fs, dst,
paint);
copy_v(pod, lattice.fXDivs, xs,
- lattice.fYDivs, ys);
+ lattice.fYDivs, ys,
+ lattice.fFlags, fs);
}
void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
@@ -686,10 +690,12 @@ void SkLiteDL::drawImageRect(const SkImage* image, const SkRect* src, const SkRe
void SkLiteDL::drawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
int xs = lattice.fXCount, ys = lattice.fYCount;
- size_t bytes = (xs + ys) * sizeof(int);
- void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, dst, paint);
+ int fs = lattice.fFlags ? (xs + 1) * (ys + 1) : 0;
+ size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::Flags);
+ void* pod = this->push<DrawImageLattice>(bytes, sk_ref_sp(image), xs, ys, fs, dst, paint);
copy_v(pod, lattice.fXDivs, xs,
- lattice.fYDivs, ys);
+ lattice.fYDivs, ys,
+ lattice.fFlags, fs);
}
void SkLiteDL::drawText(const void* text, size_t bytes,
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 3df64227a6..4520b6d325 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -316,6 +316,9 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
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)));
SkRect dst;
reader->readRect(&dst);
canvas->drawImageLattice(image, lattice, dst, paint);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 8eab63016b..5ee2e9fb35 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -538,7 +538,9 @@ 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
- size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount) * kUInt32Size;
+ int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
+ size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
+ SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags));
// op + paint index + image index + lattice + dst rect
size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
@@ -549,6 +551,8 @@ void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& la
fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
this->addInt(lattice.fYCount);
fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
+ this->addInt(flagCount);
+ fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
this->addRect(dst);
this->validate(initialOffset, size);
}
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 6545586499..2952591319 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -106,6 +106,7 @@ 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;
fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint);
}
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 840e19b90d..4c09e514be 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -238,9 +238,11 @@ 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;
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), dst);
+ lattice.fYCount, this->copy(lattice.fYDivs, lattice.fYCount),
+ flagCount, this->copy(lattice.fFlags, flagCount), dst);
}
void SkRecorder::onDrawText(const void* text, size_t byteLength,
diff --git a/src/gpu/batches/GrNinePatch.cpp b/src/gpu/batches/GrNinePatch.cpp
index 3417c5c095..522e775c33 100644
--- a/src/gpu/batches/GrNinePatch.cpp
+++ b/src/gpu/batches/GrNinePatch.cpp
@@ -82,7 +82,7 @@ private:
int patchCnt = fPatches.count();
int numRects = 0;
for (int i = 0; i < patchCnt; i++) {
- numRects += fPatches[i].fIter->numRects();
+ numRects += fPatches[i].fIter->numRectsToDraw();
}
SkAutoTUnref<const GrBuffer> indexBuffer(
@@ -132,7 +132,7 @@ private:
if (!isScaleTranslate) {
SkPoint* positions = reinterpret_cast<SkPoint*>(patchVerts);
patch.fViewMatrix.mapPointsWithStride(positions, vertexStride,
- kVertsPerRect * patch.fIter->numRects());
+ kVertsPerRect * patch.fIter->numRectsToDraw());
}
}
helper.recordDraw(target, gp.get());