diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/frame/local_frame_view.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/frame/local_frame_view.cc | 664 |
1 files changed, 371 insertions, 293 deletions
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc index cd23c7cd570..0bae92b6617 100644 --- a/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/chromium/third_party/blink/renderer/core/frame/local_frame_view.cc @@ -46,13 +46,13 @@ #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h" #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h" #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/animation/document_animations.h" #include "third_party/blink/renderer/core/css/font_face_set_document.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" +#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h" #include "third_party/blink/renderer/core/dom/static_node_list.h" #include "third_party/blink/renderer/core/editing/compute_layer_selection.h" #include "third_party/blink/renderer/core/editing/drag_caret.h" @@ -124,6 +124,7 @@ #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" #include "third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h" #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" +#include "third_party/blink/renderer/core/paint/cull_rect_updater.h" #include "third_party/blink/renderer/core/paint/frame_painter.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_painter.h" @@ -256,14 +257,11 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect) // updates. We can't throttle it here or it seems the root compositor // doesn't get setup properly. lifecycle_updates_throttled_(!GetFrame().IsMainFrame()), - current_update_lifecycle_phases_target_state_( - DocumentLifecycle::kUninitialized), - past_layout_lifecycle_update_(false), + target_state_(DocumentLifecycle::kUninitialized), suppress_adjust_view_size_(false), intersection_observation_state_(kNotNeeded), needs_forced_compositing_update_(false), needs_focus_on_fragment_(false), - in_lifecycle_update_(false), main_thread_scrolling_reasons_(0), forced_layout_stack_depth_(0), forced_layout_start_time_(base::TimeTicks()), @@ -292,6 +290,7 @@ LocalFrameView::~LocalFrameView() { void LocalFrameView::Trace(Visitor* visitor) const { visitor->Trace(frame_); + visitor->Trace(update_plugins_timer_); visitor->Trace(fragment_anchor_); visitor->Trace(scrollable_areas_); visitor->Trace(animating_scrollable_areas_); @@ -416,6 +415,24 @@ void LocalFrameView::Dispose() { if (viewport_scrollable_area_) viewport_scrollable_area_->ClearScrollableArea(); + // If we have scheduled plugins to be updated, cancel it. They will still be + // notified before they are destroyed. + if (update_plugins_timer_.IsActive()) + update_plugins_timer_.Stop(); + part_update_set_.clear(); + + // These are LayoutObjects whose layout has been deferred to a subsequent + // lifecycle update. Not gonna happen. + layout_subtree_root_list_.Clear(); + + // TODO(szager): LayoutObjects are supposed to remove themselves from these + // tracking groups when they update style or are destroyed, but sometimes they + // are missed. It would be good to understand how/why that happens, but in the + // mean time, it's not safe to keep pointers around to defunct LayoutObjects. + orthogonal_writing_mode_root_list_.Clear(); + viewport_constrained_objects_.reset(); + background_attachment_fixed_objects_.clear(); + // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing // partially destroyed |this| via |m_autoSizeInfo->m_frameView|. auto_size_info_.Clear(); @@ -581,12 +598,6 @@ void LocalFrameView::AdjustViewSizeAndLayout() { } } -void LocalFrameView::UpdateCountersAfterStyleChange() { - auto* layout_view = GetLayoutView(); - DCHECK(layout_view); - layout_view->UpdateCounters(); -} - void LocalFrameView::CountObjectsNeedingLayout(unsigned& needs_layout_objects, unsigned& total_objects, bool& is_subtree) { @@ -629,7 +640,7 @@ void LocalFrameView::PerformPreLayoutTasks() { document->EvaluateMediaQueryList(); } - document->UpdateStyleAndLayoutTree(); + document->UpdateStyleAndLayoutTreeForThisDocument(); // Update style for all embedded SVG documents underneath this frame, so // that intrinsic size computation for any embedded objects has up-to-date @@ -637,7 +648,7 @@ void LocalFrameView::PerformPreLayoutTasks() { ForAllChildLocalFrameViews([](LocalFrameView& view) { Document& document = *view.GetFrame().GetDocument(); if (document.IsSVGDocument()) - document.UpdateStyleAndLayoutTree(); + document.UpdateStyleAndLayoutTreeForThisDocument(); }); Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean); @@ -763,8 +774,6 @@ void LocalFrameView::PerformLayout(bool in_subtree_layout) { if (!LayoutFromRootObject(*root)) continue; - root->PaintingLayer()->UpdateLayerPositionsAfterLayout(); - // We need to ensure that we mark up all layoutObjects up to the // LayoutView for paint invalidation. This simplifies our code as we // just always do a full tree walk. @@ -943,9 +952,6 @@ void LocalFrameView::UpdateLayout() { frame_timing_requests_dirty_ = true; - if (!in_subtree_layout) - GetLayoutView()->EnclosingLayer()->UpdateLayerPositionsAfterLayout(); - TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( TRACE_DISABLED_BY_DEFAULT("blink.debug.layout.trees"), "LayoutTree", this, TracedLayoutObject::Create(*GetLayoutView(), true)); @@ -1011,14 +1017,8 @@ void LocalFrameView::DidFinishForcedLayout(DocumentUpdateReason reason) { forced_layout_stack_depth_--; if (!forced_layout_stack_depth_ && base::TimeTicks::IsHighResolution()) { LocalFrameUkmAggregator& aggregator = EnsureUkmAggregator(); - aggregator.RecordSample( - static_cast<size_t>(LocalFrameUkmAggregator::kForcedStyleAndLayout), - forced_layout_start_time_, base::TimeTicks::Now()); - if (reason == DocumentUpdateReason::kHitTest) { - aggregator.RecordSample( - static_cast<size_t>(LocalFrameUkmAggregator::kHitTestDocumentUpdate), - forced_layout_start_time_, base::TimeTicks::Now()); - } + aggregator.RecordForcedLayoutSample(reason, forced_layout_start_time_, + base::TimeTicks::Now()); } } @@ -1094,6 +1094,9 @@ DocumentLifecycle& LocalFrameView::Lifecycle() const { void LocalFrameView::RunPostLifecycleSteps() { AllowThrottlingScope allow_throttling(*this); RunIntersectionObserverSteps(); + ForAllRemoteFrameViews([](RemoteFrameView& frame_view) { + frame_view.UpdateCompositingScaleFactor(); + }); } void LocalFrameView::RunIntersectionObserverSteps() { @@ -1114,7 +1117,7 @@ void LocalFrameView::RunIntersectionObserverSteps() { LayoutObject* layout_object = GetLayoutView(); IntRect main_frame_dimensions = To<LayoutBox>(layout_object)->PixelSnappedLayoutOverflowRect(); - GetFrame().Client()->OnMainFrameIntersectionChanged(WebRect( + GetFrame().Client()->OnMainFrameIntersectionChanged(IntRect( 0, 0, main_frame_dimensions.Width(), main_frame_dimensions.Height())); } @@ -1137,7 +1140,7 @@ void LocalFrameView::ForceUpdateViewportIntersections() { // update; but we can't wait for a lifecycle update to run them, because a // hidden frame won't run lifecycle updates. Force layout and run them now. DisallowThrottlingScope disallow_throttling(*this); - UpdateLifecycleToCompositingCleanPlusScrolling( + UpdateLifecycleToPrePaintClean( DocumentUpdateReason::kIntersectionObservation); UpdateViewportIntersectionsForSubtree( IntersectionObservation::kImplicitRootObserversNeedUpdate | @@ -1251,25 +1254,20 @@ void LocalFrameView::AdjustMediaTypeForPrinting(bool printing) { void LocalFrameView::AddBackgroundAttachmentFixedObject(LayoutObject* object) { DCHECK(!background_attachment_fixed_objects_.Contains(object)); - background_attachment_fixed_objects_.insert(object); - // Ensure main thread scrolling reasons are recomputed. - SetNeedsPaintPropertyUpdate(); - // The object's scroll properties are not affected by its own background. - object->SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling(); + // Ensure main thread scrolling reasons of the ancestor scroll nodes are + // recomputed. The object's own scroll properties are not affected. + object->ForceAllAncestorsNeedPaintPropertyUpdate(); } void LocalFrameView::RemoveBackgroundAttachmentFixedObject( LayoutObject* object) { - DCHECK(background_attachment_fixed_objects_.Contains(object)); - background_attachment_fixed_objects_.erase(object); - // Ensure main thread scrolling reasons are recomputed. - SetNeedsPaintPropertyUpdate(); - // The object's scroll properties are not affected by its own background. - object->SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling(); + // Ensure main thread scrolling reasons of the ancestor scroll nodes are + // recomputed. The object's own scroll properties are not affected. + object->ForceAllAncestorsNeedPaintPropertyUpdate(); } bool LocalFrameView::RequiresMainThreadScrollingForBackgroundAttachmentFixed() @@ -1525,6 +1523,9 @@ void LocalFrameView::UpdateCompositedSelectionIfNeeded() { if (!RuntimeEnabledFeatures::CompositedSelectionUpdateEnabled()) return; + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + return; + TRACE_EVENT0("blink", "LocalFrameView::updateCompositedSelectionIfNeeded"); Page* page = GetFrame().GetPage(); @@ -1563,8 +1564,14 @@ void LocalFrameView::SetNeedsCompositingUpdate( if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) return; if (auto* layout_view = GetLayoutView()) { - if (frame_->GetDocument()->IsActive()) - layout_view->Compositor()->SetNeedsCompositingUpdate(update_type); + if (frame_->GetDocument()->IsActive()) { + auto* compositor = layout_view->Compositor(); + compositor->SetNeedsCompositingUpdate(update_type); + // Even if the frame is throttlable, we may still need to decomposite it + // in response to a visibility change. + if (compositor->StaleInCompositingMode()) + needs_forced_compositing_update_ = true; + } } } @@ -2000,6 +2007,7 @@ void LocalFrameView::PerformPostLayoutTasks() { DCHECK(!IsInPerformLayout()); TRACE_EVENT0("blink,benchmark", "LocalFrameView::performPostLayoutTasks"); + GetLayoutView()->EnclosingLayer()->UpdateLayerPositionsAfterLayout(); frame_->Selection().DidLayout(); DCHECK(frame_->GetDocument()); @@ -2160,6 +2168,12 @@ void LocalFrameView::WillBeRemovedFromFrame() { } } +bool LocalFrameView::IsUpdatingLifecycle() const { + LocalFrameView* root_view = GetFrame().LocalFrameRoot().View(); + DCHECK(root_view); + return root_view->target_state_ != DocumentLifecycle::kUninitialized; +} + LocalFrameView* LocalFrameView::ParentFrameView() const { if (!IsAttached()) return nullptr; @@ -2220,6 +2234,7 @@ bool LocalFrameView::UpdateAllLifecyclePhases(DocumentUpdateReason reason) { // kLayoutClean. ForAllThrottledLocalFrameViews([](LocalFrameView& frame_view) { DCHECK(frame_view.intersection_observation_state_ != kRequired || + frame_view.IsDisplayLocked() || frame_view.Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean); }); @@ -2298,8 +2313,7 @@ bool LocalFrameView::UpdateLifecycleToLayoutClean(DocumentUpdateReason reason) { void LocalFrameView::ScheduleVisualUpdateForPaintInvalidationIfNeeded() { LocalFrame& local_frame_root = GetFrame().LocalFrameRoot(); // We need a full lifecycle update to clear pending paint invalidations. - if (local_frame_root.View()->current_update_lifecycle_phases_target_state_ < - DocumentLifecycle::kPaintClean || + if (local_frame_root.View()->target_state_ < DocumentLifecycle::kPaintClean || Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean) { // Schedule visual update to process the paint invalidation in the next // cycle. @@ -2360,6 +2374,18 @@ bool LocalFrameView::LocalFrameTreeAllowsThrottling() const { return false; } +void LocalFrameView::PrepareForLifecycleUpdateRecursive() { + // We will run lifecycle phases for LocalFrameViews that are unthrottled; or + // are throttled but require IntersectionObserver steps to run. + if (!ShouldThrottleRendering() || + intersection_observation_state_ == kRequired) { + Lifecycle().EnsureStateAtMost(DocumentLifecycle::kVisualUpdatePending); + ForAllChildLocalFrameViews([](LocalFrameView& child) { + child.PrepareForLifecycleUpdateRecursive(); + }); + } +} + // TODO(leviw): We don't assert lifecycle information from documents in child // WebPluginContainerImpls. bool LocalFrameView::UpdateLifecyclePhases( @@ -2406,36 +2432,27 @@ bool LocalFrameView::UpdateLifecyclePhases( if (frame_->IsLocalRoot()) UpdateLayerDebugInfoEnabled(); + // If we're throttling and we aren't required to run the IntersectionObserver + // steps, then we don't need to update lifecycle phases. The throttling status + // will get updated in RunPostLifecycleSteps(). + if (ShouldThrottleRendering() && + intersection_observation_state_ < kRequired) { + return Lifecycle().GetState() == target_state; + } + + PrepareForLifecycleUpdateRecursive(); + // This is used to guard against reentrance. It is also used in conjunction // with the current lifecycle state to determine which phases are yet to run - // in this cycle. + // in this cycle. Note that this may change the return value of + // ShouldThrottleRendering(), hence it cannot be moved before the preceeding + // code, which relies on the prior value of ShouldThrottleRendering(). base::AutoReset<DocumentLifecycle::LifecycleState> target_state_scope( - ¤t_update_lifecycle_phases_target_state_, target_state); - // This is used to check if we're within a lifecycle update but have passed - // the layout update phase. Note there is a bit of a subtlety here: it's not - // sufficient for us to check the current lifecycle state, since it can be - // past kLayoutClean but the function to run style and layout phase has not - // actually been run yet. Since this bool affects throttling, and throttling, - // in turn, determines whether style and layout function will run, we need a - // separate bool. - base::AutoReset<bool> past_layout_lifecycle_resetter( - &past_layout_lifecycle_update_, false); - base::AutoReset<bool> in_lifecycle_scope(&in_lifecycle_update_, true); - - // If we're throttling, then we don't need to update lifecycle phases. The - // throttling status will get updated in RunPostLifecycleSteps(). - if (ShouldThrottleRendering()) { - return Lifecycle().GetState() == target_state; - } + &target_state_, target_state); lifecycle_data_.start_time = base::TimeTicks::Now(); ++lifecycle_data_.count; - ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { - frame_view.Lifecycle().EnsureStateAtMost( - DocumentLifecycle::kVisualUpdatePending); - }); - if (target_state == DocumentLifecycle::kPaintClean) { { TRACE_EVENT0("blink", "LocalFrameView::WillStartLifecycleUpdate"); @@ -2487,6 +2504,9 @@ bool LocalFrameView::UpdateLifecyclePhases( void LocalFrameView::UpdateLifecyclePhasesInternal( DocumentLifecycle::LifecycleState target_state) { + // RunScrollTimelineSteps must not run more than once. + bool should_run_scroll_timeline_steps = true; + // Run style, layout, compositing and prepaint lifecycle phases and deliver // resize observations if required. Resize observer callbacks/delegates have // the potential to dirty layout (until loop limit is reached) and therefore @@ -2495,7 +2515,23 @@ void LocalFrameView::UpdateLifecyclePhasesInternal( // Note that after ResizeObserver has settled, we also run intersection // observations that need to be delievered in post-layout. This process can // also dirty layout, which will run this loop again. + + // A LocalFrameView can be unthrottled at this point, but become throttled as + // it advances through lifecycle stages. If that happens, it will prevent + // subsequent passes through the loop from updating the newly-throttled views. + // To avoid that, we lock in the set of unthrottled views before entering the + // loop. + HeapVector<Member<LocalFrameView>> unthrottled_frame_views; + ForAllNonThrottledLocalFrameViews( + [&unthrottled_frame_views](LocalFrameView& frame_view) { + unthrottled_frame_views.push_back(&frame_view); + }); + while (true) { + for (LocalFrameView* frame_view : unthrottled_frame_views) { + frame_view->Lifecycle().EnsureStateAtMost( + DocumentLifecycle::kVisualUpdatePending); + } bool run_more_lifecycle_phases = RunStyleAndLayoutLifecyclePhases(target_state); if (!run_more_lifecycle_phases) @@ -2536,7 +2572,7 @@ void LocalFrameView::UpdateLifecyclePhasesInternal( run_more_lifecycle_phases = RunPrePaintLifecyclePhase(target_state); DCHECK(ShouldThrottleRendering() || Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean); - if (!run_more_lifecycle_phases) + if (ShouldThrottleRendering() || !run_more_lifecycle_phases) return; run_more_lifecycle_phases = @@ -2546,6 +2582,24 @@ void LocalFrameView::UpdateLifecyclePhasesInternal( } } + // Some features may require several passes over style and layout + // within the same lifecycle update. + bool needs_to_repeat_lifecycle = false; + + // ScrollTimelines may be associated with a source that never had a + // a chance to get a layout box at the time style was calculated; when + // this situation happens, RunScrollTimelineSteps will re-snapshot all + // affected timelines and dirty style for associated effect targets. + // + // https://github.com/w3c/csswg-drafts/issues/5261 + if (RuntimeEnabledFeatures::CSSScrollTimelineEnabled() && + should_run_scroll_timeline_steps) { + should_run_scroll_timeline_steps = false; + needs_to_repeat_lifecycle = RunScrollTimelineSteps(); + if (needs_to_repeat_lifecycle) + continue; + } + // ResizeObserver and post-layout IntersectionObserver observation // deliveries may dirty style and layout. RunResizeObserverSteps will return // true if any observer ran that may have dirtied style or layout; @@ -2553,7 +2607,7 @@ void LocalFrameView::UpdateLifecyclePhasesInternal( // observations led to content-visibility intersection changing visibility // state synchronously (which happens on the first intersection // observeration of a context). - bool needs_to_repeat_lifecycle = RunResizeObserverSteps(target_state); + needs_to_repeat_lifecycle = RunResizeObserverSteps(target_state); // Only run the rest of the steps here if resize observer is done. if (needs_to_repeat_lifecycle) continue; @@ -2576,14 +2630,29 @@ void LocalFrameView::UpdateLifecyclePhasesInternal( DCHECK_EQ(target_state, DocumentLifecycle::kPaintClean); RunPaintLifecyclePhase(); - DCHECK(ShouldThrottleRendering() || - frame_->GetDocument()->IsCapturingLayout() || + DCHECK(ShouldThrottleRendering() || AnyFrameIsPrintingOrPaintingPreview() || Lifecycle().GetState() == DocumentLifecycle::kPaintClean); ForAllRemoteFrameViews( [](RemoteFrameView& frame_view) { frame_view.UpdateCompositingRect(); }); } +bool LocalFrameView::RunScrollTimelineSteps() { + DCHECK_GE(Lifecycle().GetState(), + DocumentLifecycle::kCompositingAssignmentsClean); + bool re_run_lifecycles = false; + ForAllNonThrottledLocalFrameViews( + [&re_run_lifecycles](LocalFrameView& frame_view) { + frame_view.GetFrame() + .GetDocument() + ->GetDocumentAnimations() + .ValidateTimelines(); + re_run_lifecycles |= (frame_view.Lifecycle().GetState() < + DocumentLifecycle::kCompositingAssignmentsClean); + }); + return re_run_lifecycles; +} + bool LocalFrameView::RunResizeObserverSteps( DocumentLifecycle::LifecycleState target_state) { bool re_run_lifecycles = false; @@ -2612,7 +2681,10 @@ bool LocalFrameView::RunStyleAndLayoutLifecyclePhases( TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunStyleAndLayoutLifecyclePhases"); UpdateStyleAndLayoutIfNeededRecursive(); - DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean); + DCHECK(ShouldThrottleRendering() || + Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean); + if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean) + return false; frame_->GetDocument() ->GetRootScrollerController() @@ -2633,18 +2705,6 @@ bool LocalFrameView::RunStyleAndLayoutLifecyclePhases( if (target_state == DocumentLifecycle::kLayoutClean) return false; - // This will be reset by AutoReset in the calling function - // (UpdateLifecyclePhases()). - past_layout_lifecycle_update_ = true; - - // After layout and the |past_layout_lifecycle_update_| update, the value of - // ShouldThrottleRendering() can change. OOPIF local frame roots that are - // throttled can return now that layout is clean. This situation happens if - // the throttling was disabled due to required intersection observation, which - // can now be run. - if (ShouldThrottleRendering()) - return false; - // Now we can run post layout steps in preparation for further phases. ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { frame_view.PerformScrollAnchoringAdjustments(); @@ -2735,21 +2795,41 @@ bool LocalFrameView::RunPrePaintLifecyclePhase( #endif } - ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { - frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPrePaint); - if (frame_view.CanThrottleRendering()) { - // This frame can be throttled but not throttled, meaning we are not in an - // AllowThrottlingScope. Now this frame may contain dirty paint flags, and - // we need to propagate the flags into the ancestor chain so that - // PrePaintTreeWalk can reach this frame. - frame_view.SetNeedsPaintPropertyUpdate(); - // We may record more pre-composited layers under the frame. - if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) - frame_view.SetPaintArtifactCompositorNeedsUpdate(); - if (auto* owner = frame_view.GetLayoutEmbeddedContent()) - owner->SetShouldCheckForPaintInvalidation(); - } - }); + ForAllNonThrottledLocalFrameViews( + [](LocalFrameView& frame_view) { + frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPrePaint); + // We skipped pre-paint for this frame while it was throttled, or we + // have never run pre-paint for this frame. Either way, we're + // unthrottled now, so we must propagate our dirty bits into our + // parent frame so that pre-paint reaches into this frame. + if (LayoutView* layout_view = frame_view.GetLayoutView()) { + if (auto* owner = frame_view.GetFrame().OwnerLayoutObject()) { + if (layout_view->NeedsPaintPropertyUpdate() || + layout_view->DescendantNeedsPaintPropertyUpdate()) { + owner->SetDescendantNeedsPaintPropertyUpdate(); + } + if (layout_view->ShouldCheckForPaintInvalidation()) { + owner->SetShouldCheckForPaintInvalidation(); + } + if (layout_view->EffectiveAllowedTouchActionChanged() || + layout_view->DescendantEffectiveAllowedTouchActionChanged()) { + owner->MarkDescendantEffectiveAllowedTouchActionChanged(); + } + if (layout_view->BlockingWheelEventHandlerChanged() || + layout_view->DescendantBlockingWheelEventHandlerChanged()) { + owner->MarkDescendantBlockingWheelEventHandlerChanged(); + } + if (RuntimeEnabledFeatures::CullRectUpdateEnabled() && + (layout_view->Layer()->NeedsCullRectUpdate() || + layout_view->Layer()->DescendantNeedsCullRectUpdate())) { + layout_view->Layer() + ->MarkCompositingContainerChainForNeedsCullRectUpdate(); + } + } + } + }, + // Use post-order to ensure correct flag propagation for nested frames. + kPostOrder); { SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), @@ -2767,98 +2847,110 @@ bool LocalFrameView::RunPrePaintLifecyclePhase( return target_state > DocumentLifecycle::kPrePaintClean; } +bool LocalFrameView::AnyFrameIsPrintingOrPaintingPreview() { + bool any_frame_is_printing_or_painting_preview = false; + ForAllNonThrottledLocalFrameViews( + [&any_frame_is_printing_or_painting_preview](LocalFrameView& frame_view) { + if (frame_view.GetFrame().GetDocument()->IsPrintingOrPaintingPreview()) + any_frame_is_printing_or_painting_preview = true; + }); + return any_frame_is_printing_or_painting_preview; +} + void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) { TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase"); // While printing or capturing a paint preview of a document, the paint walk // is done into a special canvas. There is no point doing a normal paint step // (or animations update) when in this mode. - bool is_capturing_layout = frame_->GetDocument()->IsCapturingLayout(); - bool repainted = false; - if (!is_capturing_layout) - repainted = PaintTree(benchmark_mode); - - if (benchmark_mode == - PaintBenchmarkMode::kForcePaintArtifactCompositorUpdate || - // TODO(paint-dev): Separate requirement for update for repaint and full - // PaintArtifactCompositor update. - (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && - benchmark_mode != PaintBenchmarkMode::kNormal)) { + if (AnyFrameIsPrintingOrPaintingPreview()) + return; + + bool repainted = PaintTree(benchmark_mode); + + if (paint_artifact_compositor_ && + (benchmark_mode == + PaintBenchmarkMode::kForcePaintArtifactCompositorUpdate || + // TODO(paint-dev): Separate requirement for update for repaint and full + // PaintArtifactCompositor update. + (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && + benchmark_mode != PaintBenchmarkMode::kNormal))) { paint_artifact_compositor_->SetNeedsUpdate(); } - if (!is_capturing_layout) { - bool needed_update = !paint_artifact_compositor_ || - paint_artifact_compositor_->NeedsUpdate(); - PushPaintArtifactToCompositor(repainted); - size_t total_animations_count = 0; - bool current_frame_had_raf = false; - bool next_frame_has_pending_raf = false; - ForAllNonThrottledLocalFrameViews([this, &total_animations_count, - ¤t_frame_had_raf, - &next_frame_has_pending_raf]( - LocalFrameView& frame_view) { - if (auto* scrollable_area = frame_view.GetScrollableArea()) - scrollable_area->UpdateCompositorScrollAnimations(); - if (const auto* animating_scrollable_areas = - frame_view.AnimatingScrollableAreas()) { - for (PaintLayerScrollableArea* area : *animating_scrollable_areas) - area->UpdateCompositorScrollAnimations(); - } - frame_view.GetLayoutView() - ->GetDocument() - .GetDocumentAnimations() - .UpdateAnimations(DocumentLifecycle::kPaintClean, - paint_artifact_compositor_.get()); - Document& document = frame_view.GetLayoutView()->GetDocument(); - total_animations_count += - document.GetDocumentAnimations().GetAnimationsCount(); - current_frame_had_raf |= document.CurrentFrameHadRAF(); - next_frame_has_pending_raf |= document.NextFrameHasPendingRAF(); - }); - - if (GetLayoutView()->GetDocument().View() && - GetLayoutView()->GetDocument().View()->GetCompositorAnimationHost()) { - GetLayoutView() - ->GetDocument() - .View() - ->GetCompositorAnimationHost() - ->SetAnimationCounts(total_animations_count, current_frame_had_raf, - next_frame_has_pending_raf); - } + bool needed_update = + !paint_artifact_compositor_ || paint_artifact_compositor_->NeedsUpdate(); + PushPaintArtifactToCompositor(repainted); + size_t total_animations_count = 0; + bool current_frame_had_raf = false; + bool next_frame_has_pending_raf = false; + ForAllNonThrottledLocalFrameViews( + [this, &total_animations_count, ¤t_frame_had_raf, + &next_frame_has_pending_raf](LocalFrameView& frame_view) { + if (auto* scrollable_area = frame_view.GetScrollableArea()) + scrollable_area->UpdateCompositorScrollAnimations(); + if (const auto* animating_scrollable_areas = + frame_view.AnimatingScrollableAreas()) { + for (PaintLayerScrollableArea* area : *animating_scrollable_areas) + area->UpdateCompositorScrollAnimations(); + } + { + // Updating animations can notify ready promises which could mutate + // the DOM. We should delay these until we have finished the lifecycle + // update. https://crbug.com/1196781 + ScriptForbiddenScope forbid_script; + frame_view.GetLayoutView() + ->GetDocument() + .GetDocumentAnimations() + .UpdateAnimations(DocumentLifecycle::kPaintClean, + paint_artifact_compositor_.get()); + } + Document& document = frame_view.GetLayoutView()->GetDocument(); + total_animations_count += + document.GetDocumentAnimations().GetAnimationsCount(); + current_frame_had_raf |= document.CurrentFrameHadRAF(); + next_frame_has_pending_raf |= document.NextFrameHasPendingRAF(); + }); - // Initialize animation properties in the newly created paint property - // nodes according to the current animation state. This is mainly for - // the running composited animations which didn't change state during - // above UpdateAnimations() but associated with new paint property nodes. - if (needed_update) { - auto* root_layer = RootCcLayer(); - if (root_layer && root_layer->layer_tree_host()) { - root_layer->layer_tree_host() - ->mutator_host() - ->InitClientAnimationState(); - } + if (GetLayoutView()->GetDocument().View() && + GetLayoutView()->GetDocument().View()->GetCompositorAnimationHost()) { + GetLayoutView() + ->GetDocument() + .View() + ->GetCompositorAnimationHost() + ->SetAnimationCounts(total_animations_count, current_frame_had_raf, + next_frame_has_pending_raf); + } + + // Initialize animation properties in the newly created paint property + // nodes according to the current animation state. This is mainly for + // the running composited animations which didn't change state during + // above UpdateAnimations() but associated with new paint property nodes. + if (needed_update) { + auto* root_layer = RootCcLayer(); + if (root_layer && root_layer->layer_tree_host()) { + root_layer->layer_tree_host()->mutator_host()->InitClientAnimationState(); } + } - // Notify the controller that the artifact has been pushed and some - // lifecycle state can be freed (such as raster invalidations). - if (paint_controller_) - paint_controller_->FinishCycle(); + // Notify the controller that the artifact has been pushed and some + // lifecycle state can be freed (such as raster invalidations). + if (paint_controller_) + paint_controller_->FinishCycle(); - if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer(); - if (root) { - ForAllPaintingGraphicsLayers(*root, [](GraphicsLayer& layer) { - // Notify the paint controller that the artifact has been pushed and - // some lifecycle state can be freed (such as raster invalidations). - layer.GetPaintController().FinishCycle(); - }); - } + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer(); + if (root) { + ForAllPaintingGraphicsLayers(*root, [](GraphicsLayer& layer) { + // Notify the paint controller that the artifact has been pushed and + // some lifecycle state can be freed (such as raster invalidations). + layer.GetPaintController().FinishCycle(); + }); } - - if (paint_artifact_compositor_) - paint_artifact_compositor_->ClearPropertyTreeChangedState(); } + if (paint_artifact_compositor_) + paint_artifact_compositor_->ClearPropertyTreeChangedState(); + if (GetPage()) GetPage()->Animator().ReportFrameAnimations(GetCompositorAnimationHost()); } @@ -3161,12 +3253,31 @@ void LocalFrameView::PushPaintArtifactToCompositor(bool repainted) { }); } + WTF::Vector<std::unique_ptr<DocumentTransition::Request>> + document_transition_requests; + // TODO(vmpstr): We should make this work for subframes as well. + AppendDocumentTransitionRequests(document_transition_requests); + paint_artifact_compositor_->Update( - pre_composited_layers_, viewport_properties, scroll_translation_nodes); + pre_composited_layers_, viewport_properties, scroll_translation_nodes, + std::move(document_transition_requests)); probe::LayerTreePainted(&GetFrame()); } +void LocalFrameView::AppendDocumentTransitionRequests( + WTF::Vector<std::unique_ptr<DocumentTransition::Request>>& requests) { + DCHECK(frame_ && frame_->GetDocument()); + auto* document_transition_supplement = + DocumentTransitionSupplement::FromIfExists(*frame_->GetDocument()); + if (!document_transition_supplement) + return; + auto* document_transition = document_transition_supplement->GetTransition(); + auto pending_request = document_transition->TakePendingRequest(); + if (pending_request) + requests.push_back(std::move(pending_request)); +} + std::unique_ptr<JSONObject> LocalFrameView::CompositedLayersAsJSON( LayerTreeFlags flags) { auto* root_frame_view = GetFrame().LocalFrameRoot().View(); @@ -3196,7 +3307,7 @@ void LocalFrameView::UpdateStyleAndLayoutIfNeededRecursive() { { SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(), LocalFrameUkmAggregator::kStyle); - frame_->GetDocument()->UpdateStyleAndLayoutTree(); + frame_->GetDocument()->UpdateStyleAndLayoutTreeForThisDocument(); // Update style for all embedded SVG documents underneath this frame, so // that intrinsic size computation for any embedded objects has up-to-date @@ -3204,7 +3315,7 @@ void LocalFrameView::UpdateStyleAndLayoutIfNeededRecursive() { ForAllChildLocalFrameViews([](LocalFrameView& view) { Document& document = *view.GetFrame().GetDocument(); if (document.IsSVGDocument()) - document.UpdateStyleAndLayoutTree(); + document.UpdateStyleAndLayoutTreeForThisDocument(); }); } @@ -3691,7 +3802,8 @@ void LocalFrameView::AttachToLayout() { if (parent_view->IsVisible()) SetParentVisible(true); UpdateRenderThrottlingStatus(IsHiddenForThrottling(), - parent_view->CanThrottleRendering()); + parent_view->CanThrottleRendering(), + IsDisplayLocked()); // We may have updated paint properties in detached frame subtree for // printing (see UpdateLifecyclePhasesForPrinting()). The paint properties @@ -3775,7 +3887,15 @@ void LocalFrameView::PropagateFrameRects() { } }); - GetFrame().Client()->FrameRectsChanged(FrameRect()); + // To limit the number of Mojo communications, only notify the browser when + // the rect's size changes, not when the position changes. The size needs to + // be replicated if the iframe goes out-of-process. + IntSize frame_size = FrameRect().Size(); + if (!frame_size_ || *frame_size_ != frame_size) { + frame_size_ = frame_size; + GetFrame().GetLocalFrameHostRemote().FrameSizeChanged( + gfx::Size(frame_size)); + } // It's possible for changing the frame rect to not generate a layout // or any other event tracked by accessibility, we've seen this with @@ -3796,33 +3916,6 @@ void LocalFrameView::SetLayoutSizeInternal(const IntSize& size) { SetNeedsLayout(); } -void LocalFrameView::ClipPaintRect(FloatRect* paint_rect) const { - // TODO(wangxianzhu): Support ChromeClient::VisibleContentRectForPainting() - // with CompositeAfterPaint. - DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); - - // Paint the whole rect if ClipsContent is false, meaning that the whole - // document should be recorded. This occurs if: - // - A paint preview is being captured. - // - WebPreferences::record_whole_document is true. - if (!frame_->ClipsContent()) - return; - - // By default we consider the bounds of the FrameView to be what is considered - // visible for the Frame. - IntRect visible_rect = IntRect(IntPoint(), Size()); - // Non-main frames always clip to their FrameView bounds. Main frames can - // have this behaviour modified by devtools. - if (frame_->IsMainFrame()) { - // If devtools is overriding the viewport, then the FrameView's bounds are - // not what we should paint, instead we should paint inside the bounds - // specified by devtools. - GetPage()->GetChromeClient().OverrideVisibleRectForMainFrame(*frame_, - &visible_rect); - } - paint_rect->Intersect(visible_rect); -} - void LocalFrameView::DidChangeScrollOffset() { GetFrame().Client()->DidChangeScrollOffset(); if (GetFrame().IsMainFrame()) { @@ -3998,13 +4091,19 @@ void LocalFrameView::Paint(GraphicsContext& context, const GlobalPaintFlags global_paint_flags, const CullRect& cull_rect, const IntSize& paint_offset) const { - // When capturing a Paint Preview we want to capture scrollable embedded - // content separately. Paint should stop here and ask the browser to - // coordinate painting such frames as a separate task. - if (context.IsPaintingPreview() && LayoutViewport()->ScrollsOverflow()) { - // If capture fails we should fallback to capturing inline if possible. - if (CapturePaintPreview(context, paint_offset)) - return; + const auto* owner_layout_object = GetFrame().OwnerLayoutObject(); + base::Optional<Document::PaintPreviewScope> paint_preview; + if (owner_layout_object && + owner_layout_object->GetDocument().IsPaintingPreview()) { + paint_preview.emplace(*GetFrame().GetDocument()); + // When capturing a Paint Preview we want to capture scrollable embedded + // content separately. Paint should stop here and ask the browser to + // coordinate painting such frames as a separate task. + if (LayoutViewport()->ScrollsOverflow()) { + // If capture fails we should fallback to capturing inline if possible. + if (CapturePaintPreview(context, paint_offset)) + return; + } } // |paint_offset| is not used because paint properties of the contents will @@ -4051,7 +4150,10 @@ void LocalFrameView::PaintOutsideOfLifecycle( frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint); }); - PaintInternal(context, global_paint_flags, cull_rect); + { + OverriddenCullRectScope force_cull_rect(*this, cull_rect); + PaintInternal(context, global_paint_flags, cull_rect); + } ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean); @@ -4068,7 +4170,10 @@ void LocalFrameView::PaintContentsOutsideOfLifecycle( frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint); }); - FramePainter(*this).PaintContents(context, global_paint_flags, cull_rect); + { + OverriddenCullRectScope force_cull_rect(*this, cull_rect); + FramePainter(*this).PaintContents(context, global_paint_flags, cull_rect); + } ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean); @@ -4078,6 +4183,7 @@ void LocalFrameView::PaintContentsOutsideOfLifecycle( void LocalFrameView::PaintContentsForTest(const CullRect& cull_rect) { AllowThrottlingScope allow_throttling(*this); Lifecycle().AdvanceTo(DocumentLifecycle::kInPaint); + OverriddenCullRectScope force_cull_rect(*this, cull_rect); if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { PaintController& paint_controller = EnsurePaintController(); if (GetLayoutView()->Layer()->SelfOrDescendantNeedsRepaint()) { @@ -4277,7 +4383,7 @@ bool LocalFrameView::UpdateViewportIntersectionsForSubtree( unsigned flags = GetIntersectionObservationFlags(parent_flags); bool needs_occlusion_tracking = false; - if (!NeedsLayout()) { + if (!NeedsLayout() || IsDisplayLocked()) { // Notify javascript IntersectionObservers if (IntersectionObserverController* controller = GetFrame().GetDocument()->GetIntersectionObserverController()) { @@ -4287,7 +4393,12 @@ bool LocalFrameView::UpdateViewportIntersectionsForSubtree( intersection_observation_state_ = kNotNeeded; } - UpdateViewportIntersection(flags, needs_occlusion_tracking); + { + SCOPED_UMA_AND_UKM_TIMER( + EnsureUkmAggregator(), + LocalFrameUkmAggregator::kUpdateViewportIntersection); + UpdateViewportIntersection(flags, needs_occlusion_tracking); + } for (Frame* child = frame_->Tree().FirstChild(); child; child = child->Tree().NextSibling()) { @@ -4321,26 +4432,19 @@ void LocalFrameView::CrossOriginToMainFrameChanged() { // If any of these conditions hold, then a change in cross-origin status does // not affect throttling. if (lifecycle_updates_throttled_ || IsSubtreeThrottled() || - !IsHiddenForThrottling()) { + IsDisplayLocked() || !IsHiddenForThrottling()) { return; } RenderThrottlingStatusChanged(); - // We need to invalidate unconditionally, so if it didn't happen during - // RenderThrottlingStatusChanged, do it now. - if (CanThrottleRendering()) - InvalidateForThrottlingChange(); // Immediately propagate changes to children. UpdateRenderThrottlingStatus(IsHiddenForThrottling(), IsSubtreeThrottled(), - true); + IsDisplayLocked(), true); } void LocalFrameView::CrossOriginToParentFrameChanged() { - if (base::FeatureList::IsEnabled( - blink::features::kCompositeCrossOriginIframes)) { - if (LayoutView* layout_view = GetLayoutView()) { - if (PaintLayer* root_layer = layout_view->Layer()) - root_layer->SetNeedsCompositingInputsUpdate(); - } + if (LayoutView* layout_view = GetLayoutView()) { + if (PaintLayer* root_layer = layout_view->Layer()) + root_layer->SetNeedsCompositingInputsUpdate(); } } @@ -4367,11 +4471,21 @@ void LocalFrameView::RenderThrottlingStatusChanged() { SetPaintArtifactCompositorNeedsUpdate(); if (!CanThrottleRendering()) { - InvalidateForThrottlingChange(); + // Start ticking animation frames again if necessary. + if (GetPage()) + GetPage()->Animator().ScheduleVisualUpdate(frame_.Get()); + // Ensure we'll recompute viewport intersection for the frame subtree during + // the scheduled visual update. + SetIntersectionObservationState(kRequired); + // When a frame is throttled, we typically delete its previous painted + // output, so it will need to be repainted, even if nothing else has + // changed. + if (LayoutView* layout_view = GetLayoutView()) + layout_view->Layer()->SetNeedsRepaint(); } else if (GetFrame().IsLocalRoot()) { // By this point, every frame in the local frame tree has become throttled, // so painting the tree should just clear the previous painted output. - DCHECK(!in_lifecycle_update_); + DCHECK(!IsUpdatingLifecycle()); AllowThrottlingScope allow_throtting(*this); RunPaintLifecyclePhase(); } @@ -4386,26 +4500,6 @@ void LocalFrameView::RenderThrottlingStatusChanged() { #endif } -void LocalFrameView::InvalidateForThrottlingChange() { - // Start ticking animation frames again if necessary. - if (GetPage()) - GetPage()->Animator().ScheduleVisualUpdate(frame_.Get()); - // Force a full repaint of this frame to ensure we are not left with a - // partially painted version of this frame's contents if we skipped - // painting them while the frame was throttled. - LayoutView* layout_view = GetLayoutView(); - if (layout_view) { - layout_view->InvalidatePaintForViewAndDescendants(); - // Also need to update all paint properties that might be skipped while - // the frame was throttled. - layout_view->AddSubtreePaintPropertyUpdateReason( - SubtreePaintPropertyUpdateReason::kPreviouslySkipped); - } - // Ensure we'll recompute viewport intersection for the frame subtree during - // the scheduled visual update. - SetIntersectionObservationState(kRequired); -} - void LocalFrameView::SetNeedsForcedCompositingUpdate() { needs_forced_compositing_update_ = true; if (LocalFrameView* parent = ParentFrameView()) @@ -4479,14 +4573,25 @@ bool LocalFrameView::ShouldThrottleRendering() const { if (!throttled_for_global_reasons || needs_forced_compositing_update_) return false; - if (intersection_observation_state_ == kRequired) { - auto* local_frame_root_view = GetFrame().LocalFrameRoot().View(); - // When doing a lifecycle update required by intersection observer, we can - // throttle lifecycle states after layout. Outside of lifecycle updates, - // the frame should be considered throttled because it is not fully updating - // the lifecycle. - return !local_frame_root_view->in_lifecycle_update_ || - local_frame_root_view->past_layout_lifecycle_update_; + // If we're currently running a lifecycle update, and we are required to run + // the IntersectionObserver steps at the end of the update, then there are two + // courses of action, depending on whether this frame is display locked by its + // parent frame: + // + // - If it is NOT display locked, then we suppress throttling to force the + // lifecycle update to proceed up to the state required to run + // IntersectionObserver. + // + // - If it IS display locked, then we still need IntersectionObserver to + // run; but the display lock status will short-circuit the + // IntersectionObserver algorithm and create degenerate "not intersecting" + // notifications. Hence, we don't need to force lifecycle phases to run, + // because IntersectionObserver will not need access to up-to-date + // geometry. So there is no point in suppressing throttling here. + auto* local_frame_root_view = GetFrame().LocalFrameRoot().View(); + if (local_frame_root_view->IsUpdatingLifecycle() && + intersection_observation_state_ == kRequired && !IsDisplayLocked()) { + return Lifecycle().GetState() >= DocumentLifecycle::kPrePaintClean; } return true; @@ -4498,10 +4603,10 @@ bool LocalFrameView::ShouldThrottleRenderingForTest() const { } bool LocalFrameView::CanThrottleRendering() const { - if (lifecycle_updates_throttled_) - return true; - if (IsSubtreeThrottled()) + if (lifecycle_updates_throttled_ || IsSubtreeThrottled() || + IsDisplayLocked()) { return true; + } // We only throttle hidden cross-origin frames. This is to avoid a situation // where an ancestor frame directly depends on the pipeline timing of a // descendant and breaks as a result of throttling. The rationale is that @@ -4513,10 +4618,11 @@ bool LocalFrameView::CanThrottleRendering() const { void LocalFrameView::UpdateRenderThrottlingStatus(bool hidden_for_throttling, bool subtree_throttled, + bool display_locked, bool recurse) { bool was_throttled = CanThrottleRendering(); - FrameView::UpdateRenderThrottlingStatus(hidden_for_throttling, - subtree_throttled, recurse); + FrameView::UpdateRenderThrottlingStatus( + hidden_for_throttling, subtree_throttled, display_locked, recurse); if (was_throttled != CanThrottleRendering()) RenderThrottlingStatusChanged(); } @@ -4528,8 +4634,6 @@ void LocalFrameView::BeginLifecycleUpdates() { if (GetFrame().GetDocument()->IsInitialEmptyDocument()) return; lifecycle_updates_throttled_ = false; - if (auto* owner = GetLayoutEmbeddedContent()) - owner->SetShouldCheckForPaintInvalidation(); LayoutView* layout_view = GetLayoutView(); bool layout_view_is_empty = layout_view && !layout_view->FirstChild(); @@ -4588,20 +4692,6 @@ int LocalFrameView::InitialViewportHeight() const { return initial_viewport_size_.Height(); } -bool LocalFrameView::HasVisibleSlowRepaintViewportConstrainedObjects() const { - if (!ViewportConstrainedObjects()) - return false; - for (const LayoutObject* layout_object : *ViewportConstrainedObjects()) { - DCHECK(layout_object->HasLayer()); - DCHECK(layout_object->StyleRef().GetPosition() == EPosition::kFixed || - layout_object->StyleRef().GetPosition() == EPosition::kSticky); - if (To<LayoutBoxModelObject>(layout_object) - ->IsSlowRepaintConstrainedObject()) - return true; - } - return false; -} - MainThreadScrollingReasons LocalFrameView::MainThreadScrollingReasonsPerFrame() const { MainThreadScrollingReasons reasons = @@ -4614,18 +4704,6 @@ MainThreadScrollingReasons LocalFrameView::MainThreadScrollingReasonsPerFrame() reasons |= cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; } - - // Force main-thread scrolling if the frame has uncomposited position: fixed - // elements. Note: we care about this not only for input-scrollable frames - // but also for overflow: hidden frames, because script can run composited - // smooth-scroll animations. For this reason, we use HasOverflow instead of - // ScrollsOverflow (which is false for overflow: hidden). - if (LayoutViewport()->HasOverflow() && - GetLayoutView()->StyleRef().VisibleToHitTesting() && - HasVisibleSlowRepaintViewportConstrainedObjects()) { - reasons |= - cc::MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects; - } return reasons; } |