<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[158982] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/158982">158982</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2013-11-08 17:43:45 -0800 (Fri, 08 Nov 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Remote Layer Tree: RemoteLayerBackingStore partial repaint is broken for the tile cache
https://bugs.webkit.org/show_bug.cgi?id=123944

Reviewed by Simon Fraser.

Ensure that the tile cache retrieves repaint rects from the tile layer,
not from the tiled backing layer.

Rework RemoteLayerBackingStore painting to fix some rounding issues
that would cause pixel cracks upon repaint, and to speed it up a bit.

* Shared/mac/RemoteLayerBackingStore.h:
Redefine RepaintRectList because we can't include WebLayer.h here yet.
Remove createBackingStore, which was never implemented.
Remove mapToContentCoordinates, because we don't need it on Mac.

(WebKit::RemoteLayerBackingStore::paintingRects): Added.

* Shared/mac/RemoteLayerBackingStore.mm:
(RemoteLayerBackingStore::setNeedsDisplay):
(RemoteLayerBackingStore::display):
Stop using mapToContentCoordinates.

(RemoteLayerBackingStore::drawInContext):
Use clipping instead of painting the image multiple times.
Never repaint more than the dirty region's bounds.
Don't waste time with all of the drawNativeImage code, just use CG.
Unindent the switch's cases.
Store the rects we're painting so that enumerateRectsBeingDrawn can get them.
Pixel-snap the rects we're painting.
Clip the context before going to paint.

* WebProcess/WebPage/mac/PlatformCALayerRemote.cpp:
(PlatformCALayerRemote::enumerateRectsBeingDrawn):
* WebProcess/WebPage/mac/PlatformCALayerRemote.h:
Retrieve the rects currently being painted from our backing store, and
transform them (mostly) according to the CTM, to match the transformation
that will have occurred underneath wkCALayerEnumerateRectsBeingDrawnWithBlock.

* platform/graphics/ca/PlatformCALayer.h:
* platform/graphics/ca/mac/PlatformCALayerMac.h:
* platform/graphics/ca/mac/PlatformCALayerMac.mm:
(PlatformCALayerMac::enumerateRectsBeingDrawn):
Allow the PlatformCALayer to decide how to enumerate rects to paint.

* WebCore.exp.in:
* platform/graphics/mac/WebLayer.h:
Add RepaintRectList, remove some unnecessary WebCore::s.

* platform/graphics/mac/WebLayer.mm:
(WebCore::collectRectsToPaint):
Factor collectRectsToPaint out; it just grabs the rects from
the layer and makes the decision whether to repaint the bounds
of the dirty region or just the subregions.

Move calls to collectRectsToPaint() to callers of drawLayerContents(),
so that TileController can collect rects from the appropriate source
(the Tile layer) and other layers just continue grabbing them from
their relevant layers.

Make sure that the list that comes from collectRectsToPaint() always
has at least one rect in it (appending the clip bounds if we don't
want to repaint subregions) so we can simplify logic in drawLayerContents.

(WebCore::drawLayerContents):
Remove code to support CompositingCoordinatesBottomUp, as it's only
used on Windows, so this Mac-specific code doesn't need to support it.

Simplify logic given that dirtyRects will always be non-empty.

