blob: b6f0e1d076f762318cf9bcbeefba02cabf0a6667 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PaintInvalidator_h
#define PaintInvalidator_h
#include "core/layout/LayoutObject.h"
#include "core/paint/PaintPropertyTreeBuilder.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/wtf/Vector.h"
namespace blink {
struct CORE_EXPORT PaintInvalidatorContext {
USING_FAST_MALLOC(PaintInvalidatorContext);
public:
PaintInvalidatorContext() : parent_context(nullptr) {}
PaintInvalidatorContext(const PaintInvalidatorContext& parent_context)
: parent_context(&parent_context),
subtree_flags(parent_context.subtree_flags),
paint_invalidation_container(
parent_context.paint_invalidation_container),
paint_invalidation_container_for_stacked_contents(
parent_context.paint_invalidation_container_for_stacked_contents),
painting_layer(parent_context.painting_layer) {}
// This method is virtual temporarily to adapt PaintInvalidatorContext and the
// legacy PaintInvalidationState for code shared by old code and new code.
virtual void MapLocalRectToVisualRectInBacking(const LayoutObject&,
LayoutRect&) const;
bool NeedsVisualRectUpdate(const LayoutObject& object) const {
if (!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled())
return true;
#if DCHECK_IS_ON()
if (force_visual_rect_update_for_checking_)
return true;
#endif
return object.NeedsPaintOffsetAndVisualRectUpdate() ||
(subtree_flags & PaintInvalidatorContext::kSubtreeVisualRectUpdate);
}
const PaintInvalidatorContext* parent_context;
enum SubtreeFlag {
kSubtreeInvalidationChecking = 1 << 0,
kSubtreeVisualRectUpdate = 1 << 1,
kSubtreeFullInvalidation = 1 << 2,
kSubtreeFullInvalidationForStackedContents = 1 << 3,
kSubtreeSVGResourceChange = 1 << 4,
// TODO(crbug.com/637313): This is temporary before we support filters in
// paint property tree.
kSubtreeSlowPathRect = 1 << 5,
// When this flag is set, no paint or raster invalidation will be issued
// for the subtree.
//
// Context: some objects in this paint walk, for example SVG resource
// container subtrees, always paint onto temporary PaintControllers which
// don't have cache, and don't actually have any raster regions, so they
// don't need any invalidation. They are used as "painting subroutines"
// for one or more other locations in SVG.
kSubtreeNoInvalidation = 1 << 6,
};
unsigned subtree_flags = 0;
// The following fields can be null only before
// PaintInvalidator::updateContext().
// The current paint invalidation container for normal flow objects.
// It is the enclosing composited object.
const LayoutBoxModelObject* paint_invalidation_container = nullptr;
// The current paint invalidation container for stacked contents (stacking
// contexts or positioned objects). It is the nearest ancestor composited
// object which establishes a stacking context. See
// Source/core/paint/README.md ### PaintInvalidationState for details on how
// stacked contents' paint invalidation containers differ.
const LayoutBoxModelObject*
paint_invalidation_container_for_stacked_contents = nullptr;
PaintLayer* painting_layer = nullptr;
// Store the old visual rect in the paint invalidation backing's coordinates.
// It does *not* account for composited scrolling.
// See LayoutObject::adjustVisualRectForCompositedScrolling().
LayoutRect old_visual_rect;
// Use LayoutObject::visualRect() to get the new visual rect.
// Store the origin of the object's local coordinates in the paint
// invalidation backing's coordinates. They are used to detect layoutObject
// shifts that force a full invalidation and invalidation check in subtree.
// The points do *not* account for composited scrolling. See
// LayoutObject::adjustVisualRectForCompositedScrolling().
LayoutPoint old_location;
LayoutPoint new_location;
private:
friend class PaintInvalidator;
const PaintPropertyTreeBuilderFragmentContext* tree_builder_context_ =
nullptr;
#if DCHECK_IS_ON()
bool tree_builder_context_actually_needed_ = false;
friend class FindVisualRectNeedingUpdateScope;
friend class FindVisualRectNeedingUpdateScopeBase;
mutable bool force_visual_rect_update_for_checking_ = false;
#endif
};
class PaintInvalidator {
public:
void InvalidatePaint(LocalFrameView&,
const PaintPropertyTreeBuilderContext*,
PaintInvalidatorContext&);
void InvalidatePaint(const LayoutObject&,
const PaintPropertyTreeBuilderContext*,
PaintInvalidatorContext&);
// Process objects needing paint invalidation on the next frame.
// See the definition of PaintInvalidationDelayedFull for more details.
void ProcessPendingDelayedPaintInvalidations();
private:
friend struct PaintInvalidatorContext;
template <typename Rect, typename Point>
static LayoutRect MapLocalRectToVisualRectInBacking(
const LayoutObject&,
const Rect&,
const PaintInvalidatorContext&);
ALWAYS_INLINE LayoutRect
ComputeVisualRectInBacking(const LayoutObject&,
const PaintInvalidatorContext&);
ALWAYS_INLINE LayoutPoint
ComputeLocationInBacking(const LayoutObject&, const PaintInvalidatorContext&);
ALWAYS_INLINE void UpdatePaintingLayer(const LayoutObject&,
PaintInvalidatorContext&);
ALWAYS_INLINE void UpdatePaintInvalidationContainer(const LayoutObject&,
PaintInvalidatorContext&);
ALWAYS_INLINE void UpdateVisualRectIfNeeded(
const LayoutObject&,
const PaintPropertyTreeBuilderContext*,
PaintInvalidatorContext&);
ALWAYS_INLINE void UpdateVisualRect(const LayoutObject&,
PaintInvalidatorContext&);
Vector<const LayoutObject*> pending_delayed_paint_invalidations_;
};
} // namespace blink
#endif // PaintInvalidator_h