Title: [152550] branches/safari-537-branch/Source/WebCore
- Revision
- 152550
- Author
- [email protected]
- Date
- 2013-07-10 14:37:37 -0700 (Wed, 10 Jul 2013)
Log Message
Merged r152548. <rdar://problem/14286329>
Modified Paths
Diff
Modified: branches/safari-537-branch/Source/WebCore/ChangeLog (152549 => 152550)
--- branches/safari-537-branch/Source/WebCore/ChangeLog 2013-07-10 21:34:47 UTC (rev 152549)
+++ branches/safari-537-branch/Source/WebCore/ChangeLog 2013-07-10 21:37:37 UTC (rev 152550)
@@ -1,5 +1,49 @@
2013-07-10 Lucas Forschler <[email protected]>
+ Merge r152548
+
+ 2013-07-10 Tim Horton <[email protected]>
+
+ Deferring layer flushes can cause painting without layout being done
+ https://bugs.webkit.org/show_bug.cgi?id=118493
+
+ Reviewed by Simon Fraser.
+
+ r147797 added a mechanism for the TileController to inform RenderLayerCompositor
+ that it had performed an action (setNeedsDisplay, etc.) that would cause CoreAnimation
+ to call back into us to paint in this runloop, and that it shouldn't throttle the next
+ layer flush.
+
+ However, if tiles were created and left unparented (because the TileController was
+ out-of-window), when they are later parented, we failed to inform RenderLayerCompositor
+ that they were about to call back for painting, and so it would happily throttle the
+ next layer flush, and layout would be out of date, and garbage and corruption could result.
+
+ To resolve this, rework the logic surrounding parenting existing-but-unparented tiles
+ to ensure that they get added to the TileController's dirtyRect.
+
+ No new tests; the bug only reproduces under specific timing circumstances, and
+ manifests itself as an assertion failure or garbage on the screen, so it's quite
+ hard to make a workable test.
+
+ * platform/graphics/ca/mac/TileController.mm:
+ (WebCore::TileController::revalidateTiles):
+ - Factor out the code to parent unparented tiles so that it is shared between the
+ created-new-tile and reparenting-existing-tile cases.
+ - Keep track of whether we updated the frame of a pre-existing tile.
+ - If the tile is dirty and needed to be parented (because either it's new
+ or hadn't been parented before), add it to the dirty rect list.
+ - If the tile changed size, add it to the dirty rect list.
+
+ (WebCore::TileController::ensureTilesForRect):
+ Ditto everything from revalidateTiles.
+
+ (WebCore::TileController::createTileLayer):
+ - Explicitly mark fresh tiles as needing display, so that we can depend on
+ [WebTileLayer needsDisplay] in revalidateTiles to tell us that it's dirty.
+
+2013-07-10 Lucas Forschler <[email protected]>
+
Merge r152541
2013-07-09 Roger Fong <[email protected]>
Modified: branches/safari-537-branch/Source/WebCore/platform/graphics/ca/mac/TileController.mm (152549 => 152550)
--- branches/safari-537-branch/Source/WebCore/platform/graphics/ca/mac/TileController.mm 2013-07-10 21:34:47 UTC (rev 152549)
+++ branches/safari-537-branch/Source/WebCore/platform/graphics/ca/mac/TileController.mm 2013-07-10 21:37:37 UTC (rev 152550)
@@ -686,26 +686,30 @@
IntRect tileRect = rectForTileIndex(tileIndex);
m_primaryTileCoverageRect.unite(tileRect);
+ bool shouldChangeTileLayerFrame = false;
+
TileInfo& tileInfo = m_tiles.add(tileIndex, TileInfo()).iterator->value;
- if (!tileInfo.layer) {
+ if (!tileInfo.layer)
tileInfo.layer = createTileLayer(tileRect);
- if (!m_unparentsOffscreenTiles || m_isInWindow)
- [m_tileContainerLayer.get() addSublayer:tileInfo.layer.get()];
- } else {
- if ((!m_unparentsOffscreenTiles || m_isInWindow) && ![tileInfo.layer.get() superlayer])
- [m_tileContainerLayer.get() addSublayer:tileInfo.layer.get()];
-
+ else {
// We already have a layer for this tile. Ensure that its size is correct.
FloatSize tileLayerSize([tileInfo.layer.get() frame].size);
- if (tileLayerSize == FloatSize(tileRect.size()))
- continue;
+ shouldChangeTileLayerFrame = tileLayerSize != FloatSize(tileRect.size());
- [tileInfo.layer.get() setFrame:tileRect];
+ if (shouldChangeTileLayerFrame)
+ [tileInfo.layer.get() setFrame:tileRect];
}
-
- FloatRect scaledTileRect = tileRect;
- scaledTileRect.scale(1 / m_scale);
- dirtyRects.append(scaledTileRect);
+
+ bool shouldParentTileLayer = (!m_unparentsOffscreenTiles || m_isInWindow) && ![tileInfo.layer.get() superlayer];
+
+ if (shouldParentTileLayer)
+ [m_tileContainerLayer.get() addSublayer:tileInfo.layer.get()];
+
+ if ((shouldParentTileLayer && [tileInfo.layer.get() needsDisplay]) || shouldChangeTileLayerFrame) {
+ FloatRect scaledTileRect = tileRect;
+ scaledTileRect.scale(1 / m_scale);
+ dirtyRects.append(scaledTileRect);
+ }
}
}
@@ -752,6 +756,8 @@
if (dirtyRects.isEmpty())
return;
+
+ // This will ensure we flush compositing state and do layout in this run loop iteration.
platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects);
}
@@ -836,18 +842,18 @@
IntRect tileRect = rectForTileIndex(tileIndex);
TileInfo& tileInfo = m_tiles.add(tileIndex, TileInfo()).iterator->value;
- if (!tileInfo.layer) {
+
+ bool shouldChangeTileLayerFrame = false;
+
+ if (!tileInfo.layer)
tileInfo.layer = createTileLayer(tileRect);
- [m_tileContainerLayer.get() addSublayer:tileInfo.layer.get()];
- } else {
- if (![tileInfo.layer.get() superlayer])
- [m_tileContainerLayer.get() addSublayer:tileInfo.layer.get()];
-
+ else {
// We already have a layer for this tile. Ensure that its size is correct.
CGSize tileLayerSize = [tileInfo.layer.get() frame].size;
- if (tileLayerSize.width >= tileRect.width() && tileLayerSize.height >= tileRect.height())
- continue;
- [tileInfo.layer.get() setFrame:tileRect];
+ shouldChangeTileLayerFrame = tileLayerSize.width < tileRect.width() || tileLayerSize.height < tileRect.height();
+
+ if (shouldChangeTileLayerFrame)
+ [tileInfo.layer.get() setFrame:tileRect];
}
if (!tileRect.intersects(m_primaryTileCoverageRect)) {
@@ -855,9 +861,16 @@
++tilesInCohort;
}
- FloatRect scaledTileRect = tileRect;
- scaledTileRect.scale(1 / m_scale);
- dirtyRects.append(scaledTileRect);
+ bool shouldParentTileLayer = ![tileInfo.layer.get() superlayer];
+
+ if (shouldParentTileLayer)
+ [m_tileContainerLayer.get() addSublayer:tileInfo.layer.get()];
+
+ if ((shouldParentTileLayer && [tileInfo.layer.get() needsDisplay]) || shouldChangeTileLayerFrame) {
+ FloatRect scaledTileRect = tileRect;
+ scaledTileRect.scale(1 / m_scale);
+ dirtyRects.append(scaledTileRect);
+ }
}
}
@@ -867,6 +880,7 @@
if (m_tiledScrollingIndicatorLayer)
updateTileCoverageMap();
+ // This will ensure we flush compositing state and do layout in this run loop iteration.
if (!dirtyRects.isEmpty())
platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects);
}
@@ -993,12 +1007,9 @@
RetainPtr<WebTileLayer> TileController::createTileLayer(const IntRect& tileRect)
{
RetainPtr<WebTileLayer> layer = LayerPool::sharedPool()->takeLayerWithSize(tileRect.size());
- if (layer) {
- // If we were able to restore a layer from the LayerPool, we should call setNeedsDisplay to
- // ensure we avoid stale content.
+ if (layer)
[layer resetPaintCount];
- [layer setNeedsDisplay];
- } else
+ else
layer = adoptNS([[WebTileLayer alloc] init]);
[layer.get() setAnchorPoint:CGPointZero];
[layer.get() setFrame:tileRect];
@@ -1016,6 +1027,8 @@
[layer.get() setAcceleratesDrawing:m_acceleratesDrawing];
#endif
+ [layer setNeedsDisplay];
+
return layer;
}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes