<!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>[192689] 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/192689">192689</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2015-11-20 12:05:05 -0800 (Fri, 20 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Back-buffer to front-buffer copy fails for some buffer formats
https://bugs.webkit.org/show_bug.cgi?id=151475
rdar://problem/23617899

Reviewed by Tim Horton.

Source/WebCore:

Fix some fo the bitsPerComponent/bitsPerPixel options in IOSurface::ensurePlatformContext()
for RGB10 buffers. Fix IOSurface::format() to return the new formats.

Implement IOSurface::copyToSurface(), which does a synchronous copy between
surfaces.

* platform/graphics/cocoa/IOSurface.h:
* platform/graphics/cocoa/IOSurface.mm:
(IOSurface::create):
(IOSurface::ensurePlatformContext):
(IOSurface::format):
(IOSurface::copyToSurface):

Source/WebKit2:

When displaying RemoteLayerBackingStore, we copy the back buffer to the front
buffer before painting the updated regions. For buffers using Format::RGB10A8,
the CGImage-based copy fails, so in this case, use IOSurface::copyToSurface().

Reorganized RemoteLayerBackingStore::drawInContext() to make this a bit easier
to understand. First, we either copy the entire surface over, or paint the backImage.
Then we clip to the dirty rects, and clear them, then paint the layer contents.

