mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-09 04:25:38 +00:00
Bug 1364622 - Introduce a helper function for computing the async transform for a scroll thumb layer. r=kats
MozReview-Commit-ID: DFFcmBxzI84 --HG-- extra : rebase_source : 3fdd6a00215ba8bfc9a717d3ab0e7ba0e21d4700
This commit is contained in:
parent
3172b1d2a0
commit
9460cdd08b
@ -1106,30 +1106,62 @@ static void
|
||||
ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
const LayerMetricsWrapper& aContent,
|
||||
bool aScrollbarIsDescendant)
|
||||
{
|
||||
AsyncTransformComponentMatrix clipTransform;
|
||||
|
||||
LayerToParentLayerMatrix4x4 transform =
|
||||
AsyncCompositionManager::ComputeTransformForScrollThumb(
|
||||
aScrollbar->GetLocalTransformTyped(),
|
||||
aContent.GetTransform(),
|
||||
aContent.GetApzc(),
|
||||
aContent.Metrics(),
|
||||
aScrollbar->GetScrollThumbData(),
|
||||
aScrollbarIsDescendant,
|
||||
&clipTransform);
|
||||
|
||||
if (aScrollbarIsDescendant) {
|
||||
// We also need to make a corresponding change on the clip rect of all the
|
||||
// layers on the ancestor chain from the scrollbar layer up to but not
|
||||
// including the layer with the async transform. Otherwise the scrollbar
|
||||
// shifts but gets clipped and so appears to flicker.
|
||||
for (Layer* ancestor = aScrollbar; ancestor != aContent.GetLayer(); ancestor = ancestor->GetParent()) {
|
||||
TransformClipRect(ancestor, clipTransform);
|
||||
}
|
||||
}
|
||||
|
||||
SetShadowTransform(aScrollbar, transform);
|
||||
}
|
||||
|
||||
/* static */ LayerToParentLayerMatrix4x4
|
||||
AsyncCompositionManager::ComputeTransformForScrollThumb(
|
||||
const LayerToParentLayerMatrix4x4& aCurrentTransform,
|
||||
const Matrix4x4& aScrollableContentTransform,
|
||||
AsyncPanZoomController* aApzc,
|
||||
const FrameMetrics& aMetrics,
|
||||
const ScrollThumbData& aThumbData,
|
||||
bool aScrollbarIsDescendant,
|
||||
AsyncTransformComponentMatrix* aOutClipTransform)
|
||||
{
|
||||
// We only apply the transform if the scroll-target layer has non-container
|
||||
// children (i.e. when it has some possibly-visible content). This is to
|
||||
// avoid moving scroll-bars in the situation that only a scroll information
|
||||
// layer has been built for a scroll frame, as this would result in a
|
||||
// disparity between scrollbars and visible content.
|
||||
if (aContent.IsScrollInfoLayer()) {
|
||||
return;
|
||||
if (aMetrics.IsScrollInfoLayer()) {
|
||||
return LayerToParentLayerMatrix4x4{};
|
||||
}
|
||||
|
||||
const FrameMetrics& metrics = aContent.Metrics();
|
||||
AsyncPanZoomController* apzc = aContent.GetApzc();
|
||||
MOZ_RELEASE_ASSERT(apzc);
|
||||
MOZ_RELEASE_ASSERT(aApzc);
|
||||
|
||||
AsyncTransformComponentMatrix asyncTransform =
|
||||
apzc->GetCurrentAsyncTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
aApzc->GetCurrentAsyncTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
|
||||
// |asyncTransform| represents the amount by which we have scrolled and
|
||||
// zoomed since the last paint. Because the scrollbar was sized and positioned based
|
||||
// on the painted content, we need to adjust it based on asyncTransform so that
|
||||
// it reflects what the user is actually seeing now.
|
||||
AsyncTransformComponentMatrix scrollbarTransform;
|
||||
const ScrollThumbData& thumbData = aScrollbar->GetScrollThumbData();
|
||||
if (thumbData.mDirection == ScrollDirection::VERTICAL) {
|
||||
if (aThumbData.mDirection == ScrollDirection::VERTICAL) {
|
||||
const ParentLayerCoord asyncScrollY = asyncTransform._42;
|
||||
const float asyncZoomY = asyncTransform._22;
|
||||
|
||||
@ -1139,13 +1171,13 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
const float yScale = 1.f / asyncZoomY;
|
||||
|
||||
// Note: |metrics.GetZoom()| doesn't yet include the async zoom.
|
||||
const CSSToParentLayerScale effectiveZoom(metrics.GetZoom().yScale * asyncZoomY);
|
||||
const CSSToParentLayerScale effectiveZoom(aMetrics.GetZoom().yScale * asyncZoomY);
|
||||
|
||||
// Here we convert the scrollbar thumb ratio into a true unitless ratio by
|
||||
// dividing out the conversion factor from the scrollframe's parent's space
|
||||
// to the scrollframe's space.
|
||||
const float ratio = thumbData.mThumbRatio /
|
||||
(metrics.GetPresShellResolution() * asyncZoomY);
|
||||
const float ratio = aThumbData.mThumbRatio /
|
||||
(aMetrics.GetPresShellResolution() * asyncZoomY);
|
||||
// The scroll thumb needs to be translated in opposite direction of the
|
||||
// async scroll. This is because scrolling down, which translates the layer
|
||||
// content up, should result in moving the scroll thumb down.
|
||||
@ -1162,26 +1194,26 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
// a change of basis. We have a method to help with that,
|
||||
// Matrix4x4::ChangeBasis(), but it wouldn't necessarily make the code
|
||||
// cleaner in this case).
|
||||
const CSSCoord thumbOrigin = (metrics.GetScrollOffset().y * ratio);
|
||||
const CSSCoord thumbOrigin = (aMetrics.GetScrollOffset().y * ratio);
|
||||
const CSSCoord thumbOriginScaled = thumbOrigin * yScale;
|
||||
const CSSCoord thumbOriginDelta = thumbOriginScaled - thumbOrigin;
|
||||
const ParentLayerCoord thumbOriginDeltaPL = thumbOriginDelta * effectiveZoom;
|
||||
yTranslation -= thumbOriginDeltaPL;
|
||||
|
||||
if (metrics.IsRootContent()) {
|
||||
if (aMetrics.IsRootContent()) {
|
||||
// Scrollbar for the root are painted at the same resolution as the
|
||||
// content. Since the coordinate space we apply this transform in includes
|
||||
// the resolution, we need to adjust for it as well here. Note that in
|
||||
// another metrics.IsRootContent() hunk below we apply a
|
||||
// resolution-cancelling transform which ensures the scroll thumb isn't
|
||||
// actually rendered at a larger scale.
|
||||
yTranslation *= metrics.GetPresShellResolution();
|
||||
yTranslation *= aMetrics.GetPresShellResolution();
|
||||
}
|
||||
|
||||
scrollbarTransform.PostScale(1.f, yScale, 1.f);
|
||||
scrollbarTransform.PostTranslate(0, yTranslation, 0);
|
||||
}
|
||||
if (thumbData.mDirection == ScrollDirection::HORIZONTAL) {
|
||||
if (aThumbData.mDirection == ScrollDirection::HORIZONTAL) {
|
||||
// See detailed comments under the VERTICAL case.
|
||||
|
||||
const ParentLayerCoord asyncScrollX = asyncTransform._41;
|
||||
@ -1189,20 +1221,20 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
|
||||
const float xScale = 1.f / asyncZoomX;
|
||||
|
||||
const CSSToParentLayerScale effectiveZoom(metrics.GetZoom().xScale * asyncZoomX);
|
||||
const CSSToParentLayerScale effectiveZoom(aMetrics.GetZoom().xScale * asyncZoomX);
|
||||
|
||||
const float ratio = thumbData.mThumbRatio /
|
||||
(metrics.GetPresShellResolution() * asyncZoomX);
|
||||
const float ratio = aThumbData.mThumbRatio /
|
||||
(aMetrics.GetPresShellResolution() * asyncZoomX);
|
||||
ParentLayerCoord xTranslation = -asyncScrollX * ratio;
|
||||
|
||||
const CSSCoord thumbOrigin = (metrics.GetScrollOffset().x * ratio);
|
||||
const CSSCoord thumbOrigin = (aMetrics.GetScrollOffset().x * ratio);
|
||||
const CSSCoord thumbOriginScaled = thumbOrigin * xScale;
|
||||
const CSSCoord thumbOriginDelta = thumbOriginScaled - thumbOrigin;
|
||||
const ParentLayerCoord thumbOriginDeltaPL = thumbOriginDelta * effectiveZoom;
|
||||
xTranslation -= thumbOriginDeltaPL;
|
||||
|
||||
if (metrics.IsRootContent()) {
|
||||
xTranslation *= metrics.GetPresShellResolution();
|
||||
if (aMetrics.IsRootContent()) {
|
||||
xTranslation *= aMetrics.GetPresShellResolution();
|
||||
}
|
||||
|
||||
scrollbarTransform.PostScale(xScale, 1.f, 1.f);
|
||||
@ -1210,7 +1242,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
}
|
||||
|
||||
LayerToParentLayerMatrix4x4 transform =
|
||||
aScrollbar->GetLocalTransformTyped() * scrollbarTransform;
|
||||
aCurrentTransform * scrollbarTransform;
|
||||
|
||||
AsyncTransformComponentMatrix compensation;
|
||||
// If the scrollbar layer is for the root then the content's resolution
|
||||
@ -1218,11 +1250,11 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
// thumb's size to vary with the zoom (other than its length reflecting the
|
||||
// fraction of the scrollable length that's in view, which is taken care of
|
||||
// above), we apply a transform to cancel out this resolution.
|
||||
if (metrics.IsRootContent()) {
|
||||
if (aMetrics.IsRootContent()) {
|
||||
compensation =
|
||||
AsyncTransformComponentMatrix::Scaling(
|
||||
metrics.GetPresShellResolution(),
|
||||
metrics.GetPresShellResolution(),
|
||||
aMetrics.GetPresShellResolution(),
|
||||
aMetrics.GetPresShellResolution(),
|
||||
1.0f).Inverse();
|
||||
}
|
||||
// If the scrollbar layer is a child of the content it is a scrollbar for,
|
||||
@ -1238,9 +1270,9 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
// and then unapplying it after unapplying the async transform.
|
||||
if (aScrollbarIsDescendant) {
|
||||
AsyncTransformComponentMatrix overscroll =
|
||||
apzc->GetOverscrollTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
aApzc->GetOverscrollTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
Matrix4x4 asyncUntransform = (asyncTransform * overscroll).Inverse().ToUnknownMatrix();
|
||||
Matrix4x4 contentTransform = aContent.GetTransform();
|
||||
Matrix4x4 contentTransform = aScrollableContentTransform;
|
||||
Matrix4x4 contentUntransform = contentTransform.Inverse();
|
||||
|
||||
AsyncTransformComponentMatrix asyncCompensation =
|
||||
@ -1251,17 +1283,15 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
|
||||
compensation = compensation * asyncCompensation;
|
||||
|
||||
// We also need to make a corresponding change on the clip rect of all the
|
||||
// layers on the ancestor chain from the scrollbar layer up to but not
|
||||
// including the layer with the async transform. Otherwise the scrollbar
|
||||
// shifts but gets clipped and so appears to flicker.
|
||||
for (Layer* ancestor = aScrollbar; ancestor != aContent.GetLayer(); ancestor = ancestor->GetParent()) {
|
||||
TransformClipRect(ancestor, asyncCompensation);
|
||||
// Pass the async compensation out to the caller so that it can use it
|
||||
// to transform clip transforms as needed.
|
||||
if (aOutClipTransform) {
|
||||
*aOutClipTransform = asyncCompensation;
|
||||
}
|
||||
}
|
||||
transform = transform * compensation;
|
||||
|
||||
SetShadowTransform(aScrollbar, transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
static LayerMetricsWrapper
|
||||
|
@ -131,6 +131,38 @@ public:
|
||||
};
|
||||
|
||||
typedef std::map<Layer*, ClipParts> ClipPartsCache;
|
||||
|
||||
/**
|
||||
* Compute the updated shadow transform for a scroll thumb layer that
|
||||
* reflects async scrolling of the associated scroll frame.
|
||||
*
|
||||
* @param aCurrentTransform The current shadow transform on the scroll thumb
|
||||
* layer, as returned by Layer::GetLocalTransform() or similar.
|
||||
* @param aScrollableContentTransform The current content transform on the
|
||||
* scrollable content, as returned by Layer::GetTransform().
|
||||
* @param aApzc The APZC that scrolls the scroll frame.
|
||||
* @param aMetrics The metrics associated with the scroll frame, reflecting
|
||||
* the last paint of the associated content. Note: this metrics should
|
||||
* NOT reflect async scrolling, i.e. they should be the layer tree's
|
||||
* copy of the metrics, or APZC's last-content-paint metrics.
|
||||
* @param aThumbData The scroll thumb data for the the scroll thumb layer.
|
||||
* @param aScrollbarIsDescendant True iff. the scroll thumb layer is a
|
||||
* descendant of the layer bearing the scroll frame's metrics.
|
||||
* @param aOutClipTransform If not null, and |aScrollbarIsDescendant| is true,
|
||||
* this will be populated with a transform that should be applied to the
|
||||
* clip rects of all layers between the scroll thumb layer and the ancestor
|
||||
* layer for the scrollable content.
|
||||
* @return The new shadow transform for the scroll thumb layer, including
|
||||
* any pre- or post-scales.
|
||||
*/
|
||||
static LayerToParentLayerMatrix4x4 ComputeTransformForScrollThumb(
|
||||
const LayerToParentLayerMatrix4x4& aCurrentTransform,
|
||||
const gfx::Matrix4x4& aScrollableContentTransform,
|
||||
AsyncPanZoomController* aApzc,
|
||||
const FrameMetrics& aMetrics,
|
||||
const ScrollThumbData& aThumbData,
|
||||
bool aScrollbarIsDescendant,
|
||||
AsyncTransformComponentMatrix* aOutClipTransform);
|
||||
private:
|
||||
// Return true if an AsyncPanZoomController content transform was
|
||||
// applied for |aLayer|. |*aOutFoundRoot| is set to true on Android only, if
|
||||
|
Loading…
x
Reference in New Issue
Block a user