Diff
Modified: trunk/Source/WebCore/ChangeLog (157657 => 157658)
--- trunk/Source/WebCore/ChangeLog 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebCore/ChangeLog 2013-10-19 00:51:07 UTC (rev 157658)
@@ -1,3 +1,26 @@
+2013-10-18 Tim Horton <[email protected]>
+
+ Remote Layer Tree: Double-buffering and minimization of repaints
+ https://bugs.webkit.org/show_bug.cgi?id=123043
+
+ Reviewed by Simon Fraser.
+
+ No new tests, not yet testable.
+
+ * WebCore.exp.in:
+ Export one version of drawLayerContents and Region::contains.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ Expose WebLayer.h as a private header.
+
+ * platform/graphics/mac/WebLayer.h:
+ Clean up this header, and add a new drawLayerContents that can operate without a CALayer.
+
+ * platform/graphics/mac/WebLayer.mm:
+ (WebCore::drawLayerContents):
+ Split drawLayerContents into one method that acquires properties CALayer,
+ and one that just does the painting.
+
2013-10-18 Anders Carlsson <[email protected]>
Try to fix the Lion build.
Modified: trunk/Source/WebCore/WebCore.exp.in (157657 => 157658)
--- trunk/Source/WebCore/WebCore.exp.in 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebCore/WebCore.exp.in 2013-10-19 00:51:07 UTC (rev 157658)
@@ -676,6 +676,7 @@
__ZN7WebCore17SQLiteTransactionD1Ev
__ZN7WebCore17SubresourceLoader6createEPNS_5FrameEPNS_14CachedResourceERKNS_15ResourceRequestERKNS_21ResourceLoaderOptionsE
__ZN7WebCore17cacheDOMStructureEPNS_17JSDOMGlobalObjectEPN3JSC9StructureEPKNS2_9ClassInfoE
+__ZN7WebCore17drawLayerContentsEP9CGContextPNS_15PlatformCALayerENS_9FloatRectEN3WTF6VectorIS4_Lm5ENS5_15CrashOnOverflowEEEb
__ZN7WebCore17languageDidChangeEv
__ZN7WebCore17openTemporaryFileERKN3WTF6StringERi
__ZN7WebCore17setCookiesFromDOMERKNS_21NetworkStorageSessionERKNS_3URLES5_RKN3WTF6StringE
@@ -1708,6 +1709,8 @@
__ZNK7WebCore6Editor9canDeleteEv
__ZNK7WebCore6Length22decrementCalculatedRefEv
__ZNK7WebCore6Region5rectsEv
+__ZNK7WebCore6Region8containsERKS0_
+__ZNK7WebCore6Region9totalAreaEv
__ZNK7WebCore6Widget14platformWidgetEv
__ZNK7WebCore6Widget23convertToContainingViewERKNS_7IntRectE
__ZNK7WebCore6Widget23convertToContainingViewERKNS_8IntPointE
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (157657 => 157658)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-10-19 00:51:07 UTC (rev 157658)
@@ -461,7 +461,7 @@
0FCF332C0F2B9A25004B6795 /* WebTiledLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FCF33280F2B9A25004B6795 /* WebTiledLayer.mm */; };
0FCF332D0F2B9A25004B6795 /* WebTiledLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCF33290F2B9A25004B6795 /* WebTiledLayer.h */; };
0FCF332E0F2B9A25004B6795 /* WebLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FCF332A0F2B9A25004B6795 /* WebLayer.mm */; };
- 0FCF332F0F2B9A25004B6795 /* WebLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCF332B0F2B9A25004B6795 /* WebLayer.h */; };
+ 0FCF332F0F2B9A25004B6795 /* WebLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCF332B0F2B9A25004B6795 /* WebLayer.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD3080E117CF7E700A791F7 /* RenderFrameBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3080C117CF7E700A791F7 /* RenderFrameBase.cpp */; };
0FD3080F117CF7E700A791F7 /* RenderFrameBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3080D117CF7E700A791F7 /* RenderFrameBase.h */; };
0FD308D5117D168500A791F7 /* RenderIFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD308D3117D168400A791F7 /* RenderIFrame.cpp */; };
Modified: trunk/Source/WebCore/platform/graphics/mac/WebLayer.h (157657 => 157658)
--- trunk/Source/WebCore/platform/graphics/mac/WebLayer.h 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebCore/platform/graphics/mac/WebLayer.h 2013-10-19 00:51:07 UTC (rev 157658)
@@ -29,20 +29,24 @@
#if USE(ACCELERATED_COMPOSITING)
#import <QuartzCore/QuartzCore.h>
+#import <WebCore/FloatRect.h>
+#import <wtf/Vector.h>
-namespace WebCore {
- class GraphicsLayer;
- class PlatformCALayer;
- class PlatformCALayerClient;
-}
+const unsigned webLayerMaxRectsToPaint = 5;
+const float webLayerWastedSpaceThreshold = 0.75f;
-@interface WebLayer : CALayer
-{
-}
+@interface WebLayer : CALayer
@end
+namespace WebCore {
+class GraphicsLayer;
+class PlatformCALayer;
+class PlatformCALayerClient;
+
// Functions allows us to share implementation across WebTiledLayer and WebLayer
void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayer*);
+void drawLayerContents(CGContextRef, WebCore::PlatformCALayer*, WebCore::FloatRect layerBounds, Vector<WebCore::FloatRect, webLayerMaxRectsToPaint> dirtyRects, bool isTiledLayer);
+}
#endif // USE(ACCELERATED_COMPOSITING)
Modified: trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm (157657 => 157658)
--- trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm 2013-10-19 00:51:07 UTC (rev 157658)
@@ -43,20 +43,45 @@
using namespace WebCore;
-@implementation WebLayer
+namespace WebCore {
void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayer* platformLayer)
{
+ CGRect layerBounds = [layer bounds];
+
+ __block double totalRectArea = 0;
+ __block unsigned rectCount = 0;
+ __block Vector<FloatRect, webLayerMaxRectsToPaint> dirtyRects;
+
+ wkCALayerEnumerateRectsBeingDrawnWithBlock(layer, context, ^(CGRect rect) {
+ if (++rectCount > webLayerMaxRectsToPaint)
+ return;
+
+ totalRectArea += rect.size.width * rect.size.height;
+ dirtyRects.append(rect);
+ });
+
+ FloatRect clipBounds = CGContextGetClipBoundingBox(context);
+ double clipArea = clipBounds.width() * clipBounds.height();
+
+ if (rectCount >= webLayerMaxRectsToPaint || totalRectArea >= clipArea * webLayerWastedSpaceThreshold)
+ dirtyRects.clear();
+
+ bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]];
+ drawLayerContents(context, platformLayer, layerBounds, dirtyRects, isTiledLayer);
+}
+
+void drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformLayer, FloatRect layerBounds, Vector<FloatRect, webLayerMaxRectsToPaint> dirtyRects, bool isTiledLayer)
+{
WebCore::PlatformCALayerClient* layerContents = platformLayer->owner();
if (!layerContents)
return;
CGContextSaveGState(context);
- CGRect layerBounds = [layer bounds];
if (layerContents->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) {
CGContextScaleCTM(context, 1, -1);
- CGContextTranslateCTM(context, 0, -layerBounds.size.height);
+ CGContextTranslateCTM(context, 0, -layerBounds.height());
}
[NSGraphicsContext saveGraphicsState];
@@ -87,24 +112,13 @@
#endif
ThemeMac::setFocusRingClipRect(focusRingClipRect);
- const float wastedSpaceThreshold = 0.75f;
- const unsigned maxRectsToPaint = 5;
-
- double clipArea = clipBounds.width() * clipBounds.height();
- __block double totalRectArea = 0;
- __block unsigned rectCount = 0;
- __block Vector<FloatRect, maxRectsToPaint> dirtyRects;
-
- wkCALayerEnumerateRectsBeingDrawnWithBlock(layer, context, ^(CGRect rect) {
- if (++rectCount > maxRectsToPaint)
- return;
-
- totalRectArea += rect.size.width * rect.size.height;
- dirtyRects.append(rect);
- });
-
- if (rectCount < maxRectsToPaint && totalRectArea < clipArea * wastedSpaceThreshold) {
- for (unsigned i = 0; i < rectCount; ++i) {
+ // If we have no dirty rects, repaint the whole layer.
+ if (dirtyRects.isEmpty()) {
+ // CGContextGetClipBoundingBox() gives us the bounds of the dirty region, so clipBounds
+ // encompasses all the dirty rects.
+ layerContents->platformCALayerPaintContents(graphicsContext, enclosingIntRect(clipBounds));
+ } else {
+ for (unsigned i = 0; i < dirtyRects.size(); ++i) {
const FloatRect& currentRect = dirtyRects[i];
GraphicsContextStateSaver stateSaver(graphicsContext);
@@ -112,10 +126,6 @@
layerContents->platformCALayerPaintContents(graphicsContext, enclosingIntRect(currentRect));
}
- } else {
- // CGContextGetClipBoundingBox() gives us the bounds of the dirty region, so clipBounds
- // encompasses all the dirty rects.
- layerContents->platformCALayerPaintContents(graphicsContext, enclosingIntRect(clipBounds));
}
ThemeMac::setFocusRingClipRect(FloatRect());
@@ -128,13 +138,11 @@
CGContextRestoreGState(context);
- // Always update the repain count so that it's accurate even if the count itself is not shown. This will be useful
+ // Always update the repaint count so that it's accurate even if the count itself is not shown. This will be useful
// for the Web Inspector feeding this information through the LayerTreeAgent.
int repaintCount = layerContents->platformCALayerIncrementRepaintCount();
if (!platformLayer->usesTiledBackingLayer() && layerContents && layerContents->platformCALayerShowRepaintCounter(platformLayer)) {
- bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]];
-
char text[16]; // that's a lot of repaints
snprintf(text, sizeof(text), "%d", repaintCount);
@@ -170,7 +178,10 @@
}
}
+}
+@implementation WebLayer
+
- (id<CAAction>)actionForKey:(NSString *)key
{
// Fix for <rdar://problem/9015675>: Force the layer content to be updated when the tree is reparented.
Modified: trunk/Source/WebKit2/ChangeLog (157657 => 157658)
--- trunk/Source/WebKit2/ChangeLog 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebKit2/ChangeLog 2013-10-19 00:51:07 UTC (rev 157658)
@@ -1,3 +1,36 @@
+2013-10-18 Tim Horton <[email protected]>
+
+ Remote Layer Tree: Double-buffering and minimization of repaints
+ https://bugs.webkit.org/show_bug.cgi?id=123043
+
+ Reviewed by Simon Fraser.
+
+ * WebProcess/WebPage/mac/PlatformCALayerRemote.cpp:
+ (PlatformCALayerRemote::ensureBackingStore):
+ Don't worry about isOpaque with RemoteLayerBackingStore; this is a
+ optimization that is causing trouble; we can re-add it later.
+
+ (PlatformCALayerRemote::setBounds):
+ Make sure that we will repaint if our bounds change.
+
+ * WebProcess/WebPage/mac/RemoteLayerBackingStore.h:
+ (WebKit::RemoteLayerBackingStore::bitmap):
+ Keep a front and back buffer; return the front buffer when being asked for the bitmap.
+ Keep a Region of repaint areas.
+
+ * WebProcess/WebPage/mac/RemoteLayerBackingStore.mm:
+ (RemoteLayerBackingStore::RemoteLayerBackingStore):
+ (RemoteLayerBackingStore::encode):
+ (RemoteLayerBackingStore::decode):
+ Serialize only the front buffer, since the UI process only needs that.
+
+ (RemoteLayerBackingStore::setNeedsDisplay):
+ Store repaint rects instead of always setting the whole layer to be dirty.
+
+ (RemoteLayerBackingStore::display):
+ Paint into the back buffer (copying valid parts over from the front buffer),
+ then swap it to the front buffer. Use drawLayerContents so we get repaint counters, etc.
+
2013-10-18 Anders Carlsson <[email protected]>
Try to fix the Lion build.
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp (157657 => 157658)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp 2013-10-19 00:51:07 UTC (rev 157658)
@@ -101,11 +101,10 @@
void PlatformCALayerRemote::ensureBackingStore()
{
if (m_properties.backingStore.layer() == this
- && m_properties.backingStore.size() == m_properties.size
- && m_properties.backingStore.isOpaque() == m_properties.opaque)
+ && m_properties.backingStore.size() == m_properties.size)
return;
- m_properties.backingStore = RemoteLayerBackingStore(this, expandedIntSize(m_properties.size), m_properties.opaque);
+ m_properties.backingStore = RemoteLayerBackingStore(this, expandedIntSize(m_properties.size));
}
void PlatformCALayerRemote::setNeedsDisplay(const FloatRect* dirtyRect)
@@ -218,6 +217,8 @@
{
m_properties.size = value.size();
m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::SizeChanged);
+
+ ensureBackingStore();
}
FloatPoint3D PlatformCALayerRemote::position() const
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerBackingStore.h (157657 => 157658)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerBackingStore.h 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerBackingStore.h 2013-10-19 00:51:07 UTC (rev 157658)
@@ -29,7 +29,8 @@
#if USE(ACCELERATED_COMPOSITING)
#include "ShareableBitmap.h"
-#include <WebCore/IntRect.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/Region.h>
namespace WebKit {
@@ -38,16 +39,15 @@
class RemoteLayerBackingStore {
public:
RemoteLayerBackingStore();
- RemoteLayerBackingStore(PlatformCALayerRemote*, WebCore::IntSize, bool isOpaque);
+ RemoteLayerBackingStore(PlatformCALayerRemote*, WebCore::IntSize);
void setNeedsDisplay(WebCore::IntRect);
void setNeedsDisplay();
bool display();
- ShareableBitmap* bitmap() const { return m_bitmap.get(); }
+ ShareableBitmap* bitmap() const { return m_frontBuffer.get(); }
WebCore::IntSize size() const { return m_size; }
- bool isOpaque() const { return m_isOpaque; }
PlatformCALayerRemote* layer() const { return m_layer; }
@@ -58,11 +58,11 @@
PlatformCALayerRemote* m_layer;
WebCore::IntSize m_size;
- bool m_isOpaque;
- bool m_needsFullRepaint;
+ WebCore::Region m_dirtyRegion;
- RefPtr<ShareableBitmap> m_bitmap;
+ RefPtr<ShareableBitmap> m_frontBuffer;
+ RefPtr<ShareableBitmap> m_backBuffer;
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerBackingStore.mm (157657 => 157658)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerBackingStore.mm 2013-10-19 00:46:12 UTC (rev 157657)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerBackingStore.mm 2013-10-19 00:51:07 UTC (rev 157658)
@@ -32,15 +32,14 @@
#import "ArgumentCoders.h"
#import "ShareableBitmap.h"
#import "WebCoreArgumentCoders.h"
+#import <WebCore/WebLayer.h>
using namespace WebCore;
using namespace WebKit;
-RemoteLayerBackingStore::RemoteLayerBackingStore(PlatformCALayerRemote* layer, IntSize size, bool isOpaque)
+RemoteLayerBackingStore::RemoteLayerBackingStore(PlatformCALayerRemote* layer, IntSize size)
: m_layer(layer)
, m_size(size)
- , m_isOpaque(isOpaque)
- , m_needsFullRepaint(true)
{
ASSERT(layer);
}
@@ -53,7 +52,7 @@
void RemoteLayerBackingStore::encode(CoreIPC::ArgumentEncoder& encoder) const
{
ShareableBitmap::Handle handle;
- m_bitmap->createHandle(handle);
+ m_frontBuffer->createHandle(handle);
encoder << handle;
encoder << m_size;
@@ -64,7 +63,7 @@
ShareableBitmap::Handle handle;
if (!decoder.decode(handle))
return false;
- result.m_bitmap = ShareableBitmap::create(handle);
+ result.m_frontBuffer = ShareableBitmap::create(handle);
if (!decoder.decode(result.m_size))
return false;
@@ -74,13 +73,12 @@
void RemoteLayerBackingStore::setNeedsDisplay(IntRect rect)
{
- // FIXME: Only repaint dirty regions.
- setNeedsDisplay();
+ m_dirtyRegion.unite(rect);
}
void RemoteLayerBackingStore::setNeedsDisplay()
{
- m_needsFullRepaint = true;
+ setNeedsDisplay(IntRect(IntPoint(), m_size));
}
bool RemoteLayerBackingStore::display()
@@ -88,28 +86,56 @@
if (!m_layer)
return false;
- if (!m_layer->owner()->platformCALayerDrawsContent()) {
- // If we previously were drawsContent=YES, and now are not, we need
- // to note that our backing store has changed (by being cleared).
- if (m_bitmap) {
- m_bitmap = nullptr;
- return true;
- }
+ // If we previously were drawsContent=YES, and now are not, we need
+ // to note that our backing store has been cleared.
+ if (!m_layer->owner()->platformCALayerDrawsContent())
+ return m_frontBuffer;
+
+ if (m_dirtyRegion.isEmpty())
return false;
+
+ m_backBuffer = ShareableBitmap::createShareable(m_size, ShareableBitmap::SupportsAlpha);
+ if (!m_frontBuffer)
+ m_dirtyRegion.unite(IntRect(IntPoint(), m_size));
+
+ IntRect layerBounds(IntPoint(), m_size);
+
+ if (m_layer->owner()->platformCALayerShowRepaintCounter(m_layer)) {
+ IntRect indicatorRect = IntRect(0, 0, 52, 27);
+ if (m_layer->owner()->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp)
+ indicatorRect.setY(layerBounds.height() - indicatorRect.y() - indicatorRect.height());
+
+ m_dirtyRegion.unite(indicatorRect);
}
- if (m_bitmap && !m_needsFullRepaint)
- return false;
+ std::unique_ptr<GraphicsContext> context = m_backBuffer->createGraphicsContext();
- if (!m_bitmap) {
- m_bitmap = ShareableBitmap::createShareable(m_size, m_isOpaque ? ShareableBitmap::NoFlags : ShareableBitmap::SupportsAlpha);
- m_needsFullRepaint = true;
+ Vector<IntRect> dirtyRects = m_dirtyRegion.rects();
+
+ // If we have less than webLayerMaxRectsToPaint rects to paint and they cover less
+ // than webLayerWastedSpaceThreshold of the area, we'll do a partial repaint.
+ Vector<FloatRect, webLayerMaxRectsToPaint> rectsToPaint;
+ if (dirtyRects.size() <= webLayerMaxRectsToPaint && m_dirtyRegion.totalArea() <= webLayerWastedSpaceThreshold * layerBounds.width() * layerBounds.height()) {
+ // Copy over the parts of the front buffer that we're not going to repaint.
+ if (m_frontBuffer) {
+ Region cleanRegion(layerBounds);
+ cleanRegion.subtract(m_dirtyRegion);
+
+ RetainPtr<CGImageRef> frontImage = m_frontBuffer->makeCGImage();
+
+ for (const auto& rect : cleanRegion.rects())
+ context->drawNativeImage(frontImage.get(), m_frontBuffer->size(), ColorSpaceDeviceRGB, rect, rect);
+ }
+
+ for (const auto& rect : dirtyRects)
+ rectsToPaint.append(rect);
}
- std::unique_ptr<GraphicsContext> context = m_bitmap->createGraphicsContext();
- m_layer->owner()->platformCALayerPaintContents(*context.get(), IntRect(IntPoint(), m_size));
+ drawLayerContents(context->platformContext(), m_layer, layerBounds, rectsToPaint, false);
+ m_dirtyRegion = Region();
- m_needsFullRepaint = false;
+ m_frontBuffer = m_backBuffer;
+ m_backBuffer = nullptr;
return true;
}