Bug 1384181 - Reorganize the WebRenderScrollData code to work with layers-free transactions. r?
Until now WebRenderScrollData was only used with "layers" WR
transactions, but we want to use it with layers-free transactions as
well. As such, we need to allow collecting information from display items
instead of layers. This restructures the code a little bit to allow
that. This patch should not have any functional effect on the "layers"
codepath, but on the "layers-free" codepath it is now actually
populating some rudimentary data into the WebRenderScrollData before
sending it across. This will be fleshed out in future patches.
MozReview-Commit-ID: BROqpsHPRND
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -233,48 +233,38 @@ WebRenderLayerManager::CreateWebRenderCo
aDisplayList->AppendToBottom(itemSameCoordinateSystemChildren);
item->~nsDisplayItem();
continue;
}
savedItems.AppendToTop(item);
if (apzEnabled) {
+ bool forceNewLayerData = false;
+
+ // For some types of display items we want to force a new
+ // WebRenderLayerScrollData object, to ensure we preserve the APZ-relevant
+ // data that is in the display item.
+ switch (itemType) {
+ case nsDisplayItem::TYPE_SCROLL_INFO_LAYER:
+ forceNewLayerData = true;
+ break;
+ default:
+ break;
+ }
+
+ // Anytime the ASR changes we also want to force a new layer data because
+ // the stack of scroll metadata is going to be different for this
+ // display item than previously, so we can't squash the display items
+ // into the same "layer".
const ActiveScrolledRoot* asr = item->GetActiveScrolledRoot();
- // The ASR check here is just an optimization to avoid doing any unnecessary
- // work in a common case, where adjacent items in the display list have
- // the same ASR.
- if (asr && asr != lastAsr) {
+ if (forceNewLayerData || asr != lastAsr) {
lastAsr = asr;
- FrameMetrics::ViewID id = nsLayoutUtils::ViewIDForASR(asr);
- if (mScrollMetadata.find(id) == mScrollMetadata.end()) {
- // We pass null here for the display item clip because we don't need
- // the clip to be in the ScrollMetadata here; we will push the clip
- // information into the WR display list directly.
- Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
- nullptr, item->ReferenceFrame(),
- ContainerLayerParameters(), nullptr);
- MOZ_ASSERT(metadata);
- mScrollMetadata[id] = *metadata;
- }
- }
- if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) {
- // we should only really get one scroll info layer per scroll id, so
- // it's not worth trying to get the ViewID and checking to see if we
- // already have it in mScrollMetadata before doing the work of computing
- // the metadata.
- nsDisplayScrollInfoLayer* info = static_cast<nsDisplayScrollInfoLayer*>(item);
- UniquePtr<ScrollMetadata> metadata = info->ComputeScrollMetadata(
- nullptr, ContainerLayerParameters());
- MOZ_ASSERT(metadata);
- MOZ_ASSERT(metadata->GetMetrics().IsScrollInfoLayer());
- FrameMetrics::ViewID id = metadata->GetMetrics().GetScrollId();
- if (mScrollMetadata.find(id) == mScrollMetadata.end()) {
- mScrollMetadata[id] = *metadata;
- }
+ mLayerScrollData.emplace_back();
+ mLayerScrollData.back().Initialize(mScrollData, item);
}
}
if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
aDisplayListBuilder)) {
PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
}
}
@@ -532,66 +522,77 @@ WebRenderLayerManager::EndTransactionInt
if (mEndTransactionWithoutLayers) {
// aDisplayList being null here means this is an empty transaction following a layers-free
// transaction, so we reuse the previously built displaylist and scroll
// metadata information
if (aDisplayList && aDisplayListBuilder) {
StackingContextHelper sc;
mParentCommands.Clear();
- mScrollMetadata.clear();
+ mScrollData = WebRenderScrollData();
+ MOZ_ASSERT(mLayerScrollData.empty());
CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
builder.Finalize(contentSize, mBuiltDisplayList);
+
+ // Append the WebRenderLayerScrollData items into WebRenderScrollData
+ // in reverse order, from topmost to bottommost. This is in keeping with
+ // the semantics of WebRenderScrollData.
+ for (auto i = mLayerScrollData.crbegin(); i != mLayerScrollData.crend(); i++) {
+ mScrollData.AddLayerData(*i);
+ }
+ mLayerScrollData.clear();
}
builder.PushBuiltDisplayList(mBuiltDisplayList);
WrBridge()->AddWebRenderParentCommands(mParentCommands);
} else {
+ mScrollData = WebRenderScrollData();
+
mRoot->StartPendingAnimations(mAnimationReadyTime);
StackingContextHelper sc;
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
+
+ // Need to do this after RenderLayer because the compositor animation IDs
+ // get populated during RenderLayer and we need those.
+ PopulateScrollData(mScrollData, mRoot.get());
}
mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
WrBridge()->ClearReadLocks();
// We can't finish this transaction so return. This usually
// happens in an empty transaction where we can't repaint a painted layer.
// In this case, leave the transaction open and let a full transaction happen.
if (mTransactionIncomplete) {
DiscardLocalImages();
WrBridge()->ProcessWebRenderParentCommands();
return false;
}
- WebRenderScrollData scrollData;
if (AsyncPanZoomEnabled()) {
- scrollData.SetFocusTarget(mFocusTarget);
+ mScrollData.SetFocusTarget(mFocusTarget);
mFocusTarget = FocusTarget();
if (mIsFirstPaint) {
- scrollData.SetIsFirstPaint();
+ mScrollData.SetIsFirstPaint();
mIsFirstPaint = false;
}
- scrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
- if (mRoot) {
- PopulateScrollData(scrollData, mRoot.get());
- }
+ mScrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
}
bool sync = mTarget != nullptr;
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
{
AutoProfilerTracing
tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
- WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, scrollData);
+ WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, mScrollData);
}
MakeSnapshotIfRequired(size);
mNeedsComposite = false;
ClearDisplayItemLayers();
// this may result in Layers being deleted, which results in
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -1,23 +1,26 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_WEBRENDERLAYERMANAGER_H
#define GFX_WEBRENDERLAYERMANAGER_H
+#include <vector>
+
#include "gfxPrefs.h"
#include "Layers.h"
#include "mozilla/MozPromise.h"
#include "mozilla/layers/APZTestData.h"
#include "mozilla/layers/FocusTarget.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TransactionIdAllocator.h"
+#include "mozilla/layers/WebRenderScrollData.h"
#include "mozilla/layers/WebRenderUserData.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsDisplayList.h"
class nsIWidget;
namespace mozilla {
@@ -231,19 +234,22 @@ private:
LayerRefArray mKeepAlive;
// These fields are used to save a copy of the display list for
// empty transactions in layers-free mode.
wr::BuiltDisplayList mBuiltDisplayList;
nsTArray<WebRenderParentCommand> mParentCommands;
- // We need this for building scroll data for the compositor in
- // layers-free mode
- std::unordered_map<FrameMetrics::ViewID, ScrollMetadata> mScrollMetadata;
+ // This holds the scroll data that we need to send to the compositor for
+ // APZ to do it's job
+ WebRenderScrollData mScrollData;
+ // We use this as a temporary data structure while building the mScrollData
+ // inside a layers-free transaction.
+ std::vector<WebRenderLayerScrollData> mLayerScrollData;
// Layers that have been mutated. If we have an empty transaction
// then a display item layer will no longer be valid
// if it was a mutated layers.
void AddMutatedLayer(Layer* aLayer);
void ClearMutatedLayers();
LayerRefArray mMutatedLayers;
bool mTransactionIncomplete;
--- a/gfx/layers/wr/WebRenderScrollData.cpp
+++ b/gfx/layers/wr/WebRenderScrollData.cpp
@@ -11,16 +11,22 @@
#include "nsTArray.h"
#include "UnitTransforms.h"
namespace mozilla {
namespace layers {
WebRenderLayerScrollData::WebRenderLayerScrollData()
: mDescendantCount(-1)
+ , mTransformIsPerspective(false)
+ , mEventRegionsOverride(EventRegionsOverride::NoOverride)
+ , mScrollbarAnimationId(0)
+ , mScrollbarTargetContainerId(FrameMetrics::NULL_SCROLL_ID)
+ , mIsScrollbarContainer(false)
+ , mFixedPosScrollContainerId(FrameMetrics::NULL_SCROLL_ID)
{
}
WebRenderLayerScrollData::~WebRenderLayerScrollData()
{
}
void
@@ -49,16 +55,41 @@ WebRenderLayerScrollData::Initialize(Web
: EventRegionsOverride::NoOverride;
mScrollThumbData = aLayer->GetScrollThumbData();
mScrollbarAnimationId = aLayer->GetCompositorAnimationsId();
mScrollbarTargetContainerId = aLayer->GetScrollbarTargetContainerId();
mIsScrollbarContainer = aLayer->IsScrollbarContainer();
mFixedPosScrollContainerId = aLayer->GetFixedPositionScrollContainerId();
}
+void
+WebRenderLayerScrollData::Initialize(WebRenderScrollData& aOwner,
+ nsDisplayItem* aItem)
+{
+ mDescendantCount = 0;
+
+ MOZ_ASSERT(aItem);
+ if (aItem->GetType() == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) {
+ nsDisplayScrollInfoLayer* info = static_cast<nsDisplayScrollInfoLayer*>(aItem);
+ UniquePtr<ScrollMetadata> metadata = info->ComputeScrollMetadata(
+ nullptr, ContainerLayerParameters());
+ MOZ_ASSERT(metadata);
+ MOZ_ASSERT(metadata->GetMetrics().IsScrollInfoLayer());
+ mScrollIds.AppendElement(aOwner.AddMetadata(*metadata));
+ }
+ for (const ActiveScrolledRoot* asr = aItem->GetActiveScrolledRoot();
+ asr;
+ asr = asr->mParent) {
+ Maybe<ScrollMetadata> metadata = asr->mScrollableFrame->ComputeScrollMetadata(
+ nullptr, aItem->ReferenceFrame(), ContainerLayerParameters(), nullptr);
+ MOZ_ASSERT(metadata);
+ mScrollIds.AppendElement(aOwner.AddMetadata(metadata.ref()));
+ }
+}
+
int32_t
WebRenderLayerScrollData::GetDescendantCount() const
{
MOZ_ASSERT(mDescendantCount >= 0); // check that it was set
return mDescendantCount;
}
size_t
@@ -108,16 +139,23 @@ size_t
WebRenderScrollData::AddNewLayerData()
{
size_t len = mLayerScrollData.Length();
Unused << mLayerScrollData.AppendElement();
return len;
}
size_t
+WebRenderScrollData::AddLayerData(const WebRenderLayerScrollData& aData)
+{
+ mLayerScrollData.AppendElement(aData);
+ return mLayerScrollData.Length() - 1;
+}
+
+size_t
WebRenderScrollData::GetLayerCount() const
{
return mLayerScrollData.Length();
}
WebRenderLayerScrollData*
WebRenderScrollData::GetLayerDataMutable(size_t aIndex)
{
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -36,16 +36,18 @@ public:
~WebRenderLayerScrollData();
// Actually initialize the object. This is not done during the constructor
// for optimization purposes (the call site is hard to write efficiently
// if we do this in the constructor).
void Initialize(WebRenderScrollData& aOwner,
Layer* aLayer,
int32_t aDescendantCount);
+ void Initialize(WebRenderScrollData& aOwner,
+ nsDisplayItem* aItem);
int32_t GetDescendantCount() const;
size_t GetScrollMetadataCount() const;
// Return the ScrollMetadata object that used to be on the original Layer
// at the given index. Since we deduplicate the ScrollMetadata objects into
// the array in the owning WebRenderScrollData object, we need to be passed
// in a reference to that owner as well.
@@ -107,16 +109,19 @@ public:
~WebRenderScrollData();
// Add the given ScrollMetadata if it doesn't already exist. Return an index
// that can be used to look up the metadata later.
size_t AddMetadata(const ScrollMetadata& aMetadata);
// Add a new empty WebRenderLayerScrollData and return the index that can be
// used to look it up via GetLayerData.
size_t AddNewLayerData();
+ // Add the provided WebRenderLayerScrollData and return the index that can
+ // be used to look it up via GetLayerData.
+ size_t AddLayerData(const WebRenderLayerScrollData& aData);
size_t GetLayerCount() const;
// Return a pointer to the scroll data at the given index. Use with caution,
// as the pointer may be invalidated if this WebRenderScrollData is mutated.
WebRenderLayerScrollData* GetLayerDataMutable(size_t aIndex);
const WebRenderLayerScrollData* GetLayerData(size_t aIndex) const;