Batched implementation of drawLattice() for GPU
Bechmarks (Nexus 6P):
Src=100x100, Dst=250x250, NumRects=9
Android 77.7us
Skia (without patch) 57.2us
Skia (with patch) 30.9us
Src=100x100, Dst=500x500, NumRects=9
Android 77.0us
Skia (without patch) 56.9us
Skia (with patch) 31.8us
Src=100x100, Dst=1000x1000, NumRects=9
Android 180us
Skia (without patch) 96.8us
Skia (with patch) 70.5us
Src=100x100, Dst=250x250, NumRects=15
Android 208us
Skia (without patch) 155us
Skia (with patch) 38.2us
Src=100x100, Dst=500x500, NumRects=15
Android 207us
Skia (without patch) 152us
Skia (with patch) 38.4us
Src=100x100, Dst=1000x1000, NumRects=15
Android 233us
Skia (without patch) 156us
Skia (with patch) 99.9us
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2255963002
Committed: https://skia.googlesource.com/skia/+/93242c4ae50dfcc0d922cdb3ba80bbc7b4bbe93d
Review-Url: https://codereview.chromium.org/2255963002
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 202be23..db14498 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -35,6 +35,8 @@
#include "../private/GrAuditTrail.h"
+#include "SkLatticeIter.h"
+
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
#define ASSERT_SINGLE_OWNER \
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
@@ -999,23 +1001,23 @@
this->internalDrawPath(clip, paint, viewMatrix, path, style);
}
-void GrDrawContext::drawImageNine(const GrClip& clip,
- const GrPaint& paint,
- const SkMatrix& viewMatrix,
- int imageWidth,
- int imageHeight,
- const SkIRect& center,
- const SkRect& dst) {
+void GrDrawContext::drawImageLattice(const GrClip& clip,
+ const GrPaint& paint,
+ const SkMatrix& viewMatrix,
+ int imageWidth,
+ int imageHeight,
+ std::unique_ptr<SkLatticeIter> iter,
+ const SkRect& dst) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
- GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
+ GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageLattice");
AutoCheckFlush acf(fDrawingManager);
SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
imageWidth, imageHeight,
- center, dst));
+ std::move(iter), dst));
GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 376d5e1..040833b 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1409,8 +1409,10 @@
return;
}
- fDrawContext->drawImageNine(fClip, grPaint, *draw.fMatrix, producer->width(),
- producer->height(), center, dst);
+ std::unique_ptr<SkLatticeIter> iter(
+ new SkLatticeIter(producer->width(), producer->height(), center, dst));
+ fDrawContext->drawImageLattice(fClip, grPaint, *draw.fMatrix, producer->width(),
+ producer->height(), std::move(iter), dst);
}
void SkGpuDevice::drawImageNine(const SkDraw& draw, const SkImage* image,
@@ -1440,6 +1442,61 @@
this->drawProducerNine(draw, &maker, center, dst, paint);
}
+void SkGpuDevice::drawProducerLattice(const SkDraw& draw, GrTextureProducer* producer,
+ const SkCanvas::Lattice& lattice, const SkRect& dst,
+ const SkPaint& paint) {
+ GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerLattice", fContext);
+
+ CHECK_SHOULD_DRAW(draw);
+
+ static const GrTextureParams::FilterMode kMode = GrTextureParams::kNone_FilterMode;
+ sk_sp<GrFragmentProcessor> fp(
+ producer->createFragmentProcessor(SkMatrix::I(),
+ SkRect::MakeIWH(producer->width(), producer->height()),
+ GrTextureProducer::kNo_FilterConstraint, true,
+ &kMode, fDrawContext->getColorSpace(),
+ fDrawContext->sourceGammaTreatment()));
+ GrPaint grPaint;
+ if (!SkPaintToGrPaintWithTexture(this->context(), fDrawContext.get(), paint, *draw.fMatrix,
+ std::move(fp), producer->isAlphaOnly(), &grPaint)) {
+ return;
+ }
+
+ std::unique_ptr<SkLatticeIter> iter(
+ new SkLatticeIter(producer->width(), producer->height(), lattice, dst));
+ fDrawContext->drawImageLattice(fClip, grPaint, *draw.fMatrix, producer->width(),
+ producer->height(), std::move(iter), dst);
+}
+
+void SkGpuDevice::drawImageLattice(const SkDraw& draw, const SkImage* image,
+ const SkCanvas::Lattice& lattice, const SkRect& dst,
+ const SkPaint& paint) {
+ ASSERT_SINGLE_OWNER
+ uint32_t pinnedUniqueID;
+ if (sk_sp<GrTexture> tex = as_IB(image)->refPinnedTexture(&pinnedUniqueID)) {
+ CHECK_SHOULD_DRAW(draw);
+ GrTextureAdjuster adjuster(tex.get(), image->alphaType(), image->bounds(), pinnedUniqueID,
+ as_IB(image)->onImageInfo().colorSpace());
+ this->drawProducerLattice(draw, &adjuster, lattice, dst, paint);
+ } else {
+ SkBitmap bm;
+ if (SkImageCacherator* cacher = as_IB(image)->peekCacherator()) {
+ GrImageTextureMaker maker(fContext, cacher, image, SkImage::kAllow_CachingHint);
+ this->drawProducerLattice(draw, &maker, lattice, dst, paint);
+ } else if (as_IB(image)->getROPixels(&bm)) {
+ this->drawBitmapLattice(draw, bm, lattice, dst, paint);
+ }
+ }
+}
+
+void SkGpuDevice::drawBitmapLattice(const SkDraw& draw, const SkBitmap& bitmap,
+ const SkCanvas::Lattice& lattice, const SkRect& dst,
+ const SkPaint& paint) {
+ ASSERT_SINGLE_OWNER
+ GrBitmapTextureMaker maker(fContext, bitmap);
+ this->drawProducerLattice(draw, &maker, lattice, dst, paint);
+}
+
///////////////////////////////////////////////////////////////////////////////
// must be in SkCanvas::VertexMode order
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 2185f16..d5fe04f 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -122,6 +122,11 @@
void drawBitmapNine(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint& paint) override;
+ void drawImageLattice(const SkDraw&, const SkImage*, const SkCanvas::Lattice&,
+ const SkRect& dst, const SkPaint&) override;
+ void drawBitmapLattice(const SkDraw&, const SkBitmap&, const SkCanvas::Lattice&,
+ const SkRect& dst, const SkPaint&) override;
+
void drawSpecial(const SkDraw&, SkSpecialImage*,
int left, int top, const SkPaint& paint) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
@@ -243,6 +248,9 @@
void drawProducerNine(const SkDraw&, GrTextureProducer*, const SkIRect& center,
const SkRect& dst, const SkPaint&);
+ void drawProducerLattice(const SkDraw&, GrTextureProducer*, const SkCanvas::Lattice& lattice,
+ const SkRect& dst, const SkPaint&);
+
bool drawDashLine(const SkPoint pts[2], const SkPaint& paint);
void drawStrokedLine(const SkPoint pts[2], const SkDraw&, const SkPaint&);
diff --git a/src/gpu/batches/GrNinePatch.cpp b/src/gpu/batches/GrNinePatch.cpp
index cde3d26..3417c5c 100644
--- a/src/gpu/batches/GrNinePatch.cpp
+++ b/src/gpu/batches/GrNinePatch.cpp
@@ -29,15 +29,14 @@
static const int kVertsPerRect = 4;
static const int kIndicesPerRect = 6;
- static const int kRectsPerInstance = 9; // We could skip empty rects
GrNonAANinePatchBatch(GrColor color, const SkMatrix& viewMatrix, int imageWidth,
- int imageHeight, const SkIRect& center, const SkRect &dst)
+ int imageHeight, std::unique_ptr<SkLatticeIter> iter, const SkRect &dst)
: INHERITED(ClassID()) {
Patch& patch = fPatches.push_back();
patch.fViewMatrix = viewMatrix;
patch.fColor = color;
- patch.fCenter = center;
+ patch.fIter = std::move(iter);
patch.fDst = dst;
fImageWidth = imageWidth;
@@ -53,12 +52,9 @@
SkString str;
for (int i = 0; i < fPatches.count(); ++i) {
- str.appendf("%d: Color: 0x%08x Center [L: %d, T: %d, R: %d, B: %d], "
- "Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
+ str.appendf("%d: Color: 0x%08x Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
i,
fPatches[i].fColor,
- fPatches[i].fCenter.fLeft, fPatches[i].fCenter.fTop,
- fPatches[i].fCenter.fRight, fPatches[i].fCenter.fBottom,
fPatches[i].fDst.fLeft, fPatches[i].fDst.fTop,
fPatches[i].fDst.fRight, fPatches[i].fDst.fBottom);
}
@@ -84,35 +80,40 @@
size_t vertexStride = gp->getVertexStride();
int patchCnt = fPatches.count();
+ int numRects = 0;
+ for (int i = 0; i < patchCnt; i++) {
+ numRects += fPatches[i].fIter->numRects();
+ }
SkAutoTUnref<const GrBuffer> indexBuffer(
target->resourceProvider()->refQuadIndexBuffer());
InstancedHelper helper;
void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
indexBuffer, kVertsPerRect,
- kIndicesPerRect, patchCnt * kRectsPerInstance);
+ kIndicesPerRect, numRects);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
+ intptr_t verts = reinterpret_cast<intptr_t>(vertices);
for (int i = 0; i < patchCnt; i++) {
- intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
- i * kRectsPerInstance * kVertsPerRect * vertexStride;
-
const Patch& patch = fPatches[i];
- SkLatticeIter iter(fImageWidth, fImageHeight, patch.fCenter, patch.fDst);
+
+ // Apply the view matrix here if it is scale-translate. Otherwise, we need to
+ // wait until we've created the dst rects.
+ bool isScaleTranslate = patch.fViewMatrix.isScaleTranslate();
+ if (isScaleTranslate) {
+ patch.fIter->mapDstScaleTranslate(patch.fViewMatrix);
+ }
SkRect srcR, dstR;
- while (iter.next(&srcR, &dstR)) {
+ intptr_t patchVerts = verts;
+ while (patch.fIter->next(&srcR, &dstR)) {
SkPoint* positions = reinterpret_cast<SkPoint*>(verts);
-
positions->setRectFan(dstR.fLeft, dstR.fTop,
dstR.fRight, dstR.fBottom, vertexStride);
- SkASSERT(!patch.fViewMatrix.hasPerspective());
- patch.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerRect);
-
// Setup local coords
static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
SkPoint* coords = reinterpret_cast<SkPoint*>(verts + kLocalOffset);
@@ -126,6 +127,13 @@
}
verts += kVertsPerRect * vertexStride;
}
+
+ // If we didn't handle it above, apply the matrix here.
+ if (!isScaleTranslate) {
+ SkPoint* positions = reinterpret_cast<SkPoint*>(patchVerts);
+ patch.fViewMatrix.mapPointsWithStride(positions, vertexStride,
+ kVertsPerRect * patch.fIter->numRects());
+ }
}
helper.recordDraw(target, gp.get());
}
@@ -151,14 +159,14 @@
fOverrides = that->fOverrides;
}
- fPatches.push_back_n(that->fPatches.count(), that->fPatches.begin());
+ fPatches.move_back_n(that->fPatches.count(), that->fPatches.begin());
this->joinBounds(*that);
return true;
}
struct Patch {
SkMatrix fViewMatrix;
- SkIRect fCenter;
+ std::unique_ptr<SkLatticeIter> fIter;
SkRect fDst;
GrColor fColor;
};
@@ -173,7 +181,8 @@
namespace GrNinePatch {
GrDrawBatch* CreateNonAA(GrColor color, const SkMatrix& viewMatrix, int imageWidth, int imageHeight,
- const SkIRect& center, const SkRect& dst) {
- return new GrNonAANinePatchBatch(color, viewMatrix, imageWidth, imageHeight, center, dst);
+ std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) {
+ return new GrNonAANinePatchBatch(color, viewMatrix, imageWidth, imageHeight, std::move(iter),
+ dst);
}
};
diff --git a/src/gpu/batches/GrNinePatch.h b/src/gpu/batches/GrNinePatch.h
index 0a4ffd6..02664c6 100644
--- a/src/gpu/batches/GrNinePatch.h
+++ b/src/gpu/batches/GrNinePatch.h
@@ -9,16 +9,18 @@
#define GrNinePatch_DEFINED
#include "GrColor.h"
+#include "SkCanvas.h"
class GrDrawBatch;
class SkBitmap;
+class SkLatticeIter;
class SkMatrix;
struct SkIRect;
struct SkRect;
namespace GrNinePatch {
GrDrawBatch* CreateNonAA(GrColor color, const SkMatrix& viewMatrix, int imageWidth, int imageHeight,
- const SkIRect& center, const SkRect& dst);
+ std::unique_ptr<SkLatticeIter> iter, const SkRect& dst);
};
#endif