Add onDrawBitmapLattice(), avoid unnecessary bitmap->image copy

out/Release/nanobench --match Lattice --config gpu --ms 3000
3.42ms -> 17.2us

For reference, a loop over drawBitmapRects (which is what
Android currently does) is about 13us.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2205273003

Review-Url: https://codereview.chromium.org/2205273003
This commit is contained in:
msarett 2016-08-16 09:31:08 -07:00 committed by Commit bot
parent c4d2f90731
commit 168820625c
14 changed files with 171 additions and 82 deletions

View File

@ -1439,14 +1439,16 @@ protected:
SrcRectConstraint);
virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
const SkPaint*);
virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
const SkPaint*);
virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
SrcRectConstraint);
virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*);
virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
const SkPaint*);
virtual void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
const SkPaint*);
enum ClipEdgeStyle {
kHard_ClipEdgeStyle,

View File

@ -198,6 +198,8 @@ protected:
SkCanvas::SrcRectConstraint) = 0;
virtual void drawBitmapNine(const SkDraw&, const SkBitmap&, const SkIRect& center,
const SkRect& dst, const SkPaint&);
virtual void drawBitmapLattice(const SkDraw&, const SkBitmap&, const SkCanvas::Lattice&,
const SkRect& dst, const SkPaint&);
virtual void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
virtual void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst,

View File

@ -2057,6 +2057,19 @@ void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const
}
}
void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
RETURN_ON_NULL(image);
if (dst.isEmpty()) {
return;
}
if (SkLatticeIter::Valid(image->width(), image->height(), lattice)) {
this->onDrawImageLattice(image, lattice, dst, paint);
} else {
this->drawImageRect(image, dst, paint);
}
}
void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
if (bitmap.drawsNothing()) {
return;
@ -2093,25 +2106,17 @@ void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, con
} else {
this->drawBitmapRect(bitmap, dst, paint);
}
}
void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
this->drawImageLattice(image.get(), lattice, dst, paint);
}
void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
RETURN_ON_NULL(image);
if (dst.isEmpty()) {
if (bitmap.drawsNothing() || dst.isEmpty()) {
return;
}
if (SkLatticeIter::Valid(image->width(), image->height(), lattice)) {
this->onDrawImageLattice(image, lattice, dst, paint);
if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), lattice)) {
this->onDrawBitmapLattice(bitmap, lattice, dst, paint);
} else {
this->drawImageRect(image, dst, paint);
this->drawBitmapRect(bitmap, dst, paint);
}
}
@ -2419,29 +2424,6 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S
LOOPER_END
}
void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
if (nullptr == paint || paint->canComputeFastBounds()) {
SkRect storage;
if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
return;
}
}
SkLazyPaint lazy;
if (nullptr == paint) {
paint = lazy.init();
}
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
}
LOOPER_END
}
void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint constraint) {
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
@ -2612,6 +2594,52 @@ void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, c
LOOPER_END
}
void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
if (nullptr == paint || paint->canComputeFastBounds()) {
SkRect storage;
if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
return;
}
}
SkLazyPaint lazy;
if (nullptr == paint) {
paint = lazy.init();
}
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
}
LOOPER_END
}
void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
if (nullptr == paint || paint->canComputeFastBounds()) {
SkRect storage;
if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
return;
}
}
SkLazyPaint lazy;
if (nullptr == paint) {
paint = lazy.init();
}
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint());
}
LOOPER_END
}
class SkDeviceFilteredPaint {
public:
SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {

View File

@ -12,6 +12,7 @@
#include "SkImage_Base.h"
#include "SkImageFilter.h"
#include "SkImageFilterCache.h"
#include "SkImagePriv.h"
#include "SkLatticeIter.h"
#include "SkMetaData.h"
#include "SkPatchUtils.h"
@ -152,17 +153,6 @@ void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar
}
}
void SkBaseDevice::drawImageLattice(const SkDraw& draw, const SkImage* image,
const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint& paint) {
SkLatticeIter iter(image->width(), image->height(), lattice, dst);
SkRect srcR, dstR;
while (iter.next(&srcR, &dstR)) {
this->drawImageRect(draw, image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
}
}
void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
const SkRect& dst, const SkPaint& paint,
SkCanvas::SrcRectConstraint constraint) {
@ -193,6 +183,28 @@ void SkBaseDevice::drawBitmapNine(const SkDraw& draw, const SkBitmap& bitmap, co
}
}
void SkBaseDevice::drawImageLattice(const SkDraw& draw, const SkImage* image,
const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint& paint) {
SkLatticeIter iter(image->width(), image->height(), lattice, dst);
SkRect srcR, dstR;
while (iter.next(&srcR, &dstR)) {
this->drawImageRect(draw, image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
}
}
void SkBaseDevice::drawBitmapLattice(const SkDraw& draw, const SkBitmap& bitmap,
const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint& paint) {
SkLatticeIter iter(bitmap.width(), bitmap.height(), lattice, dst);
SkRect srcR, dstR;
while (iter.next(&srcR, &dstR)) {
this->drawBitmapRect(draw, bitmap, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
}
}
void SkBaseDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[],
const SkRect tex[], const SkColor colors[], int count,
SkXfermode::Mode mode, const SkPaint& paint) {

View File

@ -624,6 +624,15 @@ void SkLiteDL::drawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRec
const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
this->push<DrawImageRect>(0, SkImage::MakeFromBitmap(bm), src, dst, paint, constraint);
}
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,
paint);
copy_v(pod, lattice.fXDivs, xs,
lattice.fYDivs, ys);
}
void SkLiteDL::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
this->push<DrawImage>(0, sk_ref_sp(image), x,y, paint);

