diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc | 131 |
1 files changed, 101 insertions, 30 deletions
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc index 325f8c5af37..a79f58d730d 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc @@ -6,31 +6,25 @@ #include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/geometry/layout_rect.h" +#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h" +#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h" +#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/transforms/affine_transform.h" namespace blink { -CullRect::CullRect(const CullRect& cull_rect, const IntPoint& offset) { - rect_ = cull_rect.rect_; - rect_.MoveBy(offset); +bool CullRect::Intersects(const IntRect& rect) const { + return IsInfinite() || rect.Intersects(rect_); } -CullRect::CullRect(const CullRect& cull_rect, const IntSize& offset) { - rect_ = cull_rect.rect_; - rect_.Move(offset); +bool CullRect::Intersects(const LayoutRect& rect) const { + return IsInfinite() || rect_.Intersects(EnclosingIntRect(rect)); } -bool CullRect::IntersectsCullRect(const IntRect& bounding_box) const { - return bounding_box.Intersects(rect_); -} - -bool CullRect::IntersectsCullRect(const AffineTransform& transform, - const FloatRect& bounding_box) const { - return transform.MapRect(bounding_box).Intersects(rect_); -} - -bool CullRect::IntersectsCullRect(const LayoutRect& rect_arg) const { - return rect_.Intersects(EnclosingIntRect(rect_arg)); +bool CullRect::IntersectsTransformed(const AffineTransform& transform, + const FloatRect& rect) const { + return IsInfinite() || transform.MapRect(rect).Intersects(rect_); } bool CullRect::IntersectsHorizontalRange(LayoutUnit lo, LayoutUnit hi) const { @@ -41,23 +35,100 @@ bool CullRect::IntersectsVerticalRange(LayoutUnit lo, LayoutUnit hi) const { return !(lo >= rect_.MaxY() || hi <= rect_.Y()); } -void CullRect::UpdateCullRect( - const AffineTransform& local_to_parent_transform) { - if (rect_ != LayoutRect::InfiniteIntRect()) - rect_ = local_to_parent_transform.Inverse().MapRect(rect_); +void CullRect::MoveBy(const IntPoint& offset) { + if (!IsInfinite()) + rect_.MoveBy(offset); +} + +void CullRect::Move(const IntSize& offset) { + if (!IsInfinite()) + rect_.Move(offset); +} + +CullRect::ApplyTransformResult CullRect::ApplyTransformInternal( + const TransformPaintPropertyNode* transform) { + if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + if (const auto* scroll = transform->ScrollNode()) { + rect_.Intersect(scroll->ContainerRect()); + if (rect_.IsEmpty()) + return kNotExpanded; + rect_ = transform->Matrix().Inverse().MapRect(rect_); + + // Expand the cull rect for scrolling contents in case of composited + // scrolling. + // TODO(wangxianzhu): options for non-composited-scrolling contents: + // 1. to use non-composted-scrolling heuristics to avoid expansion; + // 2. to reduce the 4000px distance, no matter if the contents with be + // composited scrolling. + // 3. mixed method of 1 and 2, e.g. the distance could be a function of + // confidence that the contents will be composited scrolling. + static const int kPixelDistanceToExpand = 4000; + rect_.Inflate(kPixelDistanceToExpand); + // Don't clip the cull rect by contents size to let ChangedEnough() work + // even if the new cull rect exceeds the bounds of contents rect. + return rect_.Contains(IntRect(IntPoint(), scroll->ContentsSize())) + ? kExpandedForWholeScrollingContents + : kExpandedForPartialScrollingContents; + } + } + + if (!IsInfinite()) + rect_ = transform->Matrix().Inverse().MapRect(rect_); + return kNotExpanded; } -void CullRect::UpdateForScrollingContents( - const IntRect& overflow_clip_rect, - const AffineTransform& local_to_parent_transform) { +void CullRect::ApplyTransforms(const TransformPaintPropertyNode* source, + const TransformPaintPropertyNode* destination, + const base::Optional<CullRect>& old_cull_rect) { DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled()); - rect_.Intersect(overflow_clip_rect); - UpdateCullRect(local_to_parent_transform); - // TODO(wangxianzhu, chrishtr): How about non-composited scrolling contents? - // The distance to expand the cull rect for scrolling contents. - static const int kPixelDistanceToExpand = 4000; - rect_.Inflate(kPixelDistanceToExpand); + Vector<const TransformPaintPropertyNode*> scroll_translations; + for (const auto* t = destination; t != source; t = t->Parent()) { + if (!t) { + // |source| is not an ancestor of |destination|. Simply map. + GeometryMapper::SourceToDestinationRect(source, destination, rect_); + return; + } + if (t->ScrollNode()) + scroll_translations.push_back(t); + } + + const auto* last_transform = source; + ApplyTransformResult last_scroll_translation_result = kNotExpanded; + for (auto it = scroll_translations.rbegin(); it != scroll_translations.rend(); + ++it) { + const auto* scroll_translation = *it; + if (!IsInfinite()) { + GeometryMapper::SourceToDestinationRect( + last_transform, scroll_translation->Parent(), rect_); + } + last_scroll_translation_result = ApplyTransformInternal(scroll_translation); + last_transform = scroll_translation; + } + + if (!IsInfinite()) + GeometryMapper::SourceToDestinationRect(last_transform, destination, rect_); + + if (last_scroll_translation_result == kExpandedForPartialScrollingContents && + old_cull_rect && !ChangedEnough(*old_cull_rect)) + rect_ = old_cull_rect->Rect(); +} + +bool CullRect::ChangedEnough(const CullRect& old_cull_rect) const { + DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled()); + + const auto& new_rect = Rect(); + const auto& old_rect = old_cull_rect.Rect(); + if (old_rect == new_rect || (old_rect.IsEmpty() && new_rect.IsEmpty())) + return false; + + if (old_rect.IsEmpty()) + return true; + + auto expanded_old_rect = old_rect; + static const int kChangedEnoughMinimumDistance = 512; + expanded_old_rect.Inflate(kChangedEnoughMinimumDistance); + return !expanded_old_rect.Contains(new_rect); } } // namespace blink |