Title: [166541] trunk/Source/WebKit2
Revision
166541
Author
[email protected]
Date
2014-03-31 16:00:30 -0700 (Mon, 31 Mar 2014)

Log Message

Double-buffer RemoteLayerBackingStore
https://bugs.webkit.org/show_bug.cgi?id=130990

Reviewed by Simon Fraser.

We'll keep a front and back buffer for each surface; the front is generally currently
being displayed in the UI process, and the back is the one we'll paint into.

Swap the two surfaces each time we paint; since we synchronize with the UI process,
the old front surface will generally be out-of-use by the render server by the time
we paint again. However, since render server commits are asynchronous and we have 
no way to syncronize with them yet, we have to check if the (swapped to front) back buffer is in use,
and create a new front buffer if it is.

Triple-buffering would solve this problem, as would synchronization with the render server,
as would a pool of surfaces - we will revisit these solutions in future patches.

* Shared/mac/RemoteLayerBackingStore.h:
* Shared/mac/RemoteLayerBackingStore.mm:
(RemoteLayerBackingStore::ensureBackingStore):
(RemoteLayerBackingStore::clearBackingStore):
Factor clearBackingStore() out of ensureBackingStore() and display().

(RemoteLayerBackingStore::display):
Swap buffers. Since m_backSurface will hold on to the back surface's CGContext,
we don't need to worry about tearing down the image first anymore.
Don't worry about creating a back image (nor copying it into the front image)
if we're going to paint the whole layer.

(RemoteLayerBackingStore::drawInContext):
Fix some names.

(RemoteLayerBackingStore::applyBackingStoreToLayer):
Reduce duplication.

(RemoteLayerBackingStore::createImageForFrontBuffer): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (166540 => 166541)


--- trunk/Source/WebKit2/ChangeLog	2014-03-31 22:52:31 UTC (rev 166540)
+++ trunk/Source/WebKit2/ChangeLog	2014-03-31 23:00:30 UTC (rev 166541)
@@ -1,5 +1,44 @@
 2014-03-31  Tim Horton  <[email protected]>
 
+        Double-buffer RemoteLayerBackingStore
+        https://bugs.webkit.org/show_bug.cgi?id=130990
+
+        Reviewed by Simon Fraser.
+
+        We'll keep a front and back buffer for each surface; the front is generally currently
+        being displayed in the UI process, and the back is the one we'll paint into.
+
+        Swap the two surfaces each time we paint; since we synchronize with the UI process,
+        the old front surface will generally be out-of-use by the render server by the time
+        we paint again. However, since render server commits are asynchronous and we have 
+        no way to syncronize with them yet, we have to check if the (swapped to front) back buffer is in use,
+        and create a new front buffer if it is.
+
+        Triple-buffering would solve this problem, as would synchronization with the render server,
+        as would a pool of surfaces - we will revisit these solutions in future patches.
+
+        * Shared/mac/RemoteLayerBackingStore.h:
+        * Shared/mac/RemoteLayerBackingStore.mm:
+        (RemoteLayerBackingStore::ensureBackingStore):
+        (RemoteLayerBackingStore::clearBackingStore):
+        Factor clearBackingStore() out of ensureBackingStore() and display().
+
+        (RemoteLayerBackingStore::display):
+        Swap buffers. Since m_backSurface will hold on to the back surface's CGContext,
+        we don't need to worry about tearing down the image first anymore.
+        Don't worry about creating a back image (nor copying it into the front image)
+        if we're going to paint the whole layer.
+
+        (RemoteLayerBackingStore::drawInContext):
+        Fix some names.
+
+        (RemoteLayerBackingStore::applyBackingStoreToLayer):
+        Reduce duplication.
+
+        (RemoteLayerBackingStore::createImageForFrontBuffer): Deleted.
+
+2014-03-31  Tim Horton  <[email protected]>
+
         Synchronize Web process remote layer tree commits with CoreAnimation commits in the UI process
         https://bugs.webkit.org/show_bug.cgi?id=130984
 

Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h (166540 => 166541)


--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h	2014-03-31 22:52:31 UTC (rev 166540)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h	2014-03-31 23:00:30 UTC (rev 166541)
@@ -75,11 +75,11 @@
 #endif
         return !!m_frontBuffer;
     }
