зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1664101 - Store displayport margins in unadjusted form. r=kats
Where an adjustment (to reflect a delta between the APZ and layout scroll offsets) is necessary, the inputs needed to compute the adjustment are stored with the margins, and the adjustment is applied at query time. A couple of notes on this patch: * Storing DisplayPortMargins::mLayoutOffset is probably unnecessary, we should be able to just query the scroll frame's layout offset when applying the margins. * Some callers of DisplayPortMargins::WithNoAdjustment() may be incorrect, in that they pass in margins that are relative to the visual viewport but do not make a corresponding adjustment. This is a pre-existing issue that this patch just makes clearer. As this is a regression-prone area, this patch is careful to avoid making any functional changes, leaving the above issues to be addressed in future bugs. Differential Revision: https://phabricator.services.mozilla.com/D92506
This commit is contained in:
Родитель
715fb4d644
Коммит
5fac61e3d1
|
@ -528,8 +528,9 @@ nsDOMWindowUtils::SetDisplayPortMarginsForElement(
|
|||
ScreenMargin displayportMargins(aTopMargin, aRightMargin, aBottomMargin,
|
||||
aLeftMargin);
|
||||
|
||||
DisplayPortUtils::SetDisplayPortMargins(aElement, presShell,
|
||||
displayportMargins, aPriority);
|
||||
DisplayPortUtils::SetDisplayPortMargins(
|
||||
aElement, presShell,
|
||||
DisplayPortMargins::WithNoAdjustment(displayportMargins), aPriority);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -48,16 +48,6 @@ using dom::BrowserParent;
|
|||
uint64_t APZCCallbackHelper::sLastTargetAPZCNotificationInputBlock =
|
||||
uint64_t(-1);
|
||||
|
||||
ScreenMargin APZCCallbackHelper::AdjustDisplayPortForScrollDelta(
|
||||
ScreenMargin aMargins, ScreenPoint aScrollDelta) {
|
||||
ScreenMargin margins = aMargins;
|
||||
margins.left -= aScrollDelta.x;
|
||||
margins.right += aScrollDelta.x;
|
||||
margins.top -= aScrollDelta.y;
|
||||
margins.bottom += aScrollDelta.y;
|
||||
return margins;
|
||||
}
|
||||
|
||||
static ScreenMargin RecenterDisplayPort(const ScreenMargin& aDisplayPort) {
|
||||
ScreenMargin margins = aDisplayPort;
|
||||
margins.right = margins.left = margins.LeftRight() / 2;
|
||||
|
@ -157,7 +147,7 @@ static CSSPoint ScrollFrameTo(nsIScrollableFrame* aFrame,
|
|||
* update the callback-transform stored on the content, and return a new
|
||||
* display port.
|
||||
*/
|
||||
static ScreenMargin ScrollFrame(nsIContent* aContent,
|
||||
static DisplayPortMargins ScrollFrame(nsIContent* aContent,
|
||||
const RepaintRequest& aRequest) {
|
||||
// Scroll the window to the desired spot
|
||||
nsIScrollableFrame* sf =
|
||||
|
@ -182,7 +172,8 @@ static ScreenMargin ScrollFrame(nsIContent* aContent,
|
|||
}
|
||||
}
|
||||
bool scrollUpdated = false;
|
||||
ScreenMargin displayPortMargins = aRequest.GetDisplayPortMargins();
|
||||
auto displayPortMargins =
|
||||
DisplayPortMargins::WithNoAdjustment(aRequest.GetDisplayPortMargins());
|
||||
CSSPoint apzScrollOffset = aRequest.GetVisualScrollOffset();
|
||||
CSSPoint actualScrollOffset = ScrollFrameTo(sf, aRequest, scrollUpdated);
|
||||
CSSPoint scrollDelta = apzScrollOffset - actualScrollOffset;
|
||||
|
@ -201,9 +192,9 @@ static ScreenMargin ScrollFrame(nsIContent* aContent,
|
|||
} else {
|
||||
// Correct the display port due to the difference between the requested
|
||||
// and actual scroll offsets.
|
||||
displayPortMargins = APZCCallbackHelper::AdjustDisplayPortForScrollDelta(
|
||||
aRequest.GetDisplayPortMargins(),
|
||||
scrollDelta * aRequest.DisplayportPixelsPerCSSPixel());
|
||||
displayPortMargins = DisplayPortMargins::WithAdjustment(
|
||||
aRequest.GetDisplayPortMargins(), apzScrollOffset, actualScrollOffset,
|
||||
aRequest.DisplayportPixelsPerCSSPixel());
|
||||
}
|
||||
} else if (aRequest.IsRootContent() &&
|
||||
apzScrollOffset != aRequest.GetLayoutScrollOffset()) {
|
||||
|
@ -214,9 +205,9 @@ static ScreenMargin ScrollFrame(nsIContent* aContent,
|
|||
// account for a difference between the requested and actual scroll
|
||||
// offsets in repaints requested by
|
||||
// AsyncPanZoomController::NotifyLayersUpdated.
|
||||
displayPortMargins = APZCCallbackHelper::AdjustDisplayPortForScrollDelta(
|
||||
aRequest.GetDisplayPortMargins(),
|
||||
scrollDelta * aRequest.DisplayportPixelsPerCSSPixel());
|
||||
displayPortMargins = DisplayPortMargins::WithAdjustment(
|
||||
aRequest.GetDisplayPortMargins(), apzScrollOffset, actualScrollOffset,
|
||||
aRequest.DisplayportPixelsPerCSSPixel());
|
||||
} else {
|
||||
// For whatever reason we couldn't update the scroll offset on the scroll
|
||||
// frame, which means the data APZ used for its displayport calculation is
|
||||
|
@ -224,7 +215,8 @@ static ScreenMargin ScrollFrame(nsIContent* aContent,
|
|||
// tile-align the recentered displayport because tile-alignment depends on
|
||||
// the scroll position, and the scroll position here is out of our control.
|
||||
// See bug 966507 comment 21 for a more detailed explanation.
|
||||
displayPortMargins = RecenterDisplayPort(aRequest.GetDisplayPortMargins());
|
||||
displayPortMargins = DisplayPortMargins::WithNoAdjustment(
|
||||
RecenterDisplayPort(aRequest.GetDisplayPortMargins()));
|
||||
}
|
||||
|
||||
// APZ transforms inputs assuming we applied the exact scroll offset it
|
||||
|
@ -250,7 +242,7 @@ static ScreenMargin ScrollFrame(nsIContent* aContent,
|
|||
}
|
||||
|
||||
static void SetDisplayPortMargins(PresShell* aPresShell, nsIContent* aContent,
|
||||
ScreenMargin aDisplayPortMargins,
|
||||
const DisplayPortMargins& aDisplayPortMargins,
|
||||
CSSSize aDisplayPortBase) {
|
||||
if (!aContent) {
|
||||
return;
|
||||
|
@ -352,7 +344,7 @@ void APZCCallbackHelper::UpdateRootFrame(const RepaintRequest& aRequest) {
|
|||
|
||||
// Do this as late as possible since scrolling can flush layout. It also
|
||||
// adjusts the display port margins, so do it before we set those.
|
||||
ScreenMargin displayPortMargins = ScrollFrame(content, aRequest);
|
||||
DisplayPortMargins displayPortMargins = ScrollFrame(content, aRequest);
|
||||
|
||||
SetDisplayPortMargins(presShell, content, displayPortMargins,
|
||||
aRequest.CalculateCompositedSizeInCssPixels());
|
||||
|
@ -370,7 +362,7 @@ void APZCCallbackHelper::UpdateSubFrame(const RepaintRequest& aRequest) {
|
|||
|
||||
// We don't currently support zooming for subframes, so nothing extra
|
||||
// needs to be done beyond the tasks common to this and UpdateRootFrame.
|
||||
ScreenMargin displayPortMargins = ScrollFrame(content, aRequest);
|
||||
DisplayPortMargins displayPortMargins = ScrollFrame(content, aRequest);
|
||||
if (RefPtr<PresShell> presShell = GetPresShell(content)) {
|
||||
SetDisplayPortMargins(presShell, content, displayPortMargins,
|
||||
aRequest.CalculateCompositedSizeInCssPixels());
|
||||
|
@ -435,8 +427,8 @@ void APZCCallbackHelper::InitializeRootDisplayport(PresShell* aPresShell) {
|
|||
DisplayPortUtils::SetDisplayPortBaseIfNotSet(content, baseRect);
|
||||
// Note that we also set the base rect that goes with these margins in
|
||||
// nsRootBoxFrame::BuildDisplayList.
|
||||
DisplayPortUtils::SetDisplayPortMargins(content, aPresShell, ScreenMargin(),
|
||||
0);
|
||||
DisplayPortUtils::SetDisplayPortMargins(content, aPresShell,
|
||||
DisplayPortMargins::Empty(), 0);
|
||||
DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
|
||||
content->GetPrimaryFrame());
|
||||
}
|
||||
|
|
|
@ -172,12 +172,6 @@ class APZCCallbackHelper {
|
|||
|
||||
static void CancelAutoscroll(const ScrollableLayerGuid::ViewID& aScrollId);
|
||||
|
||||
/* Adjust the display-port margins by the difference between the requested
|
||||
* scroll offset and the resulting scroll offset after setting the requested
|
||||
* value. */
|
||||
static ScreenMargin AdjustDisplayPortForScrollDelta(ScreenMargin aMargins,
|
||||
ScreenPoint aScrollDelta);
|
||||
|
||||
/*
|
||||
* Check if the scrollable frame is currently in the middle of a main thread
|
||||
* async or smooth scroll, or has already requested some other apz scroll that
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "nsSubDocumentFrame.h"
|
||||
#include "RetainedDisplayListBuilder.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using gfx::gfxVars;
|
||||
|
@ -38,6 +40,44 @@ typedef ScrollableLayerGuid::ViewID ViewID;
|
|||
|
||||
static LazyLogModule sDisplayportLog("apz.displayport");
|
||||
|
||||
/* static */
|
||||
DisplayPortMargins DisplayPortMargins::WithAdjustment(
|
||||
const ScreenMargin& aMargins, const CSSPoint& aVisualOffset,
|
||||
const CSSPoint& aLayoutOffset, const CSSToScreenScale2D& aScale) {
|
||||
return DisplayPortMargins{aMargins, aVisualOffset, aLayoutOffset, aScale};
|
||||
}
|
||||
|
||||
/* static */
|
||||
DisplayPortMargins DisplayPortMargins::WithNoAdjustment(
|
||||
const ScreenMargin& aMargins) {
|
||||
// Use values such that GetRelativeToLayoutViewport() will just return
|
||||
// mMargins.
|
||||
return WithAdjustment(aMargins, CSSPoint(), CSSPoint(),
|
||||
CSSToScreenScale2D(1.0, 1.0));
|
||||
}
|
||||
|
||||
ScreenMargin DisplayPortMargins::GetRelativeToLayoutViewport() const {
|
||||
ScreenPoint scrollDelta = (mVisualOffset - mLayoutOffset) * mScale;
|
||||
ScreenMargin margins = mMargins;
|
||||
margins.left -= scrollDelta.x;
|
||||
margins.right += scrollDelta.x;
|
||||
margins.top -= scrollDelta.y;
|
||||
margins.bottom += scrollDelta.y;
|
||||
return margins;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOs,
|
||||
const DisplayPortMargins& aMargins) {
|
||||
if (aMargins.mVisualOffset == CSSPoint() &&
|
||||
aMargins.mLayoutOffset == CSSPoint()) {
|
||||
aOs << aMargins.mMargins;
|
||||
} else {
|
||||
aOs << "{" << aMargins.mMargins << "," << aMargins.mVisualOffset << ","
|
||||
<< aMargins.mLayoutOffset << "}";
|
||||
}
|
||||
return aOs;
|
||||
}
|
||||
|
||||
// Return the maximum displayport size, based on the LayerManager's maximum
|
||||
// supported texture size. The result is in app units.
|
||||
static nscoord GetMaxDisplayPortSize(nsIContent* aContent,
|
||||
|
@ -191,6 +231,8 @@ static nsRect GetDisplayPortFromMarginsData(
|
|||
|
||||
bool useWebRender = gfxVars::UseWebRender();
|
||||
|
||||
ScreenMargin margins = aMarginsData->mMargins.GetRelativeToLayoutViewport();
|
||||
|
||||
if (presShell->IsDisplayportSuppressed()) {
|
||||
alignment = ScreenSize(1, 1);
|
||||
} else if (useWebRender) {
|
||||
|
@ -230,7 +272,7 @@ static nsRect GetDisplayPortFromMarginsData(
|
|||
|
||||
if (StaticPrefs::layers_enable_tiles_AtStartup() || useWebRender) {
|
||||
// Expand the rect by the margins
|
||||
screenRect.Inflate(aMarginsData->mMargins);
|
||||
screenRect.Inflate(margins);
|
||||
} else {
|
||||
// Calculate the displayport to make sure we fit within the max texture size
|
||||
// when not tiling.
|
||||
|
@ -250,7 +292,6 @@ static nsRect GetDisplayPortFromMarginsData(
|
|||
MAX_ALIGN_ROUNDING * alignment.height;
|
||||
|
||||
// For each axis, inflate the margins up to the maximum size.
|
||||
const ScreenMargin& margins = aMarginsData->mMargins;
|
||||
if (screenRect.height < maxHeightScreenPx) {
|
||||
int32_t budget = maxHeightScreenPx - screenRect.height;
|
||||
// Scale the margins down to fit into the budget if necessary, maintaining
|
||||
|
@ -295,7 +336,7 @@ static nsRect GetDisplayPortFromMarginsData(
|
|||
// If we have non-zero margins, expand the displayport for the low-res buffer
|
||||
// if that's what we're drawing. If we have zero margins, we want the
|
||||
// displayport to reflect the scrollport.
|
||||
if (aMarginsData->mMargins != ScreenMargin()) {
|
||||
if (margins != ScreenMargin()) {
|
||||
result = ApplyRectMultiplier(result, aMultiplier);
|
||||
}
|
||||
|
||||
|
@ -402,7 +443,7 @@ static bool GetDisplayPortImpl(
|
|||
result = GetDisplayPortFromRectData(aContent, rectData, aMultiplier);
|
||||
} else if (isDisplayportSuppressed ||
|
||||
nsLayoutUtils::ShouldDisableApzForElement(aContent)) {
|
||||
DisplayPortMarginsPropertyData noMargins(ScreenMargin(), 1,
|
||||
DisplayPortMarginsPropertyData noMargins(DisplayPortMargins::Empty(), 1,
|
||||
/*painted=*/false);
|
||||
result = GetDisplayPortFromMarginsData(aContent, &noMargins, aMultiplier);
|
||||
} else {
|
||||
|
@ -546,7 +587,7 @@ void DisplayPortUtils::InvalidateForDisplayPortChange(
|
|||
|
||||
bool DisplayPortUtils::SetDisplayPortMargins(nsIContent* aContent,
|
||||
PresShell* aPresShell,
|
||||
const ScreenMargin& aMargins,
|
||||
const DisplayPortMargins& aMargins,
|
||||
uint32_t aPriority,
|
||||
RepaintMode aRepaintMode) {
|
||||
MOZ_ASSERT(aContent);
|
||||
|
@ -745,7 +786,9 @@ bool DisplayPortUtils::CalculateAndSetDisplayPortMargins(
|
|||
ScreenMargin displayportMargins = layers::apz::CalculatePendingDisplayPort(
|
||||
metrics, ParentLayerPoint(0.0f, 0.0f));
|
||||
PresShell* presShell = frame->PresContext()->GetPresShell();
|
||||
return SetDisplayPortMargins(content, presShell, displayportMargins, 0,
|
||||
return SetDisplayPortMargins(
|
||||
content, presShell,
|
||||
DisplayPortMargins::WithNoAdjustment(displayportMargins), 0,
|
||||
aRepaintMode);
|
||||
}
|
||||
|
||||
|
@ -813,7 +856,8 @@ void DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
|
|||
if (nsLayoutUtils::AsyncPanZoomEnabled(frame) &&
|
||||
!HasDisplayPort(frame->GetContent())) {
|
||||
SetDisplayPortMargins(frame->GetContent(), frame->PresShell(),
|
||||
ScreenMargin(), 0, RepaintMode::Repaint);
|
||||
DisplayPortMargins::Empty(), 0,
|
||||
RepaintMode::Repaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -945,14 +989,13 @@ static void UpdateDisplayPortMarginsForPendingMetrics(
|
|||
|
||||
CSSPoint frameScrollOffset =
|
||||
CSSPoint::FromAppUnits(frame->GetScrollPosition());
|
||||
CSSPoint scrollDelta = aMetrics.GetVisualScrollOffset() - frameScrollOffset;
|
||||
ScreenMargin displayPortMargins =
|
||||
APZCCallbackHelper::AdjustDisplayPortForScrollDelta(
|
||||
aMetrics.GetDisplayPortMargins(),
|
||||
scrollDelta * aMetrics.DisplayportPixelsPerCSSPixel());
|
||||
|
||||
DisplayPortUtils::SetDisplayPortMargins(content, presShell,
|
||||
displayPortMargins, 0);
|
||||
DisplayPortUtils::SetDisplayPortMargins(
|
||||
content, presShell,
|
||||
DisplayPortMargins::WithAdjustment(
|
||||
aMetrics.GetDisplayPortMargins(), aMetrics.GetVisualScrollOffset(),
|
||||
frameScrollOffset, aMetrics.DisplayportPixelsPerCSSPixel()),
|
||||
0);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsRect.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
|
||||
class nsIContent;
|
||||
class nsIFrame;
|
||||
|
@ -63,11 +64,45 @@ struct DisplayPortPropertyData {
|
|||
bool mPainted;
|
||||
};
|
||||
|
||||
struct DisplayPortMargins {
|
||||
// The margins relative to the visual scroll offset.
|
||||
ScreenMargin mMargins;
|
||||
|
||||
// Some information captured at the time the margins are stored.
|
||||
// This ensures that we can express the margins as being relative to
|
||||
// the correct scroll offset when applying them.
|
||||
|
||||
// APZ's visual scroll offset at the time it requested the margins.
|
||||
CSSPoint mVisualOffset;
|
||||
|
||||
// The scroll frame's layout scroll offset at the time the margins
|
||||
// were saved.
|
||||
CSSPoint mLayoutOffset;
|
||||
|
||||
// The scale required to convert between the CSS cordinates of
|
||||
// mVisualOffset and mLayoutOffset, and the Screen coordinates of mMargins.
|
||||
CSSToScreenScale2D mScale;
|
||||
|
||||
static DisplayPortMargins WithAdjustment(const ScreenMargin& aMargins,
|
||||
const CSSPoint& aVisualOffset,
|
||||
const CSSPoint& aLayoutOffset,
|
||||
const CSSToScreenScale2D& aScale);
|
||||
|
||||
static DisplayPortMargins WithNoAdjustment(const ScreenMargin& aMargins);
|
||||
|
||||
static DisplayPortMargins Empty() { return WithNoAdjustment(ScreenMargin()); }
|
||||
|
||||
ScreenMargin GetRelativeToLayoutViewport() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& aOs,
|
||||
const DisplayPortMargins& aMargins);
|
||||
};
|
||||
|
||||
struct DisplayPortMarginsPropertyData {
|
||||
DisplayPortMarginsPropertyData(const ScreenMargin& aMargins,
|
||||
DisplayPortMarginsPropertyData(const DisplayPortMargins& aMargins,
|
||||
uint32_t aPriority, bool aPainted)
|
||||
: mMargins(aMargins), mPriority(aPriority), mPainted(aPainted) {}
|
||||
ScreenMargin mMargins;
|
||||
DisplayPortMargins mMargins;
|
||||
uint32_t mPriority;
|
||||
bool mPainted;
|
||||
};
|
||||
|
@ -159,8 +194,9 @@ class DisplayPortUtils {
|
|||
* @return true if the new margins were applied.
|
||||
*/
|
||||
static bool SetDisplayPortMargins(
|
||||
nsIContent* aContent, PresShell* aPresShell, const ScreenMargin& aMargins,
|
||||
uint32_t aPriority = 0, RepaintMode aRepaintMode = RepaintMode::Repaint);
|
||||
nsIContent* aContent, PresShell* aPresShell,
|
||||
const DisplayPortMargins& aMargins, uint32_t aPriority = 0,
|
||||
RepaintMode aRepaintMode = RepaintMode::Repaint);
|
||||
|
||||
/**
|
||||
* Set the display port base rect for given element to be used with display
|
||||
|
|
|
@ -2246,8 +2246,9 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, bool aIsRoot)
|
|||
// If we have tiling but no APZ, then set a 0-margin display port on
|
||||
// active scroll containers so that we paint by whole tile increments
|
||||
// when scrolling.
|
||||
DisplayPortUtils::SetDisplayPortMargins(
|
||||
mOuter->GetContent(), mOuter->PresShell(), ScreenMargin(), 0);
|
||||
DisplayPortUtils::SetDisplayPortMargins(mOuter->GetContent(),
|
||||
mOuter->PresShell(),
|
||||
DisplayPortMargins::Empty(), 0);
|
||||
DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
|
||||
mOuter);
|
||||
}
|
||||
|
@ -3936,7 +3937,8 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// with the silent change, since we explicitly request partial updates
|
||||
// to be disabled on the next paint.
|
||||
DisplayPortUtils::SetDisplayPortMargins(
|
||||
mOuter->GetContent(), mOuter->PresShell(), ScreenMargin(), 0,
|
||||
mOuter->GetContent(), mOuter->PresShell(),
|
||||
DisplayPortMargins::Empty(), 0,
|
||||
DisplayPortUtils::RepaintMode::DoNotRepaint);
|
||||
// Call DecideScrollableLayer to recompute mWillBuildScrollableLayer
|
||||
// and recompute the current animated geometry root if needed. It's
|
||||
|
|
Загрузка…
Ссылка в новой задаче