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();
}