Changeset 288267 in webkit
- Timestamp:
- Jan 19, 2022 7:53:27 PM (6 months ago)
- Location:
- trunk
- Files:
-
- 6 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/rendering/RenderElement.cpp (modified) (5 diffs)
-
Source/WebCore/rendering/RenderElement.h (modified) (1 diff)
-
Source/WebCore/rendering/RenderLayer.cpp (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r288266 r288267 1 2022-01-19 Simon Fraser <simon.fraser@apple.com> 2 3 <dialog> with transformed ancestor asserts under RenderGeometryMap 4 https://bugs.webkit.org/show_bug.cgi?id=235194 5 6 Reviewed by Antti Koivisto. 7 8 * TestExpectations: imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/top-layer-parent-transform.html 9 no longer asserts. 10 1 11 2022-01-19 Devin Rousso <drousso@apple.com> 2 12 -
trunk/LayoutTests/TestExpectations
r288132 r288267 2369 2369 webkit.org/b/229315 imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-replaced-renderer.html [ ImageOnlyFailure ] 2370 2370 webkit.org/b/229315 imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/modal-dialog-in-table-column.html [ ImageOnlyFailure ] 2371 # Needs layer re-parenting2372 webkit.org/b/234980 [ Debug ] imported/w3c/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/top-layer-parent-transform.html [ Crash ]2373 2371 2374 2372 # Assertion failure in MessagePort::contextDestroyed, usually attributed to later tests -
trunk/Source/WebCore/ChangeLog
r288264 r288267 1 2022-01-19 Simon Fraser <simon.fraser@apple.com> 2 3 <dialog> with transformed ancestor asserts under RenderGeometryMap 4 https://bugs.webkit.org/show_bug.cgi?id=235194 5 6 Reviewed by Antti Koivisto. 7 8 With this change we reparent the RenderLayers of top layer elements under the RenderView's 9 layer. This makes the RenderLayer hierarchy a closer match to the containing block 10 hierarchy, and means that all the existing RenderLayer tree walks that use 11 parent()/firstChild()/nextSibling() traverse the the "top layer" layers as children of the 12 RenderView. This in turn means that the various bits of RenderLayer state that track the 13 state of descendants (e.g. m_hasVisibleDescendant, m_hasSelfPaintingLayerDescendant, 14 m_hasNotIsolatedBlendingDescendants) reflect descendency in the top-layer-aware hierarchy. 15 16 Note that m_hasVisibleDescendant is about the inherited `visibility` property which follows 17 DOM order, but since we consult it during painting-related tree walks, we want this state to 18 reflect the top-layer-aware tree. 19 20 The patch adds top-layer-aware helpers on RenderElement to find the parent and next sibling, 21 and uses those when parenting layers. 22 23 In addition, when the top layer status changes for a RenderLayer, we unparent and 24 re-parent its layer (which in turn should toggle the relevant dirty bits). 25 26 * rendering/RenderElement.cpp: 27 (WebCore::findNextLayer): 28 (WebCore::layerNextSiblingRespectingTopLayer): 29 (WebCore::addLayers): 30 (WebCore::RenderElement::layerParentRespectingTopLayer const): 31 (WebCore::RenderElement::layerNextSiblingRespectingTopLayer const): 32 (WebCore::RenderElement::insertedIntoTree): 33 (WebCore::RenderElement::willBeRemovedFromTree): 34 (WebCore::RenderElement::findNextLayer const): Deleted. 35 * rendering/RenderElement.h: 36 * rendering/RenderLayer.cpp: 37 (WebCore::RenderLayer::insertOnlyThisLayer): 38 (WebCore::RenderLayer::stackingContext const): No need for the explicit establishesTopLayer() check. 39 (WebCore::RenderLayer::setHasVisibleContent): 40 (WebCore::RenderLayer::dirtyAncestorChainVisibleDescendantStatus): 41 (WebCore::RenderLayer::setAncestorChainHasVisibleDescendant): 42 (WebCore::RenderLayer::enclosingAncestorForPosition const): No need for the explicit establishesTopLayer() check. 43 (WebCore::RenderLayer::paintLayerWithEffects): Ditto 44 (WebCore::RenderLayer::establishesTopLayerWillChange): 45 (WebCore::RenderLayer::establishesTopLayerDidChange): 46 (WebCore::RenderLayer::clipCrossesPaintingBoundary const): No need for the explicit establishesTopLayer() check. 47 (WebCore::RenderLayer::calculateClipRects const): Ditto 48 1 49 2022-01-19 Chris Dumez <cdumez@apple.com> 2 50 -
trunk/Source/WebCore/rendering/RenderElement.cpp
r288127 r288267 635 635 } 636 636 637 static RenderLayer* findNextLayer(const RenderElement& currRenderer, RenderLayer& parentLayer, const RenderObject* siblingToTraverseFrom, bool checkParent = true) 638 { 639 // Step 1: If our layer is a child of the desired parent, then return our layer. 640 auto* ourLayer = currRenderer.hasLayer() ? downcast<RenderLayerModelObject>(currRenderer).layer() : nullptr; 641 if (ourLayer && ourLayer->parent() == &parentLayer) 642 return ourLayer; 643 644 // Step 2: If we don't have a layer, or our layer is the desired parent, then descend 645 // into our siblings trying to find the next layer whose parent is the desired parent. 646 if (!ourLayer || ourLayer == &parentLayer) { 647 for (auto* child = siblingToTraverseFrom ? siblingToTraverseFrom->nextSibling() : currRenderer.firstChild(); child; child = child->nextSibling()) { 648 if (!is<RenderElement>(*child)) 649 continue; 650 if (auto* nextLayer = findNextLayer(downcast<RenderElement>(*child), parentLayer, nullptr, false)) 651 return nextLayer; 652 } 653 } 654 655 // Step 3: If our layer is the desired parent layer, then we're finished. We didn't 656 // find anything. 657 if (ourLayer == &parentLayer) 658 return nullptr; 659 660 // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that 661 // follow us to see if we can locate a layer. 662 if (checkParent && currRenderer.parent()) 663 return findNextLayer(*currRenderer.parent(), parentLayer, &currRenderer, true); 664 665 return nullptr; 666 } 667 668 static RenderLayer* layerNextSiblingRespectingTopLayer(const RenderElement& renderer, RenderLayer& parentLayer) 669 { 670 ASSERT_IMPLIES(isInTopLayerOrBackdrop(renderer.style(), renderer.element()), renderer.hasLayer()); 671 672 if (is<RenderLayerModelObject>(renderer) && isInTopLayerOrBackdrop(renderer.style(), renderer.element())) { 673 auto& layerModelObject = downcast<RenderLayerModelObject>(renderer); 674 ASSERT(layerModelObject.hasLayer()); 675 auto topLayerLayers = RenderLayer::topLayerRenderLayers(renderer.view()); 676 auto layerIndex = topLayerLayers.find(layerModelObject.layer()); 677 if (layerIndex != notFound && layerIndex < topLayerLayers.size() - 1) 678 return topLayerLayers[layerIndex + 1]; 679 680 return nullptr; 681 } 682 683 return findNextLayer(*renderer.parent(), parentLayer, &renderer); 684 } 685 637 686 static void addLayers(const RenderElement& addedRenderer, RenderElement& currentRenderer, RenderLayer& parentLayer, std::optional<RenderLayer*>& beforeChild) 638 687 { 639 688 if (currentRenderer.hasLayer()) { 640 689 if (!beforeChild.has_value()) 641 beforeChild = addedRenderer.parent()->findNextLayer(parentLayer, &addedRenderer);690 beforeChild = layerNextSiblingRespectingTopLayer(addedRenderer, parentLayer); 642 691 643 692 parentLayer.addChild(*downcast<RenderLayerModelObject>(currentRenderer).layer(), beforeChild.value()); … … 687 736 } 688 737 689 RenderLayer* RenderElement::findNextLayer(RenderLayer& parentLayer, const RenderObject* siblingToTraverseFrom, bool checkParent) const 690 { 691 // Step 1: If our layer is a child of the desired parent, then return our layer. 692 auto* ourLayer = hasLayer() ? downcast<RenderLayerModelObject>(*this).layer() : nullptr; 693 if (ourLayer && ourLayer->parent() == &parentLayer) 694 return ourLayer; 695 696 // Step 2: If we don't have a layer, or our layer is the desired parent, then descend 697 // into our siblings trying to find the next layer whose parent is the desired parent. 698 if (!ourLayer || ourLayer == &parentLayer) { 699 for (auto* child = siblingToTraverseFrom ? siblingToTraverseFrom->nextSibling() : firstChild(); child; child = child->nextSibling()) { 700 if (!is<RenderElement>(*child)) 701 continue; 702 if (auto* nextLayer = downcast<RenderElement>(*child).findNextLayer(parentLayer, nullptr, false)) 703 return nextLayer; 704 } 705 } 706 707 // Step 3: If our layer is the desired parent layer, then we're finished. We didn't 708 // find anything. 709 if (ourLayer == &parentLayer) 710 return nullptr; 711 712 // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that 713 // follow us to see if we can locate a layer. 714 if (checkParent && parent()) 715 return parent()->findNextLayer(parentLayer, this, true); 716 717 return nullptr; 738 RenderLayer* RenderElement::layerParent() const 739 { 740 ASSERT_IMPLIES(isInTopLayerOrBackdrop(style(), element()), hasLayer()); 741 742 if (hasLayer() && isInTopLayerOrBackdrop(style(), element())) 743 return view().layer(); 744 745 return parent()->enclosingLayer(); 746 } 747 748 // This answers the question "if this renderer had a layer, what would its next sibling layer be". 749 RenderLayer* RenderElement::layerNextSibling(RenderLayer& parentLayer) const 750 { 751 return WebCore::layerNextSiblingRespectingTopLayer(*this, parentLayer); 718 752 } 719 753 … … 962 996 // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children 963 997 // and don't have a layer attached to ourselves. 964 RenderLayer* layer = nullptr;998 RenderLayer* parentLayer = nullptr; 965 999 if (firstChild() || hasLayer()) { 966 layer = parent()->enclosingLayer();967 addLayers( layer);1000 auto* parentLayer = layerParent(); 1001 addLayers(parentLayer); 968 1002 } 969 1003 … … 971 1005 // that needs to be drawn and layer visibility optimization can't be used 972 1006 if (parent()->style().visibility() != Visibility::Visible && style().visibility() == Visibility::Visible && !hasLayer()) { 973 if (! layer)974 layer = parent()->enclosingLayer();975 if ( layer)976 layer->dirtyVisibleContentStatus();1007 if (!parentLayer) 1008 parentLayer = layerParent(); 1009 if (parentLayer) 1010 parentLayer->dirtyVisibleContentStatus(); 977 1011 } 978 1012 … … 983 1017 { 984 1018 // If we remove a visible child from an invisible parent, we don't know the layer visibility any more. 985 RenderLayer* layer = nullptr;986 1019 if (parent()->style().visibility() != Visibility::Visible && style().visibility() == Visibility::Visible && !hasLayer()) { 987 if ((layer = parent()->enclosingLayer())) 988 layer->dirtyVisibleContentStatus(); 1020 // FIXME: should get parent layer. Necessary? 1021 if (auto* enclosingLayer = parent()->enclosingLayer()) 1022 enclosingLayer->dirtyVisibleContentStatus(); 989 1023 } 990 1024 // Keep our layer hierarchy updated. 991 1025 if (firstChild() || hasLayer()) { 992 if (!layer) 993 layer = parent()->enclosingLayer(); 994 removeLayers(layer); 1026 auto* parentLayer = layerParent(); 1027 removeLayers(parentLayer); 995 1028 } 996 1029 -
trunk/Source/WebCore/rendering/RenderElement.h
r288127 r288267 109 109 // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy 110 110 // can contain a mixture of boxes and other object types, these functions need to be in the base class. 111 RenderLayer* layerParent() const; 112 RenderLayer* layerNextSibling(RenderLayer& parentLayer) const; 111 113 void addLayers(RenderLayer* parentLayer); 112 114 void removeLayers(RenderLayer* parentLayer); 113 115 void moveLayers(RenderLayer* oldParent, RenderLayer& newParent); 114 RenderLayer* findNextLayer(RenderLayer& parentLayer, const RenderObject* siblingToTraverseFrom, bool checkParent = true) const;115 116 116 117 virtual void dirtyLinesFromChangedChild(RenderObject&) { } -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r288127 r288267 484 484 // We need to connect ourselves when our renderer() has a parent. 485 485 // Find our enclosingLayer and add ourselves. 486 auto* parentLayer = renderer(). parent()->enclosingLayer();486 auto* parentLayer = renderer().layerParent(); 487 487 if (!parentLayer) 488 488 return; 489 489 490 auto* beforeChild = parentLayer->reflectionLayer() != this ? renderer(). parent()->findNextLayer(*parentLayer, &renderer()) : nullptr;490 auto* beforeChild = parentLayer->reflectionLayer() != this ? renderer().layerNextSibling(*parentLayer) : nullptr; 491 491 parentLayer->addChild(*this, beforeChild); 492 492 } … … 654 654 RenderLayer* RenderLayer::stackingContext() const 655 655 { 656 if (establishesTopLayer())657 return renderer().view().layer();658 659 656 auto* layer = parent(); 660 657 while (layer && !layer->isStackingContext()) … … 662 659 663 660 ASSERT(!layer || layer->isStackingContext()); 661 ASSERT_IMPLIES(establishesTopLayer(), !layer || layer == renderer().view().layer()); 664 662 return layer; 665 663 } … … 1483 1481 // As we became visible, we need to dirty our stacking containers ancestors to be properly 1484 1482 // collected. FIXME: When compositing, we could skip this dirtying phase. 1485 for ( RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) {1483 for (auto* sc = stackingContext(); sc; sc = sc->stackingContext()) { 1486 1484 sc->dirtyZOrderLists(); 1487 1485 if (sc->hasVisibleContent()) … … 1503 1501 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus() 1504 1502 { 1505 for ( RenderLayer* layer = this; layer; layer = layer->parent()) {1503 for (auto* layer = this; layer; layer = layer->parent()) { 1506 1504 if (layer->m_visibleDescendantStatusDirty) 1507 1505 break; … … 1513 1511 void RenderLayer::setAncestorChainHasVisibleDescendant() 1514 1512 { 1515 for ( RenderLayer* layer = this; layer; layer = layer->parent()) {1513 for (auto* layer = this; layer; layer = layer->parent()) { 1516 1514 if (shouldApplyPaintContainment(renderer())) { 1517 1515 m_hasVisibleDescendant = true; … … 1837 1835 RenderLayer* RenderLayer::enclosingAncestorForPosition(PositionType position) const 1838 1836 { 1839 if (establishesTopLayer()) 1840 return renderer().view().layer(); 1841 1842 RenderLayer* curr = parent(); 1837 auto* curr = parent(); 1843 1838 while (curr && !isContainerForPositioned(*curr, position, establishesTopLayer())) 1844 1839 curr = curr->parent(); 1845 1840 1841 ASSERT_IMPLIES(establishesTopLayer(), !curr || curr == renderer().view().layer()); 1846 1842 return curr; 1847 1843 } … … 3072 3068 // layer from the parent now, assuming there is a parent 3073 3069 if (paintFlags & PaintLayerFlag::HaveTransparency) { 3074 // Top layer elements are not affected by ancestor opacities 3075 if (!establishesTopLayer() && parent()) 3070 if (parent()) 3076 3071 parent()->beginTransparencyLayers(context, paintingInfo, paintingInfo.paintDirtyRect); 3077 3072 else … … 4022 4017 void RenderLayer::establishesTopLayerWillChange() 4023 4018 { 4024 dirtyStackingContextZOrderLists(); 4019 if (auto* parentLayer = parent()) 4020 parentLayer->removeChild(*this); 4025 4021 } 4026 4022 4027 4023 void RenderLayer::establishesTopLayerDidChange() 4028 4024 { 4029 dirtyStackingContextZOrderLists(); 4030 if (isStackingContext()) 4031 dirtyZOrderLists(); 4025 if (auto* parentLayer = renderer().layerParent()) 4026 parentLayer->addChild(*this); 4032 4027 } 4033 4028 … … 4499 4494 bool RenderLayer::clipCrossesPaintingBoundary() const 4500 4495 { 4501 if (establishesTopLayer())4502 return true;4503 4504 4496 return parent()->enclosingPaginationLayer(IncludeCompositedPaginatedLayers) != enclosingPaginationLayer(IncludeCompositedPaginatedLayers) 4505 4497 || parent()->enclosingCompositingLayerForRepaint() != enclosingCompositingLayerForRepaint(); … … 4589 4581 Ref<ClipRects> RenderLayer::parentClipRects(const ClipRectsContext& clipRectsContext) const 4590 4582 { 4591 ASSERT(parent() || establishesTopLayer());4592 4593 auto containerLayer = establishesTopLayer() ? renderer().view().layer() :parent();4583 ASSERT(parent()); 4584 4585 auto containerLayer = parent(); 4594 4586 auto temporaryParentClipRects = [&](const ClipRectsContext& clipContext) { 4595 4587 auto parentClipRects = ClipRects::create();
Note: See TracChangeset
for help on using the changeset viewer.