Title: [136174] trunk/Source/WebCore
Revision
136174
Author
[email protected]
Date
2012-11-29 15:21:09 -0800 (Thu, 29 Nov 2012)

Log Message

Avoid painting lots of small rects in WebLayer painting
https://bugs.webkit.org/show_bug.cgi?id=103673

Reviewed by Tim Horton.

r109186 added code in drawLayerContents() to enumerate over the rects in
the CALayer's dirty region, and paint them individually. This was done
to help performance on the IE Maze Solver test.

On large, complex pages like Facebook, the overhead of traversing the
RenderLayer tree for painting is such that it's better to paint a single,
or fewer rects rather than lots of little ones.

So adopt a heuristic similar to that in DrawingArea, where if the
combined area of the small rects is 75% or more of the combined rect,
just paint the combined rect. Also paint the combined rect if there
are more than 5 individual rects.

I verified that this preserves the optimization for IE Maze Solver.

* platform/graphics/mac/WebLayer.mm:
(drawLayerContents):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (136173 => 136174)


--- trunk/Source/WebCore/ChangeLog	2012-11-29 23:17:24 UTC (rev 136173)
+++ trunk/Source/WebCore/ChangeLog	2012-11-29 23:21:09 UTC (rev 136174)
@@ -1,3 +1,28 @@
+2012-11-29  Simon Fraser  <[email protected]>
+
+        Avoid painting lots of small rects in WebLayer painting
+        https://bugs.webkit.org/show_bug.cgi?id=103673
+
+        Reviewed by Tim Horton.
+
+        r109186 added code in drawLayerContents() to enumerate over the rects in
+        the CALayer's dirty region, and paint them individually. This was done
+        to help performance on the IE Maze Solver test.
+        
+        On large, complex pages like Facebook, the overhead of traversing the
+        RenderLayer tree for painting is such that it's better to paint a single,
+        or fewer rects rather than lots of little ones.
+        
+        So adopt a heuristic similar to that in DrawingArea, where if the
+        combined area of the small rects is 75% or more of the combined rect,
+        just paint the combined rect. Also paint the combined rect if there
+        are more than 5 individual rects.
+        
+        I verified that this preserves the optimization for IE Maze Solver.
+
+        * platform/graphics/mac/WebLayer.mm:
+        (drawLayerContents):
+
 2012-11-29  Eugene Klyuchnikov  <[email protected]>
 
         Web Inspector: Web Inspector: Make main-thread monitoring go through InspectorController.

Modified: trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm (136173 => 136174)


--- trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm	2012-11-29 23:17:24 UTC (rev 136173)
+++ trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm	2012-11-29 23:21:09 UTC (rev 136174)
@@ -85,18 +85,37 @@
     ThemeMac::setFocusRingClipRect(transform.mapRect(clipBounds));
 
 #if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
-    __block GraphicsContext* ctx = &graphicsContext;
+    const float wastedSpaceThreshold = 0.75f;
+    const unsigned maxRectsToPaint = 5;
 
-    wkCALayerEnumerateRectsBeingDrawnWithBlock(layer, context, ^(CGRect rect){
-        FloatRect rectBeingDrawn(rect);
-        rectBeingDrawn.intersect(clipBounds);
-        
-        GraphicsContextStateSaver stateSaver(*ctx);
-        ctx->clip(rectBeingDrawn);
-        
-        layerContents->platformCALayerPaintContents(*ctx, enclosingIntRect(rectBeingDrawn));
+    double clipArea = clipBounds.width() * clipBounds.height();
+    __block double totalRectArea = 0;
+    __block unsigned rectCount = 0;
+    __block Vector<FloatRect, maxRectsToPaint> dirtyRects;
+    
+    wkCALayerEnumerateRectsBeingDrawnWithBlock(layer, context, ^(CGRect rect) {
+        if (++rectCount > maxRectsToPaint)
+            return;
+
+        totalRectArea += rect.size.width * rect.size.height;
+        dirtyRects.append(rect);
     });
 
+    if (rectCount < maxRectsToPaint && totalRectArea < clipArea * wastedSpaceThreshold) {
+        for (unsigned i = 0; i < rectCount; ++i) {
+            const FloatRect& currentRect = dirtyRects[i];
+            
+            GraphicsContextStateSaver stateSaver(graphicsContext);
+            graphicsContext.clip(currentRect);
+            
+            layerContents->platformCALayerPaintContents(graphicsContext, enclosingIntRect(currentRect));
+        }
+    } else {
+        // CGContextGetClipBoundingBox() gives us the bounds of the dirty region, so clipBounds
+        // encompasses all the dirty rects.
+        layerContents->platformCALayerPaintContents(graphicsContext, enclosingIntRect(clipBounds));
+    }
+
 #else
     IntRect clip(enclosingIntRect(clipBounds));
     layerContents->platformCALayerPaintContents(graphicsContext, clip);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to