diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2021-12-03 16:48:47 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2021-12-04 11:30:52 +0100 |
commit | 0a596fbd94e1750e9d1f5cdab624c719b33c3ab4 (patch) | |
tree | 20265ee4889ac31a4dccc3e1553f8ac814ae023c /vcl/inc/skia | |
parent | 42bf88831dbaa4ad22ab8e1e03b375ad520fd2f7 (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.hxx | 11 | ||||
-rw-r--r-- | vcl/inc/skia/utils.hxx | 26 |
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 } |