Modernize calls to drawImage
1. drawBitmap --> drawImage
2. drawImage now always requires sampling parameter
Bug:178700363
Test: make
Change-Id: I96f610a180b3774ba955cc334949fd62b1cf4d69
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index ab9b8b5..859a555 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -362,13 +362,8 @@
return source;
} else {
SkBitmap bitmap;
- const SkImageInfo& info = source.info();
- bitmap.allocPixels(info.makeColorType(kN32_SkColorType));
-
- SkCanvas canvas(bitmap);
- canvas.drawColor(0);
- canvas.drawBitmap(source, 0.0f, 0.0f, nullptr);
-
+ bitmap.allocPixels(source.info().makeColorType(kN32_SkColorType));
+ bitmap.writePixels(source.pixmap());
return bitmap;
}
}
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index f4c633f..ca2ada9 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -127,10 +127,11 @@
const SkMatrix& totalMatrix = canvas->getTotalMatrix();
SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height());
+ SkSamplingOptions sampling;
if (getForceFilter() || shouldFilterRect(totalMatrix, imageRect, imageRect)) {
- paint.setFilterQuality(kLow_SkFilterQuality);
+ sampling = SkSamplingOptions(SkFilterMode::kLinear);
}
- canvas->drawImage(layerImage.get(), 0, 0, &paint);
+ canvas->drawImage(layerImage.get(), 0, 0, sampling, &paint);
// restore the original matrix
if (nonIdentityMatrix) {
canvas->restore();
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 11a9086..96118aa 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -487,7 +487,9 @@
tree->getPaintFor(&paint, tree->stagingProperties());
}
- void draw(SkCanvas* canvas, const SkMatrix&) const { mRoot->draw(canvas, mBounds, paint); }
+ void draw(SkCanvas* canvas, const SkMatrix&) const {
+ mRoot->draw(canvas, mBounds, paint);
+ }
sp<VectorDrawableRoot> mRoot;
SkRect mBounds;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 1a8d9eb..8fddf71 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -565,7 +565,8 @@
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) {
auto image = bitmap.makeImage();
apply_looper(paint, [&](const SkPaint& p) {
- mCanvas->drawImage(image, left, top, &p);
+ auto sampling = SkSamplingOptions(p.getFilterQuality());
+ mCanvas->drawImage(image, left, top, sampling, &p);
});
}
@@ -574,7 +575,8 @@
SkAutoCanvasRestore acr(mCanvas, true);
mCanvas->concat(matrix);
apply_looper(paint, [&](const SkPaint& p) {
- mCanvas->drawImage(image, 0, 0, &p);
+ auto sampling = SkSamplingOptions(p.getFilterQuality());
+ mCanvas->drawImage(image, 0, 0, sampling, &p);
});
}
@@ -586,10 +588,17 @@
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
apply_looper(paint, [&](const SkPaint& p) {
- mCanvas->drawImageRect(image, srcRect, dstRect, &p, SkCanvas::kFast_SrcRectConstraint);
+ auto sampling = SkSamplingOptions(p.getFilterQuality());
+ mCanvas->drawImageRect(image, srcRect, dstRect, sampling, &p,
+ SkCanvas::kFast_SrcRectConstraint);
});
}
+static SkFilterMode paintToFilter(const Paint* paint) {
+ return paint && paint->isFilterBitmap() ? SkFilterMode::kLinear
+ : SkFilterMode::kNearest;
+}
+
void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
const float* vertices, const int* colors, const Paint* paint) {
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
@@ -664,18 +673,25 @@
}
#endif
+ auto image = bitmap.makeImage();
+
// cons-up a shader for the bitmap
Paint pnt;
if (paint) {
pnt = *paint;
}
- SkSamplingOptions sampling(pnt.isFilterBitmap() ? SkFilterMode::kLinear
- : SkFilterMode::kNearest,
- SkMipmapMode::kNone);
- pnt.setShader(bitmap.makeImage()->makeShader(sampling));
+ SkSamplingOptions sampling(paintToFilter(&pnt));
+ pnt.setShader(image->makeShader(sampling));
+
auto v = builder.detach();
apply_looper(&pnt, [&](const SkPaint& p) {
- mCanvas->drawVertices(v, SkBlendMode::kModulate, p);
+ SkPaint copy(p);
+ auto s = SkSamplingOptions(p.getFilterQuality());
+ if (s != sampling) {
+ // apply_looper changed the quality?
+ copy.setShader(image->makeShader(s));
+ }
+ mCanvas->drawVertices(v, SkBlendMode::kModulate, copy);
});
}
@@ -700,13 +716,11 @@
NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
}
- SkFilterMode filter = paint && paint->isFilterBitmap() ? SkFilterMode::kLinear
- : SkFilterMode::kNearest;
-
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
auto image = bitmap.makeImage();
apply_looper(paint, [&](const SkPaint& p) {
+ auto filter = SkSamplingOptions(p.getFilterQuality()).filter;
mCanvas->drawImageLattice(image.get(), lattice, dst, filter, &p);
});
}
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 6030c36..4a21ad6 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -507,10 +507,12 @@
sk_sp<SkImage> cachedBitmap = getBitmapUpdateIfDirty().makeImage();
+ // HWUI always draws VD with bilinear filtering.
+ auto sampling = SkSamplingOptions(SkFilterMode::kLinear);
int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
canvas->drawImageRect(cachedBitmap, SkRect::MakeWH(scaledWidth, scaledHeight), bounds,
- &paint, SkCanvas::kFast_SrcRectConstraint);
+ sampling, &paint, SkCanvas::kFast_SrcRectConstraint);
}
void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) {
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index cceba59..86b1ac7 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -351,21 +351,24 @@
const sk_sp<Bitmap>& bitmap,
float left,
float top,
+ SkFilterMode filter,
SkPaint paint
) : left(left),
top(top),
+ filter(filter),
paint(std::move(paint)),
bitmap(bitmap),
image(bitmap->makeImage()) { }
float left;
float top;
+ SkFilterMode filter;
SkPaint paint;
sk_sp<Bitmap> bitmap;
sk_sp<SkImage> image;
void draw(SkCanvas* canvas) const {
- canvas->drawImage(image, left, top, &paint);
+ canvas->drawImage(image, left, top, SkSamplingOptions(filter), &paint);
}
ASSERT_DRAWABLE()
};
@@ -377,15 +380,18 @@
const sk_sp<Bitmap>& bitmap,
SkRect src,
SkRect dst,
+ SkFilterMode filter,
SkPaint paint
) : src(src),
dst(dst),
+ filter(filter),
paint(std::move(paint)),
bitmap(bitmap),
image(bitmap->makeImage()) { }
SkRect src;
SkRect dst;
+ SkFilterMode filter;
SkPaint paint;
sk_sp<Bitmap> bitmap;
sk_sp<SkImage> image;
@@ -394,6 +400,7 @@
canvas->drawImageRect(image,
src,
dst,
+ SkSamplingOptions(filter),
&paint,
SkCanvas::kFast_SrcRectConstraint
);
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index f055c6e..ade63e5 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -437,11 +437,11 @@
if (outputMatrix.invert(&inverse)) {
SkCanvas canvas(tmp, SkCanvas::ColorBehavior::kLegacy);
canvas.setMatrix(inverse);
- SkPaint paint;
- paint.setFilterQuality(kLow_SkFilterQuality); // bilinear
SkBitmap priorFrame;
priorFrame.installPixels(outputInfo, pixels, rowBytes);
- canvas.drawBitmap(priorFrame, 0, 0, &paint);
+ priorFrame.setImmutable(); // Don't want asImage() to force a copy
+ canvas.drawImage(priorFrame.asImage(), 0, 0,
+ SkSamplingOptions(SkFilterMode::kLinear));
} else {
ALOGE("Failed to invert matrix!");
}
@@ -458,11 +458,11 @@
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
- paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
SkCanvas canvas(scaledBm, SkCanvas::ColorBehavior::kLegacy);
canvas.setMatrix(outputMatrix);
- canvas.drawBitmap(tmp, 0.0f, 0.0f, &paint);
+ tmp.setImmutable(); // Don't want asImage() to force copy
+ canvas.drawImage(tmp.asImage(), 0, 0, SkSamplingOptions(SkFilterMode::kLinear), &paint);
}
return result;
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index cf02051..4e9daa4 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -457,11 +457,12 @@
// outputBitmap. Otherwise we would blend by default, which is not
// what we want.
paint.setBlendMode(SkBlendMode::kSrc);
- paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
SkCanvas canvas(outputBitmap, SkCanvas::ColorBehavior::kLegacy);
canvas.scale(scaleX, scaleY);
- canvas.drawBitmap(decodingBitmap, 0.0f, 0.0f, &paint);
+ decodingBitmap.setImmutable(); // so .asImage() doesn't make a copy
+ canvas.drawImage(decodingBitmap.asImage(), 0.0f, 0.0f,
+ SkSamplingOptions(SkFilterMode::kLinear), &paint);
} else {
outputBitmap.swap(decodingBitmap);
}
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index f95f347..34df5dd 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -141,18 +141,20 @@
// then use nearest neighbor, otherwise use bilerp sampling.
// Skia TextureOp has the above logic build-in, but not NonAAFillRectOp. TextureOp works
// only for SrcOver blending and without color filter (readback uses Src blending).
+ SkSamplingOptions sampling(SkFilterMode::kNearest);
if (layer->getForceFilter() ||
shouldFilterRect(totalMatrix, skiaSrcRect, skiaDestRect)) {
- paint.setFilterQuality(kLow_SkFilterQuality);
+ sampling = SkSamplingOptions(SkFilterMode::kLinear);
}
- canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, &paint,
+ canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
SkCanvas::kFast_SrcRectConstraint);
} else {
SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height());
+ SkSamplingOptions sampling(SkFilterMode::kNearest);
if (layer->getForceFilter() || shouldFilterRect(totalMatrix, imageRect, imageRect)) {
- paint.setFilterQuality(kLow_SkFilterQuality);
+ sampling = SkSamplingOptions(SkFilterMode::kLinear);
}
- canvas->drawImage(layerImage.get(), 0, 0, &paint);
+ canvas->drawImage(layerImage.get(), 0, 0, sampling, &paint);
}
// restore the original matrix
if (nonIdentityMatrix) {
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 070a765..75815bb6 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -169,7 +169,6 @@
static bool layerNeedsPaint(const LayerProperties& properties, float alphaMultiplier,
SkPaint* paint) {
- paint->setFilterQuality(kLow_SkFilterQuality);
if (alphaMultiplier < 1.0f || properties.alpha() < 255 ||
properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr ||
properties.getImageFilter() != nullptr) {
@@ -226,6 +225,7 @@
SkASSERT(properties.effectiveLayerType() == LayerType::RenderLayer);
SkPaint paint;
layerNeedsPaint(layerProperties, alphaMultiplier, &paint);
+ SkSamplingOptions sampling(SkFilterMode::kLinear);
// surfaces for layers are created on LAYER_SIZE boundaries (which are >= layer size) so
// we need to restrict the portion of the surface drawn to the size of the renderNode.
@@ -239,7 +239,7 @@
"SurfaceID|%" PRId64, renderNode->uniqueId()).c_str(), nullptr);
}
canvas->drawImageRect(renderNode->getLayerSurface()->makeImageSnapshot(), bounds,
- bounds, &paint);
+ bounds, sampling, &paint, SkCanvas::kStrict_SrcRectConstraint);
if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 80eddaf..6456e36 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -656,7 +656,7 @@
SkPaint paint;
const SkColor* colors = kOverdrawColors[static_cast<int>(Properties::overdrawColorSet)];
paint.setColorFilter(SkOverdrawColorFilter::MakeWithSkColors(colors));
- surface->getCanvas()->drawImage(counts.get(), 0.0f, 0.0f, &paint);
+ surface->getCanvas()->drawImage(counts.get(), 0.0f, 0.0f, SkSamplingOptions(), &paint);
}
} /* namespace skiapipeline */
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index bc8ce42..bae11f7 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -182,7 +182,7 @@
auto functorImage = SkImage::MakeFromAHardwareBuffer(mFrameBuffer.get(), kPremul_SkAlphaType,
canvas->imageInfo().refColorSpace(),
kBottomLeft_GrSurfaceOrigin);
- canvas->drawImage(functorImage, 0, 0, &paint);
+ canvas->drawImage(functorImage, 0, 0, SkSamplingOptions(), &paint);
canvas->restore();
}
diff --git a/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp b/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp
index 1d17a02..716d397 100644
--- a/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp
+++ b/libs/hwui/tests/common/scenes/ReadbackFromHardwareBitmap.cpp
@@ -51,7 +51,7 @@
hardwareBitmap->height(), &canvasBitmap));
SkCanvas skCanvas(canvasBitmap);
- skCanvas.drawBitmap(readback, 0, 0);
+ skCanvas.drawImage(readback.asImage(), 0, 0);
canvas.drawBitmap(*heapBitmap, 0, 0, nullptr);
canvas.drawBitmap(*hardwareBitmap, 0, 500, nullptr);
diff --git a/libs/hwui/tests/microbench/CanvasOpBench.cpp b/libs/hwui/tests/microbench/CanvasOpBench.cpp
index ef5749e..e7ba471 100644
--- a/libs/hwui/tests/microbench/CanvasOpBench.cpp
+++ b/libs/hwui/tests/microbench/CanvasOpBench.cpp
@@ -85,6 +85,7 @@
iconBitmap,
0,
0,
+ SkFilterMode::kNearest,
SkPaint{}
});
canvas.restore();
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index c9e8d80..54970df 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -474,6 +474,7 @@
bitmap,
7,
19,
+ SkFilterMode::kNearest,
SkPaint{}
}
);
@@ -496,7 +497,7 @@
buffer.push<Op::DrawImageRect> ({
bitmap, SkRect::MakeWH(100, 100),
SkRect::MakeLTRB(120, 110, 220, 210),
- SkPaint{}
+ SkFilterMode::kNearest, SkPaint{}
}
);