aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkBitmapDevice.cpp
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-05-10 15:26:44 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-11 13:38:53 +0000
commit87f807136c216f5db12568afc2e5c8e893b99ef1 (patch)
tree1625d2b629a5edf49278f939fc80c0a41f6dd07a /src/core/SkBitmapDevice.cpp
parent4a41355057ce3b4488e2055f4b6544441a06bcfe (diff)
A8 fast path for raster clip masks
When the clip mask is already A8, we don't need to convert explicitly. Before: 792.72 clipmask_a8 8888 After: 560.06 clipmask_a8 8888 BUG=skia:6005 Change-Id: I9a319df9a82edfc9b412787a36f037bbe82c2825 Reviewed-on: https://skia-review.googlesource.com/16420 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src/core/SkBitmapDevice.cpp')
-rw-r--r--src/core/SkBitmapDevice.cpp67
1 files changed, 56 insertions, 11 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index f6286210aa..981273ad9d 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -388,6 +388,30 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain
///////////////////////////////////////////////////////////////////////////////
+namespace {
+
+class SkAutoDeviceClipRestore {
+public:
+ SkAutoDeviceClipRestore(SkBaseDevice* device, const SkIRect& clip)
+ : fDevice(device)
+ , fPrevCTM(device->ctm()) {
+ fDevice->save();
+ fDevice->setCTM(SkMatrix::I());
+ fDevice->clipRect(SkRect::Make(clip), SkClipOp::kIntersect, false);
+ fDevice->setCTM(fPrevCTM);
+ }
+
+ ~SkAutoDeviceClipRestore() {
+ fDevice->restore(fPrevCTM);
+ }
+
+private:
+ SkBaseDevice* fDevice;
+ const SkMatrix fPrevCTM;
+};
+
+} // anonymous ns
+
void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint,
SkImage* clipImage, const SkMatrix& clipMatrix) {
SkASSERT(!src->isTextureBacked());
@@ -430,7 +454,6 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain
}
const SkMatrix totalMatrix = SkMatrix::Concat(this->ctm(), clipMatrix);
-
SkRect clipBounds;
totalMatrix.mapRect(&clipBounds, SkRect::Make(clipImage->bounds()));
const SkIRect srcBounds = srcImage->bounds().makeOffset(x, y);
@@ -440,18 +463,40 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain
return;
}
- sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(),
- maskBounds.height()));
- SkCanvas* canvas = surf->getCanvas();
- canvas->translate(-maskBounds.x(), -maskBounds.y());
- canvas->concat(totalMatrix);
- canvas->drawImage(clipImage, 0, 0);
- sk_sp<SkImage> mask = surf->makeImageSnapshot();
+ sk_sp<SkImage> mask;
+ SkMatrix maskMatrix, shaderMatrix;
+ SkTLazy<SkAutoDeviceClipRestore> autoClipRestore;
+
+ SkMatrix totalInverse;
+ if (clipImage->isAlphaOnly() && totalMatrix.invert(&totalInverse)) {
+ // If the mask is already in A8 format, we can draw it directly
+ // (while compensating in the shader matrix).
+ mask = sk_ref_sp(clipImage);
+ maskMatrix = totalMatrix;
+ shaderMatrix = SkMatrix::Concat(totalInverse, SkMatrix::MakeTrans(x, y));
+
+ // If the mask is not fully contained within the src layer, we must clip.
+ if (!srcBounds.contains(clipBounds)) {
+ autoClipRestore.init(this, srcBounds);
+ }
- const SkMatrix m = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y());
- paint.writable()->setShader(srcImage->makeShader(&m));
+ maskBounds.offsetTo(0, 0);
+ } else {
+ // Otherwise, we convert the mask to A8 explicitly.
+ sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(),
+ maskBounds.height()));
+ SkCanvas* canvas = surf->getCanvas();
+ canvas->translate(-maskBounds.x(), -maskBounds.y());
+ canvas->concat(totalMatrix);
+ canvas->drawImage(clipImage, 0, 0);
+
+ mask = surf->makeImageSnapshot();
+ maskMatrix = SkMatrix::I();
+ shaderMatrix = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y());
+ }
- SkAutoDeviceCTMRestore adctmr(this, SkMatrix::I());
+ SkAutoDeviceCTMRestore adctmr(this, maskMatrix);
+ paint.writable()->setShader(srcImage->makeShader(&shaderMatrix));
this->drawImage(mask.get(), maskBounds.x(), maskBounds.y(), *paint);
}