summaryrefslogtreecommitdiff
path: root/vcl/inc/skia
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-12-03 16:48:47 +0100
committerLuboš Luňák <l.lunak@collabora.com>2021-12-04 11:30:52 +0100
commit0a596fbd94e1750e9d1f5cdab624c719b33c3ab4 (patch)
tree20265ee4889ac31a4dccc3e1553f8ac814ae023c /vcl/inc/skia
parent42bf88831dbaa4ad22ab8e1e03b375ad520fd2f7 (diff)
only bilinear+mipmap for Skia/raster to-screen drawing (tdf#146024)
The code already tries to hide the cost of the high-quality bicubic scaling by caching, but there are still cases where there's too much scaling done. Since this is only drawing to screen, use only bilinear+mipmap scaling in raster mode, which should be good enough (it's what the "super" scaling VCL algorithm for BmpScaleFlag::Default does as well). Change-Id: I75c86932e097411422dc1ef5e0534059dbf11ff8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126326 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl/inc/skia')
-rw-r--r--vcl/inc/skia/gdiimpl.hxx11
-rw-r--r--vcl/inc/skia/utils.hxx26
2 files changed, 28 insertions, 9 deletions
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index 2473d0918284..b5144a249207 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -296,6 +296,17 @@ protected:
void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency,
bool useAA);
+ BmpScaleFlag goodScalingQuality() const { return SkiaHelper::goodScalingQuality(isGPU()); }
+ SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scalingFactor,
+ int srcScalingFactor = 1)
+ {
+ return SkiaHelper::makeSamplingOptions(rPosAry, scalingFactor, srcScalingFactor, isGPU());
+ }
+ SkSamplingOptions makeSamplingOptions(const SkMatrix& matrix, int scalingFactor)
+ {
+ return SkiaHelper::makeSamplingOptions(goodScalingQuality(), matrix, scalingFactor);
+ }
+
// Create SkPaint to use when drawing to the surface. It is not to be used
// when doing internal drawing such as when merging two bitmaps together.
// This may apply some default settings to the paint as necessary.
diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx
index c4d671ed6b7e..35180c016e24 100644
--- a/vcl/inc/skia/utils.hxx
+++ b/vcl/inc/skia/utils.hxx
@@ -135,6 +135,16 @@ inline bool isUnitTestRunning(const char* name = nullptr)
return testname != nullptr && std::string_view(name) == testname;
}
+// Scaling done on the GPU is fast, but bicubic done in raster mode can be slow
+// if done too much, and it generally shouldn't be needed for to-screen drawing.
+// In that case use only BmpScaleFlag::Default, which is bilinear+mipmap,
+// which should be good enough (and that's what the "super" bitmap scaling
+// algorithm done by VCL does as well).
+inline BmpScaleFlag goodScalingQuality(bool isGPU)
+{
+ return isGPU ? BmpScaleFlag::BestQuality : BmpScaleFlag::Default;
+}
+
// Normal scaling algorithms have a poor quality when downscaling a lot.
// https://bugs.chromium.org/p/skia/issues/detail?id=11810 suggests to use mipmaps
// in such a case, which is annoying to do explicitly instead of Skia deciding which
@@ -156,7 +166,9 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, SkMatrix
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
return SkSamplingOptions(SkCubicResampler::Mitchell());
case BmpScaleFlag::Default:
- return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
+ // Use SkMipmapMode::kNearest for better quality when downscaling. SkMipmapMode::kLinear
+ // would be even better, but it is not specially optimized in raster mode.
+ return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest);
case BmpScaleFlag::Fast:
case BmpScaleFlag::NearestNeighbor:
return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
@@ -179,7 +191,8 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, const Siz
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
return SkSamplingOptions(SkCubicResampler::Mitchell());
case BmpScaleFlag::Default:
- return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
+ // As in the first overload, use kNearest.
+ return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest);
case BmpScaleFlag::Fast:
case BmpScaleFlag::NearestNeighbor:
return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
@@ -190,7 +203,7 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, const Siz
}
inline SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scalingFactor,
- int srcScalingFactor = 1)
+ int srcScalingFactor, bool isGPU)
{
// If there will be scaling, make it smooth, but not in unittests, as those often
// require exact color values and would be confused by this.
@@ -203,12 +216,7 @@ inline SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scal
if (srcScalingFactor != 1)
srcSize *= srcScalingFactor;
if (srcSize != destSize)
- {
- if (srcSize.Width() / destSize.Width() >= downscaleRatioThreshold
- || srcSize.Height() / destSize.Height() >= downscaleRatioThreshold)
- return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
- return SkSamplingOptions(SkCubicResampler::Mitchell()); // best
- }
+ return makeSamplingOptions(goodScalingQuality(isGPU), srcSize, destSize, 1);
return SkSamplingOptions(); // none
}