Commit dd04f482 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Add early return logic to LayoutNGBlockFlowMixin::NodeAtPoint

Following r813630 crrev.com/c/2448269 that added the early
return to |NGBoxFragmentPainter::NodeAtPoint|, this patch:
* Extracts more correct early return logic from |LayoutBox::
  HitTestAllPhases|. It looks like |LayoutNGBlockFlowMixin|
  copied from it in 2017 (r508056 crrev.com/c/710498), but
  the logic in |LayoutBox::HitTestAllPhases| evolved.
* Changes |IsScrollContainer| to
  |ShouldClipOverflowAlongBothAxis| because it misses
  other clipping situations.
* Changes to unite |PhysicalBorderBoxRect| and the overflow.
* Changes |LayoutNGBlockFlowMixin| to apply the early return
  logic not only when |NGPaintFragment|.

The early return in |LayoutNGBlockFlowMixin| improves the
perf test by ~65%, to almost equivalent to M85.

Note the previous patch (r813630) should match this, I will
do it in a following patch.

Bug: 1134574
Change-Id: If8e2fc5f52254168cd994c7fdf1d54aa5653da0c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2448709
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814225}
parent f0280e6c
......@@ -2238,30 +2238,38 @@ LayoutUnit LayoutBox::AdjustContentBoxLogicalHeightForBoxSizing(
}
// Hit Testing
bool LayoutBox::HitTestAllPhases(HitTestResult& result,
const HitTestLocation& hit_test_location,
const PhysicalOffset& accumulated_offset,
HitTestFilter hit_test_filter) {
bool LayoutBox::MayIntersect(const HitTestResult& result,
const HitTestLocation& hit_test_location,
const PhysicalOffset& accumulated_offset) const {
NOT_DESTROYED();
// Check if we need to do anything at all.
// If we have clipping, then we can't have any spillout.
// TODO(pdr): Why is this optimization not valid for the effective root?
if (!IsEffectiveRootScroller()) {
PhysicalRect overflow_box;
if (result.GetHitTestRequest().GetType() &
HitTestRequest::kHitTestVisualOverflow) {
overflow_box = PhysicalVisualOverflowRectIncludingFilters();
} else {
overflow_box = (IsScrollContainer() || ShouldApplyPaintContainment())
? PhysicalBorderBoxRect()
: PhysicalVisualOverflowRect();
}
if (UNLIKELY(IsEffectiveRootScroller()))
return true;
PhysicalRect adjusted_overflow_box = overflow_box;
adjusted_overflow_box.Move(accumulated_offset);
if (!hit_test_location.Intersects(adjusted_overflow_box))
return false;
PhysicalRect overflow_box;
if (result.GetHitTestRequest().GetType() &
HitTestRequest::kHitTestVisualOverflow) {
overflow_box = PhysicalVisualOverflowRectIncludingFilters();
} else {
// Unite because overflow may not include borders.
overflow_box = PhysicalBorderBoxRect();
if (!ShouldClipOverflowAlongBothAxis() && HasVisualOverflow())
overflow_box.Unite(PhysicalVisualOverflowRect());
}
overflow_box.Move(accumulated_offset);
return hit_test_location.Intersects(overflow_box);
}
bool LayoutBox::HitTestAllPhases(HitTestResult& result,
const HitTestLocation& hit_test_location,
const PhysicalOffset& accumulated_offset,
HitTestFilter hit_test_filter) {
NOT_DESTROYED();
if (!MayIntersect(result, hit_test_location, accumulated_offset))
return false;
return LayoutObject::HitTestAllPhases(result, hit_test_location,
accumulated_offset, hit_test_filter);
}
......@@ -2271,6 +2279,9 @@ bool LayoutBox::NodeAtPoint(HitTestResult& result,
const PhysicalOffset& accumulated_offset,
HitTestAction action) {
NOT_DESTROYED();
if (!MayIntersect(result, hit_test_location, accumulated_offset))
return false;
bool should_hit_test_self = IsInSelfHitTestingPhase(action);
if (should_hit_test_self && IsScrollContainer() &&
......
......@@ -995,6 +995,10 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
const HitTestLocation&,
const PhysicalOffset& accumulated_offset,
HitTestAction) override;
// Fast check if |NodeAtPoint| may find a hit.
bool MayIntersect(const HitTestResult& result,
const HitTestLocation& hit_test_location,
const PhysicalOffset& accumulated_offset) const;
// This function calculates the preferred widths for an object.
//
......
......@@ -216,17 +216,10 @@ bool LayoutNGBlockFlowMixin<Base>::NodeAtPoint(
const HitTestLocation& hit_test_location,
const PhysicalOffset& accumulated_offset,
HitTestAction action) {
if (!Base::MayIntersect(result, hit_test_location, accumulated_offset))
return false;
if (const NGPaintFragment* paint_fragment = PaintFragment()) {
if (!Base::IsEffectiveRootScroller()) {
// Check if we need to do anything at all.
// If we have clipping, then we can't have any spillout.
PhysicalRect overflow_box = Base::IsScrollContainer()
? Base::PhysicalBorderBoxRect()
: Base::PhysicalVisualOverflowRect();
overflow_box.Move(accumulated_offset);
if (!hit_test_location.Intersects(overflow_box))
return false;
}
if (Base::IsInSelfHitTestingPhase(action) && Base::IsScrollContainer() &&
Base::HitTestOverflowControl(result, hit_test_location,
accumulated_offset))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment