summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-04-06 17:10:20 +0200
committerLuboš Luňák <l.lunak@collabora.com>2020-04-07 11:54:13 +0200
commit81edf0ceef264dbbb338d2ed91378baa59b7a3bf (patch)
tree24195f6909f720a16afe393064a128a95cdc490a
parent2fcfbd73768b69ba58607a054e7f851be2942992 (diff)
optimize SkiaSalGraphicsImpl area copying
SkSurface::draw() can avoid copies if it detects the source and destination are the same surface. This can especially make a difference on Windows with raster, because RasterWindowContext_win shares the surface's pixel data with BITMAPINFO, which resets SkSurface's fWeOwnThePixels, making even makeImageSnapshot() do copies. Can be seen in the profile e.g. for tdf#131408. Change-Id: I08d08974c4725824e05c5644549b920f69b9ce64 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91773 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--vcl/skia/gdiimpl.cxx52
1 files changed, 35 insertions, 17 deletions
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index e4f064589b21..8b484ea124c7 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -852,6 +852,20 @@ bool SkiaSalGraphicsImpl::drawPolyPolygonBezier(sal_uInt32, const sal_uInt32*,
return false;
}
+static void copyArea(SkCanvas* canvas, sk_sp<SkSurface> surface, long nDestX, long nDestY,
+ long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight)
+{
+ // Using SkSurface::draw() should be more efficient than SkSurface::makeImageSnapshot(),
+ // because it may detect copying to itself and avoid some needless copies.
+ // It cannot do a subrectangle though, so clip.
+ canvas->save();
+ canvas->clipRect(SkRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight));
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
+ surface->draw(canvas, nDestX - nSrcX, nDestY - nSrcY, &paint);
+ canvas->restore();
+}
+
void SkiaSalGraphicsImpl::copyArea(long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth,
long nSrcHeight, bool /*bWindowInvalidate*/)
{
@@ -861,12 +875,7 @@ void SkiaSalGraphicsImpl::copyArea(long nDestX, long nDestY, long nSrcX, long nS
SAL_INFO("vcl.skia.trace", "copyarea(" << this << "): " << Point(nSrcX, nSrcY) << "->"
<< Point(nDestX, nDestY) << "/"
<< Size(nSrcWidth, nSrcHeight));
- // Do not use makeImageSnapshot(rect), as that one may make a needless data copy.
- sk_sp<SkImage> image = mSurface->makeImageSnapshot();
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
- getDrawCanvas()->drawImageRect(image, SkIRect::MakeXYWH(nSrcX, nSrcY, nSrcWidth, nSrcHeight),
- SkRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight), &paint);
+ ::copyArea(getDrawCanvas(), mSurface, nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight);
if (mXorMode) // limit xor area update
mXorExtents = SkRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight);
postDraw();
@@ -884,17 +893,26 @@ void SkiaSalGraphicsImpl::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcG
}
else
src = this;
- SAL_INFO("vcl.skia.trace", "copybits(" << this << "): (" << src << "):" << rPosAry);
- // Do not use makeImageSnapshot(rect), as that one may make a needless data copy.
- sk_sp<SkImage> image = src->mSurface->makeImageSnapshot();
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
- getDrawCanvas()->drawImageRect(
- image,
- SkIRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight),
- SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth,
- rPosAry.mnDestHeight),
- &paint);
+ if (rPosAry.mnSrcWidth == rPosAry.mnDestWidth && rPosAry.mnSrcHeight == rPosAry.mnDestHeight)
+ {
+ SAL_INFO("vcl.skia.trace", "copybits(" << this << "): copy area:" << rPosAry);
+ ::copyArea(getDrawCanvas(), src->mSurface, rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX,
+ rPosAry.mnSrcY, rPosAry.mnDestWidth, rPosAry.mnDestHeight);
+ }
+ else
+ {
+ SAL_INFO("vcl.skia.trace", "copybits(" << this << "): (" << src << "):" << rPosAry);
+ // Do not use makeImageSnapshot(rect), as that one may make a needless data copy.
+ sk_sp<SkImage> image = src->mSurface->makeImageSnapshot();
+ SkPaint paint;
+ paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
+ getDrawCanvas()->drawImageRect(image,
+ SkIRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY,
+ rPosAry.mnSrcWidth, rPosAry.mnSrcHeight),
+ SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY,
+ rPosAry.mnDestWidth, rPosAry.mnDestHeight),
+ &paint);
+ }
if (mXorMode) // limit xor area update
mXorExtents = SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth,
rPosAry.mnDestHeight);