From 1266e0674b84528d69306df8d8ea0c2cbb7e9130 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 26 May 2015 12:40:24 -0700 Subject: [PATCH] Move the APZ scroll frame clip onto FrameMetrics. (bug 1148582 part 3, r=mstange,tn) --- gfx/ipc/GfxMessageUtils.h | 2 ++ gfx/layers/FrameMetrics.h | 22 +++++++++++- gfx/layers/LayersLogging.cpp | 3 ++ gfx/layers/apz/src/AsyncPanZoomController.cpp | 1 + .../composite/AsyncCompositionManager.cpp | 11 ++++++ ipc/glue/IPCMessageUtils.h | 35 +++++++++++++++++++ layout/base/FrameLayerBuilder.cpp | 18 +--------- layout/base/nsDisplayList.cpp | 6 ++-- layout/base/nsLayoutUtils.cpp | 8 +++++ layout/base/nsLayoutUtils.h | 2 ++ layout/generic/nsGfxScrollFrame.cpp | 33 ++++++++++++++--- layout/generic/nsGfxScrollFrame.h | 7 ++-- layout/generic/nsIScrollableFrame.h | 1 - layout/reftests/bugs/reftest.list | 2 +- 14 files changed, 118 insertions(+), 33 deletions(-) diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index 674bd529e95..e8df05d2375 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -732,6 +732,7 @@ struct ParamTraits WriteParam(aMsg, aParam.GetLineScrollAmount()); WriteParam(aMsg, aParam.GetPageScrollAmount()); WriteParam(aMsg, aParam.AllowVerticalScrollWithWheel()); + WriteParam(aMsg, aParam.mClipRect); WriteParam(aMsg, aParam.GetContentDescription()); } @@ -774,6 +775,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mLineScrollAmount) && ReadParam(aMsg, aIter, &aResult->mPageScrollAmount) && ReadParam(aMsg, aIter, &aResult->mAllowVerticalScrollWithWheel) && + ReadParam(aMsg, aIter, &aResult->mClipRect) && ReadContentDescription(aMsg, aIter, aResult)); } }; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index bcdc06944ad..51653166da5 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -8,6 +8,7 @@ #include // for uint32_t, uint64_t #include "Units.h" // for CSSRect, CSSPixel, etc +#include "mozilla/Maybe.h" #include "mozilla/gfx/BasePoint.h" // for BasePoint #include "mozilla/gfx/Rect.h" // for RoundedIn #include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor @@ -98,7 +99,8 @@ public: mDoSmoothScroll == aOther.mDoSmoothScroll && mLineScrollAmount == aOther.mLineScrollAmount && mPageScrollAmount == aOther.mPageScrollAmount && - mAllowVerticalScrollWithWheel == aOther.mAllowVerticalScrollWithWheel; + mAllowVerticalScrollWithWheel == aOther.mAllowVerticalScrollWithWheel && + mClipRect == aOther.mClipRect; } bool operator!=(const FrameMetrics& aOther) const { @@ -517,6 +519,21 @@ public: mAllowVerticalScrollWithWheel = true; } + void SetClipRect(const Maybe& aClipRect) + { + mClipRect = aClipRect; + } + const Maybe& GetClipRect() const + { + return mClipRect; + } + bool HasClipRect() const { + return mClipRect.isSome(); + } + const ParentLayerIntRect& ClipRect() const { + return mClipRect.ref(); + } + private: // The pres-shell resolution that has been induced on the document containing @@ -688,6 +705,9 @@ private: // Whether or not the frame can be vertically scrolled with a mouse wheel. bool mAllowVerticalScrollWithWheel; + // The clip rect to use when compositing a layer with this FrameMetrics. + Maybe mClipRect; + // WARNING!!!! // // When adding new fields to FrameMetrics, the following places should be diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index a9b8cde910e..d7049de072b 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -183,6 +183,9 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) { AppendToString(aStream, m.GetScrollParentId(), "] [scrollParent="); } + if (m.HasClipRect()) { + AppendToString(aStream, m.ClipRect(), "] [clip="); + } AppendToString(aStream, m.GetZoom(), "] [z=", "] }"); } else { AppendToString(aStream, m.GetDisplayPortMargins(), " [dpm="); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index e238dda682c..13fc4c94c2d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2898,6 +2898,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri mFrameMetrics.SetHasScrollgrab(aLayerMetrics.GetHasScrollgrab()); mFrameMetrics.SetLineScrollAmount(aLayerMetrics.GetLineScrollAmount()); mFrameMetrics.SetPageScrollAmount(aLayerMetrics.GetPageScrollAmount()); + mFrameMetrics.SetClipRect(aLayerMetrics.GetClipRect()); if (scrollOffsetUpdated) { APZC_LOG("%p updating scroll offset from %s to %s\n", this, diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index a3863387de9..7d0b397c825 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -623,6 +623,17 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) // Apply the render offset mLayerManager->GetCompositor()->SetScreenRenderOffset(offset); + // See the comment below - the first FrameMetrics has the clip computed + // by layout (currently, effectively the composition bounds), which we + // intersect here to include the layer clip. + if (i == 0 && metrics.HasClipRect()) { + if (clipRect) { + clipRect = Some(clipRect.value().Intersect(metrics.ClipRect())); + } else { + clipRect = Some(metrics.ClipRect()); + } + } + combinedAsyncTransformWithoutOverscroll *= asyncTransformWithoutOverscroll; combinedAsyncTransform *= (Matrix4x4(asyncTransformWithoutOverscroll) * overscrollTransform); if (i > 0 && clipRect) { diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index 3144f9bf288..8552662fde6 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -12,6 +12,7 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/DebugOnly.h" +#include "mozilla/Maybe.h" #include "mozilla/TimeStamp.h" #ifdef XP_WIN #include "mozilla/TimeStamp_windows.h" @@ -805,6 +806,40 @@ struct ParamTraits { }; +template +struct ParamTraits< mozilla::Maybe > +{ + typedef mozilla::Maybe paramType; + + static void Write(Message* msg, const paramType& param) + { + if (param.isSome()) { + WriteParam(msg, true); + WriteParam(msg, param.value()); + } else { + WriteParam(msg, false); + } + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + bool isSome; + if (!ReadParam(msg, iter, &isSome)) { + return false; + } + if (isSome) { + T tmp; + if (!ReadParam(msg, iter, &tmp)) { + return false; + } + *result = mozilla::Some(mozilla::Move(tmp)); + } else { + *result = mozilla::Nothing(); + } + return true; + } +}; + } /* namespace IPC */ #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */ diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index c4a6722ee27..7798101cf8f 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -4241,8 +4241,6 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) } uint32_t baseLength = metricsArray.Length(); - ParentLayerIntRect tmpClipRect; - const ParentLayerIntRect* layerClip = aEntry->mLayer->GetClipRect().ptrOr(nullptr); nsIFrame* fParent; for (const nsIFrame* f = aEntry->mAnimatedGeometryRoot; f != mContainerAnimatedGeometryRoot; @@ -4267,23 +4265,9 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) continue; } - Maybe clipRect; scrollFrame->ComputeFrameMetrics(aEntry->mLayer, mContainerReferenceFrame, - mParameters, &clipRect, &metricsArray); - if (clipRect) { - ParentLayerIntRect pixClip = ViewAs(ScaleToNearestPixels(*clipRect)); - if (layerClip) { - tmpClipRect.IntersectRect(pixClip, *layerClip); - } else { - tmpClipRect = pixClip; - } - layerClip = &tmpClipRect; - // XXX this could cause IPC churn due to cliprects being updated - // twice during layer building --- for non-PaintedLayers that have - // both CSS and scroll clipping. - } + mParameters, &metricsArray); } - aEntry->mLayer->SetClipRect(ToMaybe(layerClip)); // Watch out for FrameMetrics copies in profiles aEntry->mLayer->SetFrameMetrics(metricsArray); } diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index a086b878861..2ba47a54d2d 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1543,7 +1543,7 @@ already_AddRefed nsDisplayList::PaintRoot(nsDisplayListBuilder* aB presShell->GetRootScrollFrame(), content, aBuilder->FindReferenceFrameFor(frame), - root, FrameMetrics::NULL_SCROLL_ID, viewport, + root, FrameMetrics::NULL_SCROLL_ID, viewport, Nothing(), isRoot, containerParameters)); } @@ -4175,7 +4175,7 @@ nsDisplaySubDocument::ComputeFrameMetrics(Layer* aLayer, return MakeUnique( nsLayoutUtils::ComputeFrameMetrics( mFrame, rootScrollFrame, rootScrollFrame->GetContent(), ReferenceFrame(), - aLayer, mScrollParentId, viewport, + aLayer, mScrollParentId, viewport, Nothing(), isRootContentDocument, params)); } @@ -4447,7 +4447,7 @@ nsDisplayScrollInfoLayer::ComputeFrameMetrics(Layer* aLayer, nsLayoutUtils::ComputeFrameMetrics( mScrolledFrame, mScrollFrame, mScrollFrame->GetContent(), ReferenceFrame(), aLayer, - mScrollParentId, viewport, false, params))); + mScrollParentId, viewport, Nothing(), false, params))); } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 1970b1bbba0..f3dcda88f91 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -8134,6 +8134,7 @@ nsLayoutUtils::ComputeFrameMetrics(nsIFrame* aForFrame, Layer* aLayer, ViewID aScrollParentId, const nsRect& aViewport, + const Maybe& aClipRect, bool aIsRoot, const ContainerLayerParameters& aContainerParameters) { @@ -8261,6 +8262,13 @@ nsLayoutUtils::ComputeFrameMetrics(nsIFrame* aForFrame, * metrics.GetCumulativeResolution() * layerToParentLayerScale; + if (aClipRect) { + ParentLayerRect rect = LayoutDeviceRect::FromAppUnits(*aClipRect, auPerDevPixel) + * metrics.GetCumulativeResolution() + * layerToParentLayerScale; + metrics.SetClipRect(Some(RoundedToInt(rect))); + } + // For the root scroll frame of the root content document (RCD-RSF), the above calculation // will yield the size of the viewport frame as the composition bounds, which // doesn't actually correspond to what is visible when diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 90c5e49b84f..3c7017753ec 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -8,6 +8,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/Maybe.h" #include "nsBoundingMetrics.h" #include "nsChangeHint.h" #include "nsAutoPtr.h" @@ -2628,6 +2629,7 @@ public: Layer* aLayer, ViewID aScrollParentId, const nsRect& aViewport, + const mozilla::Maybe& aClipRect, bool aIsRoot, const ContainerLayerParameters& aContainerParameters); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 1c7aff3b9c5..db577675751 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -56,6 +56,7 @@ #include "gfxPlatform.h" #include "gfxPrefs.h" #include "AsyncScrollBase.h" +#include "UnitTransforms.h" #include #include #include @@ -3042,7 +3043,6 @@ void ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, - Maybe* aClipRect, nsTArray* aOutput) const { if (!mShouldBuildScrollableLayer || mIsScrollableLayerInRootContainer) { @@ -3065,6 +3065,7 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer, nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(aContainerReferenceFrame); bool isRoot = mIsRoot && mOuter->PresContext()->IsRootContentDocument(); + Maybe parentLayerClip; if (needsParentLayerClip) { nsRect clip = nsRect(mScrollPort.TopLeft() + toReferenceFrame, nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter)); @@ -3074,9 +3075,31 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer, clip.height = NSToCoordRound(clip.height / res); } - // When using containers, the container layer contains the clip. Otherwise - // we always include the clip. - *aClipRect = Some(clip); + parentLayerClip = Some(clip); + } + + if (!gfxPrefs::AsyncPanZoomEnabled()) { + if (parentLayerClip) { + // If APZ is not enabled, we still need the displayport to be clipped + // in the compositor. + ParentLayerIntRect displayportClip = + ViewAs( + parentLayerClip->ScaleToNearestPixels( + aParameters.mXScale, + aParameters.mYScale, + mScrolledFrame->PresContext()->AppUnitsPerDevPixel())); + + ParentLayerIntRect layerClip; + if (const ParentLayerIntRect* origClip = aLayer->GetClipRect().ptrOr(nullptr)) { + layerClip = displayportClip.Intersect(*origClip); + } else { + layerClip = displayportClip; + } + aLayer->SetClipRect(Some(layerClip)); + } + + // Return early, since if we don't use APZ we don't need FrameMetrics. + return; } MOZ_ASSERT(mScrolledFrame->GetContent()); @@ -3086,7 +3109,7 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer, nsLayoutUtils::ComputeFrameMetrics( mScrolledFrame, mOuter, mOuter->GetContent(), aContainerReferenceFrame, aLayer, mScrollParentID, - scrollport, isRoot, aParameters); + scrollport, parentLayerClip, isRoot, aParameters); } bool diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 8ef216ad266..470514cdc8e 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -378,7 +378,6 @@ public: bool WantAsyncScroll() const; void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, - mozilla::Maybe* aClipRect, nsTArray* aOutput) const; // nsIScrollbarMediator @@ -833,10 +832,9 @@ public: } virtual void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, - mozilla::Maybe* aClipRect, nsTArray* aOutput) const override { mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, - aParameters, aClipRect, aOutput); + aParameters, aOutput); } virtual bool IsIgnoringViewportClipping() const override { return mHelper.IsIgnoringViewportClipping(); @@ -1226,10 +1224,9 @@ public: } virtual void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, - mozilla::Maybe* aClipRect, nsTArray* aOutput) const override { mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, - aParameters, aClipRect, aOutput); + aParameters, aOutput); } virtual bool IsIgnoringViewportClipping() const override { return mHelper.IsIgnoringViewportClipping(); diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 1d3b32fd044..1764b3ed8ee 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -418,7 +418,6 @@ public: virtual void ComputeFrameMetrics(mozilla::layers::Layer* aLayer, nsIFrame* aContainerReferenceFrame, const ContainerLayerParameters& aParameters, - mozilla::Maybe* aOutClipRect, nsTArray* aOutput) const = 0; /** diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 403a2858ca1..96b8fe638fd 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1847,7 +1847,7 @@ test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.htm == 1059498-2.html 1059498-1-ref.html == 1059498-3.html 1059498-1-ref.html skip-if(Mulet) == 1062108-1.html 1062108-1-ref.html # Bug 1139893: font rounding failure, tracked in bug 1141535 -fails-if(Android) fuzzy-if(Mulet,1,5) == 1062792-1.html 1062792-1-ref.html +fuzzy-if(Mulet,1,5) == 1062792-1.html 1062792-1-ref.html == 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html == 1069716-1.html 1069716-1-ref.html