Bug 1257641 - Use empty transactions to carry scroll offset updates to APZ that don't require a repaint. r=mattwoodrow,mstange,botond
MozReview-Commit-ID: KNeGSKldmp7
This commit is contained in:
@@ -26,6 +26,15 @@ template <typename T> struct ParamTraits;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* Helper struct to hold a couple of fields that can be updated as part of
|
||||
* an empty transaction.
|
||||
*/
|
||||
struct ScrollUpdateInfo {
|
||||
uint32_t mScrollGeneration;
|
||||
CSSPoint mScrollOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* The viewport and displayport metrics for the painted frame at the
|
||||
* time of a layer-tree transaction. These metrics are especially
|
||||
@@ -44,6 +53,9 @@ public:
|
||||
enum ScrollOffsetUpdateType : uint8_t {
|
||||
eNone, // The default; the scroll offset was not updated
|
||||
eMainThread, // The scroll offset was updated by the main thread.
|
||||
ePending, // The scroll offset was updated on the main thread, but not
|
||||
// painted, so the layer texture data is still at the old
|
||||
// offset.
|
||||
|
||||
eSentinel // For IPC use only
|
||||
};
|
||||
@@ -241,6 +253,13 @@ public:
|
||||
mDoSmoothScroll = aOther.mDoSmoothScroll;
|
||||
}
|
||||
|
||||
void UpdatePendingScrollInfo(const ScrollUpdateInfo& aInfo)
|
||||
{
|
||||
mScrollOffset = aInfo.mScrollOffset;
|
||||
mScrollGeneration = aInfo.mScrollGeneration;
|
||||
mScrollUpdateType = ePending;
|
||||
}
|
||||
|
||||
void UpdateScrollInfo(uint32_t aScrollGeneration, const CSSPoint& aScrollOffset)
|
||||
{
|
||||
mScrollOffset = aScrollOffset;
|
||||
@@ -380,6 +399,11 @@ public:
|
||||
mScrollGeneration = aScrollGeneration;
|
||||
}
|
||||
|
||||
ScrollOffsetUpdateType GetScrollUpdateType() const
|
||||
{
|
||||
return mScrollUpdateType;
|
||||
}
|
||||
|
||||
bool GetScrollOffsetUpdated() const
|
||||
{
|
||||
return mScrollUpdateType != eNone;
|
||||
|
||||
@@ -567,6 +567,11 @@ Layer::ApplyPendingUpdatesToSubtree()
|
||||
for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
child->ApplyPendingUpdatesToSubtree();
|
||||
}
|
||||
if (!GetParent()) {
|
||||
// Once we're done recursing through the whole tree, clear the pending
|
||||
// updates from the manager.
|
||||
Manager()->ClearPendingScrollInfoUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -946,6 +951,15 @@ Layer::ApplyPendingUpdatesForThisTransaction()
|
||||
mPendingAnimations = nullptr;
|
||||
Mutated();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
|
||||
FrameMetrics& fm = mScrollMetadata[i].GetMetrics();
|
||||
Maybe<ScrollUpdateInfo> update = Manager()->GetPendingScrollInfoUpdate(fm.GetScrollId());
|
||||
if (update) {
|
||||
fm.UpdatePendingScrollInfo(update.value());
|
||||
Mutated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
@@ -2446,6 +2460,29 @@ LayerManager::IsLogEnabled()
|
||||
return MOZ_LOG_TEST(GetLog(), LogLevel::Debug);
|
||||
}
|
||||
|
||||
void
|
||||
LayerManager::SetPendingScrollUpdateForNextTransaction(FrameMetrics::ViewID aScrollId,
|
||||
const ScrollUpdateInfo& aUpdateInfo)
|
||||
{
|
||||
mPendingScrollUpdates[aScrollId] = aUpdateInfo;
|
||||
}
|
||||
|
||||
Maybe<ScrollUpdateInfo>
|
||||
LayerManager::GetPendingScrollInfoUpdate(FrameMetrics::ViewID aScrollId)
|
||||
{
|
||||
auto it = mPendingScrollUpdates.find(aScrollId);
|
||||
if (it != mPendingScrollUpdates.end()) {
|
||||
return Some(it->second);
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManager::ClearPendingScrollInfoUpdate()
|
||||
{
|
||||
mPendingScrollUpdates.clear();
|
||||
}
|
||||
|
||||
void
|
||||
PrintInfo(std::stringstream& aStream, LayerComposite* aLayerComposite)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef GFX_LAYERS_H
|
||||
#define GFX_LAYERS_H
|
||||
|
||||
#include <map>
|
||||
#include <stdint.h> // for uint32_t, uint64_t, uint8_t
|
||||
#include <stdio.h> // for FILE
|
||||
#include <sys/types.h> // for int32_t, int64_t
|
||||
@@ -698,6 +699,19 @@ private:
|
||||
FramesTimingRecording mRecording;
|
||||
|
||||
TimeStamp mTabSwitchStart;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Methods to store/get/clear a "pending scroll info update" object on a
|
||||
* per-scrollid basis. This is used for empty transactions that push over
|
||||
* scroll position updates to the APZ code.
|
||||
*/
|
||||
void SetPendingScrollUpdateForNextTransaction(FrameMetrics::ViewID aScrollId,
|
||||
const ScrollUpdateInfo& aUpdateInfo);
|
||||
Maybe<ScrollUpdateInfo> GetPendingScrollInfoUpdate(FrameMetrics::ViewID aScrollId);
|
||||
void ClearPendingScrollInfoUpdate();
|
||||
private:
|
||||
std::map<FrameMetrics::ViewID,ScrollUpdateInfo> mPendingScrollUpdates;
|
||||
};
|
||||
|
||||
typedef InfallibleTArray<Animation> AnimationArray;
|
||||
@@ -857,6 +871,7 @@ public:
|
||||
*/
|
||||
void SetScrollMetadata(const ScrollMetadata& aScrollMetadata)
|
||||
{
|
||||
Manager()->ClearPendingScrollInfoUpdate();
|
||||
if (mScrollMetadata.Length() != 1 || mScrollMetadata[0] != aScrollMetadata) {
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FrameMetrics", this));
|
||||
mScrollMetadata.ReplaceElementsAt(0, mScrollMetadata.Length(), aScrollMetadata);
|
||||
@@ -884,6 +899,7 @@ public:
|
||||
*/
|
||||
void SetScrollMetadata(const nsTArray<ScrollMetadata>& aMetadataArray)
|
||||
{
|
||||
Manager()->ClearPendingScrollInfoUpdate();
|
||||
if (mScrollMetadata != aMetadataArray) {
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FrameMetrics", this));
|
||||
mScrollMetadata = aMetadataArray;
|
||||
|
||||
@@ -191,7 +191,7 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m,
|
||||
AppendToString(aStream, m.GetZoom(), " z=");
|
||||
AppendToString(aStream, m.GetExtraResolution(), " er=");
|
||||
aStream << nsPrintfCString(")] [u=(%d %d %lu)",
|
||||
m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(),
|
||||
m.GetScrollUpdateType(), m.GetDoSmoothScroll(),
|
||||
m.GetScrollGeneration()).get();
|
||||
AppendToString(aStream, m.GetScrollParentId(), "] [p=");
|
||||
aStream << nsPrintfCString("] [i=(%ld %lld %d)] }",
|
||||
|
||||
@@ -3388,7 +3388,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
||||
APZC_LOG("%p NotifyLayersUpdated short-circuit\n", this);
|
||||
return;
|
||||
}
|
||||
mLastContentPaintMetrics = aLayerMetrics;
|
||||
if (aLayerMetrics.GetScrollUpdateType() != FrameMetrics::ScrollOffsetUpdateType::ePending) {
|
||||
mLastContentPaintMetrics = aLayerMetrics;
|
||||
}
|
||||
|
||||
mFrameMetrics.SetScrollParentId(aLayerMetrics.GetScrollParentId());
|
||||
APZC_LOG_FM(aLayerMetrics, "%p got a NotifyLayersUpdated with aIsFirstPaint=%d, aThisLayerTreeUpdated=%d",
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
#include <mozilla/layers/AxisPhysicsMSDModel.h>
|
||||
#include "mozilla/layers/LayerTransactionChild.h"
|
||||
#include "mozilla/layers/ScrollLinkedEffectDetector.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "LayersLogging.h" // for Stringify
|
||||
#include <algorithm>
|
||||
@@ -2752,14 +2751,18 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
|
||||
!content->GetComposedDoc()->HasScrollLinkedEffect()) {
|
||||
nsIWidget* widget = presContext->GetNearestWidget();
|
||||
LayerManager* manager = widget ? widget->GetLayerManager() : nullptr;
|
||||
ShadowLayerForwarder* forwarder = manager ? manager->AsShadowForwarder() : nullptr;
|
||||
if (forwarder && forwarder->HasShadowManager()) {
|
||||
if (manager) {
|
||||
mozilla::layers::FrameMetrics::ViewID id;
|
||||
DebugOnly<bool> success = nsLayoutUtils::FindIDFor(content, &id);
|
||||
MOZ_ASSERT(success); // we have a displayport, we better have an ID
|
||||
forwarder->GetShadowManager()->SendUpdateScrollOffset(id,
|
||||
mScrollGeneration, CSSPoint::FromAppUnits(GetScrollPosition()));
|
||||
|
||||
// Schedule an empty transaction to carry over the scroll offset update,
|
||||
// instead of a full transaction. This empty transaction might still get
|
||||
// squashed into a full transaction if something happens to trigger one.
|
||||
schedulePaint = false;
|
||||
manager->SetPendingScrollUpdateForNextTransaction(id,
|
||||
{ mScrollGeneration, CSSPoint::FromAppUnits(GetScrollPosition()) });
|
||||
mOuter->SchedulePaint(nsIFrame::PAINT_COMPOSITE_ONLY);
|
||||
PAINT_SKIP_LOG("Skipping due to APZ-forwarded main-thread scroll\n");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user