drawBitmapRect() should not touch the CTM when mask filters are present

Blur sigma calculations are CTM dependent, so we cannot take the
drawBitmap() fast path in the presence of mask filters.

BUG=skia:5682
R=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2286873002

Review-Url: https://codereview.chromium.org/2286873002
This commit is contained in:
fmalita 2016-08-26 13:04:14 -07:00 committed by Commit bot
parent febb224699
commit ab83da7142
2 changed files with 54 additions and 14 deletions

View File

@ -93,17 +93,43 @@ static sk_sp<SkImage> makebm(SkCanvas* origCanvas, SkBitmap* resultBM, int w, in
return image;
}
static void canvasproc(SkCanvas* canvas, SkImage*, const SkBitmap& bm, const SkIRect& srcR,
const SkRect& dstR) {
canvas->drawBitmapRect(bm, srcR, dstR, nullptr);
static void bitmapproc(SkCanvas* canvas, SkImage*, const SkBitmap& bm, const SkIRect& srcR,
const SkRect& dstR, const SkPaint* paint) {
canvas->drawBitmapRect(bm, srcR, dstR, paint);
}
static void bitmapsubsetproc(SkCanvas* canvas, SkImage*, const SkBitmap& bm, const SkIRect& srcR,
const SkRect& dstR, const SkPaint* paint) {
if (!bm.bounds().contains(srcR)) {
bitmapproc(canvas, nullptr, bm, srcR, dstR, paint);
return;
}
SkBitmap subset;
if (bm.extractSubset(&subset, srcR)) {
canvas->drawBitmapRect(subset, dstR, paint);
}
}
static void imageproc(SkCanvas* canvas, SkImage* image, const SkBitmap&, const SkIRect& srcR,
const SkRect& dstR) {
canvas->drawImageRect(image, srcR, dstR, nullptr);
const SkRect& dstR, const SkPaint* paint) {
canvas->drawImageRect(image, srcR, dstR, paint);
}
typedef void DrawRectRectProc(SkCanvas*, SkImage*, const SkBitmap&, const SkIRect&, const SkRect&);
static void imagesubsetproc(SkCanvas* canvas, SkImage* image, const SkBitmap& bm,
const SkIRect& srcR, const SkRect& dstR, const SkPaint* paint) {
if (!image->bounds().contains(srcR)) {
imageproc(canvas, image, bm, srcR, dstR, paint);
return;
}
if (sk_sp<SkImage> subset = image->makeSubset(srcR)) {
canvas->drawImageRect(subset, dstR, paint);
}
}
typedef void DrawRectRectProc(SkCanvas*, SkImage*, const SkBitmap&, const SkIRect&, const SkRect&,
const SkPaint*);
static const int gSize = 1024;
static const int gBmpSize = 2048;
@ -164,7 +190,7 @@ protected:
for (int h = 1; h <= kMaxSrcRectSize; h *= 4) {
SkIRect srcRect = SkIRect::MakeXYWH((gBmpSize - w) / 2, (gBmpSize - h) / 2, w, h);
fProc(canvas, fImage.get(), fLargeBitmap, srcRect, dstRect);
fProc(canvas, fImage.get(), fLargeBitmap, srcRect, dstRect, nullptr);
SkString label;
label.appendf("%d x %d", w, h);
@ -206,9 +232,10 @@ protected:
paint.setMaskFilter(SkBlurMaskFilter::Make(
kNormal_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)),
SkBlurMaskFilter::kHighQuality_BlurFlag |
SkBlurMaskFilter::kIgnoreTransform_BlurFlag));
canvas->drawBitmapRect(bm, srcRect, dstRect, &paint);
SkBlurMaskFilter::kHighQuality_BlurFlag));
sk_sp<SkImage> image(SkImage::MakeFromBitmap(bm));
fProc(canvas, image.get(), bm, srcRect, dstRect, &paint);
}
}
@ -216,5 +243,7 @@ private:
typedef skiagm::GM INHERITED;
};
DEF_GM( return new DrawBitmapRectGM(canvasproc, nullptr); )
DEF_GM( return new DrawBitmapRectGM(imageproc, "-imagerect"); )
DEF_GM( return new DrawBitmapRectGM(bitmapproc , nullptr); )
DEF_GM( return new DrawBitmapRectGM(bitmapsubsetproc, "-subset"); )
DEF_GM( return new DrawBitmapRectGM(imageproc , "-imagerect"); )
DEF_GM( return new DrawBitmapRectGM(imagesubsetproc , "-imagerect-subset"); )

View File

@ -233,6 +233,15 @@ void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
draw.drawBitmap(bitmap, matrix, nullptr, paint);
}
static inline bool CanApplyDstMatrixAsCTM(const SkMatrix& m, const SkPaint& paint) {
if (!paint.getMaskFilter()) {
return true;
}
// Some mask filters parameters (sigma) depend on the CTM/scale.
return m.getType() <= SkMatrix::kTranslate_Mask;
}
void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
const SkRect* src, const SkRect& dst,
const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
@ -309,8 +318,10 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
// We can go faster by just calling drawBitmap, which will concat the
// matrix with the CTM, and try to call drawSprite if it can. If not,
// it will make a shader and call drawRect, as we do below.
draw.drawBitmap(*bitmapPtr, matrix, dstPtr, paint);
return;
if (CanApplyDstMatrixAsCTM(matrix, paint)) {
draw.drawBitmap(*bitmapPtr, matrix, dstPtr, paint);
return;
}
}
USE_SHADER: