vcl/skia/gdiimpl.cxx | 55 ++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 26 deletions(-)
New commits: commit c5785d3ccccbd0ff575df08a1192f4e7f736750e Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Sat Dec 4 11:52:26 2021 +0100 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Mon Dec 6 17:08:34 2021 +0100 a large but clipped image may still be cached from a previous call Canvas apparently likes to redraw only small parts of the background, which means that there may be repeated scaling of clipped parts of a large background image that are considered too clipped to be cached, but even the drawing of the clipped part may add up to be costly in the end if done often. Refusing the caching only after checking whether the image is possibly cached may avoid some of the drawing in case there was an initial drawing that wasn't clipped and thus generated the cached image. Helps a bit with e.g. tdf#136223. Change-Id: I4de6164940ec7a06fb6ae2f504907b4fa076f1d4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126412 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index f6620dfaafc0..593e2ffb57e4 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1586,9 +1586,37 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma if (reduceRatio < 10) return {}; } + // Do not cache the result if it would take most of the cache and thus get evicted soon. + if (targetSize.Width() * targetSize.Height() * 4 > maxImageCacheSize() * 0.7) + return {}; + + // Use ready direct image if they are both available, now even the size doesn't matter + // (we'll scale as necessary and it's better to scale from the original). Require only + // that they are the same size, or that one prefers a shader or doesn't exist + // (i.e. avoid two images of different size). + bitmapReady = bitmap.GetSkImage(DirectImage::Yes) != nullptr; + alphaBitmapReady = alphaBitmap && alphaBitmap->GetAlphaSkImage(DirectImage::Yes) != nullptr; + if (bitmapReady && alphaBitmap && !alphaBitmapReady && !alphaBitmap->PreferSkShader()) + bitmapReady = false; + if (alphaBitmapReady && !bitmapReady && bitmap.PreferSkShader()) + alphaBitmapReady = false; + + DirectImage bitmapType = bitmapReady ? DirectImage::Yes : DirectImage::No; + DirectImage alphaBitmapType = alphaBitmapReady ? DirectImage::Yes : DirectImage::No; + + // Try to find a cached result, this time after possible delayed scaling. + OString key = makeCachedImageKey(bitmap, alphaBitmap, targetSize, bitmapType, alphaBitmapType); + if (sk_sp<SkImage> image = findCachedImage(key)) + { + assert(imageSize(image) == targetSize); + 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. + // a very large image only to not use most of it. Do this only after checking whether + // the image is already cached, since it might have been already cached in a previous + // call that had the draw area large enough to be seen as worth caching. const Size drawAreaSize = mClipRegion.GetBoundRect().GetSize() * mScaling; if (targetSize.Width() > drawAreaSize.Width() || targetSize.Height() > drawAreaSize.Height()) { @@ -1613,31 +1641,6 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma return {}; } } - // Do not cache the result if it would take most of the cache and thus get evicted soon. - if (targetSize.Width() * targetSize.Height() * 4 > maxImageCacheSize() * 0.7) - return {}; - - // Use ready direct image if they are both available, now even the size doesn't matter - // (we'll scale as necessary and it's better to scale from the original). Require only - // that they are the same size, or that one prefers a shader or doesn't exist - // (i.e. avoid two images of different size). - bitmapReady = bitmap.GetSkImage(DirectImage::Yes) != nullptr; - alphaBitmapReady = alphaBitmap && alphaBitmap->GetAlphaSkImage(DirectImage::Yes) != nullptr; - if (bitmapReady && alphaBitmap && !alphaBitmapReady && !alphaBitmap->PreferSkShader()) - bitmapReady = false; - if (alphaBitmapReady && !bitmapReady && bitmap.PreferSkShader()) - alphaBitmapReady = false; - - DirectImage bitmapType = bitmapReady ? DirectImage::Yes : DirectImage::No; - DirectImage alphaBitmapType = alphaBitmapReady ? DirectImage::Yes : DirectImage::No; - - // Try to find a cached result, this time after possible delayed scaling. - OString key = makeCachedImageKey(bitmap, alphaBitmap, targetSize, bitmapType, alphaBitmapType); - if (sk_sp<SkImage> image = findCachedImage(key)) - { - assert(imageSize(image) == targetSize); - return image; - } Size sourceSize; if (bitmapReady)