Title: [109843] trunk/Source
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)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to