<!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>[168657] 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/168657">168657</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-05-12 16:31:56 -0700 (Mon, 12 May 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Triple-buffer RemoteLayerBackingStore
https://bugs.webkit.org/show_bug.cgi?id=132786
&lt;rdar://problem/16877498&gt;

Reviewed by Simon Fraser.

We need three buffers because we're currently unable to synchronize
with the render server to swap when they're not in use, so we were
throwing surfaces away far too frequently.

This hugely reduces time spent in IOSurface::create on various repaint benchmarks.

* Shared/mac/RemoteLayerBackingStore.h:
(WebKit::RemoteLayerBackingStore::hasFrontBuffer):
(WebKit::RemoteLayerBackingStore::volatility): Deleted.
* Shared/mac/RemoteLayerBackingStore.mm:
(WebKit::RemoteLayerBackingStore::RemoteLayerBackingStore):
(WebKit::RemoteLayerBackingStore::clearBackingStore):
(WebKit::RemoteLayerBackingStore::encode):
(WebKit::RemoteLayerBackingStore::decode):
(WebKit::RemoteLayerBackingStore::swapToValidFrontBuffer):
(WebKit::RemoteLayerBackingStore::display):
(WebKit::RemoteLayerBackingStore::applyBackingStoreToLayer):
(WebKit::RemoteLayerBackingStore::setBufferVolatility):
(WebKit::RemoteLayerBackingStore::Buffer::discard):
(WebKit::RemoteLayerBackingStore::setVolatility): Deleted.
* Shared/mac/RemoteLayerBackingStoreCollection.mm:
(WebKit::RemoteLayerBackingStoreCollection::purgeabilityTimerFired):
Put the ShareableBitmap/IOSurface and a volatility bit in a Buffer struct.
Also factor out &quot;throw away this buffer and put it in the pool&quot; into Buffer::discard().
We keep a volatility bit because querying IOSurface purgeability is expensive,
and we have a guarantee that any changes will happen in the Web process
and go through this class (the lack of this guarantee in most cases is why I'm not
putting this bit in WebCore::IOSurface itself).

Make it so that each buffer's volatility can be adjusted individually
by setBufferVolatility(), and adopt in RemoteLayerBackingStoreCollection.

Add a third buffer, m_secondaryBackBuffer, which will swap with the back buffer
before swapping front and back if the back buffer (soon to be the front buffer)
is still in use by the render server. This means that we will almost never
have to throw away a surface because it's in use (and conversely never need
to make a new surface).

Adjust RemoteLayerBackingStoreCollection to make secondary back surfaces purgeable
more aggressively than others.</pre>

