(Mostly) respect FilterQuality in draw[stretchy]
Bug: b/77917978
For
drawImageLattice
drawBitmapLattice
drawImageNine
drawBitmapNine
, respect the SkFilterQuality on the SkPaint. Previously the GPU used
the lowest quality to avoid a bleeding effect, leading to ugly nine-
patches on Android.
For all backends, cap the filter quality at kLow_SkFilterQuality.
Update SkCanvas' documentation to specify this.
Change-Id: Id28c7753834975f039170f14bc51be4f2bd44d41
Reviewed-on: https://skia-review.googlesource.com/121891
Reviewed-by: Cary Clark <caryclark@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
Auto-Submit: Leon Scroggins <scroggo@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7398f28..fa2c08a 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1725,6 +1725,29 @@
constraint);
}
+namespace {
+class NoneOrLowQualityFilterPaint : SkNoncopyable {
+public:
+ NoneOrLowQualityFilterPaint(const SkPaint* origPaint) {
+ if (origPaint && origPaint->getFilterQuality() > kLow_SkFilterQuality) {
+ fLazyPaint.set(*origPaint);
+ fLazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
+ fPaint = fLazyPaint.get();
+ } else {
+ fPaint = origPaint;
+ }
+ }
+
+ const SkPaint* get() const {
+ return fPaint;
+ }
+
+private:
+ const SkPaint* fPaint;
+ SkLazyPaint fLazyPaint;
+};
+} // namespace
+
void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
const SkPaint* paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
@@ -1733,7 +1756,8 @@
return;
}
if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
- this->onDrawImageNine(image, center, dst, paint);
+ NoneOrLowQualityFilterPaint lowPaint(paint);
+ this->onDrawImageNine(image, center, dst, lowPaint.get());
} else {
this->drawImageRect(image, dst, paint);
}
@@ -1755,7 +1779,8 @@
}
if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
- this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
+ NoneOrLowQualityFilterPaint lowPaint(paint);
+ this->onDrawImageLattice(image, latticePlusBounds, dst, lowPaint.get());
} else {
this->drawImageRect(image, dst, paint);
}
@@ -1796,7 +1821,8 @@
return;
}
if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
- this->onDrawBitmapNine(bitmap, center, dst, paint);
+ NoneOrLowQualityFilterPaint lowPaint(paint);
+ this->onDrawBitmapNine(bitmap, center, dst, lowPaint.get());
} else {
this->drawBitmapRect(bitmap, dst, paint);
}
@@ -1817,7 +1843,8 @@
}
if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
- this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
+ NoneOrLowQualityFilterPaint lowPaint(paint);
+ this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, lowPaint.get());
} else {
this->drawBitmapRect(bitmap, dst, paint);
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3a48e8c..138d41f 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1350,6 +1350,15 @@
}
}
+// When drawing nine-patches or n-patches, cap the filter quality at kBilerp.
+static GrSamplerState::Filter compute_lattice_filter_mode(const SkPaint& paint) {
+ if (paint.getFilterQuality() == kNone_SkFilterQuality) {
+ return GrSamplerState::Filter::kNearest;
+ }
+
+ return GrSamplerState::Filter::kBilerp;
+}
+
void SkGpuDevice::drawProducerNine(GrTextureProducer* producer,
const SkIRect& center, const SkRect& dst, const SkPaint& paint) {
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerNine", fContext.get());
@@ -1371,7 +1380,7 @@
return;
}
- static const GrSamplerState::Filter kMode = GrSamplerState::Filter::kNearest;
+ const GrSamplerState::Filter kMode = compute_lattice_filter_mode(paint);
auto fp = producer->createFragmentProcessor(
SkMatrix::I(), SkRect::MakeIWH(producer->width(), producer->height()),
GrTextureProducer::kNo_FilterConstraint, true, &kMode,
@@ -1426,7 +1435,7 @@
const SkPaint& paint) {
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerLattice", fContext.get());
- static const GrSamplerState::Filter kMode = GrSamplerState::Filter::kNearest;
+ const GrSamplerState::Filter kMode = compute_lattice_filter_mode(paint);
std::unique_ptr<GrFragmentProcessor> fp(producer->createFragmentProcessor(
SkMatrix::I(), SkRect::MakeIWH(producer->width(), producer->height()),
GrTextureProducer::kNo_FilterConstraint, true, &kMode,