- Revision
- 109843
- Author
- [email protected]
- Date
- 2012-03-05 20:33:16 -0800 (Mon, 05 Mar 2012)
Log Message
pinch-to-zoom and double-tap flicker when using the new scrolling model
https://bugs.webkit.org/show_bug.cgi?id=80368
<rdar://problem/10866221>
Reviewed by Sam Weinig.
Source/WebCore:
In order to work better with zooming, make the tile cache undo the scale transformation
and handle the scaling manually. This avoids creating huge tile backing stores when zoomed in.
* platform/graphics/ca/mac/TileCache.mm:
(WebCore::TileCache::TileCache):
Initialize m_scale to 1.
(WebCore::TileCache::setNeedsDisplayInRect):
Scale the given rect appropriately.
(WebCore::TileCache::drawLayer):
Apply a scale context transform.
(WebCore::TileCache::setScale):
No longer set the contents scale. Instead, update the scale and revalidate the tiles.
(WebCore::TileCache::revalidateTiles):
Return early if the bounds are empty. This avoids showing a single tile if that happens due to a race condition.
(WebCore::TileCache::getTileIndexRangeForRect):
Apply the scale to the bounds.
(WebCore::TileCache::createTileLayer):
Don't set the contents scale.
* platform/graphics/ca/mac/WebTileCacheLayer.mm:
(-[WebTileCacheLayer setContentsScale:]):
Call TileCache::setScale.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateCompositedBounds):
Make sure to give the tile cache layer sane composited bounds, even if the page has absolutely positioned
elements that are outside of the page.
Source/WebKit2:
Add a way for drawing areas to respond to callback based force repaint requests asynchronously.
This is currently needed for the tiled drawing area when there might be outstanding scroll updates
that are sent from the scrolling thread to the main thread and we need to ensure that they're processed
before sending a message back.
* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::forceRepaintAsync):
Add new member function.
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::forceRepaint):
Try forceRepaintAsync first.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::forceRepaintAndSendMessage):
Force the repaint and send the message.
(WebKit::dispatchBackToMainThread):
Dispatch a call to forceRepaintAndSendMessage to the main thread.
(WebKit::TiledCoreAnimationDrawingArea::forceRepaintAsync):
Dispatch a function on the scrolling thread. Its sole purpose is to dispatch a function back to the
main thread, ensuring that all previously dispatched functions have been executed.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (109842 => 109843)
--- trunk/Source/WebCore/ChangeLog 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebCore/ChangeLog 2012-03-06 04:33:16 UTC (rev 109843)
@@ -1,3 +1,45 @@
+2012-03-05 Anders Carlsson <[email protected]>
+
+ pinch-to-zoom and double-tap flicker when using the new scrolling model
+ https://bugs.webkit.org/show_bug.cgi?id=80368
+ <rdar://problem/10866221>
+
+ Reviewed by Sam Weinig.
+
+ In order to work better with zooming, make the tile cache undo the scale transformation
+ and handle the scaling manually. This avoids creating huge tile backing stores when zoomed in.
+
+ * platform/graphics/ca/mac/TileCache.mm:
+ (WebCore::TileCache::TileCache):
+ Initialize m_scale to 1.
+
+ (WebCore::TileCache::setNeedsDisplayInRect):
+ Scale the given rect appropriately.
+
+ (WebCore::TileCache::drawLayer):
+ Apply a scale context transform.
+
+ (WebCore::TileCache::setScale):
+ No longer set the contents scale. Instead, update the scale and revalidate the tiles.
+
+ (WebCore::TileCache::revalidateTiles):
+ Return early if the bounds are empty. This avoids showing a single tile if that happens due to a race condition.
+
+ (WebCore::TileCache::getTileIndexRangeForRect):
+ Apply the scale to the bounds.
+
+ (WebCore::TileCache::createTileLayer):
+ Don't set the contents scale.
+
+ * platform/graphics/ca/mac/WebTileCacheLayer.mm:
+ (-[WebTileCacheLayer setContentsScale:]):
+ Call TileCache::setScale.
+
+ * rendering/RenderLayerBacking.cpp:
+ (WebCore::RenderLayerBacking::updateCompositedBounds):
+ Make sure to give the tile cache layer sane composited bounds, even if the page has absolutely positioned
+ elements that are outside of the page.
+
2012-03-05 Leo Yang <[email protected]>
GraphicsContext3D.h should include RefCounted.h explicitly
Modified: trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.h (109842 => 109843)
--- trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.h 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.h 2012-03-06 04:33:16 UTC (rev 109843)
@@ -56,8 +56,9 @@
void setNeedsDisplay();
void setNeedsDisplayInRect(const IntRect&);
void drawLayer(WebTileLayer*, CGContextRef);
- void setContentsScale(CGFloat);
+ void setScale(CGFloat);
+
bool acceleratesDrawing() const { return m_acceleratesDrawing; }
void setAcceleratesDrawing(bool);
@@ -99,6 +100,8 @@
Timer<TileCache> m_tileRevalidationTimer;
IntRect m_tileCoverageRect;
+ CGFloat m_scale;
+
bool m_acceleratesDrawing;
RetainPtr<CGColorRef> m_tileDebugBorderColor;
Modified: trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm (109842 => 109843)
--- trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm 2012-03-06 04:33:16 UTC (rev 109843)
@@ -54,6 +54,7 @@
, m_tileContainerLayer(adoptCF([[CALayer alloc] init]))
, m_tileSize(tileSize)
, m_tileRevalidationTimer(this, &TileCache::tileRevalidationTimerFired)
+ , m_scale(1)
, m_acceleratesDrawing(false)
, m_tileDebugBorderWidth(0)
{
@@ -90,10 +91,13 @@
if (m_tiles.isEmpty())
return;
+ IntRect scaledRect = rect;
+ scaledRect.scale(m_scale);
+
// Find the tiles that need to be invalidated.
TileIndex topLeft;
TileIndex bottomRight;
- getTileIndexRangeForRect(intersection(rect, m_tileCoverageRect), topLeft, bottomRight);
+ getTileIndexRangeForRect(intersection(scaledRect, m_tileCoverageRect), topLeft, bottomRight);
for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
@@ -126,6 +130,7 @@
CGPoint layerOrigin = [layer frame].origin;
CGContextTranslateCTM(context, -layerOrigin.x, -layerOrigin.y);
+ CGContextScaleCTM(context, m_scale, m_scale);
drawLayerContents(context, layer, platformLayer);
CGContextRestoreGState(context);
@@ -162,17 +167,22 @@
CGContextRestoreGState(context);
}
-void TileCache::setContentsScale(CGFloat contentsScale)
+void TileCache::setScale(CGFloat scale)
{
+ if (m_scale == scale)
+ return;
+
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
- for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
- [it->second.get() setContentsScale:contentsScale];
+ m_scale = scale;
+ [m_tileContainerLayer.get() setTransform:CATransform3DMakeScale(1 / m_scale, 1 / m_scale, 1)];
+
+ revalidateTiles();
+
+ for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
[it->second.get() setNeedsDisplay];
- }
PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
platformLayer->owner()->platformCALayerDidCreateTiles();
- revalidateTiles();
#else
UNUSED_PARAM(contentsScale);
#endif
@@ -234,7 +244,9 @@
void TileCache::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft, TileIndex& bottomRight)
{
- IntRect clampedRect = intersection(rect, bounds());
+ IntRect clampedRect = bounds();
+ clampedRect.scale(m_scale);
+ clampedRect.intersect(rect);
topLeft.setX(max(clampedRect.x() / m_tileSize.width(), 0));
topLeft.setY(max(clampedRect.y() / m_tileSize.height(), 0));
@@ -263,7 +275,7 @@
if (!platformLayer)
return;
- if (m_visibleRect.isEmpty())
+ if (m_visibleRect.isEmpty() || bounds().isEmpty())
return;
IntRect tileCoverageRect = m_visibleRect;
@@ -351,7 +363,6 @@
[layer.get() setEdgeAntialiasingMask:0];
#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
- [layer.get() setContentsScale:[m_tileCacheLayer contentsScale]];
[layer.get() setAcceleratesDrawing:m_acceleratesDrawing];
#endif
Modified: trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm (109842 => 109843)
--- trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm 2012-03-06 04:33:16 UTC (rev 109843)
@@ -103,16 +103,7 @@
- (void)setContentsScale:(CGFloat)contentsScale
{
-#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
- CGFloat oldContentsScale = [self contentsScale];
-
- [super setContentsScale:contentsScale];
-
- if (contentsScale != oldContentsScale)
- _tileCache->setContentsScale(contentsScale);
-#else
- UNUSED_PARAM(contentsScale);
-#endif
+ _tileCache->setScale(contentsScale);
}
- (CALayer *)tileContainerLayer
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (109842 => 109843)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2012-03-06 04:33:16 UTC (rev 109843)
@@ -236,7 +236,7 @@
// We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist. If this
// is a fullscreen renderer, don't clip to the viewport, as the renderer will be asked to
// display outside of the viewport bounds.
- if (compositor()->compositingConsultsOverlap() && !layerOrAncestorIsTransformed(m_owningLayer)
+ if (compositor()->compositingConsultsOverlap() && (!layerOrAncestorIsTransformed(m_owningLayer) || m_usingTiledCacheLayer)
#if ENABLE(FULLSCREEN_API)
&& !layerOrAncestorIsFullScreen(m_owningLayer)
#endif
Modified: trunk/Source/WebKit2/ChangeLog (109842 => 109843)
--- trunk/Source/WebKit2/ChangeLog 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebKit2/ChangeLog 2012-03-06 04:33:16 UTC (rev 109843)
@@ -1,3 +1,35 @@
+2012-03-05 Anders Carlsson <[email protected]>
+
+ pinch-to-zoom and double-tap flicker when using the new scrolling model
+ https://bugs.webkit.org/show_bug.cgi?id=80368
+ <rdar://problem/10866221>
+
+ Reviewed by Sam Weinig.
+
+ Add a way for drawing areas to respond to callback based force repaint requests asynchronously.
+ This is currently needed for the tiled drawing area when there might be outstanding scroll updates
+ that are sent from the scrolling thread to the main thread and we need to ensure that they're processed
+ before sending a message back.
+
+ * WebProcess/WebPage/DrawingArea.h:
+ (WebKit::DrawingArea::forceRepaintAsync):
+ Add new member function.
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::forceRepaint):
+ Try forceRepaintAsync first.
+
+ * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+ (WebKit::forceRepaintAndSendMessage):
+ Force the repaint and send the message.
+
+ (WebKit::dispatchBackToMainThread):
+ Dispatch a call to forceRepaintAndSendMessage to the main thread.
+
+ (WebKit::TiledCoreAnimationDrawingArea::forceRepaintAsync):
+ Dispatch a function on the scrolling thread. Its sole purpose is to dispatch a function back to the
+ main thread, ensuring that all previously dispatched functions have been executed.
+
2012-03-05 Enrica Casucci <[email protected]>
Can't type on some websites (plug-ins steal key events).
Modified: trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h (109842 => 109843)
--- trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebKit2/WebProcess/WebPage/DrawingArea.h 2012-03-06 04:33:16 UTC (rev 109843)
@@ -66,6 +66,7 @@
// FIXME: These should be pure virtual.
virtual void pageBackgroundTransparencyChanged() { }
virtual void forceRepaint() { }
+ virtual bool forceRepaintAsync(uint64_t callbackID) { return false; }
virtual void setLayerTreeStateIsFrozen(bool) { }
virtual bool layerTreeStateIsFrozen() const { return false; }
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (109842 => 109843)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2012-03-06 04:33:16 UTC (rev 109843)
@@ -1821,6 +1821,9 @@
void WebPage::forceRepaint(uint64_t callbackID)
{
+ if (m_drawingArea->forceRepaintAsync(callbackID))
+ return;
+
forceRepaintWithoutCallback();
send(Messages::WebPageProxy::VoidCallback(callbackID));
}
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h (109842 => 109843)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h 2012-03-06 04:33:16 UTC (rev 109843)
@@ -53,6 +53,7 @@
virtual void scroll(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) OVERRIDE;
virtual void forceRepaint() OVERRIDE;
+ virtual bool forceRepaintAsync(uint64_t callbackID) OVERRIDE;
virtual void setLayerTreeStateIsFrozen(bool) OVERRIDE;
virtual bool layerTreeStateIsFrozen() const OVERRIDE;
virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) OVERRIDE;
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm (109842 => 109843)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm 2012-03-06 04:32:25 UTC (rev 109842)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm 2012-03-06 04:33:16 UTC (rev 109843)
@@ -31,6 +31,7 @@
#import "LayerHostingContext.h"
#import "LayerTreeContext.h"
#import "WebPage.h"
+#import "WebPageProxyMessages.h"
#import "WebProcess.h"
#import <QuartzCore/QuartzCore.h>
#import <WebCore/Frame.h>
@@ -40,7 +41,9 @@
#import <WebCore/RenderLayerCompositor.h>
#import <WebCore/RenderView.h>
#import <WebCore/ScrollingCoordinator.h>
+#import <WebCore/ScrollingThread.h>
#import <WebCore/Settings.h>
+#import <wtf/MainThread.h>
@interface CATransaction (Details)
+ (void)synchronize;
@@ -125,6 +128,36 @@
[CATransaction synchronize];
}
+#if ENABLE(THREADED_SCROLLING)
+static void forceRepaintAndSendMessage(uint64_t webPageID, uint64_t callbackID)
+{
+ WebPage* webPage = WebProcess::shared().webPage(webPageID);
+ if (!webPage)
+ return;
+
+ webPage->drawingArea()->forceRepaint();
+ webPage->send(Messages::WebPageProxy::VoidCallback(callbackID));
+}
+
+static void dispatchBackToMainThread(uint64_t webPageID, uint64_t callbackID)
+{
+ callOnMainThread(bind(forceRepaintAndSendMessage, webPageID, callbackID));
+}
+#endif
+
+bool TiledCoreAnimationDrawingArea::forceRepaintAsync(uint64_t callbackID)
+{
+#if ENABLE(THREADED_SCROLLING)
+ if (m_layerTreeStateIsFrozen)
+ return false;
+
+ ScrollingThread::dispatch(bind(dispatchBackToMainThread, m_webPage->pageID(), callbackID));
+ return true;
+#else
+ return false;
+#endif
+}
+
void TiledCoreAnimationDrawingArea::setLayerTreeStateIsFrozen(bool layerTreeStateIsFrozen)
{
if (m_layerTreeStateIsFrozen == layerTreeStateIsFrozen)