<h3>Modified Paths</h3>
<ul>
<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="#trunkSourceWebKit2SharedmacRemoteLayerBackingStoreCollectionmm">trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (168656 => 168657)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-05-12 23:29:18 UTC (rev 168656)
+++ trunk/Source/WebKit2/ChangeLog        2014-05-12 23:31:56 UTC (rev 168657)
</span><span class="lines">@@ -1,3 +1,52 @@
</span><ins>+2014-05-12  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Triple-buffer RemoteLayerBackingStore
+        https://bugs.webkit.org/show_bug.cgi?id=132786
+        &lt;rdar://problem/16877498&gt;
+
+        Reviewed by Simon Fraser.
+
+        We need three buffers because we're currently unable to synchronize
+        with the render server to swap when they're not in use, so we were
+        throwing surfaces away far too frequently.
+
+        This hugely reduces time spent in IOSurface::create on various repaint benchmarks.
+
+        * Shared/mac/RemoteLayerBackingStore.h:
+        (WebKit::RemoteLayerBackingStore::hasFrontBuffer):
+        (WebKit::RemoteLayerBackingStore::volatility): Deleted.
+        * Shared/mac/RemoteLayerBackingStore.mm:
+        (WebKit::RemoteLayerBackingStore::RemoteLayerBackingStore):
+        (WebKit::RemoteLayerBackingStore::clearBackingStore):
+        (WebKit::RemoteLayerBackingStore::encode):
+        (WebKit::RemoteLayerBackingStore::decode):
+        (WebKit::RemoteLayerBackingStore::swapToValidFrontBuffer):
+        (WebKit::RemoteLayerBackingStore::display):
+        (WebKit::RemoteLayerBackingStore::applyBackingStoreToLayer):
+        (WebKit::RemoteLayerBackingStore::setBufferVolatility):
+        (WebKit::RemoteLayerBackingStore::Buffer::discard):
+        (WebKit::RemoteLayerBackingStore::setVolatility): Deleted.
+        * Shared/mac/RemoteLayerBackingStoreCollection.mm:
+        (WebKit::RemoteLayerBackingStoreCollection::purgeabilityTimerFired):
+        Put the ShareableBitmap/IOSurface and a volatility bit in a Buffer struct.
+        Also factor out &quot;throw away this buffer and put it in the pool&quot; into Buffer::discard().
+        We keep a volatility bit because querying IOSurface purgeability is expensive,
+        and we have a guarantee that any changes will happen in the Web process
+        and go through this class (the lack of this guarantee in most cases is why I'm not
+        putting this bit in WebCore::IOSurface itself).
+
+        Make it so that each buffer's volatility can be adjusted individually
+        by setBufferVolatility(), and adopt in RemoteLayerBackingStoreCollection.
+
+        Add a third buffer, m_secondaryBackBuffer, which will swap with the back buffer
+        before swapping front and back if the back buffer (soon to be the front buffer)
+        is still in use by the render server. This means that we will almost never
+        have to throw away a surface because it's in use (and conversely never need
+        to make a new surface).
+
+        Adjust RemoteLayerBackingStoreCollection to make secondary back surfaces purgeable
+        more aggressively than others.
+
</ins><span class="cx"> 2014-05-12  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r165972): Can't type into text fields in Flash
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h (168656 => 168657)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h        2014-05-12 23:29:18 UTC (rev 168656)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h        2014-05-12 23:31:56 UTC (rev 168657)
</span><span class="lines">@@ -76,27 +76,27 @@
</span><span class="cx">     {
</span><span class="cx"> #if USE(IOSURFACE)
</span><span class="cx">         if (m_acceleratesDrawing)
</span><del>-            return !!m_frontSurface;
</del><ins>+            return !!m_frontBuffer.surface;
</ins><span class="cx"> #endif
</span><del>-        return !!m_frontBuffer;
</del><ins>+        return !!m_frontBuffer.bitmap;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CGContextRef&gt; takeFrontContextPendingFlush();
</span><span class="cx"> 
</span><del>-    enum class Volatility {
-        NonVolatile,
-        BackBufferVolatile,
-        AllBuffersVolatile
</del><ins>+    enum class BufferType {
+        Front,
+        Back,
+        SecondaryBack
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-    Volatility volatility() const { return m_volatility; }
-    bool setVolatility(Volatility);
</del><ins>+    bool setBufferVolatility(BufferType type, bool isVolatile);
</ins><span class="cx"> 
</span><span class="cx">     std::chrono::steady_clock::time_point lastDisplayTime() const { return m_lastDisplayTime; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void drawInContext(WebCore::GraphicsContext&amp;, CGImageRef backImage);
</span><span class="cx">     void clearBackingStore();
</span><ins>+    void swapToValidFrontBuffer();
</ins><span class="cx"> 
</span><span class="cx">     PlatformCALayerRemote* m_layer;
</span><span class="cx"> 
</span><span class="lines">@@ -106,19 +106,26 @@
</span><span class="cx"> 
</span><span class="cx">     WebCore::Region m_dirtyRegion;
</span><span class="cx"> 
</span><del>-    RefPtr&lt;ShareableBitmap&gt; m_frontBuffer;
-    RefPtr&lt;ShareableBitmap&gt; m_backBuffer;
</del><ins>+    struct Buffer {
+        RefPtr&lt;ShareableBitmap&gt; bitmap;
</ins><span class="cx"> #if USE(IOSURFACE)
</span><del>-    RefPtr&lt;WebCore::IOSurface&gt; m_frontSurface;
-    RefPtr&lt;WebCore::IOSurface&gt; m_backSurface;
</del><ins>+        RefPtr&lt;WebCore::IOSurface&gt; surface;
+        bool isVolatile = false;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+        void discard();
+    };
+
+    Buffer m_frontBuffer;
+    Buffer m_backBuffer;
+#if USE(IOSURFACE)
+    Buffer m_secondaryBackBuffer;
+#endif
+
</ins><span class="cx">     RetainPtr&lt;CGContextRef&gt; m_frontContextPendingFlush;
</span><span class="cx"> 
</span><span class="cx">     bool m_acceleratesDrawing;
</span><span class="cx"> 
</span><del>-    Volatility m_volatility;
-
</del><span class="cx">     WebCore::RepaintRectList m_paintingRects;
</span><span class="cx"> 
</span><span class="cx">     RemoteLayerTreeContext* m_context;
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoremm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm (168656 => 168657)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm        2014-05-12 23:29:18 UTC (rev 168656)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm        2014-05-12 23:31:56 UTC (rev 168657)
</span><span class="lines">@@ -58,7 +58,6 @@
</span><span class="cx"> RemoteLayerBackingStore::RemoteLayerBackingStore(RemoteLayerTreeContext* context)
</span><span class="cx">     : m_layer(nullptr)
</span><span class="cx">     , m_isOpaque(false)
</span><del>-    , m_volatility(RemoteLayerBackingStore::Volatility::NonVolatile)
</del><span class="cx">     , m_context(context)
</span><span class="cx">     , m_lastDisplayTime(std::chrono::steady_clock::time_point::min())
</span><span class="cx"> {
</span><span class="lines">@@ -90,17 +89,11 @@
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerBackingStore::clearBackingStore()
</span><span class="cx"> {
</span><ins>+    m_frontBuffer.discard();
+    m_backBuffer.discard();
</ins><span class="cx"> #if USE(IOSURFACE)
</span><del>-    if (m_frontSurface)
-        IOSurfacePool::sharedPool().addSurface(m_frontSurface.get());
-    if (m_backSurface)
-        IOSurfacePool::sharedPool().addSurface(m_backSurface.get());
-
-    m_frontSurface = nullptr;
-    m_backSurface = nullptr;
</del><ins>+    m_secondaryBackBuffer.discard();
</ins><span class="cx"> #endif
</span><del>-    m_frontBuffer = nullptr;
-    m_backBuffer = nullptr;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteLayerBackingStore::encode(IPC::ArgumentEncoder&amp; encoder) const
</span><span class="lines">@@ -112,7 +105,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(IOSURFACE)
</span><span class="cx">     if (m_acceleratesDrawing) {
</span><del>-        mach_port_t port = m_frontSurface-&gt;createMachPort();
</del><ins>+        mach_port_t port = m_frontBuffer.surface-&gt;createMachPort();
</ins><span class="cx">         encoder &lt;&lt; IPC::MachPort(port, MACH_MSG_TYPE_MOVE_SEND);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -121,7 +114,7 @@
</span><span class="cx">     ASSERT(!m_acceleratesDrawing);
</span><span class="cx"> 
</span><span class="cx">     ShareableBitmap::Handle handle;
</span><del>-    m_frontBuffer-&gt;createHandle(handle);
</del><ins>+    m_frontBuffer.bitmap-&gt;createHandle(handle);
</ins><span class="cx">     encoder &lt;&lt; handle;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -144,7 +137,7 @@
</span><span class="cx">         IPC::MachPort machPort;
</span><span class="cx">         if (!decoder.decode(machPort))
</span><span class="cx">             return false;
</span><del>-        result.m_frontSurface = IOSurface::createFromMachPort(machPort.port(), ColorSpaceDeviceRGB);
</del><ins>+        result.m_frontBuffer.surface = IOSurface::createFromMachPort(machPort.port(), ColorSpaceDeviceRGB);
</ins><span class="cx">         mach_port_deallocate(mach_task_self(), machPort.port());
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="lines">@@ -155,7 +148,7 @@
</span><span class="cx">     ShareableBitmap::Handle handle;
</span><span class="cx">     if (!decoder.decode(handle))
</span><span class="cx">         return false;
</span><del>-    result.m_frontBuffer = ShareableBitmap::create(handle);
</del><ins>+    result.m_frontBuffer.bitmap = ShareableBitmap::create(handle);
</ins><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="lines">@@ -170,13 +163,46 @@
</span><span class="cx">     setNeedsDisplay(IntRect(IntPoint(), expandedIntSize(m_size)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RemoteLayerBackingStore::swapToValidFrontBuffer()
+{
+    FloatSize scaledSize = m_size;
+    scaledSize.scale(m_scale);
+    IntSize expandedScaledSize = roundedIntSize(scaledSize);
+
+#if USE(IOSURFACE)
+    if (m_acceleratesDrawing) {
+        if (!m_backBuffer.surface || m_backBuffer.surface-&gt;isInUse()) {
+            std::swap(m_backBuffer, m_secondaryBackBuffer);
+            if (m_backBuffer.surface &amp;&amp; m_backBuffer.surface-&gt;isInUse())
+                m_backBuffer.discard();
+        }
+
+        std::swap(m_frontBuffer, m_backBuffer);
+
+        if (!m_frontBuffer.surface)
+            m_frontBuffer.surface = IOSurface::create(expandedScaledSize, ColorSpaceDeviceRGB);
+
+        setBufferVolatility(BufferType::Front, false);
+
+        return;
+    }
+#endif
+
+    ASSERT(!m_acceleratesDrawing);
+    std::swap(m_frontBuffer, m_backBuffer);
+
+    if (!m_frontBuffer.bitmap)
+        m_frontBuffer.bitmap = ShareableBitmap::createShareable(expandedScaledSize, m_isOpaque ? ShareableBitmap::NoFlags : ShareableBitmap::SupportsAlpha);
+}
+
</ins><span class="cx"> bool RemoteLayerBackingStore::display()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_frontContextPendingFlush);
</span><span class="cx"> 
</span><span class="cx">     m_lastDisplayTime = std::chrono::steady_clock::now();
</span><span class="cx"> 
</span><del>-    setVolatility(Volatility::NonVolatile);
</del><ins>+    // Make the previous front buffer non-volatile early, so that we can dirty the whole layer if it comes back empty.
+    setBufferVolatility(BufferType::Front, false);
</ins><span class="cx"> 
</span><span class="cx">     if (m_dirtyRegion.isEmpty() || m_size.isEmpty())
</span><span class="cx">         return false;
</span><span class="lines">@@ -195,42 +221,33 @@
</span><span class="cx">     IntSize expandedScaledSize = roundedIntSize(scaledSize);
</span><span class="cx">     IntRect expandedScaledLayerBounds(IntPoint(), expandedScaledSize);
</span><span class="cx">     bool willPaintEntireBackingStore = m_dirtyRegion.contains(layerBounds);
</span><ins>+
+    swapToValidFrontBuffer();
+
</ins><span class="cx"> #if USE(IOSURFACE)
</span><span class="cx">     if (m_acceleratesDrawing) {
</span><del>-        std::swap(m_frontSurface, m_backSurface);
-
-        if (!m_frontSurface || m_frontSurface-&gt;isInUse()) {
-            if (m_frontSurface)
-                IOSurfacePool::sharedPool().addSurface(m_frontSurface.get());
-            m_frontSurface = IOSurface::create(expandedScaledSize, ColorSpaceDeviceRGB);
-        }
-
</del><span class="cx">         RetainPtr&lt;CGImageRef&gt; backImage;
</span><del>-        if (m_backSurface &amp;&amp; !willPaintEntireBackingStore)
-            backImage = m_backSurface-&gt;createImage();
</del><ins>+        if (m_backBuffer.surface &amp;&amp; !willPaintEntireBackingStore)
+            backImage = m_backBuffer.surface-&gt;createImage();
</ins><span class="cx"> 
</span><del>-        GraphicsContext&amp; context = m_frontSurface-&gt;ensureGraphicsContext();
</del><ins>+        GraphicsContext&amp; context = m_frontBuffer.surface-&gt;ensureGraphicsContext();
</ins><span class="cx"> 
</span><span class="cx">         context.scale(FloatSize(1, -1));
</span><span class="cx">         context.translate(0, -expandedScaledSize.height());
</span><span class="cx">         drawInContext(context, backImage.get());
</span><span class="cx"> 
</span><del>-        m_frontSurface-&gt;clearGraphicsContext();
</del><ins>+        m_frontBuffer.surface-&gt;clearGraphicsContext();
</ins><span class="cx"> 
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!m_acceleratesDrawing);
</span><ins>+    std::unique_ptr&lt;GraphicsContext&gt; context = m_frontBuffer.bitmap-&gt;createGraphicsContext();
</ins><span class="cx"> 
</span><del>-    std::swap(m_frontBuffer, m_backBuffer);
-    if (!m_frontBuffer)
-        m_frontBuffer = ShareableBitmap::createShareable(expandedScaledSize, m_isOpaque ? ShareableBitmap::NoFlags : ShareableBitmap::SupportsAlpha);
-    std::unique_ptr&lt;GraphicsContext&gt; context = m_frontBuffer-&gt;createGraphicsContext();
-
</del><span class="cx">     RetainPtr&lt;CGImageRef&gt; backImage;
</span><del>-    if (m_backBuffer &amp;&amp; !willPaintEntireBackingStore)
-        backImage = m_backBuffer-&gt;makeCGImage();
</del><ins>+    if (m_backBuffer.bitmap &amp;&amp; !willPaintEntireBackingStore)
+        backImage = m_backBuffer.bitmap-&gt;makeCGImage();
</ins><span class="cx"> 
</span><span class="cx">     drawInContext(*context, backImage.get());
</span><span class="cx">     
</span><span class="lines">@@ -345,13 +362,13 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(IOSURFACE)
</span><span class="cx">     if (acceleratesDrawing()) {
</span><del>-        layer.contents = (id)m_frontSurface-&gt;surface();
</del><ins>+        layer.contents = (id)m_frontBuffer.surface-&gt;surface();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!acceleratesDrawing());
</span><del>-    layer.contents = (id)m_frontBuffer-&gt;makeCGImageCopy().get();
</del><ins>+    layer.contents = (id)m_frontBuffer.bitmap-&gt;makeCGImageCopy().get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RetainPtr&lt;CGContextRef&gt; RemoteLayerBackingStore::takeFrontContextPendingFlush()
</span><span class="lines">@@ -360,40 +377,59 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if USE(IOSURFACE)
</span><del>-bool RemoteLayerBackingStore::setVolatility(Volatility volatility)
</del><ins>+bool RemoteLayerBackingStore::setBufferVolatility(BufferType type, bool isVolatile)
</ins><span class="cx"> {
</span><del>-    if (m_volatility == volatility)
-        return true;
</del><ins>+    switch(type) {
+    case BufferType::Front:
+        if (m_frontBuffer.surface &amp;&amp; m_frontBuffer.isVolatile != isVolatile) {
+            if (!isVolatile || !m_frontBuffer.surface-&gt;isInUse()) {
+                IOSurface::SurfaceState previousState = m_frontBuffer.surface-&gt;setIsVolatile(isVolatile);
+                m_frontBuffer.isVolatile = isVolatile;
</ins><span class="cx"> 
</span><del>-    bool wantsVolatileFrontBuffer = volatility == Volatility::AllBuffersVolatile;
-    bool wantsVolatileBackBuffer = volatility == Volatility::AllBuffersVolatile || volatility == Volatility::BackBufferVolatile;
-
-    // If either surface is in-use and would become volatile, don't make any changes.
-    if (wantsVolatileFrontBuffer &amp;&amp; m_frontSurface &amp;&amp; m_frontSurface-&gt;isInUse())
-        return false;
-    if (wantsVolatileBackBuffer &amp;&amp; m_backSurface &amp;&amp; m_backSurface-&gt;isInUse())
-        return false;
-
-    if (m_frontSurface) {
-        IOSurface::SurfaceState previousState = m_frontSurface-&gt;setIsVolatile(wantsVolatileFrontBuffer);
-
-        // Becoming non-volatile and the front buffer was purged, so we need to repaint.
-        if (!wantsVolatileFrontBuffer &amp;&amp; (previousState == IOSurface::SurfaceState::Empty))
-            setNeedsDisplay();
</del><ins>+                // Becoming non-volatile and the front buffer was purged, so we need to repaint.
+                if (!isVolatile &amp;&amp; (previousState == IOSurface::SurfaceState::Empty))
+                    setNeedsDisplay();
+            } else
+                return false;
+        }
+        break;
+    case BufferType::Back:
+        if (m_backBuffer.surface &amp;&amp; m_backBuffer.isVolatile != isVolatile) {
+            if (!isVolatile || !m_backBuffer.surface-&gt;isInUse()) {
+                m_backBuffer.surface-&gt;setIsVolatile(isVolatile);
+                m_backBuffer.isVolatile = isVolatile;
+            } else
+                return false;
+        }
+        break;
+    case BufferType::SecondaryBack:
+        if (m_secondaryBackBuffer.surface &amp;&amp; m_secondaryBackBuffer.isVolatile != isVolatile) {
+            if (!isVolatile || !m_secondaryBackBuffer.surface-&gt;isInUse()) {
+                m_secondaryBackBuffer.surface-&gt;setIsVolatile(isVolatile);
+                m_secondaryBackBuffer.isVolatile = isVolatile;
+            } else
+                return false;
+        }
+        break;
</ins><span class="cx">     }
</span><del>-
-    if (m_backSurface)
-        m_backSurface-&gt;setIsVolatile(wantsVolatileBackBuffer);
-
-    m_volatility = volatility;
-
</del><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> #else
</span><del>-bool RemoteLayerBackingStore::setVolatility(Volatility)
</del><ins>+bool RemoteLayerBackingStore::setBufferVolatility(BufferType, bool)
</ins><span class="cx"> {
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+void RemoteLayerBackingStore::Buffer::discard()
+{
+#if USE(IOSURFACE)
+    if (surface)
+        IOSurfacePool::sharedPool().addSurface(surface.get());
+    surface = nullptr;
+    isVolatile = false;
+#endif
+    bitmap = nullptr;
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoreCollectionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm (168656 => 168657)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm        2014-05-12 23:29:18 UTC (rev 168656)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStoreCollection.mm        2014-05-12 23:31:56 UTC (rev 168657)
</span><span class="lines">@@ -31,7 +31,8 @@
</span><span class="cx"> #import &quot;RemoteLayerTreeContext.h&quot;
</span><span class="cx"> 
</span><span class="cx"> const std::chrono::seconds purgeableBackingStoreAgeThreshold = 1_s;
</span><del>-const std::chrono::seconds purgeabilityTimerInterval = 1_s;
</del><ins>+const std::chrono::milliseconds purgeableSecondaryBackingStoreAgeThreshold = 200_ms;
+const std::chrono::milliseconds purgeabilityTimerInterval = 200_ms;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="lines">@@ -60,12 +61,18 @@
</span><span class="cx">     for (const auto&amp; backingStore : m_liveBackingStore) {
</span><span class="cx">         if (now - backingStore-&gt;lastDisplayTime() &lt; purgeableBackingStoreAgeThreshold) {
</span><span class="cx">             hadRecentlyPaintedBackingStore = true;
</span><ins>+
+            if (now - backingStore-&gt;lastDisplayTime() &gt;= purgeableSecondaryBackingStoreAgeThreshold)
+                backingStore-&gt;setBufferVolatility(RemoteLayerBackingStore::BufferType::SecondaryBack, true);
+
</ins><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // FIXME: If the layer is unparented, we should make all buffers volatile.
</span><del>-        if (!backingStore-&gt;setVolatility(RemoteLayerBackingStore::Volatility::BackBufferVolatile))
</del><ins>+        if (!backingStore-&gt;setBufferVolatility(RemoteLayerBackingStore::BufferType::SecondaryBack, true))
</ins><span class="cx">             successfullyMadeBackingStorePurgeable = false;
</span><ins>+        if (!backingStore-&gt;setBufferVolatility(RemoteLayerBackingStore::BufferType::Back, true))
+            successfullyMadeBackingStorePurgeable = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (!hadRecentlyPaintedBackingStore &amp;&amp; successfullyMadeBackingStorePurgeable)
</span></span></pre>
</div>
</div>

</body>
</html>