Diff
Modified: trunk/LayoutTests/ChangeLog (218734 => 218735)
--- trunk/LayoutTests/ChangeLog 2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/LayoutTests/ChangeLog 2017-06-23 04:34:14 UTC (rev 218735)
@@ -1,3 +1,13 @@
+2017-06-22 Antti Koivisto <[email protected]>
+
+ REGRESSION(r217695): Offscreen/overflowed items not being rendered while translating in-frame
+ https://bugs.webkit.org/show_bug.cgi?id=173732
+
+ Reviewed by Simon Fraser.
+
+ * compositing/backing/transform-transition-from-outside-view-expected.txt: Added.
+ * compositing/backing/transform-transition-from-outside-view.html: Added.
+
2017-06-22 Myles C. Maxfield <[email protected]>
@font-face rules with invalid primary fonts never download their secondary fonts
Added: trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view-expected.txt (0 => 218735)
--- trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view-expected.txt (rev 0)
+++ trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view-expected.txt 2017-06-23 04:34:14 UTC (rev 218735)
@@ -0,0 +1,28 @@
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (backingStoreAttached 1)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (backingStoreAttached 1)
+ (children 1
+ (GraphicsLayer
+ (position 94.00 86.00)
+ (bounds 148.00 128.00)
+ (drawsContent 1)
+ (backingStoreAttached 1)
+ (children 1
+ (GraphicsLayer
+ (bounds 48.00 48.00)
+ (drawsContent 1)
+ (backingStoreAttached 1)
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view.html (0 => 218735)
--- trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view.html (rev 0)
+++ trunk/LayoutTests/compositing/backing/transform-transition-from-outside-view.html 2017-06-23 04:34:14 UTC (rev 218735)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <style>
+ .box {
+ width: 120px;
+ height: 100px;
+ background-color: blue;
+ margin: 100px 100px;
+ position: relative;
+ box-shadow: 0 0 10px black;
+ transition: transform 5s;
+ transform: translateX(-400px);
+ }
+
+ .sublayer {
+ width: 20px;
+ height: 20px;
+ background-color: green;
+ position: relative;
+ box-shadow: 0 0 10px black;
+ will-change: transform;
+ }
+
+ body.changed .box {
+ transform: translateX(0px);
+ }
+ </style>
+ <script>
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ function dumpLayers()
+ {
+ if (window.testRunner) {
+ output.innerText = window.internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED);
+ testRunner.notifyDone();
+ }
+ }
+
+ window.addEventListener("load", function() {
+ document.body.classList.add('changed');
+ window.setTimeout(dumpLayers, 0);
+ });
+ </script>
+</head>
+<body>
+
+ <div class="box">
+ <div class="sublayer"></div>
+ </div>
+<pre id="output"></pre>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (218734 => 218735)
--- trunk/Source/WebCore/ChangeLog 2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/ChangeLog 2017-06-23 04:34:14 UTC (rev 218735)
@@ -1,3 +1,46 @@
+2017-06-22 Antti Koivisto <[email protected]>
+
+ REGRESSION(r217695): Offscreen/overflowed items not being rendered while translating in-frame
+ https://bugs.webkit.org/show_bug.cgi?id=173732
+
+ Reviewed by Simon Fraser.
+
+ If an accelerated animation starts completely outside the view we fail to create backing for it
+ when it moves into view.
+
+ Fix by computing the full extent rect of the animation when it starts and doing the viewport overlap
+ testing with that.
+
+ Test: compositing/backing/transform-transition-from-outside-view.html
+
+ * platform/graphics/GraphicsLayer.h:
+ (WebCore::GraphicsLayer::animationExtent):
+ (WebCore::GraphicsLayer::setAnimationExtent):
+ * platform/graphics/ca/GraphicsLayerCA.cpp:
+ (WebCore::GraphicsLayerCA::computeVisibleAndCoverageRect):
+
+ Return the current animation transformation matrix so we can use it elsewhere without recomputing.
+
+ (WebCore::GraphicsLayerCA::setVisibleAndCoverageRects):
+
+ If we have animation extent use it instead of bounds for visibility testing.
+
+ (WebCore::GraphicsLayerCA::recursiveCommitChanges):
+
+ Track if theres is a visible ancestor layer with a transition animation.
+
+ (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
+ (WebCore::GraphicsLayerCA::updateCoverage):
+
+ For simplicity create backing for all sublayers of a visible transform animated layer.
+
+ * platform/graphics/ca/GraphicsLayerCA.h:
+ (WebCore::GraphicsLayerCA::VisibleAndCoverageRects::VisibleAndCoverageRects): Deleted.
+ * rendering/RenderLayerBacking.cpp:
+ (WebCore::RenderLayerBacking::updateGeometry):
+
+ Pass the animation extent (including descendants) to GraphicsLayer.
+
2017-06-22 Chris Dumez <[email protected]>
ResourceLoadStatisticsStore should be ThreadSafeRefCounted
Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (218734 => 218735)
--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h 2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h 2017-06-23 04:34:14 UTC (rev 218735)
@@ -571,6 +571,9 @@
virtual bool isGraphicsLayerTextureMapper() const { return false; }
virtual bool isCoordinatedGraphicsLayer() const { return false; }
+ const std::optional<FloatRect>& animationExtent() const { return m_animationExtent; }
+ void setAnimationExtent(std::optional<FloatRect> animationExtent) { m_animationExtent = animationExtent; }
+
static void traverse(GraphicsLayer&, const WTF::Function<void (GraphicsLayer&)>&);
protected:
@@ -676,6 +679,7 @@
FloatSize m_contentsTilePhase;
FloatSize m_contentsTileSize;
FloatRoundedRect m_backdropFiltersRect;
+ std::optional<FloatRect> m_animationExtent;
int m_repaintCount;
CustomAppearance m_customAppearance;
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (218734 => 218735)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2017-06-23 04:34:14 UTC (rev 218735)
@@ -1343,7 +1343,7 @@
FloatRect clipRectForSelf(boundsOrigin, m_size);
if (!applyWasClamped && !mapWasClamped)
clipRectForSelf.intersect(clipRectForChildren);
-
+
if (masksToBounds()) {
ASSERT(accumulation == TransformState::FlattenTransform);
// Flatten, and replace the quad in the TransformState with one that is clipped to this layer's bounds.
@@ -1360,7 +1360,7 @@
if (quad && !mapWasClamped && !applyWasClamped)
coverageRect = (*quad).boundingBox();
- return VisibleAndCoverageRects(clipRectForSelf, coverageRect);
+ return { clipRectForSelf, coverageRect, currentTransform };
}
bool GraphicsLayerCA::adjustCoverageRect(VisibleAndCoverageRects& rects, const FloatRect& oldVisibleRect) const
@@ -1392,11 +1392,17 @@
{
bool visibleRectChanged = rects.visibleRect != m_visibleRect;
bool coverageRectChanged = rects.coverageRect != m_coverageRect;
- if (!visibleRectChanged && !coverageRectChanged)
+ if (!visibleRectChanged && !coverageRectChanged && !animationExtent())
return;
+ auto bounds = FloatRect(m_boundsOrigin, size());
+ if (auto extent = animationExtent()) {
+ // Adjust the animation extent to match the current animation position.
+ bounds = rects.animatingTransform.inverse().value_or(TransformationMatrix()).mapRect(*extent);
+ }
+
// FIXME: we need to take reflections into account when determining whether this layer intersects the coverage rect.
- bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(FloatRect(m_boundsOrigin, size()));
+ bool intersectsCoverageRect = isViewportConstrained || rects.coverageRect.intersects(bounds);
if (intersectsCoverageRect != m_intersectsCoverageRect) {
addUncommittedChanges(CoverageRectChanged);
m_intersectsCoverageRect = intersectsCoverageRect;
@@ -1490,11 +1496,13 @@
FloatPoint baseRelativePosition = positionRelativeToBase;
if (affectedByPageScale)
baseRelativePosition += m_position;
-
+
commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition);
if (isRunningTransformAnimation()) {
childCommitState.ancestorHasTransformAnimation = true;
+ if (m_intersectsCoverageRect)
+ childCommitState.ancestorWithTransformAnimationIntersectsCoverageRect = true;
affectedByTransformAnimation = true;
}
@@ -1744,7 +1752,7 @@
updateContentsScale(pageScaleFactor);
if (m_uncommittedChanges & CoverageRectChanged)
- updateCoverage();
+ updateCoverage(commitState);
if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after CoverageRectChanged, ContentsScaleChanged
updateTiles();
@@ -2282,7 +2290,7 @@
}
}
-void GraphicsLayerCA::updateCoverage()
+void GraphicsLayerCA::updateCoverage(const CommitState& commitState)
{
// FIXME: Need to set coverage on clone layers too.
if (TiledBacking* backing = tiledBacking()) {
@@ -2291,10 +2299,14 @@
}
if (canDetachBackingStore()) {
- m_layer->setBackingStoreAttached(m_intersectsCoverageRect);
+ bool requiresBacking = m_intersectsCoverageRect
+ || commitState.ancestorWithTransformAnimationIntersectsCoverageRect // FIXME: Compute backing exactly for descendants of animating layers.
+ || (isRunningTransformAnimation() && !animationExtent()); // Create backing if we don't know the animation extent.
+
+ m_layer->setBackingStoreAttached(requiresBacking);
if (m_layerClones) {
for (auto& it : *m_layerClones)
- it.value->setBackingStoreAttached(m_intersectsCoverageRect);
+ it.value->setBackingStoreAttached(requiresBacking);
}
}
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (218734 => 218735)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2017-06-23 04:34:14 UTC (rev 218735)
@@ -157,6 +157,7 @@
int treeDepth { 0 };
bool ancestorHadChanges { false };
bool ancestorHasTransformAnimation { false };
+ bool ancestorWithTransformAnimationIntersectsCoverageRect { false };
bool ancestorIsViewportConstrained { false };
};
bool needsCommit(const CommitState&);
@@ -299,12 +300,7 @@
struct VisibleAndCoverageRects {
FloatRect visibleRect;
FloatRect coverageRect;
-
- VisibleAndCoverageRects(const FloatRect& visRect, const FloatRect& covRect)
- : visibleRect(visRect)
- , coverageRect(covRect)
- {
- }
+ TransformationMatrix animatingTransform;
};
VisibleAndCoverageRects computeVisibleAndCoverageRect(TransformState&, bool accumulateTransform, ComputeVisibleRectFlags = RespectAnimatingTransforms) const;
@@ -400,7 +396,7 @@
void updateBackfaceVisibility();
void updateStructuralLayer();
void updateDrawsContent();
- void updateCoverage();
+ void updateCoverage(const CommitState&);
void updateBackgroundColor();
void updateUserInteractionEnabled();
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (218734 => 218735)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2017-06-23 02:58:03 UTC (rev 218734)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2017-06-23 04:34:14 UTC (rev 218735)
@@ -945,13 +945,17 @@
return;
const RenderStyle& style = renderer().style();
+
+ bool isRunningAcceleratedTransformAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused);
+ bool isRunningAcceleratedOpacityAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused);
+
// Set transform property, if it is not animating. We have to do this here because the transform
// is affected by the layer dimensions.
- if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused))
+ if (!isRunningAcceleratedTransformAnimation)
updateTransform(style);
// Set opacity, if it is not animating.
- if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused))
+ if (!isRunningAcceleratedOpacityAnimation)
updateOpacity(style);
updateFilters(style);
@@ -978,6 +982,14 @@
m_graphicsLayer->setPosition(primaryGraphicsLayerRect.location());
m_graphicsLayer->setSize(primaryGraphicsLayerRect.size());
+ auto computeAnimationExtent = [&] () -> std::optional<FloatRect> {
+ LayoutRect animatedBounds;
+ if (isRunningAcceleratedTransformAnimation && m_owningLayer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(animatedBounds))
+ return FloatRect(animatedBounds);
+ return { };
+ };
+ m_graphicsLayer->setAnimationExtent(computeAnimationExtent());
+
ComputedOffsets rendererOffset(m_owningLayer, LayoutRect(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
if (m_ancestorClippingLayer) {
// Clipping layer is parented in the ancestor layer.