Commit f08d28ce authored by Vladimir Levin's avatar Vladimir Levin Committed by Commit Bot

content-visibility: Remember that forced graphics updates were skipped.

This patch ensures to restore a forced graphics update which is skipped
when the layer is locked.

This is a speculative fix for the referenced bug.

TEST=Unfortunately, it seems to be a rare case that I cannot reproduce

Bug: 1133244
Change-Id: I5526e2fb8fe52b598ba7eda7fe2159fe20047659
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2452929
Commit-Queue: vmpstr <vmpstr@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814396}
parent 607c7553
......@@ -10,6 +10,7 @@
#include "base/metrics/histogram_macros.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_recalc.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
......@@ -26,6 +27,7 @@
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/pre_paint_tree_walk.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
......@@ -143,6 +145,10 @@ void DisplayLockContext::SetRequestedState(EContentVisibility state) {
// Since our state changed, check if we need to create a scoped force update
// object.
// Note that creating this forced object may cause us to dirty style, which is
// fine since we are in a style update for this subtree anyway.
StyleEngine::AllowMarkStyleDirtyFromRecalcScope scope(
element_->GetDocument().GetStyleEngine());
element_->GetDocument().GetDisplayLockDocumentState().ForceLockIfNeeded(
element_.Get());
}
......@@ -724,6 +730,19 @@ bool DisplayLockContext::MarkForCompositingUpdatesIfNeeded() {
layout_box->Layer()->SetNeedsGraphicsLayerRebuild();
needs_graphics_layer_rebuild_ = false;
if (forced_graphics_layer_update_blocked_) {
// We only add an extra dirty bit to the compositing state, which is safe
// since we do this before updating the compositing state.
DisableCompositingQueryAsserts disabler;
auto* compositing_parent =
layout_box->Layer()->EnclosingLayerWithCompositedLayerMapping(
kIncludeSelf);
compositing_parent->GetCompositedLayerMapping()
->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
}
forced_graphics_layer_update_blocked_ = false;
return true;
}
return false;
......
......@@ -166,6 +166,10 @@ class CORE_EXPORT DisplayLockContext final
needs_graphics_layer_rebuild_ = true;
}
void NotifyForcedGraphicsLayerUpdateBlocked() {
forced_graphics_layer_update_blocked_ = true;
}
// Notify this element will be disconnected.
void NotifyWillDisconnect();
......@@ -373,6 +377,8 @@ class CORE_EXPORT DisplayLockContext final
bool needs_graphics_layer_rebuild_ = false;
bool forced_graphics_layer_update_blocked_ = false;
// This is set to true if we're in the 'auto' mode and had our first
// intersection / non-intersection notification. This is reset to false if the
// 'auto' mode is added again (after being removed).
......
......@@ -3019,4 +3019,5 @@ TEST_F(DisplayLockContextTest, GraphicsLayerBitsNotCheckedInLockedSubtree) {
EXPECT_FALSE(
target_layer->GetCompositedLayerMapping()->NeedsGraphicsLayerUpdate());
}
} // namespace blink
......@@ -155,10 +155,22 @@ void GraphicsLayerUpdater::UpdateRecursive(
}
}
PaintLayer* first_child =
layer.GetLayoutObject().ChildPrePaintBlockedByDisplayLock()
? nullptr
: layer.FirstChild();
PaintLayer* first_child = layer.FirstChild();
// If we have children but the update is blocked, then we should clear the
// first child to block recursion.
if (first_child &&
layer.GetLayoutObject().ChildPrePaintBlockedByDisplayLock()) {
first_child = nullptr;
// If we have a forced update, we notify the display lock to ensure that the
// forced update resumes after the lock has been removed.
if (update_type == kForceUpdate) {
auto* context = layer.GetLayoutObject().GetDisplayLockContext();
DCHECK(context);
context->NotifyForcedGraphicsLayerUpdateBlocked();
}
}
UpdateContext child_context(context, layer);
for (PaintLayer* child = first_child; child; child = child->NextSibling()) {
UpdateRecursive(*child, update_type, child_context,
......
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