* Shared/mac/RemoteLayerBackingStore.mm:
(WebKit::RemoteLayerBackingStore::display):
(WebKit::RemoteLayerBackingStore::drawInContext):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscocoaIOSurfaceh">trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscocoaIOSurfacemm">trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedmacRemoteLayerBackingStoremm">trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192688 => 192689)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-11-20 19:20:57 UTC (rev 192688)
+++ trunk/Source/WebCore/ChangeLog        2015-11-20 20:05:05 UTC (rev 192689)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2015-11-19  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Back-buffer to front-buffer copy fails for some buffer formats
+        https://bugs.webkit.org/show_bug.cgi?id=151475
+        rdar://problem/23617899
+
+        Reviewed by Tim Horton.
+        
+        Fix some fo the bitsPerComponent/bitsPerPixel options in IOSurface::ensurePlatformContext()
+        for RGB10 buffers. Fix IOSurface::format() to return the new formats.
+        
+        Implement IOSurface::copyToSurface(), which does a synchronous copy between
+        surfaces.
+
+        * platform/graphics/cocoa/IOSurface.h:
+        * platform/graphics/cocoa/IOSurface.mm:
+        (IOSurface::create):
+        (IOSurface::ensurePlatformContext):
+        (IOSurface::format):
+        (IOSurface::copyToSurface):
+
</ins><span class="cx"> 2015-11-20  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Simple line layout: Add text-indent support.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscocoaIOSurfaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.h (192688 => 192689)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.h        2015-11-20 19:20:57 UTC (rev 192688)
+++ trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.h        2015-11-20 20:05:05 UTC (rev 192689)
</span><span class="lines">@@ -80,7 +80,7 @@
</span><span class="cx">     IntSize size() const { return m_size; }
</span><span class="cx">     size_t totalBytes() const { return m_totalBytes; }
</span><span class="cx">     ColorSpace colorSpace() const { return m_colorSpace; }
</span><del>-    Format format() const;
</del><ins>+    WEBCORE_EXPORT Format format() const;
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT bool isInUse() const;
</span><span class="cx"> 
</span><span class="lines">@@ -89,6 +89,7 @@
</span><span class="cx">     WEBCORE_EXPORT void releaseGraphicsContext();
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><ins>+    WEBCORE_EXPORT void copyToSurface(IOSurface&amp;);
</ins><span class="cx">     WEBCORE_EXPORT static void convertToFormat(std::unique_ptr&lt;WebCore::IOSurface&gt;&amp;&amp; inSurface, Format, std::function&lt;void(std::unique_ptr&lt;WebCore::IOSurface&gt;)&gt;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscocoaIOSurfacemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.mm (192688 => 192689)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.mm        2015-11-20 19:20:57 UTC (rev 192688)
+++ trunk/Source/WebCore/platform/graphics/cocoa/IOSurface.mm        2015-11-20 20:05:05 UTC (rev 192689)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> std::unique_ptr&lt;IOSurface&gt; IOSurface::create(IntSize size, ColorSpace colorSpace, Format pixelFormat)
</span><span class="cx"> {
</span><span class="cx">     // YUV422 IOSurfaces do not go in the pool.
</span><ins>+    // FIXME: Want pooling of RGB10, RGB10A8.
</ins><span class="cx">     if (pixelFormat == Format::RGBA) {
</span><span class="cx">         if (auto cachedSurface = surfaceFromPool(size, size, colorSpace))
</span><span class="cx">             return cachedSurface;
</span><span class="lines">@@ -259,8 +260,27 @@
</span><span class="cx">         return m_cgContext.get();
</span><span class="cx"> 
</span><span class="cx">     CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
</span><ins>+
</ins><span class="cx">     size_t bitsPerComponent = 8;
</span><span class="cx">     size_t bitsPerPixel = 32;
</span><ins>+    
+    switch (format()) {
+    case Format::RGBA:
+        break;
+    case Format::RGB10:
+        bitsPerComponent = 10;
+        bitsPerPixel = 32;
+        break;
+    case Format::RGB10A8:
+        // FIXME: This doesn't take the two-plane format into account.
+        bitsPerComponent = 10;
+        bitsPerPixel = 32;
+        break;
+    case Format::YUV422:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    
</ins><span class="cx">     m_cgContext = adoptCF(CGIOSurfaceContextCreate(m_surface.get(), m_contextSize.width(), m_contextSize.height(), bitsPerComponent, bitsPerPixel, cachedCGColorSpace(m_colorSpace), bitmapInfo));
</span><span class="cx"> 
</span><span class="cx">     return m_cgContext.get();
</span><span class="lines">@@ -310,6 +330,13 @@
</span><span class="cx">     unsigned pixelFormat = IOSurfaceGetPixelFormat(m_surface.get());
</span><span class="cx">     if (pixelFormat == 'BGRA')
</span><span class="cx">         return Format::RGBA;
</span><ins>+
+    if (pixelFormat == 'w30r')
+        return Format::RGB10;
+
+    if (pixelFormat == 'b3a8')
+        return Format::RGB10A8;
+
</ins><span class="cx">     if (pixelFormat == 'yuvf')
</span><span class="cx">         return Format::YUV422;
</span><span class="cx"> 
</span><span class="lines">@@ -329,6 +356,27 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><ins>+WEBCORE_EXPORT void IOSurface::copyToSurface(IOSurface&amp; destSurface)
+{
+    if (destSurface.format() != format()) {
+        WTFLogAlways(&quot;Trying to copy IOSurface to another surface with a different format&quot;);
+        return;
+    }
+
+    if (destSurface.size() != size()) {
+        WTFLogAlways(&quot;Trying to copy IOSurface to another surface with a different size&quot;);
+        return;
+    }
+
+    static IOSurfaceAcceleratorRef accelerator;
+    if (!accelerator)
+        IOSurfaceAcceleratorCreate(nullptr, nullptr, &amp;accelerator);
+
+    IOReturn ret = IOSurfaceAcceleratorTransformSurface(accelerator, m_surface.get(), destSurface.surface(), nullptr, nullptr, nullptr, nullptr, nullptr);
+    if (ret)
+        WTFLogAlways(&quot;IOSurfaceAcceleratorTransformSurface %p to %p failed with error %d&quot;, m_surface.get(), destSurface.surface(), ret);
+}
+
</ins><span class="cx"> void IOSurface::convertToFormat(std::unique_ptr&lt;WebCore::IOSurface&gt;&amp;&amp; inSurface, Format format, std::function&lt;void(std::unique_ptr&lt;WebCore::IOSurface&gt;)&gt; callback)
</span><span class="cx"> {
</span><span class="cx">     static IOSurfaceAcceleratorRef accelerator;
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (192688 => 192689)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-11-20 19:20:57 UTC (rev 192688)
+++ trunk/Source/WebKit2/ChangeLog        2015-11-20 20:05:05 UTC (rev 192689)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2015-11-19  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Back-buffer to front-buffer copy fails for some buffer formats
+        https://bugs.webkit.org/show_bug.cgi?id=151475
+        rdar://problem/23617899
+
+        Reviewed by Tim Horton.
+        
+        When displaying RemoteLayerBackingStore, we copy the back buffer to the front
+        buffer before painting the updated regions. For buffers using Format::RGB10A8,
+        the CGImage-based copy fails, so in this case, use IOSurface::copyToSurface().
+        
+        Reorganized RemoteLayerBackingStore::drawInContext() to make this a bit easier
+        to understand. First, we either copy the entire surface over, or paint the backImage.
+        Then we clip to the dirty rects, and clear them, then paint the layer contents.
+
+        * Shared/mac/RemoteLayerBackingStore.mm:
+        (WebKit::RemoteLayerBackingStore::display):
+        (WebKit::RemoteLayerBackingStore::drawInContext):
+
</ins><span class="cx"> 2015-11-19  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r192667 and r192668.
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedmacRemoteLayerBackingStoremm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm (192688 => 192689)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm        2015-11-20 19:20:57 UTC (rev 192688)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm        2015-11-20 20:05:05 UTC (rev 192689)
</span><span class="lines">@@ -252,8 +252,15 @@
</span><span class="cx"> #if USE(IOSURFACE)
</span><span class="cx">     if (m_acceleratesDrawing) {
</span><span class="cx">         RetainPtr&lt;CGImageRef&gt; backImage;
</span><del>-        if (m_backBuffer.surface &amp;&amp; !willPaintEntireBackingStore)
-            backImage = m_backBuffer.surface-&gt;createImage();
</del><ins>+        if (m_backBuffer.surface &amp;&amp; !willPaintEntireBackingStore) {
+#if PLATFORM(IOS)
+            if (m_backBuffer.surface-&gt;format() == WebCore::IOSurface::Format::RGB10A8) {
+                // FIXME: remove this when rdar://problem/23623670 is fixed.
+                m_backBuffer.surface-&gt;copyToSurface(*m_frontBuffer.surface);
+            } else
+#endif
+                backImage = m_backBuffer.surface-&gt;createImage();
+        }
</ins><span class="cx"> 
</span><span class="cx">         GraphicsContext&amp; context = m_frontBuffer.surface-&gt;ensureGraphicsContext();
</span><span class="cx"> 
</span><span class="lines">@@ -286,16 +293,6 @@
</span><span class="cx">     scaledSize.scale(m_scale);
</span><span class="cx">     IntRect scaledLayerBounds(IntPoint(), roundedIntSize(scaledSize));
</span><span class="cx"> 
</span><del>-    if (!m_isOpaque)
-        context.clearRect(scaledLayerBounds);
-
-#ifndef NDEBUG
-    if (m_isOpaque)
-        context.fillRect(scaledLayerBounds, Color(255, 0, 0));
-#endif
-
-    CGContextRef cgContext = context.platformContext();
-
</del><span class="cx">     // If we have less than webLayerMaxRectsToPaint rects to paint and they cover less
</span><span class="cx">     // than webLayerWastedSpaceThreshold of the total dirty area, we'll repaint each rect separately.
</span><span class="cx">     // Otherwise, repaint the entire bounding box of the dirty region.
</span><span class="lines">@@ -323,22 +320,26 @@
</span><span class="cx">         cgPaintingRects[i] = scaledPaintingRect;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    CGContextRef cgContext = context.platformContext();
+
</ins><span class="cx">     if (backImage) {
</span><del>-        CGContextSaveGState(cgContext);
</del><ins>+        CGContextStateSaver stateSaver(cgContext);
</ins><span class="cx">         CGContextSetBlendMode(cgContext, kCGBlendModeCopy);
</span><del>-
-        CGContextAddRect(cgContext, CGRectInfinite);
-        CGContextAddRects(cgContext, cgPaintingRects, m_paintingRects.size());
-        CGContextEOClip(cgContext);
-
</del><span class="cx">         CGContextTranslateCTM(cgContext, 0, scaledLayerBounds.height());
</span><span class="cx">         CGContextScaleCTM(cgContext, 1, -1);
</span><span class="cx">         CGContextDrawImage(cgContext, scaledLayerBounds, backImage);
</span><del>-        CGContextRestoreGState(cgContext);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     CGContextClipToRects(cgContext, cgPaintingRects, m_paintingRects.size());
</span><span class="cx"> 
</span><ins>+    if (!m_isOpaque)
+        context.clearRect(scaledLayerBounds);
+
+#ifndef NDEBUG
+    if (m_isOpaque)
+        context.fillRect(scaledLayerBounds, Color(255, 0, 0));
+#endif
+
</ins><span class="cx">     context.scale(FloatSize(m_scale, m_scale));
</span><span class="cx"> 
</span><span class="cx">     // FIXME: This should be moved to PlatformCALayerRemote for better layering.
</span></span></pre>
</div>
</div>

</body>
</html>