Commit 2be15353 authored by Vladimir Levin's avatar Vladimir Levin Committed by Commit Bot

Add PaintPropertyTreeBuildContext force_subtree_update categories.

This patch changes force_subtree_update bool into "reasons" that fall
into one of two categories:
  - Isolation piercing, meaning that the update crosses and recurses
    into an isolation boundary.
  - Isolation blocking, meaning that the recursion may be blocked by
    isolation.

R=chrishtr@chromium.org, pdr@chromium.org, wangxianzhu@chromium.org

Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Ie5389a02b8cc529ca93bf0e50b225b0f343e2439
Reviewed-on: https://chromium-review.googlesource.com/1247201Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Commit-Queue: vmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594760}
parent 978c4c87
......@@ -44,6 +44,22 @@
namespace blink {
namespace {
bool AreSubtreeUpdateReasonsIsolationPiercing(unsigned reasons) {
// This is written to mean that if we have any reason other than the specified
// ones then the reasons are isolation piercing. This means that if new
// reasons are added, they will be isolation piercing by default.
// - Isolation establishes a containing block for all descendants, so it is
// not piercing.
// TODO(vmpstr): Investigate if transform style is also isolated.
return reasons &
~(static_cast<unsigned>(
SubtreePaintPropertyUpdateReason::kContainerChainMayChange));
}
} // namespace
PaintPropertyTreeBuilderFragmentContext::
PaintPropertyTreeBuilderFragmentContext()
: current_effect(&EffectPaintPropertyNode::Root()) {
......@@ -55,6 +71,13 @@ PaintPropertyTreeBuilderFragmentContext::
&ScrollPaintPropertyNode::Root();
}
PaintPropertyTreeBuilderContext::PaintPropertyTreeBuilderContext()
: force_subtree_update_reasons(0u),
clip_changed(false),
is_repeating_fixed_position(false),
has_svg_hidden_container_ancestor(false),
supports_composited_raster_invalidation(true) {}
void VisualViewportPaintPropertyTreeBuilder::Update(
VisualViewport& visual_viewport,
PaintPropertyTreeBuilderContext& full_context) {
......@@ -112,7 +135,11 @@ class FragmentPaintPropertyTreeBuilder {
properties_(fragment_data.PaintProperties()) {}
~FragmentPaintPropertyTreeBuilder() {
full_context_.force_subtree_update |= property_added_or_removed_;
if (property_added_or_removed_) {
// Tree topology changes are blocked by isolation.
full_context_.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationBlocked;
}
#if DCHECK_IS_ON()
if (properties_)
PaintPropertyTreePrinter::UpdateDebugNames(object_, *properties_);
......@@ -159,7 +186,7 @@ class FragmentPaintPropertyTreeBuilder {
bool NeedsPaintPropertyUpdate() const {
return object_.NeedsPaintPropertyUpdate() ||
full_context_.force_subtree_update;
full_context_.force_subtree_update_reasons;
}
void OnUpdate(const ObjectPaintProperties::UpdateResult& result) {
......@@ -1263,7 +1290,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowControlsClip() {
properties_->ClearOverflowControlsClip();
}
// No need to set force_subtree_update and clip_changed because
// No need to set force_subtree_update_reasons and clip_changed because
// OverflowControlsClip applies to overflow controls only, not descendants.
// We also don't walk into custom scrollbars in PrePaintTreeWalk and
// LayoutObjects under custom scrollbars don't support paint properties.
......@@ -1550,8 +1577,11 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
// so ensure the entire subtree is updated when reasons change.
if (auto* existing_scroll = properties_->Scroll()) {
if (existing_scroll->GetMainThreadScrollingReasons() !=
state.main_thread_scrolling_reasons)
full_context_.force_subtree_update = true;
state.main_thread_scrolling_reasons) {
// Main thread scrolling reasons cross into isolation.
full_context_.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationPiercing;
}
}
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
......@@ -2042,7 +2072,9 @@ void FragmentPaintPropertyTreeBuilder::UpdateForObjectLocationAndSize(
if (fragment_data_.PaintOffset() != context_.current.paint_offset) {
// Many paint properties depend on paint offset so we force an update of
// the entire subtree on paint offset changes.
full_context_.force_subtree_update = true;
// However, they are blocked by isolation.
full_context_.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationBlocked;
object_.GetMutableForPainting().SetShouldCheckForPaintInvalidation();
fragment_data_.SetPaintOffset(context_.current.paint_offset);
......@@ -2100,7 +2132,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
#if DCHECK_IS_ON()
FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(
object_, fragment_data_, full_context_.force_subtree_update);
object_, fragment_data_, full_context_.force_subtree_update_reasons);
#endif
if (properties_) {
......@@ -2120,7 +2152,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
void FragmentPaintPropertyTreeBuilder::UpdateForChildren() {
#if DCHECK_IS_ON()
FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(
object_, fragment_data_, full_context_.force_subtree_update);
object_, fragment_data_, full_context_.force_subtree_update_reasons);
#endif
if (properties_) {
......@@ -2151,7 +2183,9 @@ void PaintPropertyTreeBuilder::InitFragmentPaintProperties(
if (needs_paint_properties) {
fragment.EnsurePaintProperties();
} else if (fragment.PaintProperties()) {
context_.force_subtree_update = true;
// Tree topology changes are blocked by isolation.
context_.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationBlocked;
fragment.ClearPaintProperties();
}
fragment.SetPaginationOffset(pagination_offset);
......@@ -2906,7 +2940,14 @@ bool PaintPropertyTreeBuilder::UpdateForChildren() {
// means it can clear that reason and possibly skip the subtree update.
if (object_.SubtreePaintPropertyUpdateReasons() !=
static_cast<unsigned>(SubtreePaintPropertyUpdateReason::kNone)) {
context_.force_subtree_update = true;
if (AreSubtreeUpdateReasonsIsolationPiercing(
object_.SubtreePaintPropertyUpdateReasons())) {
context_.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationPiercing;
} else {
context_.force_subtree_update_reasons |=
PaintPropertyTreeBuilderContext::kSubtreeUpdateIsolationBlocked;
}
}
if (object_.CanContainAbsolutePositionObjects())
context_.container_for_absolute_position = &object_;
......
......@@ -115,23 +115,15 @@ struct PaintPropertyTreeBuilderContext {
DISALLOW_NEW();
public:
PaintPropertyTreeBuilderContext() = default;
PaintPropertyTreeBuilderContext();
Vector<PaintPropertyTreeBuilderFragmentContext, 1> fragments;
const LayoutObject* container_for_absolute_position = nullptr;
const LayoutObject* container_for_fixed_position = nullptr;
// True if a change has forced all properties in a subtree to be updated. This
// can be set due to paint offset changes or when the structure of the
// property tree changes (i.e., a node is added or removed).
bool force_subtree_update = false;
// Whether a clip paint property node appeared, disappeared, or changed
// its clip since this variable was last set to false. This is used
// to find out whether a clip changed since the last transform update.
// Code outside of this class resets clip_changed to false when transforms
// change.
bool clip_changed = false;
// The physical bounding box of all appearances of the repeating table section
// in the flow thread or the paged LayoutView.
LayoutRect repeating_table_section_bounding_box;
#if DCHECK_IS_ON()
// When DCHECK_IS_ON() we create PaintPropertyTreeBuilderContext even if not
......@@ -146,21 +138,43 @@ struct PaintPropertyTreeBuilderContext {
// fragment where the object first appears.
const LayoutTableSection* repeating_table_section = nullptr;
// Specifies the reason the subtree update was forced. For simplicity, this
// only categorizes it into two categories:
// - Isolation piercing, meaning that the update is required for subtrees
// under an isolation boundary.
// - Isolation blocked, meaning that the recursion can be blocked by
// isolation.
enum SubtreeUpdateReason : unsigned {
kSubtreeUpdateIsolationPiercing = 1 << 0,
kSubtreeUpdateIsolationBlocked = 1 << 1
};
// True if a change has forced all properties in a subtree to be updated. This
// can be set due to paint offset changes or when the structure of the
// property tree changes (i.e., a node is added or removed).
unsigned force_subtree_update_reasons : 2;
// Note that the next four bitfields are conceptually bool, but are declared
// as unsigned in order to be packed in the same word as the above bitfield.
// Whether a clip paint property node appeared, disappeared, or changed
// its clip since this variable was last set to false. This is used
// to find out whether a clip changed since the last transform update.
// Code outside of this class resets clip_changed to false when transforms
// change.
unsigned clip_changed : 1;
// When printing, fixed-position objects and their descendants need to repeat
// in each page.
bool is_repeating_fixed_position = false;
unsigned is_repeating_fixed_position : 1;
// True if the current subtree is underneath a LayoutSVGHiddenContainer
// ancestor.
bool has_svg_hidden_container_ancestor = false;
// The physical bounding box of all appearances of the repeating table section
// in the flow thread or the paged LayoutView.
LayoutRect repeating_table_section_bounding_box;
unsigned has_svg_hidden_container_ancestor : 1;
// Whether composited raster invalidation is supported for this object.
// If not, subtree invalidations occur on every property tree change.
bool supports_composited_raster_invalidation = true;
unsigned supports_composited_raster_invalidation : 1;
};
class VisualViewportPaintPropertyTreeBuilder {
......
......@@ -282,7 +282,7 @@ bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate(
const LayoutObject& object,
const PrePaintTreeWalkContext& parent_context) {
if (parent_context.tree_builder_context &&
parent_context.tree_builder_context->force_subtree_update) {
parent_context.tree_builder_context->force_subtree_update_reasons) {
return true;
}
// The following CHECKs are for debugging crbug.com/816810.
......
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