Bug 1655083 - Tweak sampled APZC scroll offset to prevent unnecessary temporary surface creation. r=botond

Sometimes when sampling the APZC state we get a tiny non-zero async scroll
delta to be applied to the layer transform. This is not user-visible but it
does end up creating temporary surfaces in the layers code, and so is
undesirable. We can avoid this by tweaking the sampled APZC scroll offset
slightly. See comments in the patch for details.

Differential Revision: https://phabricator.services.mozilla.com/D84855
This commit is contained in:
Kartikaya Gupta 2020-07-24 20:02:40 +00:00
Родитель 0a72a11db7
Коммит 9b5fd8555c
2 изменённых файлов: 33 добавлений и 2 удалений

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SampledAPZCState.h"
#include "APZUtils.h"
namespace mozilla {
namespace layers {
@ -14,14 +15,18 @@ SampledAPZCState::SampledAPZCState() {}
SampledAPZCState::SampledAPZCState(const FrameMetrics& aMetrics)
: mLayoutViewport(aMetrics.GetLayoutViewport()),
mScrollOffset(aMetrics.GetScrollOffset()),
mZoom(aMetrics.GetZoom()) {}
mZoom(aMetrics.GetZoom()) {
RemoveFractionalAsyncDelta();
}
SampledAPZCState::SampledAPZCState(const FrameMetrics& aMetrics,
Maybe<CompositionPayload>&& aPayload)
: mLayoutViewport(aMetrics.GetLayoutViewport()),
mScrollOffset(aMetrics.GetScrollOffset()),
mZoom(aMetrics.GetZoom()),
mScrollPayload(std::move(aPayload)) {}
mScrollPayload(std::move(aPayload)) {
RemoveFractionalAsyncDelta();
}
bool SampledAPZCState::operator==(const SampledAPZCState& aOther) const {
// The payload doesn't factor into equality, that just comes along for
@ -59,5 +64,29 @@ void SampledAPZCState::ZoomBy(const gfxSize& aScale) {
mZoom.yScale *= aScale.height;
}
void SampledAPZCState::RemoveFractionalAsyncDelta() {
// This function is a performance hack. With non-WebRender, having small
// fractional deltas between the layout offset and scroll offset on
// container layers can trigger the creation of a temporary surface during
// composition, because it produces a non-integer translation that doesn't
// play well with layer clips. So we detect the case where the delta is
// uselessly small (0.01 parentlayer pixels or less) and tweak the sampled
// scroll offset to eliminate it. By doing this here at sample time rather
// than elsewhere in the pipeline we are least likely to break assumptions
// and invariants elsewhere in the code, since sampling effectively takes
// a snapshot of APZ state (decoupling it from APZ assumptions) and provides
// it as an input to the compositor (so all compositor state should be
// internally consistent based on this input).
if (mLayoutViewport.TopLeft() == mScrollOffset) {
return;
}
ParentLayerPoint paintedOffset = mLayoutViewport.TopLeft() * mZoom;
ParentLayerPoint asyncOffset = mScrollOffset * mZoom;
if (FuzzyEqualsAdditive(paintedOffset.x, asyncOffset.x, COORDINATE_EPSILON) &&
FuzzyEqualsAdditive(paintedOffset.y, asyncOffset.y, COORDINATE_EPSILON)) {
mScrollOffset = mLayoutViewport.TopLeft();
}
}
} // namespace layers
} // namespace mozilla

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

@ -51,6 +51,8 @@ class SampledAPZCState {
CSSToParentLayerScale2D mZoom;
// An optional payload that rides along with the sampled state.
Maybe<CompositionPayload> mScrollPayload;
void RemoveFractionalAsyncDelta();
};
} // namespace layers