+
 private:
-    void drawInContext(WebCore::GraphicsContext&, CGImageRef frontImage);
+    void drawInContext(WebCore::GraphicsContext&, CGImageRef backImage);
+    void clearBackingStore();
 
-    RetainPtr<CGImageRef> createImageForFrontBuffer() const;
-
     PlatformCALayerRemote* m_layer;
 
     WebCore::IntSize m_size;
@@ -89,8 +89,10 @@
     WebCore::Region m_dirtyRegion;
 
     RefPtr<ShareableBitmap> m_frontBuffer;
+    RefPtr<ShareableBitmap> m_backBuffer;
 #if USE(IOSURFACE)
     RefPtr<WebCore::IOSurface> m_frontSurface;
+    RefPtr<WebCore::IOSurface> m_backSurface;
 #endif
 
     bool m_acceleratesDrawing;

Modified: trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm (166540 => 166541)


--- trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm	2014-03-31 22:52:31 UTC (rev 166540)
+++ trunk/Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm	2014-03-31 23:00:30 UTC (rev 166541)
@@ -68,10 +68,17 @@
     m_acceleratesDrawing = acceleratesDrawing;
     m_isOpaque = isOpaque;
 
+    clearBackingStore();
+}
+
+void RemoteLayerBackingStore::clearBackingStore()
+{
 #if USE(IOSURFACE)
     m_frontSurface = nullptr;
+    m_backSurface = nullptr;
 #endif
     m_frontBuffer = nullptr;
+    m_backBuffer = nullptr;
 }
 
 void RemoteLayerBackingStore::encode(IPC::ArgumentEncoder& encoder) const
@@ -141,15 +148,6 @@
     setNeedsDisplay(IntRect(IntPoint(), m_size));
 }
 
