Commit 179ebccd authored by Stefan Zager's avatar Stefan Zager Committed by Commit Bot

[IntersectionObserver] Compute RootGeometry once per observer

For an observer with multiple observations, this avoids doing redundant
work to compute the local bounds of the root and its transform to
absolute coordinates.

BUG=956071

Change-Id: I587997da1f5f120a1fd276f703aa1e5a1131696b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1774246
Commit-Queue: Stefan Zager <szager@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#692206}
parent d5704c68
...@@ -217,6 +217,21 @@ IntersectionGeometry::IntersectionGeometry(const Element* root_element, ...@@ -217,6 +217,21 @@ IntersectionGeometry::IntersectionGeometry(const Element* root_element,
ComputeGeometry(root_geometry, root, target, thresholds); ComputeGeometry(root_geometry, root, target, thresholds);
} }
IntersectionGeometry::IntersectionGeometry(const RootGeometry& root_geometry,
const Element& explicit_root,
const Element& target_element,
const Vector<float>& thresholds,
unsigned flags)
: flags_(flags & kConstructorFlagsMask),
intersection_ratio_(0),
threshold_index_(0) {
LayoutObject* target = GetTargetLayoutObject(target_element);
LayoutObject* root = explicit_root.GetLayoutObject();
if (!IsContainingBlockChainDescendant(target, root))
return;
ComputeGeometry(root_geometry, root, target, thresholds);
}
IntersectionGeometry::~IntersectionGeometry() = default; IntersectionGeometry::~IntersectionGeometry() = default;
void IntersectionGeometry::ComputeGeometry(const RootGeometry& root_geometry, void IntersectionGeometry::ComputeGeometry(const RootGeometry& root_geometry,
......
...@@ -58,6 +58,12 @@ class CORE_EXPORT IntersectionGeometry { ...@@ -58,6 +58,12 @@ class CORE_EXPORT IntersectionGeometry {
const Vector<float>& thresholds, const Vector<float>& thresholds,
unsigned flags); unsigned flags);
IntersectionGeometry(const RootGeometry& root_geometry,
const Element& explicit_root,
const Element& target,
const Vector<float>& thresholds,
unsigned flags);
IntersectionGeometry(const IntersectionGeometry&) = default; IntersectionGeometry(const IntersectionGeometry&) = default;
~IntersectionGeometry(); ~IntersectionGeometry();
......
...@@ -30,6 +30,18 @@ IntersectionObservation::IntersectionObservation(IntersectionObserver& observer, ...@@ -30,6 +30,18 @@ IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
// different sentinel value. // different sentinel value.
last_threshold_index_(kMaxThresholdIndex - 1) {} last_threshold_index_(kMaxThresholdIndex - 1) {}
void IntersectionObservation::ComputeIntersection(
const IntersectionGeometry::RootGeometry& root_geometry,
unsigned compute_flags) {
if (!ShouldCompute(compute_flags))
return;
DCHECK(observer_->root());
unsigned geometry_flags = GetIntersectionGeometryFlags(compute_flags);
IntersectionGeometry geometry(root_geometry, *observer_->root(), *Target(),
observer_->thresholds(), geometry_flags);
ProcessIntersectionGeometry(geometry);
}
void IntersectionObservation::ComputeIntersection(unsigned compute_flags) { void IntersectionObservation::ComputeIntersection(unsigned compute_flags) {
if (!ShouldCompute(compute_flags)) if (!ShouldCompute(compute_flags))
return; return;
......
...@@ -21,7 +21,7 @@ class IntersectionObserver; ...@@ -21,7 +21,7 @@ class IntersectionObserver;
class IntersectionObservation final class IntersectionObservation final
: public GarbageCollected<IntersectionObservation> { : public GarbageCollected<IntersectionObservation> {
public: public:
// Flags that drive the behavior of the ComputeIntersection() method. For an // Flags that drive the behavior of the ComputeIntersections() method. For an
// explanation of implicit vs. explicit root, see intersection_observer.h. // explanation of implicit vs. explicit root, see intersection_observer.h.
enum ComputeFlags { enum ComputeFlags {
// If this bit is set, and observer_->RootIsImplicit() is true, then the // If this bit is set, and observer_->RootIsImplicit() is true, then the
...@@ -46,6 +46,9 @@ class IntersectionObservation final ...@@ -46,6 +46,9 @@ class IntersectionObservation final
Element* Target() const { return target_; } Element* Target() const { return target_; }
unsigned LastThresholdIndex() const { return last_threshold_index_; } unsigned LastThresholdIndex() const { return last_threshold_index_; }
void ComputeIntersection(unsigned flags); void ComputeIntersection(unsigned flags);
void ComputeIntersection(
const IntersectionGeometry::RootGeometry& root_geometry,
unsigned flags);
void TakeRecords(HeapVector<Member<IntersectionObserverEntry>>&); void TakeRecords(HeapVector<Member<IntersectionObserverEntry>>&);
void Disconnect(); void Disconnect();
......
...@@ -387,11 +387,13 @@ bool IntersectionObserver::ComputeIntersections(unsigned flags) { ...@@ -387,11 +387,13 @@ bool IntersectionObserver::ComputeIntersections(unsigned flags) {
DCHECK(!RootIsImplicit()); DCHECK(!RootIsImplicit());
if (!RootIsValid() || !GetExecutionContext() || observations_.IsEmpty()) if (!RootIsValid() || !GetExecutionContext() || observations_.IsEmpty())
return false; return false;
IntersectionGeometry::RootGeometry root_geometry(root()->GetLayoutObject(),
root_margin_);
HeapVector<Member<IntersectionObservation>> observations_to_process; HeapVector<Member<IntersectionObservation>> observations_to_process;
// TODO(szager): Is this copy necessary? // TODO(szager): Is this copy necessary?
CopyToVector(observations_, observations_to_process); CopyToVector(observations_, observations_to_process);
for (auto& observation : observations_to_process) { for (auto& observation : observations_to_process) {
observation->ComputeIntersection(flags); observation->ComputeIntersection(root_geometry, flags);
} }
return trackVisibility(); return trackVisibility();
} }
......
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