Skip to content

Commit

Permalink
Capturing the old view transition snapshot includes descendant view-t…
Browse files Browse the repository at this point in the history
…ransition.

https://bugs.webkit.org/show_bug.cgi?id=270056
<rdar://123606877>

Reviewed by Tim Nguyen.

The 'capture the image' algorithm should skip over descendant elements that
also have a view transition.

This changes snapshotNodeVisualOverflowClippedToViewport to call 'paint' on
the RenderLayer of the element with a view-transition directly rather than
calling it on the root elements Layer (with a subtree painting root set).

It adds a new PaintFlag 'PaintingSkipDescendantViewTransition' which skips descending
into child layers that are being separately captured in a view transition.

* LayoutTests/TestExpectations:
* Source/WebCore/dom/ViewTransition.cpp:
(WebCore::snapshotNodeVisualOverflowClippedToViewport):
(WebCore::ViewTransition::captureOldState):
* Source/WebCore/rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintList):
* Source/WebCore/rendering/RenderLayer.h:

Canonical link: https://commits.webkit.org/275312@main
  • Loading branch information
mattwoodrow committed Feb 26, 2024
1 parent c6ffba6 commit b560a1b
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 27 deletions.
9 changes: 1 addition & 8 deletions LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -6883,16 +6883,12 @@ imported/w3c/web-platform-tests/navigation-api/updateCurrentEntry-method/locatio
# Reftest failures:
imported/w3c/web-platform-tests/css/css-view-transitions/3d-transform-incoming.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/3d-transform-outgoing.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/animating-new-content-subset.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/animating-new-content.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/block-with-overflowing-text.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/capture-with-offscreen-child-translated.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/capture-with-visibility-mixed-descendants.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/content-smaller-than-box-size.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/content-with-child-with-transparent-background.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/content-with-clip-root.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/content-with-transform-old-image.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/content-with-transparent-background.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/css-tags-shared-element.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/dialog-in-top-layer-during-transition-new.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/element-is-grouping-during-animation.html [ ImageOnlyFailure ]
Expand Down Expand Up @@ -6922,10 +6918,8 @@ imported/w3c/web-platform-tests/css/css-view-transitions/object-view-box-new-ima
imported/w3c/web-platform-tests/css/css-view-transitions/object-view-box-old-image.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/old-content-captures-clip-path.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/old-content-captures-different-size.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/old-content-has-scrollbars.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/old-content-intrinsic-aspect-ratio.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/old-content-with-overflow-zoomed.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/old-root-vertical-writing-mode.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/root-captured-as-different-tag.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/root-scrollbar-with-fixed-background.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/root-style-change-during-animation.html [ ImageOnlyFailure ]
Expand All @@ -6935,7 +6929,6 @@ imported/w3c/web-platform-tests/css/css-view-transitions/root-to-shared-animatio
imported/w3c/web-platform-tests/css/css-view-transitions/snapshot-containing-block-absolute.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/span-with-overflowing-text-and-box-decorations.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/span-with-overflowing-text.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/transform-origin-view-transition-group.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/view-transition-name-is-grouping.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/writing-mode-container-resize.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/capture-with-offscreen-child.html [ ImageOnlyFailure ]
Expand Down Expand Up @@ -6976,7 +6969,7 @@ imported/w3c/web-platform-tests/css/css-view-transitions/scroller-child-abspos.h
imported/w3c/web-platform-tests/css/css-view-transitions/scroller-child.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/scroller.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/new-content-element-writing-modes.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/content-with-clip.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-view-transitions/massive-element-below-viewport-partially-onscreen-old.html [ ImageOnlyFailure ]

# Timeouts
imported/w3c/web-platform-tests/css/css-view-transitions/iframe-transition.sub.html [ Skip ]
Expand Down
41 changes: 24 additions & 17 deletions Source/WebCore/dom/ViewTransition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "Document.h"
#include "DocumentTimeline.h"
#include "FrameSnapshotting.h"
#include "HostWindow.h"
#include "JSDOMPromise.h"
#include "JSDOMPromiseDeferred.h"
#include "LayoutRect.h"
Expand Down Expand Up @@ -262,32 +263,38 @@ static ExceptionOr<void> checkDuplicateViewTransitionName(const AtomString& name
return { };
}

