diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-04-06 17:10:20 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-04-07 11:54:13 +0200 |
commit | 81edf0ceef264dbbb338d2ed91378baa59b7a3bf (patch) | |
tree | 24195f6909f720a16afe393064a128a95cdc490a | |
parent | 2fcfbd73768b69ba58607a054e7f851be2942992 (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.cxx | 52 |
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); |