Bug 1690433. Update code that looks for the presence of a display port for new minimal display ports. r=botond

This patch is the result of auditing all places that look at the presence or absence of a display port to handle minimal display ports (HasDisplayPort, GetDisplayPort, etc).

Broadly speaking the places were in two categories:
1) things related to painting, that want to consider minimal display ports as display ports for purposes of things like sending over metadata and separating out layers.
2) things that care about async scrolling, and so actually want to have a properly sized display port.

Type 1) were not changed by this patch. Type 2) were changed to consider minimal display ports as not display ports.

Again, we are aiming to leave behaviour unchanged.

Differential Revision: https://phabricator.services.mozilla.com/D103856
This commit is contained in:
Timothy Nikkel 2021-02-04 11:16:59 +00:00
Родитель e2f27ec58a
Коммит 1be3156679
10 изменённых файлов: 60 добавлений и 14 удалений

Просмотреть файл

@ -619,7 +619,7 @@ static bool PrepareForSetTargetAPZCNotification(
if (!guidIsValid) {
return false;
}
if (DisplayPortUtils::HasDisplayPort(dpElement)) {
if (DisplayPortUtils::HasNonMinimalDisplayPort(dpElement)) {
// If the element has a displayport but it hasn't been painted yet,
// we want the caller to wait for the paint to happen, but we don't
// need to set the displayport here since it's already been set.

Просмотреть файл

@ -630,6 +630,11 @@ void DisplayPortUtils::MarkDisplayPortAsPainted(nsIContent* aContent) {
}
}
bool DisplayPortUtils::HasNonMinimalDisplayPort(nsIContent* aContent) {
return HasDisplayPort(aContent) &&
!aContent->GetProperty(nsGkAtoms::MinimalDisplayPort);
}
/* static */
bool DisplayPortUtils::GetDisplayPortForVisibilityTesting(nsIContent* aContent,
nsRect* aResult) {
@ -943,7 +948,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
return false;
}
bool haveDisplayPort = HasDisplayPort(content);
bool haveDisplayPort = HasNonMinimalDisplayPort(content);
// We perform an optimization where we ensure that at least one
// async-scrollable frame (i.e. one that WantsAsyncScroll()) has a
@ -966,7 +971,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
CalculateAndSetDisplayPortMargins(scrollableFrame, aRepaintMode);
#ifdef DEBUG
haveDisplayPort = HasDisplayPort(content);
haveDisplayPort = HasNonMinimalDisplayPort(content);
MOZ_ASSERT(haveDisplayPort,
"should have a displayport after having just set it");
#endif
@ -996,7 +1001,7 @@ void DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
MOZ_ASSERT(scrollAncestor->WantAsyncScroll() ||
frame->PresShell()->GetRootScrollFrame() == frame);
if (nsLayoutUtils::AsyncPanZoomEnabled(frame) &&
!HasDisplayPort(frame->GetContent())) {
(!HasNonMinimalDisplayPort(frame->GetContent()))) {
SetDisplayPortMargins(frame->GetContent(), frame->PresShell(),
DisplayPortMargins::Empty(frame->GetContent()),
ClearMinimalDisplayPortProperty::Yes, 0,

Просмотреть файл

@ -180,6 +180,11 @@ class DisplayPortUtils {
static bool FrameHasDisplayPort(nsIFrame* aFrame,
const nsIFrame* aScrolledFrame = nullptr);
/**
* Check whether the given element has a non-minimal displayport.
*/
static bool HasNonMinimalDisplayPort(nsIContent* aContent);
/**
* Check if the given element has a margins based displayport but is missing a
* displayport base rect that it needs to properly compute a displayport rect.

Просмотреть файл

@ -169,7 +169,8 @@ void GeckoMVMContext::PostVisualViewportResizeEventByDynamicToolbar() {
void GeckoMVMContext::UpdateDisplayPortMargins() {
MOZ_ASSERT(mPresShell);
if (nsIFrame* root = mPresShell->GetRootScrollFrame()) {
bool hasDisplayPort = DisplayPortUtils::HasDisplayPort(root->GetContent());
nsIContent* content = root->GetContent();
bool hasDisplayPort = DisplayPortUtils::HasNonMinimalDisplayPort(content);
bool hasResolution = mPresShell->GetResolution() != 1.0f;
if (!hasDisplayPort && !hasResolution) {
// We only want to update the displayport if there is one already, or
@ -184,8 +185,7 @@ void GeckoMVMContext::UpdateDisplayPortMargins() {
// because non-toplevel documents have no limit on their size.
MOZ_ASSERT(
mPresShell->GetPresContext()->IsRootContentDocumentCrossProcess());
DisplayPortUtils::SetDisplayPortBaseIfNotSet(root->GetContent(),
displayportBase);
DisplayPortUtils::SetDisplayPortBaseIfNotSet(content, displayportBase);
nsIScrollableFrame* scrollable = do_QueryFrame(root);
DisplayPortUtils::CalculateAndSetDisplayPortMargins(
scrollable, DisplayPortUtils::RepaintMode::Repaint);

Просмотреть файл

@ -3294,7 +3294,7 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
presShell->GetRootScrollFrame())) {
if (dom::Element* element =
presShell->GetDocument()->GetDocumentElement()) {
if (!DisplayPortUtils::HasDisplayPort(element)) {
if (!DisplayPortUtils::HasNonMinimalDisplayPort(element)) {
APZCCallbackHelper::InitializeRootDisplayport(presShell);
}
}

Просмотреть файл

@ -3004,6 +3004,7 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange,
bool schedulePaint = true;
if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) &&
!nsLayoutUtils::ShouldDisableApzForElement(content) &&
!content->GetProperty(nsGkAtoms::MinimalDisplayPort) &&
StaticPrefs::apz_paint_skipping_enabled()) {
// If APZ is enabled with paint-skipping, there are certain conditions in
// which we can skip paints:
@ -4703,11 +4704,12 @@ void ScrollFrameHelper::ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit,
AppendScrollUpdate(
ScrollPositionUpdate::NewPureRelativeScroll(aOrigin, aMode, delta));
if (!DisplayPortUtils::HasDisplayPort(mOuter->GetContent())) {
nsIContent* content = mOuter->GetContent();
if (!DisplayPortUtils::HasNonMinimalDisplayPort(content)) {
if (MOZ_LOG_TEST(sDisplayportLog, LogLevel::Debug)) {
mozilla::layers::ScrollableLayerGuid::ViewID viewID =
mozilla::layers::ScrollableLayerGuid::NULL_SCROLL_ID;
nsLayoutUtils::FindIDFor(mOuter->GetContent(), &viewID);
nsLayoutUtils::FindIDFor(content, &viewID);
MOZ_LOG(
sDisplayportLog, LogLevel::Debug,
("ScrollBy setting displayport on scrollId=%" PRIu64 "\n", viewID));
@ -5975,6 +5977,20 @@ bool ScrollFrameHelper::IsScrollingActive(
nsContentUtils::HasScrollgrab(content);
}
bool ScrollFrameHelper::IsScrollingActiveNotMinimalDisplayPort(
nsDisplayListBuilder* aBuilder) const {
const nsStyleDisplay* disp = mOuter->StyleDisplay();
if (disp->mWillChange.bits & StyleWillChangeBits::SCROLL &&
aBuilder->IsInWillChangeBudget(mOuter, GetVisualViewportSize())) {
return true;
}
nsIContent* content = mOuter->GetContent();
return mHasBeenScrolledRecently || IsAlwaysActive() ||
DisplayPortUtils::HasNonMinimalDisplayPort(content) ||
nsContentUtils::HasScrollgrab(content);
}
/**
* Reflow the scroll area if it needs it and return its size. Also determine if
* the reflow will cause any of the scrollbars to need to be reflowed.
@ -7797,7 +7813,8 @@ void ScrollFrameHelper::ApzSmoothScrollTo(const nsPoint& aDestination,
AppendScrollUpdate(
ScrollPositionUpdate::NewSmoothScroll(aOrigin, aDestination));
if (!DisplayPortUtils::HasDisplayPort(mOuter->GetContent())) {
nsIContent* content = mOuter->GetContent();
if (!DisplayPortUtils::HasNonMinimalDisplayPort(content)) {
// If this frame doesn't have a displayport then there won't be an
// APZC instance for it and so there won't be anything to process
// this smooth scroll request. We should set a displayport on this
@ -7805,7 +7822,7 @@ void ScrollFrameHelper::ApzSmoothScrollTo(const nsPoint& aDestination,
if (MOZ_LOG_TEST(sDisplayportLog, LogLevel::Debug)) {
mozilla::layers::ScrollableLayerGuid::ViewID viewID =
mozilla::layers::ScrollableLayerGuid::NULL_SCROLL_ID;
nsLayoutUtils::FindIDFor(mOuter->GetContent(), &viewID);
nsLayoutUtils::FindIDFor(content, &viewID);
MOZ_LOG(
sDisplayportLog, LogLevel::Debug,
("ApzSmoothScrollTo setting displayport on scrollId=%" PRIu64 "\n",

Просмотреть файл

@ -378,6 +378,8 @@ class ScrollFrameHelper : public nsIReflowCallback {
public:
bool IsScrollbarOnRight() const;
bool IsScrollingActive(nsDisplayListBuilder* aBuilder) const;
bool IsScrollingActiveNotMinimalDisplayPort(
nsDisplayListBuilder* aBuilder) const;
bool IsMaybeAsynchronouslyScrolled() const {
// If this is true, then we'll build an ASR, and that's what we want
// to know I think.
@ -1042,6 +1044,10 @@ class nsHTMLScrollFrame : public nsContainerFrame,
bool IsScrollingActive(nsDisplayListBuilder* aBuilder) final {
return mHelper.IsScrollingActive(aBuilder);
}
bool IsScrollingActiveNotMinimalDisplayPort(
nsDisplayListBuilder* aBuilder) final {
return mHelper.IsScrollingActiveNotMinimalDisplayPort(aBuilder);
}
bool IsMaybeScrollingActive() const final {
return mHelper.IsMaybeScrollingActive();
}
@ -1525,6 +1531,10 @@ class nsXULScrollFrame final : public nsBoxFrame,
bool IsScrollingActive(nsDisplayListBuilder* aBuilder) final {
return mHelper.IsScrollingActive(aBuilder);
}
bool IsScrollingActiveNotMinimalDisplayPort(
nsDisplayListBuilder* aBuilder) final {
return mHelper.IsScrollingActiveNotMinimalDisplayPort(aBuilder);
}
bool IsMaybeScrollingActive() const final {
return mHelper.IsMaybeScrollingActive();
}

Просмотреть файл

@ -381,6 +381,13 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
*/
virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) = 0;
/**
* The same as IsScrollingActive but minimal display ports are not considered
* active.
*/
virtual bool IsScrollingActiveNotMinimalDisplayPort(
nsDisplayListBuilder* aBuilder) = 0;
/**
* Returns true if this scroll frame might be scrolled
* asynchronously by the compositor.

Просмотреть файл

@ -418,7 +418,9 @@ static bool CheckScrollInducedActivity(
nsIScrollableFrame* scrollFrame =
do_QueryFrame(aLayerActivity->mAnimatingScrollHandlerFrame.GetFrame());
if (scrollFrame && (!aBuilder || scrollFrame->IsScrollingActive(aBuilder))) {
if (scrollFrame &&
(!aBuilder ||
scrollFrame->IsScrollingActiveNotMinimalDisplayPort(aBuilder))) {
return true;
}

Просмотреть файл

@ -1122,7 +1122,7 @@ void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) {
return;
}
if (!DisplayPortUtils::HasDisplayPort(scrollableContent)) {
if (!DisplayPortUtils::HasNonMinimalDisplayPort(scrollableContent)) {
return;
}