<!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>[163837] trunk/Source/WebKit2</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/163837">163837</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2014-02-10 16:24:58 -0800 (Mon, 10 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Show a debug tile map indicator for UI-side compositing
https://bugs.webkit.org/show_bug.cgi?id=128553

Reviewed by Tim Horton.

Implement a tiled scrolling indicator for UI-side compositing.

The indicator is created by making another RemoteLayerTreeHost,
and decoding the transaction in it a second time to create a cloned
layer tree. In that clone commit, we modify some layer properties to
make things easier to see.

The cloned layer tree is hosted in the root layer of the main
RemoteLayerTreeHost.

RemoteLayerTreeHost was changed to not need a pointer to the WebPageProxy,
which it only used in the &quot;root layer changed&quot; case; instead, it now just
returns a bool from updateLayerTree() in that situation.

* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp: Explanatory comment.
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::setExposedRect):
(WebKit::RemoteLayerTreeDrawingAreaProxy::indicatorLocation):
(WebKit::RemoteLayerTreeDrawingAreaProxy::updateDebugIndicatorPosition):
(WebKit::RemoteLayerTreeDrawingAreaProxy::indicatorScale):
(WebKit::RemoteLayerTreeDrawingAreaProxy::updateDebugIndicator):
(WebKit::RemoteLayerTreeDrawingAreaProxy::showDebugIndicator):
* UIProcess/mac/RemoteLayerTreeHost.h:
(WebKit::RemoteLayerTreeHost::rootLayer):
(WebKit::RemoteLayerTreeHost::setIsDebugLayerTreeHost):
(WebKit::RemoteLayerTreeHost::isDebugLayerTreeHost):
* UIProcess/mac/RemoteLayerTreeHost.mm:
(WebKit::RemoteLayerTreeHost::RemoteLayerTreeHost):
(WebKit::RemoteLayerTreeHost::updateLayerTree):
(WebKit::RemoteLayerTreeHost::createLayer):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessDrawingAreaProxyh">trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxycpp">trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacRemoteLayerTreeDrawingAreaProxyh">trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacRemoteLayerTreeDrawingAreaProxymm">trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacRemoteLayerTreeHosth">trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacRemoteLayerTreeHostmm">trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/ChangeLog        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -1,5 +1,46 @@
</span><span class="cx"> 2014-02-10  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Show a debug tile map indicator for UI-side compositing
+        https://bugs.webkit.org/show_bug.cgi?id=128553
+
+        Reviewed by Tim Horton.
+        
+        Implement a tiled scrolling indicator for UI-side compositing.
+        
+        The indicator is created by making another RemoteLayerTreeHost,
+        and decoding the transaction in it a second time to create a cloned
+        layer tree. In that clone commit, we modify some layer properties to
+        make things easier to see.
+        
+        The cloned layer tree is hosted in the root layer of the main
+        RemoteLayerTreeHost.
+        
+        RemoteLayerTreeHost was changed to not need a pointer to the WebPageProxy,
+        which it only used in the &quot;root layer changed&quot; case; instead, it now just
+        returns a bool from updateLayerTree() in that situation.
+
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp: Explanatory comment.
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
+        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::setExposedRect):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::indicatorLocation):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::updateDebugIndicatorPosition):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::indicatorScale):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::updateDebugIndicator):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::showDebugIndicator):
+        * UIProcess/mac/RemoteLayerTreeHost.h:
+        (WebKit::RemoteLayerTreeHost::rootLayer):
+        (WebKit::RemoteLayerTreeHost::setIsDebugLayerTreeHost):
+        (WebKit::RemoteLayerTreeHost::isDebugLayerTreeHost):
+        * UIProcess/mac/RemoteLayerTreeHost.mm:
+        (WebKit::RemoteLayerTreeHost::RemoteLayerTreeHost):
+        (WebKit::RemoteLayerTreeHost::updateLayerTree):
+        (WebKit::RemoteLayerTreeHost::createLayer):
+
+2014-02-10  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
</ins><span class="cx">         Put a delegatesScrolling flag on WebPageProxy so that the UI process knows when scrolling is delegated
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=128429
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessDrawingAreaProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/UIProcess/DrawingAreaProxy.h        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -74,13 +74,16 @@
</span><span class="cx">     virtual void commitTransientZoom(double, WebCore::FloatPoint) { }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><del>-    void setExposedRect(const WebCore::FloatRect&amp;);
</del><ins>+    virtual void setExposedRect(const WebCore::FloatRect&amp;);
</ins><span class="cx">     WebCore::FloatRect exposedRect() const { return m_exposedRect; }
</span><span class="cx">     void exposedRectChangedTimerFired(WebCore::Timer&lt;DrawingAreaProxy&gt;*);
</span><span class="cx">     
</span><span class="cx">     void setCustomFixedPositionRect(const WebCore::FloatRect&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    virtual void showDebugIndicator(bool) { }
+    virtual bool isShowingDebugIndicator() const { return false; }
+
</ins><span class="cx"> protected:
</span><span class="cx">     explicit DrawingAreaProxy(DrawingAreaType, WebPageProxy*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessScrollingRemoteScrollingCoordinatorProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -139,6 +139,7 @@
</span><span class="cx">     m_scrollingTree-&gt;scrollPositionChangedViaDelegatedScrolling(nodeID, offset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// This comes from the scrolling tree.
</ins><span class="cx"> void RemoteScrollingCoordinatorProxy::scrollPositionChanged(WebCore::ScrollingNodeID scrolledNodeID, const WebCore::FloatPoint&amp; newScrollPosition)
</span><span class="cx"> {
</span><span class="cx">     m_webPageProxy.send(Messages::RemoteScrollingCoordinator::ScrollPositionChangedForNode(scrolledNodeID, newScrollPosition));
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacRemoteLayerTreeDrawingAreaProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DrawingAreaProxy.h&quot;
</span><span class="cx"> #include &quot;RemoteLayerTreeHost.h&quot;
</span><ins>+#include &lt;WebCore/FloatPoint.h&gt;
</ins><span class="cx"> #include &lt;WebCore/IntPoint.h&gt;
</span><span class="cx"> #include &lt;WebCore/IntSize.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -42,12 +43,22 @@
</span><span class="cx">     virtual ~RemoteLayerTreeDrawingAreaProxy();
</span><span class="cx"> 
</span><span class="cx">     const RemoteLayerTreeHost&amp; remoteLayerTreeHost() const { return m_remoteLayerTreeHost; }
</span><del>-    
</del><ins>+
</ins><span class="cx"> private:
</span><span class="cx">     virtual void sizeDidChange() override;
</span><span class="cx">     virtual void deviceScaleFactorDidChange() override;
</span><span class="cx">     virtual void didUpdateGeometry() override;
</span><span class="cx"> 
</span><ins>+    void showDebugIndicator(bool);
+
+    virtual void setExposedRect(const WebCore::FloatRect&amp;) override;
+
+    float indicatorScale(WebCore::IntSize contentsSize) const;
+    void updateDebugIndicator(WebCore::IntSize contentsSize, bool rootLayerChanged, float scale);
+    void updateDebugIndicatorPosition();
+    
+    WebCore::FloatPoint indicatorLocation() const;
+
</ins><span class="cx">     // IPC::MessageReceiver
</span><span class="cx">     virtual void didReceiveMessage(IPC::Connection*, IPC::MessageDecoder&amp;) override;
</span><span class="cx"> 
</span><span class="lines">@@ -61,6 +72,10 @@
</span><span class="cx"> 
</span><span class="cx">     WebCore::IntSize m_lastSentSize;
</span><span class="cx">     WebCore::IntSize m_lastSentLayerPosition;
</span><ins>+
+    std::unique_ptr&lt;RemoteLayerTreeHost&gt; m_debugIndicatorLayerTreeHost;
+    RetainPtr&lt;CALayer&gt; m_tileMapHostLayer;
+    RetainPtr&lt;CALayer&gt; m_exposedRectIndicatorLayer;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> DRAWING_AREA_PROXY_TYPE_CASTS(RemoteLayerTreeDrawingAreaProxy, type() == DrawingAreaTypeRemoteLayerTree);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacRemoteLayerTreeDrawingAreaProxymm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -31,12 +31,15 @@
</span><span class="cx"> #import &quot;RemoteScrollingCoordinatorProxy.h&quot;
</span><span class="cx"> #import &quot;WebPageProxy.h&quot;
</span><span class="cx"> #import &quot;WebProcessProxy.h&quot;
</span><ins>+#import &lt;WebCore/WebCoreCALayerExtras.h&gt;
</ins><span class="cx"> 
</span><ins>+using namespace WebCore;
+
</ins><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy* webPageProxy)
</span><span class="cx">     : DrawingAreaProxy(DrawingAreaTypeRemoteLayerTree, webPageProxy)
</span><del>-    , m_remoteLayerTreeHost(webPageProxy)
</del><ins>+    , m_remoteLayerTreeHost()
</ins><span class="cx">     , m_isWaitingForDidUpdateGeometry(false)
</span><span class="cx"> {
</span><span class="cx">     m_webPageProxy-&gt;process().addMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy-&gt;pageID(), *this);
</span><span class="lines">@@ -85,13 +88,152 @@
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerTreeDrawingAreaProxy::commitLayerTree(const RemoteLayerTreeTransaction&amp; layerTreeTransaction, const RemoteScrollingCoordinatorTransaction&amp; scrollingTreeTransaction)
</span><span class="cx"> {
</span><del>-    m_remoteLayerTreeHost.updateLayerTree(layerTreeTransaction);
</del><ins>+    if (m_remoteLayerTreeHost.updateLayerTree(layerTreeTransaction))
+        m_webPageProxy-&gt;setAcceleratedCompositingRootLayer(m_remoteLayerTreeHost.rootLayer());
+
</ins><span class="cx"> #if ENABLE(ASYNC_SCROLLING)
</span><span class="cx">     m_webPageProxy-&gt;scrollingCoordinatorProxy()-&gt;updateScrollingTree(scrollingTreeTransaction);
</span><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     m_webPageProxy-&gt;didCommitLayerTree(layerTreeTransaction);
</span><span class="cx"> #endif
</span><ins>+
+    showDebugIndicator(m_webPageProxy-&gt;preferences().tiledScrollingIndicatorVisible());
+
+    if (m_debugIndicatorLayerTreeHost) {
+        float scale = indicatorScale(layerTreeTransaction.contentsSize());
+        bool rootLayerChanged = m_debugIndicatorLayerTreeHost-&gt;updateLayerTree(layerTreeTransaction, scale);
+        updateDebugIndicator(layerTreeTransaction.contentsSize(), rootLayerChanged, scale);
+        m_debugIndicatorLayerTreeHost-&gt;rootLayer().name = @&quot;Indicator host root&quot;;
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static const float indicatorInset = 10;
+static const float indicatorTopInset = 100;
+
+void RemoteLayerTreeDrawingAreaProxy::setExposedRect(const WebCore::FloatRect&amp; r)
+{
+    DrawingAreaProxy::setExposedRect(r);
+    updateDebugIndicatorPosition();
+}
+
+FloatPoint RemoteLayerTreeDrawingAreaProxy::indicatorLocation() const
+{
+    if (m_webPageProxy-&gt;delegatesScrolling()) {
+        FloatPoint tiledMapLocation = exposedRect().location();
+        tiledMapLocation += FloatSize(indicatorInset, indicatorTopInset);
+        float scale = 1 / m_webPageProxy-&gt;pageScaleFactor();
+        tiledMapLocation.scale(scale, scale);
+        return tiledMapLocation;
+    }
+    
+    return FloatPoint(indicatorInset, indicatorInset);
+}
+
+void RemoteLayerTreeDrawingAreaProxy::updateDebugIndicatorPosition()
+{
+    if (!m_tileMapHostLayer)
+        return;
+
+    [m_tileMapHostLayer setPosition:indicatorLocation()];
+}
+
+float RemoteLayerTreeDrawingAreaProxy::indicatorScale(IntSize contentsSize) const
+{
+    // Pick a good scale.
+    IntSize viewSize = m_webPageProxy-&gt;viewSize();
+
+    float scale = 1;
+    if (!contentsSize.isEmpty()) {
+        float widthScale = std::min&lt;float&gt;((viewSize.width() - 2 * indicatorInset) / contentsSize.width(), 0.05);
+        scale = std::min(widthScale, static_cast&lt;float&gt;(viewSize.height() - indicatorTopInset - indicatorInset) / contentsSize.height());
+    }
+    
+    return scale;
+}
+
+void RemoteLayerTreeDrawingAreaProxy::updateDebugIndicator(IntSize contentsSize, bool rootLayerChanged, float scale)
+{
+    // Make sure we're the last sublayer.
+    CALayer *rootLayer = m_remoteLayerTreeHost.rootLayer();
+    [m_tileMapHostLayer removeFromSuperlayer];
+    [rootLayer addSublayer:m_tileMapHostLayer.get()];
+
+    // Pick a good scale.
+    IntSize viewSize = m_webPageProxy-&gt;viewSize();
+
+    [m_tileMapHostLayer setBounds:FloatRect(FloatPoint(), contentsSize)];
+    [m_tileMapHostLayer setPosition:indicatorLocation()];
+    [m_tileMapHostLayer setTransform:CATransform3DMakeScale(scale, scale, 1)];
+
+    if (rootLayerChanged) {
+        [m_tileMapHostLayer setSublayers:@[]];
+        [m_tileMapHostLayer addSublayer:m_debugIndicatorLayerTreeHost-&gt;rootLayer()];
+        [m_tileMapHostLayer addSublayer:m_exposedRectIndicatorLayer.get()];
+    }
+    
+    const float indicatorBorderWidth = 1;
+    float counterScaledBorder = indicatorBorderWidth / scale;
+
+    [m_exposedRectIndicatorLayer setBorderWidth:counterScaledBorder];
+
+    if (m_webPageProxy-&gt;delegatesScrolling()) {
+        FloatRect scaledExposedRect = exposedRect();
+        float scale = 1 / m_webPageProxy-&gt;pageScaleFactor();
+        scaledExposedRect.scale(scale, scale);
+
+        [m_exposedRectIndicatorLayer setPosition:scaledExposedRect.location()];
+        [m_exposedRectIndicatorLayer setBounds:FloatRect(FloatPoint(), scaledExposedRect.size())];
+    } else {
+        // FIXME: Get the correct scroll position.
+        [m_exposedRectIndicatorLayer setBounds:FloatRect(FloatPoint(), viewSize)];
+    }
+}
+
+void RemoteLayerTreeDrawingAreaProxy::showDebugIndicator(bool show)
+{
+    if (show == !!m_debugIndicatorLayerTreeHost)
+        return;
+    
+    if (!show) {
+        [m_tileMapHostLayer removeFromSuperlayer];
+        m_tileMapHostLayer = nullptr;
+        m_exposedRectIndicatorLayer = nullptr;
+        m_debugIndicatorLayerTreeHost = nullptr;
+        return;
+    }
+    
+    m_debugIndicatorLayerTreeHost = std::make_unique&lt;RemoteLayerTreeHost&gt;();
+    m_debugIndicatorLayerTreeHost-&gt;setIsDebugLayerTreeHost(true);
+
+    m_tileMapHostLayer = adoptNS([[CALayer alloc] init]);
+    [m_tileMapHostLayer setName:@&quot;Tile map host&quot;];
+    [m_tileMapHostLayer web_disableAllActions];
+    [m_tileMapHostLayer setAnchorPoint:CGPointZero];
+    [m_tileMapHostLayer setOpacity:0.8];
+    [m_tileMapHostLayer setMasksToBounds:YES];
+    [m_tileMapHostLayer setBorderWidth:2];
+
+    RetainPtr&lt;CGColorSpaceRef&gt; colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
+    {
+        const CGFloat components[] = { 1, 1, 1, 0.6 };
+        RetainPtr&lt;CGColorRef&gt; color = adoptCF(CGColorCreate(colorSpace.get(), components));
+        [m_tileMapHostLayer setBackgroundColor:color.get()];
+
+        const CGFloat borderCmponents[] = { 0, 0, 0, 1 };
+        RetainPtr&lt;CGColorRef&gt; borderColor = adoptCF(CGColorCreate(colorSpace.get(), borderCmponents));
+        [m_tileMapHostLayer setBorderColor:borderColor.get()];
+    }
+    
+    m_exposedRectIndicatorLayer = adoptNS([[CALayer alloc] init]);
+    [m_exposedRectIndicatorLayer web_disableAllActions];
+    [m_exposedRectIndicatorLayer setAnchorPoint:CGPointZero];
+
+    {
+        const CGFloat components[] = { 0, 1, 0, 1 };
+        RetainPtr&lt;CGColorRef&gt; color = adoptCF(CGColorCreate(colorSpace.get(), components));
+        [m_exposedRectIndicatorLayer setBorderColor:color.get()];
+    }
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacRemoteLayerTreeHosth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.h (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.h        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.h        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -39,20 +39,24 @@
</span><span class="cx"> 
</span><span class="cx"> class RemoteLayerTreeHost {
</span><span class="cx"> public:
</span><del>-    explicit RemoteLayerTreeHost(WebPageProxy*);
</del><ins>+    explicit RemoteLayerTreeHost();
</ins><span class="cx">     virtual ~RemoteLayerTreeHost();
</span><span class="cx"> 
</span><span class="cx">     CALayer *getLayer(WebCore::GraphicsLayer::PlatformLayerID) const;
</span><ins>+    CALayer *rootLayer() const { return m_rootLayer; }
</ins><span class="cx"> 
</span><del>-    void updateLayerTree(const RemoteLayerTreeTransaction&amp;);
</del><ins>+    // Returns true if the root layer changed.
+    bool updateLayerTree(const RemoteLayerTreeTransaction&amp;, float indicatorScaleFactor  = 1);
</ins><span class="cx"> 
</span><ins>+    void setIsDebugLayerTreeHost(bool flag) { m_isDebugLayerTreeHost = flag; }
+    bool isDebugLayerTreeHost() const { return m_isDebugLayerTreeHost; }
+
</ins><span class="cx"> private:
</span><span class="cx">     CALayer *createLayer(RemoteLayerTreeTransaction::LayerCreationProperties);
</span><span class="cx"> 
</span><del>-    WebPageProxy* m_webPageProxy;
-
</del><span class="cx">     CALayer *m_rootLayer;
</span><span class="cx">     HashMap&lt;WebCore::GraphicsLayer::PlatformLayerID, RetainPtr&lt;CALayer&gt;&gt; m_layers;
</span><ins>+    bool m_isDebugLayerTreeHost;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacRemoteLayerTreeHostmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.mm (163836 => 163837)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.mm        2014-02-11 00:24:55 UTC (rev 163836)
+++ trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeHost.mm        2014-02-11 00:24:58 UTC (rev 163837)
</span><span class="lines">@@ -42,9 +42,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><del>-RemoteLayerTreeHost::RemoteLayerTreeHost(WebPageProxy* webPageProxy)
-    : m_webPageProxy(webPageProxy)
-    , m_rootLayer(nullptr)
</del><ins>+RemoteLayerTreeHost::RemoteLayerTreeHost()
+    : m_rootLayer(nullptr)
+    , m_isDebugLayerTreeHost(false)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -52,17 +52,18 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RemoteLayerTreeHost::updateLayerTree(const RemoteLayerTreeTransaction&amp; transaction)
</del><ins>+bool RemoteLayerTreeHost::updateLayerTree(const RemoteLayerTreeTransaction&amp; transaction, float indicatorScaleFactor)
</ins><span class="cx"> {
</span><span class="cx">     LOG(RemoteLayerTree, &quot;%s&quot;, transaction.description().data());
</span><span class="cx"> 
</span><span class="cx">     for (auto createdLayer : transaction.createdLayers())
</span><span class="cx">         createLayer(createdLayer);
</span><span class="cx"> 
</span><ins>+    bool rootLayerChanged = false;
</ins><span class="cx">     CALayer *rootLayer = getLayer(transaction.rootLayerID());
</span><span class="cx">     if (m_rootLayer != rootLayer) {
</span><span class="cx">         m_rootLayer = rootLayer;
</span><del>-        m_webPageProxy-&gt;setAcceleratedCompositingRootLayer(m_rootLayer);
</del><ins>+        rootLayerChanged = true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (auto changedLayer : transaction.changedLayers()) {
</span><span class="lines">@@ -81,11 +82,21 @@
</span><span class="cx">         if (properties.changedProperties &amp; RemoteLayerTreeTransaction::MaskLayerChanged &amp;&amp; properties.maskLayerID)
</span><span class="cx">             relatedLayers.set(properties.maskLayerID, getLayer(properties.maskLayerID));
</span><span class="cx"> 
</span><del>-        RemoteLayerTreePropertyApplier::applyPropertiesToLayer(layer, properties, relatedLayers);
</del><ins>+        if (m_isDebugLayerTreeHost) {
+            RemoteLayerTreeTransaction::LayerProperties propertiesCopy(properties);
+            propertiesCopy.masksToBounds = false;
+            if (propertiesCopy.changedProperties &amp; RemoteLayerTreeTransaction::BorderWidthChanged)
+                propertiesCopy.borderWidth *= 1 / indicatorScaleFactor;
+            
+            RemoteLayerTreePropertyApplier::applyPropertiesToLayer(layer, propertiesCopy, relatedLayers);
+        } else
+            RemoteLayerTreePropertyApplier::applyPropertiesToLayer(layer, properties, relatedLayers);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (auto destroyedLayer : transaction.destroyedLayers())
</span><span class="cx">         m_layers.remove(destroyedLayer);
</span><ins>+
+    return rootLayerChanged;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CALayer *RemoteLayerTreeHost::getLayer(GraphicsLayer::PlatformLayerID layerID) const
</span><span class="lines">@@ -116,7 +127,10 @@
</span><span class="cx">         layer = adoptNS([[CATransformLayer alloc] init]);
</span><span class="cx">         break;
</span><span class="cx">     case PlatformCALayer::LayerTypeCustom:
</span><del>-        layer = WKMakeRenderLayer(properties.hostingContextID);
</del><ins>+        if (!m_isDebugLayerTreeHost)
+            layer = WKMakeRenderLayer(properties.hostingContextID);
+        else
+            layer = adoptNS([[CALayer alloc] init]);
</ins><span class="cx">         break;
</span><span class="cx">     default:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span></span></pre>
</div>
</div>

</body>
</html>