static RefPtr<ImageBuffer> snapshotNodeVisualOverflowClippedToViewport(LocalFrame& frame, Node& node, SnapshotOptions&& options, LayoutRect& oldOverflowRect)
static RefPtr<ImageBuffer> snapshotNodeVisualOverflowClippedToViewport(LocalFrame& frame, Node& node, LayoutRect& oldOverflowRect)
{
if (!node.renderer())
return nullptr;

auto paintBehavior = frame.view()->paintBehavior();
auto backgroundColor = frame.view()->baseBackgroundColor();
ASSERT(node.renderer()->hasLayer());
CheckedPtr layerRenderer = downcast<RenderLayerModelObject>(node.renderer());

options.flags.add(SnapshotFlags::Accelerated);
oldOverflowRect = layerRenderer->layer()->localBoundingBox();
IntRect paintRect = snappedIntRect(oldOverflowRect);

frame.view()->setBaseBackgroundColor(Color::transparentBlack);
frame.view()->setNodeToDraw(&node);
ASSERT(frame.page());
float scaleFactor = frame.page()->deviceScaleFactor();
if (frame.page()->delegatesScaling())
scaleFactor *= frame.page()->pageScaleFactor();

ASSERT(node.renderer()->hasLayer());
CheckedPtr layerRenderer = downcast<RenderLayerModelObject>(node.renderer());
ASSERT(frame.document());
auto hostWindow = (frame.document()->view() && frame.document()->view()->root()) ? frame.document()->view()->root()->hostWindow() : nullptr;

auto buffer = ImageBuffer::create(paintRect.size(), RenderingPurpose::Snapshot, scaleFactor, DestinationColorSpace::SRGB(), PixelFormat::BGRA8, { ImageBufferOptions::Accelerated }, hostWindow);
if (!buffer)
return nullptr;

IntRect paintRect = layerRenderer->layer()->absoluteBoundingBox();
paintRect.intersect(snappedIntRect(frame.view()->layoutViewportRect()));
RefPtr result = snapshotFrameRect(frame, paintRect, WTFMove(options));
buffer->context().translate(-paintRect.location());

frame.view()->setPaintBehavior(paintBehavior);
frame.view()->setBaseBackgroundColor(backgroundColor);
frame.view()->setNodeToDraw(nullptr);
auto paintFlags = RenderLayer::paintLayerPaintingCompositingAllPhasesFlags();
paintFlags.add(RenderLayer::PaintLayerFlag::TemporaryClipRects);
paintFlags.add(RenderLayer::PaintLayerFlag::AppliedTransform);
paintFlags.add(RenderLayer::PaintLayerFlag::PaintingSkipDescendantViewTransition);
layerRenderer->layer()->paint(buffer->context(), paintRect, LayoutSize(), { PaintBehavior::FlattenCompositingLayers, PaintBehavior::Snapshotting }, nullptr, paintFlags);

oldOverflowRect = layerRenderer->layer()->localBoundingBox();
return result;
return buffer;
}

// This only iterates through elements with a RenderLayer, which is sufficient for View Transitions which force their creation.
Expand Down Expand Up @@ -351,7 +358,7 @@ ExceptionOr<void> ViewTransition::captureOldState()
capture.oldSize = renderBox->size();
capture.oldProperties = copyElementBaseProperties(element);
if (m_document->frame())
capture.oldImage = snapshotNodeVisualOverflowClippedToViewport(*m_document->frame(), element.get(), { { }, PixelFormat::BGRA8, DestinationColorSpace::SRGB() }, capture.oldOverflowRect);
capture.oldImage = snapshotNodeVisualOverflowClippedToViewport(*m_document->frame(), element.get(), capture.oldOverflowRect);

auto transitionName = element->computedStyle()->viewTransitionName();
m_namedElements.add(transitionName->name, capture);
Expand Down
5 changes: 4 additions & 1 deletion Source/WebCore/rendering/RenderLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3520,8 +3520,11 @@ void RenderLayer::paintList(LayerList layerIterator, GraphicsContext& context, c
LayerListMutationDetector mutationChecker(*this);
#endif

for (auto* childLayer : layerIterator)
for (auto* childLayer : layerIterator) {
if (paintFlags.contains(PaintLayerFlag::PaintingSkipDescendantViewTransition) && childLayer->renderer().capturedInViewTransition())
continue;
childLayer->paintLayer(context, paintingInfo, paintFlags);
}
}

RenderLayer* RenderLayer::enclosingPaginationLayerInSubtree(const RenderLayer* rootLayer, PaginationInclusionMode mode) const
Expand Down
3 changes: 2 additions & 1 deletion Source/WebCore/rendering/RenderLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ class RenderLayer : public CanMakeSingleThreadWeakPtr<RenderLayer>, public CanMa

inline int zIndex() const;

enum class PaintLayerFlag : uint16_t {
enum class PaintLayerFlag : uint32_t {
HaveTransparency = 1 << 0,
AppliedTransform = 1 << 1,
TemporaryClipRects = 1 << 2,
Expand All @@ -623,6 +623,7 @@ class RenderLayer : public CanMakeSingleThreadWeakPtr<RenderLayer>, public CanMa
PaintingChildClippingMaskPhase = 1 << 13,
PaintingSVGClippingMask = 1 << 14,
CollectingEventRegion = 1 << 15,
PaintingSkipDescendantViewTransition = 1 << 16,
};
static constexpr OptionSet<PaintLayerFlag> paintLayerPaintingCompositingAllPhasesFlags() { return { PaintLayerFlag::PaintingCompositingBackgroundPhase, PaintLayerFlag::PaintingCompositingForegroundPhase }; }

Expand Down

0 comments on commit b560a1b

Please sign in to comment.