-RetainPtr<CGImageRef> RemoteLayerBackingStore::createImageForFrontBuffer() const
-{
-    if (!m_frontBuffer || m_acceleratesDrawing)
-        return nullptr;
-
-    // FIXME: Do we need Copy?
-    return m_frontBuffer->makeCGImageCopy();
-}
-
 bool RemoteLayerBackingStore::display()
 {
     if (!m_layer)
@@ -159,20 +157,16 @@
     // to note that our backing store has been cleared.
     if (!m_layer->owner() || !m_layer->owner()->platformCALayerDrawsContent()) {
         bool previouslyDrewContents = hasFrontBuffer();
-
-        m_frontBuffer = nullptr;
-#if USE(IOSURFACE)
-        m_frontSurface = nullptr;
-#endif
-
+        clearBackingStore();
         return previouslyDrewContents;
     }
 
     if (m_dirtyRegion.isEmpty() || m_size.isEmpty())
         return false;
 
+    IntRect layerBounds(IntPoint(), m_size);
     if (!hasFrontBuffer())
-        m_dirtyRegion.unite(IntRect(IntPoint(), m_size));
+        m_dirtyRegion.unite(layerBounds);
 
     if (m_layer->owner()->platformCALayerShowRepaintCounter(m_layer)) {
         IntRect indicatorRect(0, 0, 52, 27);
@@ -183,40 +177,49 @@
     scaledSize.scale(m_scale);
     IntSize expandedScaledSize = expandedIntSize(scaledSize);
 
+    bool willPaintEntireBackingStore = m_dirtyRegion.bounds().contains(layerBounds);
 #if USE(IOSURFACE)
     if (m_acceleratesDrawing) {
-        RefPtr<IOSurface> backSurface = IOSurface::create(expandedScaledSize, ColorSpaceDeviceRGB);
-        GraphicsContext& context = backSurface->ensureGraphicsContext();
+        std::swap(m_frontSurface, m_backSurface);
+
+        if (!m_frontSurface || m_frontSurface->isInUse()) {
+            // FIXME: Instead of discarding it, put the unusable in-use surface into a pool for future use.
+            m_frontSurface = IOSurface::create(expandedScaledSize, ColorSpaceDeviceRGB);
+        }
+
+        RetainPtr<CGImageRef> backImage;
+        if (m_backSurface && !willPaintEntireBackingStore)
+            backImage = m_backSurface->createImage();
+
+        GraphicsContext& context = m_frontSurface->ensureGraphicsContext();
         context.clearRect(FloatRect(FloatPoint(), expandedScaledSize));
         context.scale(FloatSize(1, -1));
         context.translate(0, -expandedScaledSize.height());
+        drawInContext(context, backImage.get());
 
-        RetainPtr<CGImageRef> frontImage;
-        if (m_frontSurface)
-            frontImage = m_frontSurface->createImage();
-        drawInContext(context, frontImage.get());
+        m_frontSurface->clearGraphicsContext();
 
-        // If our frontImage is derived from an IOSurface, we need to
-        // destroy the image before the CGContext it's derived from,
-        // so that the context doesn't make a CPU copy of the surface data.
-        frontImage = nullptr;
-        m_frontSurface = backSurface;
-
         return true;
     }
 #else
     ASSERT(!m_acceleratesDrawing);
 #endif
 
-    RetainPtr<CGImageRef> frontImage = createImageForFrontBuffer();
-    m_frontBuffer = ShareableBitmap::createShareable(expandedScaledSize, m_isOpaque ? ShareableBitmap::NoFlags : ShareableBitmap::SupportsAlpha);
+    std::swap(m_frontBuffer, m_backBuffer);
+    if (!m_frontBuffer)
+        m_frontBuffer = ShareableBitmap::createShareable(expandedScaledSize, m_isOpaque ? ShareableBitmap::NoFlags : ShareableBitmap::SupportsAlpha);
     std::unique_ptr<GraphicsContext> context = m_frontBuffer->createGraphicsContext();
-    drawInContext(*context, frontImage.get());
+
+    RetainPtr<CGImageRef> backImage;
+    if (m_backBuffer && !willPaintEntireBackingStore)
+        backImage = m_backBuffer->makeCGImage();
+
+    drawInContext(*context, backImage.get());
     
     return true;
 }
 
-void RemoteLayerBackingStore::drawInContext(GraphicsContext& context, CGImageRef frontImage)
+void RemoteLayerBackingStore::drawInContext(GraphicsContext& context, CGImageRef backImage)
 {
     IntRect layerBounds(IntPoint(), m_size);
     IntRect scaledLayerBounds(IntPoint(), expandedIntSize(m_size * m_scale));
@@ -227,6 +230,7 @@
     // 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<IntRect> dirtyRects = m_dirtyRegion.rects();
     if (dirtyRects.size() > webLayerMaxRectsToPaint || m_dirtyRegion.totalArea() > webLayerWastedSpaceThreshold * dirtyBounds.width() * dirtyBounds.height()) {
         dirtyRects.clear();
@@ -248,7 +252,7 @@
         cgPaintingRects[i] = enclosingIntRect(scaledPaintingRect);
     }
 
-    if (frontImage) {
+    if (backImage) {
         CGContextSaveGState(cgContext);
         CGContextSetBlendMode(cgContext, kCGBlendModeCopy);
 
@@ -258,7 +262,7 @@
 
         CGContextTranslateCTM(cgContext, 0, scaledLayerBounds.height());
         CGContextScaleCTM(cgContext, 1, -1);
-        CGContextDrawImage(cgContext, scaledLayerBounds, frontImage);
+        CGContextDrawImage(cgContext, scaledLayerBounds, backImage);
         CGContextRestoreGState(cgContext);
     }
 
@@ -309,15 +313,15 @@
 
 void RemoteLayerBackingStore::applyBackingStoreToLayer(CALayer *layer)
 {
+    layer.contentsOpaque = m_isOpaque;
+
 #if USE(IOSURFACE)
-    if (acceleratesDrawing())
+    if (acceleratesDrawing()) {
         layer.contents = (id)m_frontSurface->surface();
-    else
-        layer.contents = (id)createImageForFrontBuffer().get();
-#else
-    ASSERT(!acceleratesDrawing());
-    layer.contents = (id)createImageForFrontBuffer().get();
+        return;
+    }
 #endif
 
-    layer.contentsOpaque = m_isOpaque;
+    ASSERT(!acceleratesDrawing());
+    layer.contents = (id)m_frontBuffer->makeCGImageCopy().get();
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to