View File

@ -63,6 +63,8 @@ public:
void drawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, const SkPaint*);
void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
SkCanvas::SrcRectConstraint);
void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&, const SkRect&,
const SkPaint*);
void drawImage (const SkImage*, SkScalar,SkScalar, const SkPaint*);
void drawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*);

View File

@ -122,6 +122,11 @@ void SkLiteRecorder::onDrawBitmapRect(const SkBitmap& bm,
const SkPaint* paint, SrcRectConstraint constraint) {
fDL->drawBitmapRect(bm, src, dst, paint, constraint);
}
void SkLiteRecorder::onDrawBitmapLattice(const SkBitmap& bm,
const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
fDL->drawBitmapLattice(bm, lattice, dst, paint);
}
void SkLiteRecorder::onDrawImage(const SkImage* img,
SkScalar x, SkScalar y,

View File

@ -52,6 +52,8 @@ public:
void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override;
void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,
const SkPaint*) override;
void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, const SkPaint*) override;
void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
SrcRectConstraint) override;

View File

@ -480,24 +480,6 @@ void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
this->validate(initialOffset, size);
}
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;
// op + paint index + image index + lattice + dst rect
size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
this->addPaintPtr(paint);
this->addImage(image);
this->addInt(lattice.fXCount);
fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
this->addInt(lattice.fYCount);
fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
this->addRect(dst);
this->validate(initialOffset, size);
}
void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint constraint) {
// id + paint_index + image_index + bool_for_src + constraint
@ -529,6 +511,24 @@ void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center,
this->validate(initialOffset, size);
}
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;
// op + paint index + image index + lattice + dst rect
size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
this->addPaintPtr(paint);
this->addImage(image);
this->addInt(lattice.fXCount);
fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
this->addInt(lattice.fYCount);
fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
this->addRect(dst);
this->validate(initialOffset, size);
}
void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
// op + paint index + length + 'length' worth of chars + x + y

View File

@ -190,12 +190,13 @@ protected:
void onDrawRRect(const SkRRect&, const SkPaint&) override;
void onDrawPath(const SkPath&, const SkPaint&) override;
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawImageLattice(const SkImage*, const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint*) override;
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint*, SrcRectConstraint) override;
void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawImageLattice(const SkImage*, const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint*) override;
void onDrawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
@ -250,6 +251,10 @@ protected:
const SkPaint*) override {
sk_throw();
}
void onDrawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice& lattice, const SkRect& dst,
const SkPaint*) override {
sk_throw();
}
private:
SkPictureContentInfo fContentInfo;

View File

@ -206,21 +206,17 @@ void SkRecorder::onDrawBitmapNine(const SkBitmap& bitmap,
}
}
void SkRecorder::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
const SkRect& dst, const SkPaint* paint) {
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
this->onDrawImageLattice(image.get(), lattice, dst, paint);
}
void SkRecorder::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
const SkPaint* paint) {
APPEND(DrawImage, this->copy(paint), sk_ref_sp(image), left, top);
}
void SkRecorder::onDrawImageLattice(const SkImage* image,
const Lattice& lattice,
const SkRect& dst,
const SkPaint* paint) {
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);
}
void SkRecorder::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
const SkPaint* paint, SrcRectConstraint constraint) {
APPEND(DrawImageRect, this->copy(paint), sk_ref_sp(image), this->copy(src), dst, constraint);
@ -231,6 +227,13 @@ void SkRecorder::onDrawImageNine(const SkImage* image, const SkIRect& center,
APPEND(DrawImageNine, this->copy(paint), sk_ref_sp(image), center, dst);
}
void SkRecorder::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint) {
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);
}
void SkRecorder::onDrawText(const void* text, size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) {
APPEND(DrawText,

View File

@ -111,14 +111,16 @@ public:
void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
SrcRectConstraint) override;
void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
const SkPaint*) override;
void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint*, SrcRectConstraint) override;
void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*) override;
void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
const SkPaint*) override;
void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
const SkPaint*) override;
void onDrawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,

View File

@ -95,3 +95,15 @@ void SkPDFCanvas::onDrawImageLattice(const SkImage* image,
this->drawImageRect(image, srcR, dstR, paint);
}
}
void SkPDFCanvas::onDrawBitmapLattice(const SkBitmap& bitmap,
const Lattice& lattice,
const SkRect& dst,
const SkPaint* paint) {
SkLatticeIter iter(bitmap.width(), bitmap.height(), lattice, dst);
SkRect srcR, dstR;
while (iter.next(&srcR, &dstR)) {
this->drawBitmapRect(bitmap, srcR, dstR, paint);
}
}

View File

@ -40,10 +40,15 @@ protected:
SkCanvas::SrcRectConstraint) override;
void onDrawImageLattice(const SkImage*,
const Lattice& lattice,
const SkRect& dst,
const Lattice&,
const SkRect&,
const SkPaint*) override;
void onDrawBitmapLattice(const SkBitmap&,
const Lattice&,
const SkRect&,
const SkPaint*) override;
private:
typedef SkCanvas INHERITED;
};