diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-05-13 19:25:15 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-05-14 11:57:49 +0200 |
commit | 1b5bd34d8430690b19fae0d0febfd810b9525ca2 (patch) | |
tree | 41197c5562c9d7cb27172616c0a29f0e73ec1084 /vcl/skia | |
parent | fc0bff85f3338cb4fe8f4d42421cb69801cb3abb (diff) |
cache Skia' drawAlphaBitmap() in raster mode (tdf#104878)
Moving the mouse with the bug document triggers repeated calls
to drawAlphaBitmap(), which is somewhat costly if not GPU-accelerated.
Now the main cost in that bugreport is generating the frames
all over again.
Change-Id: Ic44811c713a745459f0af811c3d55038c944d89e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94152
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl/skia')
-rw-r--r-- | vcl/skia/SkiaHelper.cxx | 3 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 86 |
2 files changed, 44 insertions, 45 deletions
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index d7004a7afcb7..aab6560b2554 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -489,12 +489,13 @@ sk_sp<SkImage> findCachedImage(const OString& key) if (it->key == key) { sk_sp<SkImage> ret = it->image; - SAL_INFO("vcl.skia.trace", "findcachedimage " << it->image); + SAL_INFO("vcl.skia.trace", "findcachedimage " << it->image << " found"); imageCache->splice(imageCache->begin(), *imageCache, it); return ret; } } } + SAL_INFO("vcl.skia.trace", "findcachedimage " << key << " not found"); return nullptr; } diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 436a9d35d43d..28183ecf10f4 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1256,57 +1256,23 @@ bool SkiaSalGraphicsImpl::drawEPS(long, long, long, long, void*, sal_uInt32) return false; } -bool SkiaSalGraphicsImpl::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSourceBitmap, - const SalBitmap& rAlphaBitmap) -{ - assert(dynamic_cast<const SkiaSalBitmap*>(&rSourceBitmap)); - assert(dynamic_cast<const SkiaSalBitmap*>(&rAlphaBitmap)); - sk_sp<SkSurface> tmpSurface = SkiaHelper::createSkSurface(rSourceBitmap.GetSize()); - if (!tmpSurface) - return false; - SkCanvas* canvas = tmpSurface->getCanvas(); - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha - canvas->drawImage(static_cast<const SkiaSalBitmap&>(rSourceBitmap).GetSkImage(), 0, 0, &paint); - paint.setBlendMode(SkBlendMode::kDstOut); // VCL alpha is one-minus-alpha - canvas->drawImage(static_cast<const SkiaSalBitmap&>(rAlphaBitmap).GetAlphaSkImage(), 0, 0, - &paint); - drawImage(rPosAry, tmpSurface->makeImageSnapshot()); - return true; -} - -void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& rPosAry, const sk_sp<SkImage>& aImage, - SkBlendMode eBlendMode) -{ - SkRect aSourceRect - = SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight); - SkRect aDestinationRect = SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, - rPosAry.mnDestWidth, rPosAry.mnDestHeight); - - SkPaint aPaint; - aPaint.setBlendMode(eBlendMode); - - preDraw(); - SAL_INFO("vcl.skia.trace", "drawimage(" << this << "): " << rPosAry << ":" << int(eBlendMode)); - getDrawCanvas()->drawImageRect(aImage, aSourceRect, aDestinationRect, &aPaint); - addXorRegion(aDestinationRect); - postDraw(); -} - // 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. static sk_sp<SkImage> mergeBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap, - const Size targetSize, bool blockCaching) + const Size targetSize, bool blockCaching = false) { sk_sp<SkImage> image; OString key; - if (targetSize == bitmap.GetSize()) - blockCaching = true; // probably not much point in caching if no scaling is involved + if (alphaBitmap == nullptr && targetSize == bitmap.GetSize()) + blockCaching = true; // probably not much point in caching of just doing a copy if (targetSize.Width() > bitmap.GetSize().Width() || targetSize.Height() > bitmap.GetSize().Height()) blockCaching = true; // caching enlarging is probably wasteful and not worth it if (bitmap.GetSize().Width() < 100 && bitmap.GetSize().Height() < 100) blockCaching = true; // image too small to be worth caching + if (SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster + && targetSize == bitmap.GetSize()) + blockCaching = true; // GPU-accelerated shouldn't need caching of applying alpha if (!blockCaching) { OStringBuffer keyBuf; @@ -1377,6 +1343,36 @@ static sk_sp<SkImage> mergeBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBit return image; } +bool SkiaSalGraphicsImpl::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSourceBitmap, + const SalBitmap& rAlphaBitmap) +{ + assert(dynamic_cast<const SkiaSalBitmap*>(&rSourceBitmap)); + assert(dynamic_cast<const SkiaSalBitmap*>(&rAlphaBitmap)); + sk_sp<SkImage> image + = mergeBitmaps(static_cast<const SkiaSalBitmap&>(rSourceBitmap), + static_cast<const SkiaSalBitmap*>(&rAlphaBitmap), rSourceBitmap.GetSize()); + drawImage(rPosAry, image); + return true; +} + +void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& rPosAry, const sk_sp<SkImage>& aImage, + SkBlendMode eBlendMode) +{ + SkRect aSourceRect + = SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight); + SkRect aDestinationRect = SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, + rPosAry.mnDestWidth, rPosAry.mnDestHeight); + + SkPaint aPaint; + aPaint.setBlendMode(eBlendMode); + + preDraw(); + SAL_INFO("vcl.skia.trace", "drawimage(" << this << "): " << rPosAry << ":" << int(eBlendMode)); + getDrawCanvas()->drawImageRect(aImage, aSourceRect, aDestinationRect, &aPaint); + addXorRegion(aDestinationRect); + postDraw(); +} + bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY, @@ -1389,10 +1385,12 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const SkiaSalBitmap& rSkiaBitmap = static_cast<const SkiaSalBitmap&>(rSourceBitmap); const SkiaSalBitmap* pSkiaAlphaBitmap = static_cast<const SkiaSalBitmap*>(pAlphaBitmap); - // setup the image transformation - // using the rNull, rX, rY points as destinations for the (0,0), (Width,0), (0,Height) source points - const basegfx::B2DVector aXRel = rX - rNull; - const basegfx::B2DVector aYRel = rY - rNull; + // Setup the image transformation, + // using the rNull, rX, rY points as destinations for the (0,0), (Width,0), (0,Height) source points. + // Round to pixels, otherwise kMScaleX/Y below could be slightly != 1, causing unnecessary uncached + // scaling. + const basegfx::B2IVector aXRel = basegfx::fround(rX - rNull); + const basegfx::B2IVector aYRel = basegfx::fround(rY - rNull); const Size aSize = rSourceBitmap.GetSize(); |