vcl/inc/skia/gdiimpl.hxx |    5 +++--
 vcl/skia/gdiimpl.cxx     |   41 ++++++++++++++++-------------------------
 2 files changed, 19 insertions(+), 27 deletions(-)

New commits:
commit 4f6551d24279aab31b23f4dd668f42d6e3d15348
Author:     Luboš Luňák <[email protected]>
AuthorDate: Wed Aug 26 10:44:48 2020 +0200
Commit:     Luboš Luňák <[email protected]>
CommitDate: Wed Aug 26 11:47:46 2020 +0200

    optimize polygon merging in Skia (tdf#136139)
    
    basegfx::utils::mergeToSinglePolyPolygon() can be an expensive operation
    when many polygons are involved, and the code was calling it for every
    new polygon, which is actually not needed. Simply merge all the collected
    polygons just once before they need to be drawn.
    
    Change-Id: Id29d5dd5647d262b2cdfe9963f8d4e2ace844b66
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101384
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <[email protected]>

diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index 7413c781409b..32beae036d5f 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -286,7 +286,7 @@ protected:
     // and anything that means the next operation cannot be another one in a 
series (e.g.
     // changing colors).
     void checkPendingDrawing();
-    bool mergePolyPolygonToPrevious(const basegfx::B2DPolyPolygon& polygon, 
double transparency);
+    bool delayDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double 
transparency);
     void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double 
transparency,
                                 bool useAA);
 
@@ -320,7 +320,8 @@ protected:
     // Info about pending polygons to draw (we try to merge adjacent polygons 
into one).
     struct LastPolyPolygonInfo
     {
-        basegfx::B2DPolyPolygon polygon;
+        basegfx::B2DPolyPolygonVector polygons;
+        basegfx::B2DRange bounds;
         double transparency;
     };
     LastPolyPolygonInfo mLastPolyPolygonInfo;
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 25decef1c0ed..b80fcc301d8a 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -735,7 +735,7 @@ bool SkiaSalGraphicsImpl::drawPolyPolygon(const 
basegfx::B2DHomMatrix& rObjectTo
     SAL_INFO("vcl.skia.trace", "drawpolypolygon(" << this << "): " << 
aPolyPolygon << ":"
                                                   << mLineColor << ":" << 
mFillColor);
 
-    if (mergePolyPolygonToPrevious(aPolyPolygon, fTransparency))
+    if (delayDrawPolyPolygon(aPolyPolygon, fTransparency))
     {
         scheduleFlush();
         return true;
@@ -790,8 +790,8 @@ void SkiaSalGraphicsImpl::performDrawPolyPolygon(const 
basegfx::B2DPolyPolygon&
 #endif
 }
 
-bool SkiaSalGraphicsImpl::mergePolyPolygonToPrevious(const 
basegfx::B2DPolyPolygon& aPolyPolygon,
-                                                     double fTransparency)
+bool SkiaSalGraphicsImpl::delayDrawPolyPolygon(const basegfx::B2DPolyPolygon& 
aPolyPolygon,
+                                               double fTransparency)
 {
     // There is some code that needlessly subdivides areas into adjacent 
rectangles,
     // but Skia doesn't line them up perfectly if AA is enabled (e.g. Cairo, 
Qt5 do,
@@ -819,39 +819,30 @@ bool 
SkiaSalGraphicsImpl::mergePolyPolygonToPrevious(const basegfx::B2DPolyPolyg
     if (aPolyPolygon.count() != 1)
         return false;
 
-    if (mLastPolyPolygonInfo.polygon.count() != 0
+    if (mLastPolyPolygonInfo.polygons.size() != 0
         && (mLastPolyPolygonInfo.transparency != fTransparency
-            || 
!mLastPolyPolygonInfo.polygon.getB2DRange().overlaps(aPolyPolygon.getB2DRange())))
+            || 
!mLastPolyPolygonInfo.bounds.overlaps(aPolyPolygon.getB2DRange())))
     {
         checkPendingDrawing(); // Cannot be parts of the same larger polygon, 
draw the last and reset.
     }
-    if (mLastPolyPolygonInfo.polygon.count() == 0)
-    {
-        mLastPolyPolygonInfo.polygon = aPolyPolygon;
-        mLastPolyPolygonInfo.transparency = fTransparency;
-        return true;
-    }
-    basegfx::B2DPolyPolygon merged
-        = basegfx::utils::mergeToSinglePolyPolygon({ 
mLastPolyPolygonInfo.polygon, aPolyPolygon });
-    if (merged.count() == 0) // it wasn't actually merged
-    {
-        checkPendingDrawing();
-        mLastPolyPolygonInfo.polygon = aPolyPolygon;
-        mLastPolyPolygonInfo.transparency = fTransparency;
-        return true;
-    }
-    mLastPolyPolygonInfo.polygon = std::move(merged);
+    // Collect the polygons that can be possibly merged. Do the merging only 
once at the end,
+    // because it's not a cheap operation.
+    mLastPolyPolygonInfo.polygons.push_back(aPolyPolygon);
+    mLastPolyPolygonInfo.bounds.expand(aPolyPolygon.getB2DRange());
+    mLastPolyPolygonInfo.transparency = fTransparency;
     return true;
 }
 
 void SkiaSalGraphicsImpl::checkPendingDrawing()
 {
-    if (mLastPolyPolygonInfo.polygon.count() != 0)
+    if (mLastPolyPolygonInfo.polygons.size() != 0)
     { // Flush any pending polygon drawing.
-        basegfx::B2DPolyPolygon polygon;
-        std::swap(polygon, mLastPolyPolygonInfo.polygon);
+        basegfx::B2DPolyPolygonVector polygons;
+        std::swap(polygons, mLastPolyPolygonInfo.polygons);
         double transparency = mLastPolyPolygonInfo.transparency;
-        performDrawPolyPolygon(polygon, transparency, true);
+        mLastPolyPolygonInfo.bounds.reset();
+        basegfx::B2DPolyPolygon merged = 
basegfx::utils::mergeToSinglePolyPolygon(polygons);
+        performDrawPolyPolygon(merged, transparency, true);
     }
 }
 
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to