vcl/inc/skia/gdiimpl.hxx |   11 +++++++++++
 vcl/inc/skia/utils.hxx   |   26 +++++++++++++++++---------
 vcl/skia/gdiimpl.cxx     |   10 +++++-----
 3 files changed, 33 insertions(+), 14 deletions(-)

New commits:
commit 60b195cd41f93fc24bfb7897bde20ac3cbeadd1f
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Dec 3 16:48:47 2021 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Sat Dec 4 13:27:08 2021 +0100

    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.lu...@collabora.com>
    (cherry picked from commit 0a596fbd94e1750e9d1f5cdab624c719b33c3ab4)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126296

diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index cc4cda4b2ebd..449240623271 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -308,6 +308,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 set up for drawing lines (using mLineColor etc.).
     SkPaint makeLinePaint(double transparency = 0) const
     {
diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx
index 0583e9ceb624..1a5993bef2d3 100644
--- a/vcl/inc/skia/utils.hxx
+++ b/vcl/inc/skia/utils.hxx
@@ -133,6 +133,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
@@ -154,7 +164,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);
@@ -177,7 +189,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);
@@ -188,7 +201,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.
@@ -201,12 +214,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
 }
 
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index bab66a93c63e..6bb770d51ba0 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1487,7 +1487,7 @@ std::shared_ptr<SalBitmap> 
SkiaSalGraphicsImpl::getBitmap(tools::Long nX, tools:
     if (mScaling != 1)
     {
         if (!isUnitTestRunning())
-            bitmap->Scale(1.0 / mScaling, 1.0 / mScaling, 
BmpScaleFlag::BestQuality);
+            bitmap->Scale(1.0 / mScaling, 1.0 / mScaling, 
goodScalingQuality());
         else
         {
             // Some tests require exact pixel values and would be confused by 
smooth-scaling.
@@ -1495,7 +1495,7 @@ std::shared_ptr<SalBitmap> 
SkiaSalGraphicsImpl::getBitmap(tools::Long nX, tools:
             if 
(isUnitTestRunning("BackendTest__testDrawHaflEllipseAAWithPolyLineB2D_")
                 || isUnitTestRunning("BackendTest__testDrawRectAAWithLine_"))
             {
-                bitmap->Scale(1.0 / mScaling, 1.0 / mScaling, 
BmpScaleFlag::BestQuality);
+                bitmap->Scale(1.0 / mScaling, 1.0 / mScaling, 
goodScalingQuality());
             }
             else
                 bitmap->Scale(1.0 / mScaling, 1.0 / mScaling, 
BmpScaleFlag::NearestNeighbor);
@@ -1760,7 +1760,7 @@ sk_sp<SkImage> 
SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
         matrix.set(SkMatrix::kMScaleY, 1.0 * targetSize.Height() / 
sourceSize.Height());
         canvas->concat(matrix);
         if (!isUnitTestRunning()) // unittests want exact pixel values
-            samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality, 
matrix, 1);
+            samplingOptions = makeSamplingOptions(matrix, 1);
     }
     if (alphaBitmap != nullptr)
     {
@@ -2011,7 +2011,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
         // If the matrix changes geometry, we need to smooth-scale. If there's 
mScaling,
         // that's already been handled by mergeCacheBitmaps().
         if (matrixNeedsHighQuality(matrix))
-            samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality, 
matrix, 1);
+            samplingOptions = makeSamplingOptions(matrix, 1);
         if (fAlpha == 1.0)
         {
             // Specify sizes to scale the image size back if needed (because 
of mScaling).
@@ -2046,7 +2046,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
         canvas->concat(matrix);
         SkSamplingOptions samplingOptions;
         if (matrixNeedsHighQuality(matrix) || (mScaling != 1 && 
!isUnitTestRunning()))
-            samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality, 
matrix, mScaling);
+            samplingOptions = makeSamplingOptions(matrix, mScaling);
         if (pSkiaAlphaBitmap)
         {
             SkPaint paint;

Reply via email to