[Libreoffice-commits] core.git: vcl/skia

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Tue Apr 7 09:54:54 UTC 2020


 vcl/skia/gdiimpl.cxx |   52 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 35 insertions(+), 17 deletions(-)

New commits:
commit 81edf0ceef264dbbb338d2ed91378baa59b7a3bf
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Mon Apr 6 17:10:20 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Tue Apr 7 11:54:13 2020 +0200

    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 at collabora.com>

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);


More information about the Libreoffice-commits mailing list