summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-03-09 21:35:42 +0100
committerLuboš Luňák <l.lunak@collabora.com>2021-03-10 19:46:03 +0100
commit88b7ac11be5548f46c3664117173699046895610 (patch)
tree792dab2601ce8b48960b55be3454ca07893255cc
parentbf2ba0f39be62978b512d6ed101219b9dd0dc6e4 (diff)
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>
-rw-r--r--vcl/skia/gdiimpl.cxx31
1 files changed, 20 insertions, 11 deletions
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 1a707f7d9476..aa934f1e4942 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1543,14 +1543,12 @@ bool SkiaSalGraphicsImpl::drawEPS(tools::Long, tools::Long, tools::Long, tools::
// 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 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
// 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 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
}
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 @@ bool SkiaSalGraphicsImpl::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBi
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 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBit
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 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
<< " " << 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(