/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "mozilla/layers/WebRenderScrollData.h" #include "Layers.h" #include "LayersLogging.h" #include "mozilla/layers/WebRenderLayerManager.h" #include "mozilla/layout/RenderFrameParent.h" #include "mozilla/Unused.h" #include "nsDisplayList.h" #include "nsTArray.h" #include "UnitTransforms.h" namespace mozilla { namespace layers { WebRenderLayerScrollData::WebRenderLayerScrollData() : mDescendantCount(-1) , mTransformIsPerspective(false) , mEventRegionsOverride(EventRegionsOverride::NoOverride) , mScrollbarAnimationId(0) , mFixedPosScrollContainerId(FrameMetrics::NULL_SCROLL_ID) { } WebRenderLayerScrollData::~WebRenderLayerScrollData() { } void WebRenderLayerScrollData::InitializeRoot(int32_t aDescendantCount) { mDescendantCount = aDescendantCount; } void WebRenderLayerScrollData::Initialize(WebRenderScrollData& aOwner, nsDisplayItem* aItem, int32_t aDescendantCount, const ActiveScrolledRoot* aStopAtAsr, const Maybe& aAncestorTransform) { MOZ_ASSERT(aDescendantCount >= 0); // Ensure value is valid MOZ_ASSERT(mDescendantCount == -1); // Don't allow re-setting an already set value mDescendantCount = aDescendantCount; MOZ_ASSERT(aItem); aItem->UpdateScrollData(&aOwner, this); const ActiveScrolledRoot* asr = aItem->GetActiveScrolledRoot(); if (ActiveScrolledRoot::IsAncestor(asr, aStopAtAsr)) { // If the item's ASR is an ancestor of the stop-at ASR, then we don't need // any more metrics information because we'll end up duplicating what the // ancestor WebRenderLayerScrollData already has. asr = nullptr; } while (asr && asr != aStopAtAsr) { MOZ_ASSERT(aOwner.GetManager()); FrameMetrics::ViewID scrollId = asr->GetViewId(); if (Maybe index = aOwner.HasMetadataFor(scrollId)) { mScrollIds.AppendElement(index.ref()); } else { Maybe metadata = asr->mScrollableFrame->ComputeScrollMetadata( aOwner.GetManager(), aItem->ReferenceFrame(), ContainerLayerParameters(), nullptr); MOZ_ASSERT(metadata); MOZ_ASSERT(metadata->GetMetrics().GetScrollId() == scrollId); mScrollIds.AppendElement(aOwner.AddMetadata(metadata.ref())); } asr = asr->mParent; } // aAncestorTransform, if present, is the transform from an ancestor // nsDisplayTransform that was stored on the stacking context in order to // propagate it downwards in the tree. (i.e. |aItem| is a strict descendant of // the nsDisplayTranform which produced aAncestorTransform). We store this // separately from mTransform because in the case where we have multiple // scroll metadata on this layer item, the mAncestorTransform is associated // with the "topmost" scroll metadata, and the mTransform is associated with // the "bottommost" scroll metadata. The code in // WebRenderScrollDataWrapper::GetTransform() is responsible for combining // these transforms and exposing them appropriately. Also, we don't save the // ancestor transform for thumb layers, because those are a special case in // APZ; we need to keep the ancestor transform for the scrollable content that // the thumb scrolls, but not for the thumb itself, as it will result in // incorrect visual positioning of the thumb. if (aAncestorTransform && mScrollbarData.mScrollbarLayerType != ScrollbarLayerType::Thumb) { mAncestorTransform = *aAncestorTransform; } } int32_t WebRenderLayerScrollData::GetDescendantCount() const { MOZ_ASSERT(mDescendantCount >= 0); // check that it was set return mDescendantCount; } size_t WebRenderLayerScrollData::GetScrollMetadataCount() const { return mScrollIds.Length(); } void WebRenderLayerScrollData::AppendScrollMetadata(WebRenderScrollData& aOwner, const ScrollMetadata& aData) { mScrollIds.AppendElement(aOwner.AddMetadata(aData)); } const ScrollMetadata& WebRenderLayerScrollData::GetScrollMetadata(const WebRenderScrollData& aOwner, size_t aIndex) const { MOZ_ASSERT(aIndex < mScrollIds.Length()); return aOwner.GetScrollMetadata(mScrollIds[aIndex]); } CSSTransformMatrix WebRenderLayerScrollData::GetTransformTyped() const { return ViewAs(GetTransform()); } void WebRenderLayerScrollData::Dump(const WebRenderScrollData& aOwner) const { printf_stderr("LayerScrollData(%p) descendants %d\n", this, mDescendantCount); for (size_t i : mScrollIds) { printf_stderr(" metadata: %s\n", Stringify(aOwner.GetScrollMetadata(i)).c_str()); } printf_stderr(" ancestor transform: %s\n", Stringify(mAncestorTransform).c_str()); printf_stderr(" transform: %s perspective: %d visible: %s\n", Stringify(mTransform).c_str(), mTransformIsPerspective, Stringify(mVisibleRegion).c_str()); printf_stderr(" event regions: %s override: 0x%x\n", Stringify(mEventRegions).c_str(), mEventRegionsOverride); if (mReferentId) { printf_stderr(" ref layers id: 0x%" PRIx64 "\n", uint64_t(*mReferentId)); } printf_stderr(" scrollbar type: %d animation: %" PRIx64 "\n", (int)mScrollbarData.mScrollbarLayerType, mScrollbarAnimationId); printf_stderr(" fixed pos container: %" PRIu64 "\n", mFixedPosScrollContainerId); } WebRenderScrollData::WebRenderScrollData() : mManager(nullptr) , mIsFirstPaint(false) , mPaintSequenceNumber(0) { } WebRenderScrollData::WebRenderScrollData(WebRenderLayerManager* aManager) : mManager(aManager) , mIsFirstPaint(false) , mPaintSequenceNumber(0) { } WebRenderScrollData::~WebRenderScrollData() { } WebRenderLayerManager* WebRenderScrollData::GetManager() const { return mManager; } size_t WebRenderScrollData::AddMetadata(const ScrollMetadata& aMetadata) { FrameMetrics::ViewID scrollId = aMetadata.GetMetrics().GetScrollId(); auto insertResult = mScrollIdMap.insert(std::make_pair(scrollId, 0)); if (insertResult.second) { // Insertion took place, therefore it's a scrollId we hadn't seen before insertResult.first->second = mScrollMetadatas.Length(); mScrollMetadatas.AppendElement(aMetadata); } // else we didn't insert, because it already existed return insertResult.first->second; } size_t WebRenderScrollData::AddLayerData(const WebRenderLayerScrollData& aData) { mLayerScrollData.AppendElement(aData); return mLayerScrollData.Length() - 1; } size_t WebRenderScrollData::GetLayerCount() const { return mLayerScrollData.Length(); } const WebRenderLayerScrollData* WebRenderScrollData::GetLayerData(size_t aIndex) const { if (aIndex >= mLayerScrollData.Length()) { return nullptr; } return &(mLayerScrollData.ElementAt(aIndex)); } const ScrollMetadata& WebRenderScrollData::GetScrollMetadata(size_t aIndex) const { MOZ_ASSERT(aIndex < mScrollMetadatas.Length()); return mScrollMetadatas[aIndex]; } Maybe WebRenderScrollData::HasMetadataFor(const FrameMetrics::ViewID& aScrollId) const { auto it = mScrollIdMap.find(aScrollId); return (it == mScrollIdMap.end() ? Nothing() : Some(it->second)); } void WebRenderScrollData::SetFocusTarget(const FocusTarget& aFocusTarget) { mFocusTarget = aFocusTarget; } void WebRenderScrollData::SetIsFirstPaint() { mIsFirstPaint = true; } bool WebRenderScrollData::IsFirstPaint() const { return mIsFirstPaint; } void WebRenderScrollData::SetPaintSequenceNumber(uint32_t aPaintSequenceNumber) { mPaintSequenceNumber = aPaintSequenceNumber; } uint32_t WebRenderScrollData::GetPaintSequenceNumber() const { return mPaintSequenceNumber; } void WebRenderScrollData::ApplyUpdates(const ScrollUpdatesMap& aUpdates, uint32_t aPaintSequenceNumber) { for (const auto& update : aUpdates) { if (Maybe index = HasMetadataFor(update.first)) { mScrollMetadatas[*index].GetMetrics().UpdatePendingScrollInfo(update.second); } } mPaintSequenceNumber = aPaintSequenceNumber; } void WebRenderScrollData::Dump() const { printf_stderr("WebRenderScrollData with %zu layers firstpaint: %d\n", mLayerScrollData.Length(), mIsFirstPaint); for (size_t i = 0; i < mLayerScrollData.Length(); i++) { mLayerScrollData.ElementAt(i).Dump(*this); } } bool WebRenderScrollData::RepopulateMap() { MOZ_ASSERT(mScrollIdMap.empty()); for (size_t i = 0; i < mScrollMetadatas.Length(); i++) { FrameMetrics::ViewID scrollId = mScrollMetadatas[i].GetMetrics().GetScrollId(); mScrollIdMap.emplace(scrollId, i); } return true; } } // namespace layers } // namespace mozilla