cache extensive downscaling in GPU mode too (tdf#140925)
Change-Id: I0d77cf157bc1f669da906ed55feedee6bc78ba7b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112252
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 1a707f7..aa934f1 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1543,14 +1543,12 @@
// Create SkImage from a bitmap and possibly an alpha mask (the usual VCL one-minus-alpha),
// with the given target size. Result will be possibly cached, unless disabled.
// Especially in raster mode scaling and alpha blending may be expensive if done repeatedly.
sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitmap,
const SkiaSalBitmap* alphaBitmap,
const Size targetSize)
{
sk_sp<SkImage> image;
// GPU-accelerated drawing with SkShader should be fast enough to not need caching.
if (isGPU())
return image;
if (targetSize.IsEmpty())
return image;
if (alphaBitmap && alphaBitmap->IsFullyOpaqueAsAlpha())
@@ -1561,6 +1559,16 @@
// Image too small to be worth caching if not scaling.
if (targetSize == bitmap.GetSize() && targetSize.Width() < 100 && targetSize.Height() < 100)
return image;
// GPU-accelerated drawing with SkShader should be fast enough to not need caching.
if (isGPU())
{
// tdf#140925: But if this is such an extensive downscaling that caching the result
// would noticeably reduce amount of data processed by the GPU on repeated usage, do it.
int reduceRatio = bitmap.GetSize().Width() * bitmap.GetSize().Height() / targetSize.Width()
/ targetSize.Height();
if (reduceRatio < 10)
return image;
}
// In some cases (tdf#134237) the target size may be very large. In that case it's
// better to rely on Skia to clip and draw only the necessary, rather than prepare
// a very large image only to not use most of it.
@@ -1637,6 +1645,9 @@
}
else
canvas->drawImage(bitmap.GetSkImage(), 0, 0, samplingOptions, &paint);
if (isGPU())
SAL_INFO("vcl.skia.trace", "mergecachebitmaps(" << this << "): caching GPU downscaling:"
<< bitmap.GetSize() << "->" << targetSize);
image = makeCheckedImageSnapshot(tmpSurface);
addCachedImage(key, image);
return image;
@@ -1649,8 +1660,8 @@
assert(dynamic_cast<const SkiaSalBitmap*>(&rAlphaBitmap));
const SkiaSalBitmap& rSkiaSourceBitmap = static_cast<const SkiaSalBitmap&>(rSourceBitmap);
const SkiaSalBitmap& rSkiaAlphaBitmap = static_cast<const SkiaSalBitmap&>(rAlphaBitmap);
// In raster mode use mergeCacheBitmaps(), which will cache the result, avoiding repeated
// alpha blending or scaling. In GPU mode it is simpler to just use SkShader.
// Use mergeCacheBitmaps(), which may decide to cache the result, avoiding repeated
// alpha blending or scaling.
SalTwoRect imagePosAry(rPosAry);
Size imageSize = rSourceBitmap.GetSize();
// If the bitmap will be scaled, prefer to do it in mergeCacheBitmaps(), if possible.
@@ -1685,8 +1696,8 @@
drawShader(rPosAry, bitmap.GetSkShader(makeSamplingOptions(rPosAry)), blendMode);
return;
}
// In raster mode use mergeCacheBitmaps(), which will cache the result, avoiding repeated
// scaling. In GPU mode it is simpler to just use SkShader.
// Use mergeCacheBitmaps(), which may decide to cache the result, avoiding repeated
// scaling.
SalTwoRect imagePosAry(rPosAry);
Size imageSize = bitmap.GetSize();
// If the bitmap will be scaled, prefer to do it in mergeCacheBitmaps(), if possible.
@@ -1826,10 +1837,8 @@
<< " " << rNull << ":" << rX << ":" << rY);
addUpdateRegion(SkRect::MakeWH(GetWidth(), GetHeight())); // can't tell, use whole area
// In raster mode scaling and alpha blending is still somewhat expensive if done repeatedly,
// so use mergeCacheBitmaps(), which will cache the result if useful.
// It is better to use SkShader if in GPU mode, if the operation is simple or if the temporary
// image would be very large.
// Use mergeCacheBitmaps(), which may decide to cache the result, avoiding repeated
// alpha blending or scaling.
// The extra fAlpha blending is not cached, with the assumption that it usually gradually changes
// for each invocation.
sk_sp<SkImage> imageToDraw = mergeCacheBitmaps(