(-[WebLayer drawInContext:]):
(-[WebSimpleLayer setNeedsDisplayInRect:]):
* platform/graphics/ca/mac/TileController.mm:
(WebCore::TileController::platformCALayerPaintContents):
Adopt collectRectsToPaint.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscaPlatformCALayerh">trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscamacPlatformCALayerMach">trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscamacPlatformCALayerMacmm">trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscamacTileControllermm">trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacWebLayerh">trunk/Source/WebCore/platform/graphics/mac/WebLayer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacWebLayermm">trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerBackingStoreh">trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerBackingStoremm">trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacPlatformCALayerRemotecpp">trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacPlatformCALayerRemoteh">trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/ChangeLog        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2013-11-08  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Remote Layer Tree: RemoteLayerBackingStore partial repaint is broken for the tile cache
+        https://bugs.webkit.org/show_bug.cgi?id=123944
+
+        Reviewed by Simon Fraser.
+
+        Ensure that the tile cache retrieves repaint rects from the tile layer,
+        not from the tiled backing layer.
+
+        * platform/graphics/ca/PlatformCALayer.h:
+        * platform/graphics/ca/mac/PlatformCALayerMac.h:
+        * platform/graphics/ca/mac/PlatformCALayerMac.mm:
+        (PlatformCALayerMac::enumerateRectsBeingDrawn):
+        Allow the PlatformCALayer to decide how to enumerate rects to paint.
+
+        * WebCore.exp.in:
+        * platform/graphics/mac/WebLayer.h:
+        Add RepaintRectList, remove some unnecessary WebCore::s.
+
+        * platform/graphics/mac/WebLayer.mm:
+        (WebCore::collectRectsToPaint):
+        Factor collectRectsToPaint out; it just grabs the rects from
+        the layer and makes the decision whether to repaint the bounds
+        of the dirty region or just the subregions.
+
+        Move calls to collectRectsToPaint() to callers of drawLayerContents(),
+        so that TileController can collect rects from the appropriate source
+        (the Tile layer) and other layers just continue grabbing them from
+        their relevant layers.
+
+        Make sure that the list that comes from collectRectsToPaint() always
+        has at least one rect in it (appending the clip bounds if we don't
+        want to repaint subregions) so we can simplify logic in drawLayerContents.
+
+        (WebCore::drawLayerContents):
+        Remove code to support CompositingCoordinatesBottomUp, as it's only
+        used on Windows, so this Mac-specific code doesn't need to support it.
+
+        Simplify logic given that dirtyRects will always be non-empty.
+
+        (-[WebLayer drawInContext:]):
+        (-[WebSimpleLayer setNeedsDisplayInRect:]):
+        * platform/graphics/ca/mac/TileController.mm:
+        (WebCore::TileController::platformCALayerPaintContents):
+        Adopt collectRectsToPaint.
+
</ins><span class="cx"> 2013-11-08  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement more KeyedEncoder functionality
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/WebCore.exp.in        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -691,7 +691,7 @@
</span><span class="cx"> __ZN7WebCore17SQLiteTransactionD1Ev
</span><span class="cx"> __ZN7WebCore17SubresourceLoader6createEPNS_5FrameEPNS_14CachedResourceERKNS_15ResourceRequestERKNS_21ResourceLoaderOptionsE
</span><span class="cx"> __ZN7WebCore17cacheDOMStructureEPNS_17JSDOMGlobalObjectEPN3JSC9StructureEPKNS2_9ClassInfoE
</span><del>-__ZN7WebCore17drawLayerContentsEP9CGContextPNS_15PlatformCALayerEN3WTF6VectorINS_9FloatRectELm5ENS4_15CrashOnOverflowEEE
</del><ins>+__ZN7WebCore17drawLayerContentsEP9CGContextPNS_15PlatformCALayerERN3WTF6VectorINS_9FloatRectELm5ENS4_15CrashOnOverflowEEE
</ins><span class="cx"> __ZN7WebCore17languageDidChangeEv
</span><span class="cx"> __ZN7WebCore17openTemporaryFileERKN3WTF6StringERi
</span><span class="cx"> __ZN7WebCore17setCookiesFromDOMERKNS_21NetworkStorageSessionERKNS_3URLES5_RKN3WTF6StringE
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscaPlatformCALayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -200,6 +200,10 @@
</span><span class="cx"> 
</span><span class="cx">     virtual PassRefPtr&lt;PlatformCALayer&gt; createCompatibleLayer(LayerType, PlatformCALayerClient*) const = 0;
</span><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+    virtual void enumerateRectsBeingDrawn(CGContextRef, void (^block)(CGRect)) = 0;
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     PlatformCALayer(LayerType layerType, PlatformCALayerClient* owner)
</span><span class="cx">         : m_layerType(layerType)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscamacPlatformCALayerMach"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.h (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.h        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.h        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -141,6 +141,8 @@
</span><span class="cx"> 
</span><span class="cx">     virtual PassRefPtr&lt;PlatformCALayer&gt; createCompatibleLayer(PlatformCALayer::LayerType, PlatformCALayerClient*) const OVERRIDE;
</span><span class="cx"> 
</span><ins>+    virtual void enumerateRectsBeingDrawn(CGContextRef, void (^block)(CGRect)) OVERRIDE;
+
</ins><span class="cx"> private:
</span><span class="cx">     PlatformCALayerMac(LayerType, PlatformLayer*, PlatformCALayerClient* owner);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscamacPlatformCALayerMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -736,4 +736,9 @@
</span><span class="cx">     return PlatformCALayerMac::create(layerType, client);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformCALayerMac::enumerateRectsBeingDrawn(CGContextRef context, void (^block)(CGRect))
+{
+    wkCALayerEnumerateRectsBeingDrawnWithBlock(m_layer.get(), context, block);
+}
+
</ins><span class="cx"> #endif // USE(ACCELERATED_COMPOSITING)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscamacTileControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -172,7 +172,8 @@
</span><span class="cx">         context.translate(-layerOrigin.x(), -layerOrigin.y());
</span><span class="cx">         context.scale(FloatSize(m_scale, m_scale));
</span><span class="cx"> 
</span><del>-        drawLayerContents(context.platformContext(), m_tileCacheLayer);
</del><ins>+        RepaintRectList dirtyRects = collectRectsToPaint(context.platformContext(), platformCALayer);
+        drawLayerContents(context.platformContext(), m_tileCacheLayer, dirtyRects);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     int repaintCount = platformCALayerIncrementRepaintCount(platformCALayer);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacWebLayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/WebLayer.h (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/WebLayer.h        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/platform/graphics/mac/WebLayer.h        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -46,10 +46,12 @@
</span><span class="cx"> class PlatformCALayer;
</span><span class="cx"> class PlatformCALayerClient;
</span><span class="cx"> 
</span><ins>+typedef Vector&lt;FloatRect, webLayerMaxRectsToPaint&gt; RepaintRectList;
+
</ins><span class="cx"> // Functions allows us to share implementation across WebTiledLayer and WebLayer
</span><del>-void drawLayerContents(CGContextRef, WebCore::PlatformCALayer*);
-void drawLayerContents(CGContextRef, WebCore::PlatformCALayer*, Vector&lt;WebCore::FloatRect, webLayerMaxRectsToPaint&gt; dirtyRects);
-void drawRepaintIndicator(CGContextRef, WebCore::PlatformCALayer*, int repaintCount, CGColorRef customBackgroundColor);
</del><ins>+RepaintRectList collectRectsToPaint(CGContextRef, PlatformCALayer*);
+void drawLayerContents(CGContextRef, PlatformCALayer*, RepaintRectList&amp; dirtyRects);
+void drawRepaintIndicator(CGContextRef, PlatformCALayer*, int repaintCount, CGColorRef customBackgroundColor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // USE(ACCELERATED_COMPOSITING)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacWebLayermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -33,8 +33,6 @@
</span><span class="cx"> #import &quot;GraphicsLayerCA.h&quot;
</span><span class="cx"> #import &quot;PlatformCALayer.h&quot;
</span><span class="cx"> #import &quot;ThemeMac.h&quot;
</span><del>-#import &quot;WebCoreSystemInterface.h&quot;
-#import &lt;objc/runtime.h&gt;
</del><span class="cx"> #import &lt;QuartzCore/QuartzCore.h&gt;
</span><span class="cx"> 
</span><span class="cx"> @interface CALayer(WebCoreCALayerPrivate)
</span><span class="lines">@@ -45,32 +43,32 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-void drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer)
</del><ins>+RepaintRectList collectRectsToPaint(CGContextRef context, PlatformCALayer* platformCALayer)
</ins><span class="cx"> {
</span><span class="cx">     __block double totalRectArea = 0;
</span><span class="cx">     __block unsigned rectCount = 0;
</span><del>-    __block Vector&lt;FloatRect, webLayerMaxRectsToPaint&gt; dirtyRects;
</del><ins>+    __block RepaintRectList dirtyRects;
</ins><span class="cx"> 
</span><del>-    if (PlatformLayer *platformLayer = platformCALayer-&gt;platformLayer()) {
-        wkCALayerEnumerateRectsBeingDrawnWithBlock(platformLayer, context, ^(CGRect rect) {
-            if (++rectCount &gt; webLayerMaxRectsToPaint)
-                return;
</del><ins>+    platformCALayer-&gt;enumerateRectsBeingDrawn(context, ^(CGRect rect) {
+        if (++rectCount &gt; webLayerMaxRectsToPaint)
+            return;
</ins><span class="cx"> 
</span><del>-            totalRectArea += rect.size.width * rect.size.height;
-            dirtyRects.append(rect);
-        });
-    }
</del><ins>+        totalRectArea += rect.size.width * rect.size.height;
+        dirtyRects.append(rect);
+    });
</ins><span class="cx"> 
</span><span class="cx">     FloatRect clipBounds = CGContextGetClipBoundingBox(context);
</span><span class="cx">     double clipArea = clipBounds.width() * clipBounds.height();
</span><span class="cx"> 
</span><del>-    if (rectCount &gt;= webLayerMaxRectsToPaint || totalRectArea &gt;= clipArea * webLayerWastedSpaceThreshold)
</del><ins>+    if (rectCount &gt;= webLayerMaxRectsToPaint || totalRectArea &gt;= clipArea * webLayerWastedSpaceThreshold) {
</ins><span class="cx">         dirtyRects.clear();
</span><ins>+        dirtyRects.append(clipBounds);
+    }
</ins><span class="cx"> 
</span><del>-    drawLayerContents(context, platformCALayer, dirtyRects);
</del><ins>+    return dirtyRects;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer, Vector&lt;FloatRect, webLayerMaxRectsToPaint&gt; dirtyRects)
</del><ins>+void drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer, RepaintRectList&amp; dirtyRects)
</ins><span class="cx"> {
</span><span class="cx">     WebCore::PlatformCALayerClient* layerContents = platformCALayer-&gt;owner();
</span><span class="cx">     if (!layerContents)
</span><span class="lines">@@ -78,11 +76,8 @@
</span><span class="cx"> 
</span><span class="cx">     CGContextSaveGState(context);
</span><span class="cx"> 
</span><del>-    if (layerContents-&gt;platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) {
-        FloatRect layerBounds = platformCALayer-&gt;bounds();
-        CGContextScaleCTM(context, 1, -1);
-        CGContextTranslateCTM(context, 0, -layerBounds.height());
-    }
</del><ins>+    // We never use CompositingCoordinatesBottomUp on Mac.
+    ASSERT(layerContents-&gt;platformCALayerContentsOrientation() == GraphicsLayer::CompositingCoordinatesTopDown);
</ins><span class="cx"> 
</span><span class="cx">     [NSGraphicsContext saveGraphicsState];
</span><span class="cx"> 
</span><span class="lines">@@ -112,20 +107,11 @@
</span><span class="cx"> #endif
</span><span class="cx">     ThemeMac::setFocusRingClipRect(focusRingClipRect);
</span><span class="cx"> 
</span><del>-    // If we have no dirty rects, repaint the whole layer.
-    if (dirtyRects.isEmpty()) {
-        // CGContextGetClipBoundingBox() gives us the bounds of the dirty region, so clipBounds
-        // encompasses all the dirty rects.
-        layerContents-&gt;platformCALayerPaintContents(platformCALayer, graphicsContext, enclosingIntRect(clipBounds));
-    } else {
-        for (unsigned i = 0; i &lt; dirtyRects.size(); ++i) {
-            const FloatRect&amp; currentRect = dirtyRects[i];
-            
-            GraphicsContextStateSaver stateSaver(graphicsContext);
-            graphicsContext.clip(currentRect);
-            
-            layerContents-&gt;platformCALayerPaintContents(platformCALayer, graphicsContext, enclosingIntRect(currentRect));
-        }
</del><ins>+    for (auto rect : dirtyRects) {
+        GraphicsContextStateSaver stateSaver(graphicsContext);
+        graphicsContext.clip(rect);
+
+        layerContents-&gt;platformCALayerPaintContents(platformCALayer, graphicsContext, enclosingIntRect(rect));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ThemeMac::setFocusRingClipRect(FloatRect());
</span><span class="lines">@@ -189,8 +175,10 @@
</span><span class="cx"> - (void)drawInContext:(CGContextRef)context
</span><span class="cx"> {
</span><span class="cx">     PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
</span><del>-    if (layer)
-        drawLayerContents(context, layer);
</del><ins>+    if (layer) {
+        RepaintRectList rectsToPaint = collectRectsToPaint(context, layer);
+        drawLayerContents(context, layer, rectsToPaint);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @end // implementation WebLayer
</span><span class="lines">@@ -223,17 +211,11 @@
</span><span class="cx"> 
</span><span class="cx">     if (PlatformCALayerClient* layerOwner = platformLayer-&gt;owner()) {
</span><span class="cx">         if (layerOwner-&gt;platformCALayerDrawsContent()) {
</span><del>-            if (layerOwner-&gt;platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp)
-                dirtyRect.origin.y = [self bounds].size.height - dirtyRect.origin.y - dirtyRect.size.height;
-
</del><span class="cx">             [super setNeedsDisplayInRect:dirtyRect];
</span><span class="cx"> 
</span><span class="cx">             if (layerOwner-&gt;platformCALayerShowRepaintCounter(platformLayer)) {
</span><span class="cx">                 CGRect bounds = [self bounds];
</span><span class="cx">                 CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 52, 27);
</span><del>-                if (layerOwner-&gt;platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp)
-                    indicatorRect.origin.y = [self bounds].size.height - indicatorRect.origin.y - indicatorRect.size.height;
-
</del><span class="cx">                 [super setNeedsDisplayInRect:indicatorRect];
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebKit2/ChangeLog        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -1,3 +1,41 @@
</span><ins>+2013-11-08  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Remote Layer Tree: RemoteLayerBackingStore partial repaint is broken for the tile cache
+        https://bugs.webkit.org/show_bug.cgi?id=123944
+
+        Reviewed by Simon Fraser.
+
+        Rework RemoteLayerBackingStore painting to fix some rounding issues
+        that would cause pixel cracks upon repaint, and to speed it up a bit.
+
+        * Shared/mac/RemoteLayerBackingStore.h:
+        Redefine RepaintRectList because we can't include WebLayer.h here yet.
+        Remove createBackingStore, which was never implemented.
+        Remove mapToContentCoordinates, because we don't need it on Mac.
+
+        (WebKit::RemoteLayerBackingStore::paintingRects): Added.
+
+        * Shared/mac/RemoteLayerBackingStore.mm:
+        (RemoteLayerBackingStore::setNeedsDisplay):
+        (RemoteLayerBackingStore::display):
+        Stop using mapToContentCoordinates.
+
+        (RemoteLayerBackingStore::drawInContext):
+        Use clipping instead of painting the image multiple times.
+        Never repaint more than the dirty region's bounds.
+        Don't waste time with all of the drawNativeImage code, just use CG.
+        Unindent the switch's cases.
+        Store the rects we're painting so that enumerateRectsBeingDrawn can get them.
+        Pixel-snap the rects we're painting.
+        Clip the context before going to paint.
+
+        * WebProcess/WebPage/mac/PlatformCALayerRemote.cpp:
+        (PlatformCALayerRemote::enumerateRectsBeingDrawn):
+        * WebProcess/WebPage/mac/PlatformCALayerRemote.h:
+        Retrieve the rects currently being painted from our backing store, and
+        transform them (mostly) according to the CTM, to match the transformation
+        that will have occurred underneath wkCALayerEnumerateRectsBeingDrawnWithBlock.
+
</ins><span class="cx"> 2013-11-08  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement more KeyedEncoder functionality
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -32,6 +32,11 @@
</span><span class="cx"> #include &lt;WebCore/FloatRect.h&gt;
</span><span class="cx"> #include &lt;WebCore/Region.h&gt;
</span><span class="cx"> 
</span><ins>+// FIXME: Make PlatformCALayerRemote.cpp Objective-C so we can include WebLayer.h here and share the typedef.
+namespace WebCore {
+typedef Vector&lt;WebCore::FloatRect, 5&gt; RepaintRectList;
+}
+
</ins><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> class PlatformCALayerRemote;
</span><span class="lines">@@ -58,12 +63,11 @@
</span><span class="cx">     void encode(CoreIPC::ArgumentEncoder&amp;) const;
</span><span class="cx">     static bool decode(CoreIPC::ArgumentDecoder&amp;, RemoteLayerBackingStore&amp;);
</span><span class="cx"> 
</span><ins>+    void enumerateRectsBeingDrawn(CGContextRef, void (^)(CGRect));
+
</ins><span class="cx"> private:
</span><del>-    WebCore::IntRect mapToContentCoordinates(const WebCore::IntRect) const;
-
</del><span class="cx">     bool hasFrontBuffer() { return m_acceleratesDrawing ? !!m_frontSurface : !!m_frontBuffer; }
</span><span class="cx"> 
</span><del>-    std::unique_ptr&lt;WebCore::GraphicsContext&gt; createBackingStore();
</del><span class="cx">     void drawInContext(WebCore::GraphicsContext&amp;, CGImageRef frontImage);
</span><span class="cx"> 
</span><span class="cx">     PlatformCALayerRemote* m_layer;
</span><span class="lines">@@ -77,6 +81,8 @@
</span><span class="cx">     RetainPtr&lt;IOSurfaceRef&gt; m_frontSurface;
</span><span class="cx"> 
</span><span class="cx">     bool m_acceleratesDrawing;
</span><ins>+
+    WebCore::RepaintRectList m_paintingRects;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoremm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -110,18 +110,9 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-IntRect RemoteLayerBackingStore::mapToContentCoordinates(const IntRect rect) const
-{
-    IntRect flippedRect = rect;
-    if (m_layer-&gt;owner()-&gt;platformCALayerContentsOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp)
-        flippedRect.setY(m_size.height() - rect.y() - rect.height());
-    return flippedRect;
-}
-
</del><span class="cx"> void RemoteLayerBackingStore::setNeedsDisplay(const IntRect rect)
</span><span class="cx"> {
</span><del>-    IntRect flippedRect = mapToContentCoordinates(rect);
-    m_dirtyRegion.unite(flippedRect);
</del><ins>+    m_dirtyRegion.unite(rect);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerBackingStore::setNeedsDisplay()
</span><span class="lines">@@ -197,7 +188,7 @@
</span><span class="cx">         m_dirtyRegion.unite(IntRect(IntPoint(), m_size));
</span><span class="cx"> 
</span><span class="cx">     if (m_layer-&gt;owner()-&gt;platformCALayerShowRepaintCounter(m_layer)) {
</span><del>-        IntRect indicatorRect = mapToContentCoordinates(IntRect(0, 0, 52, 27));
</del><ins>+        IntRect indicatorRect(0, 0, 52, 27);
</ins><span class="cx">         m_dirtyRegion.unite(indicatorRect);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -232,7 +223,7 @@
</span><span class="cx">         }
</span><span class="cx">     } else {
</span><span class="cx">         RetainPtr&lt;CGImageRef&gt; frontImage = image();
</span><del>-        m_frontBuffer = ShareableBitmap::createShareable(expandedIntSize(scaledSize), ShareableBitmap::SupportsAlpha);
</del><ins>+        m_frontBuffer = ShareableBitmap::createShareable(expandedScaledSize, ShareableBitmap::SupportsAlpha);
</ins><span class="cx">         std::unique_ptr&lt;GraphicsContext&gt; context = m_frontBuffer-&gt;createGraphicsContext();
</span><span class="cx">         drawInContext(*context, frontImage.get());
</span><span class="cx">     }
</span><span class="lines">@@ -242,58 +233,93 @@
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerBackingStore::drawInContext(GraphicsContext&amp; context, CGImageRef frontImage)
</span><span class="cx"> {
</span><del>-    Vector&lt;IntRect&gt; dirtyRects = m_dirtyRegion.rects();
</del><ins>+    IntRect layerBounds(IntPoint(), m_size);
+    IntRect scaledLayerBounds(IntPoint(), expandedIntSize(m_size * m_scale));
</ins><span class="cx"> 
</span><ins>+    CGContextRef cgContext = context.platformContext();
+
</ins><span class="cx">     // If we have less than webLayerMaxRectsToPaint rects to paint and they cover less
</span><del>-    // than webLayerWastedSpaceThreshold of the area, we'll do a partial repaint.
</del><ins>+    // than webLayerWastedSpaceThreshold of the total dirty area, we'll repaint each rect separately.
+    // Otherwise, repaint the entire bounding box of the dirty region.
+    IntRect dirtyBounds = m_dirtyRegion.bounds();
+    Vector&lt;IntRect&gt; dirtyRects = m_dirtyRegion.rects();
+    if (dirtyRects.size() &gt; webLayerMaxRectsToPaint &amp;&amp; m_dirtyRegion.totalArea() &gt; webLayerWastedSpaceThreshold * dirtyBounds.width() * dirtyBounds.height()) {
+        dirtyRects.clear();
+        dirtyRects.append(dirtyBounds);
+    }
</ins><span class="cx"> 
</span><del>-    Vector&lt;FloatRect, webLayerMaxRectsToPaint&gt; rectsToPaint;
-    if (dirtyRects.size() &lt;= webLayerMaxRectsToPaint &amp;&amp; m_dirtyRegion.totalArea() &lt;= webLayerWastedSpaceThreshold * m_size.width() * m_size.height()) {
-        // Copy over the parts of the front buffer that we're not going to repaint.
-        if (frontImage) {
-            Region cleanRegion(IntRect(IntPoint(), m_size));
-            cleanRegion.subtract(m_dirtyRegion);
</del><ins>+    for (const auto&amp; rect : dirtyRects) {
+        FloatRect scaledRect(rect);
+        scaledRect.scale(m_scale, m_scale);
+        scaledRect = enclosingIntRect(scaledRect);
+        scaledRect.scale(1 / m_scale, 1 / m_scale);
+        m_paintingRects.append(scaledRect);
+    }
</ins><span class="cx"> 
</span><del>-            for (const auto&amp; rect : cleanRegion.rects()) {
-                FloatRect scaledRect = rect;
-                scaledRect.scale(m_scale);
-                FloatSize imageSize(CGImageGetWidth(frontImage), CGImageGetHeight(frontImage));
-                context.drawNativeImage(frontImage, imageSize, ColorSpaceDeviceRGB, scaledRect, scaledRect);
-            }
-        }
</del><ins>+    CGRect cgPaintingRects[webLayerMaxRectsToPaint];
+    for (size_t i = 0, dirtyRectCount = m_paintingRects.size(); i &lt; dirtyRectCount; ++i) {
+        FloatRect scaledPaintingRect = m_paintingRects[i];
+        scaledPaintingRect.scale(m_scale);
+        cgPaintingRects[i] = enclosingIntRect(scaledPaintingRect);
+    }
</ins><span class="cx"> 
</span><del>-        for (const auto&amp; rect : dirtyRects)
-            rectsToPaint.append(rect);
</del><ins>+    if (frontImage) {
+        CGContextSaveGState(cgContext);
+        CGContextSetBlendMode(cgContext, kCGBlendModeCopy);
+
+        CGContextAddRect(cgContext, CGRectInfinite);
+        CGContextAddRects(cgContext, cgPaintingRects, m_paintingRects.size());
+        CGContextEOClip(cgContext);
+
+        CGContextTranslateCTM(cgContext, 0, scaledLayerBounds.height());
+        CGContextScaleCTM(cgContext, 1, -1);
+        CGContextDrawImage(cgContext, scaledLayerBounds, frontImage);
+        CGContextRestoreGState(cgContext);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    CGContextClipToRects(cgContext, cgPaintingRects, m_paintingRects.size());
+
</ins><span class="cx">     context.scale(FloatSize(m_scale, m_scale));
</span><span class="cx"> 
</span><span class="cx">     switch (m_layer-&gt;layerType()) {
</span><del>-        case PlatformCALayer::LayerTypeSimpleLayer:
-        case PlatformCALayer::LayerTypeTiledBackingTileLayer:
-            if (rectsToPaint.isEmpty())
-                rectsToPaint.append(IntRect(IntPoint(), m_size));
-            for (const auto&amp; rect : rectsToPaint)
-                m_layer-&gt;owner()-&gt;platformCALayerPaintContents(m_layer, context, enclosingIntRect(rect));
-            break;
-        case PlatformCALayer::LayerTypeWebLayer:
-            drawLayerContents(context.platformContext(), m_layer, rectsToPaint);
-            break;
-        case PlatformCALayer::LayerTypeLayer:
-        case PlatformCALayer::LayerTypeTransformLayer:
-        case PlatformCALayer::LayerTypeWebTiledLayer:
-        case PlatformCALayer::LayerTypeTiledBackingLayer:
-        case PlatformCALayer::LayerTypePageTiledBackingLayer:
-        case PlatformCALayer::LayerTypeRootLayer:
-        case PlatformCALayer::LayerTypeAVPlayerLayer:
-        case PlatformCALayer::LayerTypeCustom:
-            ASSERT_NOT_REACHED();
-            break;
</del><ins>+    case PlatformCALayer::LayerTypeSimpleLayer:
+    case PlatformCALayer::LayerTypeTiledBackingTileLayer:
+        m_layer-&gt;owner()-&gt;platformCALayerPaintContents(m_layer, context, dirtyBounds);
+        break;
+    case PlatformCALayer::LayerTypeWebLayer:
+        drawLayerContents(cgContext, m_layer, m_paintingRects);
+        break;
+    case PlatformCALayer::LayerTypeLayer:
+    case PlatformCALayer::LayerTypeTransformLayer:
+    case PlatformCALayer::LayerTypeWebTiledLayer:
+    case PlatformCALayer::LayerTypeTiledBackingLayer:
+    case PlatformCALayer::LayerTypePageTiledBackingLayer:
+    case PlatformCALayer::LayerTypeRootLayer:
+    case PlatformCALayer::LayerTypeAVPlayerLayer:
+    case PlatformCALayer::LayerTypeCustom:
+        ASSERT_NOT_REACHED();
+        break;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     m_dirtyRegion = Region();
</span><ins>+    m_paintingRects.clear();
</ins><span class="cx"> 
</span><span class="cx">     CGContextFlush(context.platformContext());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RemoteLayerBackingStore::enumerateRectsBeingDrawn(CGContextRef context, void (^block)(CGRect))
+{
+    CGAffineTransform inverseTransform = CGAffineTransformInvert(CGContextGetCTM(context));
+
+    // We don't want to un-apply the flipping or contentsScale,
+    // because they're not applied to repaint rects.
+    inverseTransform = CGAffineTransformScale(inverseTransform, m_scale, -m_scale);
+    inverseTransform = CGAffineTransformTranslate(inverseTransform, 0, -m_size.height());
+
+    for (auto rect : m_paintingRects) {
+        CGRect rectToDraw = CGRectApplyAffineTransform(rect, inverseTransform);
+        block(rectToDraw);
+    }
+}
+
</ins><span class="cx"> #endif // USE(ACCELERATED_COMPOSITING)
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacPlatformCALayerRemotecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -502,6 +502,11 @@
</span><span class="cx">     return PlatformCALayerRemote::create(layerType, client, m_context);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PlatformCALayerRemote::enumerateRectsBeingDrawn(CGContextRef context, void (^block)(CGRect))
+{
+    m_properties.backingStore.enumerateRectsBeingDrawn(context, block);
+}
+
</ins><span class="cx"> uint32_t PlatformCALayerRemote::hostingContextID()
</span><span class="cx"> {
</span><span class="cx">     ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacPlatformCALayerRemoteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.h (158981 => 158982)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.h        2013-11-09 01:29:30 UTC (rev 158981)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.h        2013-11-09 01:43:45 UTC (rev 158982)
</span><span class="lines">@@ -146,6 +146,8 @@
</span><span class="cx"> 
</span><span class="cx">     virtual PassRefPtr&lt;PlatformCALayer&gt; createCompatibleLayer(WebCore::PlatformCALayer::LayerType, WebCore::PlatformCALayerClient*) const OVERRIDE;
</span><span class="cx"> 
</span><ins>+    virtual void enumerateRectsBeingDrawn(CGContextRef, void (^block)(CGRect)) OVERRIDE;
+
</ins><span class="cx">     virtual uint32_t hostingContextID();
</span><span class="cx"> 
</span><span class="cx"> protected:
</span></span></pre>
</div>
</div>

</body>
</html>