vcl/skia/gdiimpl.cxx |   27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

New commits:
commit 621430208d29e40ab95509a4e94da6e8313ed389
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Tue Nov 16 08:03:06 2021 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Tue Nov 16 10:41:36 2021 +0100

    optimize Skia's copyArea() to copy less data
    
    Change-Id: Ia1cd0522643b58ea1be3ad974c1fc5f7fed657d4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125268
    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 b97d2f28c428..4019c436d51d 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1347,17 +1347,32 @@ void SkiaSalGraphicsImpl::privateCopyBits(const 
SalTwoRect& rPosAry, SkiaSalGrap
                                      rPosAry.mnDestHeight));
     SkPaint paint;
     paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha
-    SkRect srcRect
-        = SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, 
rPosAry.mnSrcHeight);
+    SkIRect srcRect = SkIRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, 
rPosAry.mnSrcWidth,
+                                        rPosAry.mnSrcHeight);
     SkRect destRect = SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, 
rPosAry.mnDestWidth,
                                        rPosAry.mnDestHeight);
     // Scaling for source coordinates must be done manually.
     if (src->mScaling != 1)
         srcRect = scaleRect(srcRect, src->mScaling);
-    // Do not use makeImageSnapshot(rect), as that one may make a needless 
data copy.
-    getDrawCanvas()->drawImageRect(makeCheckedImageSnapshot(src->mSurface), 
srcRect, destRect,
-                                   makeSamplingOptions(rPosAry, mScaling, 
src->mScaling), &paint,
-                                   SkCanvas::kFast_SrcRectConstraint);
+    if (src == this)
+    {
+        // Copy-to-self means that we'd take a snapshot, which would refcount 
the data,
+        // and then drawing would result in copy in write, copying the entire 
surface.
+        // Try to copy less by making a snapshot of only what is needed.
+        sk_sp<SkImage> image = makeCheckedImageSnapshot(src->mSurface, 
srcRect);
+        srcRect.offset(-srcRect.x(), -srcRect.y());
+        getDrawCanvas()->drawImageRect(image, SkRect::Make(srcRect), destRect,
+                                       makeSamplingOptions(rPosAry, mScaling, 
src->mScaling),
+                                       &paint, 
SkCanvas::kFast_SrcRectConstraint);
+    }
+    else
+    {
+        // Do not use makeImageSnapshot(rect), as that one may make a needless 
data copy.
+        getDrawCanvas()->drawImageRect(makeCheckedImageSnapshot(src->mSurface),
+                                       SkRect::Make(srcRect), destRect,
+                                       makeSamplingOptions(rPosAry, mScaling, 
src->mScaling),
+                                       &paint, 
SkCanvas::kFast_SrcRectConstraint);
+    }
 }
 
 bool SkiaSalGraphicsImpl::blendBitmap(const SalTwoRect& rPosAry, const 
SalBitmap& rBitmap)

Reply via email to