Bug 1148582 - Apply async transforms to (ancestor) mask layers correctly. r=botond

This commit is contained in:
David Anderson 2015-06-30 21:07:09 -04:00
parent aaecf99fae
commit 6c90f76817
7 changed files with 68 additions and 23 deletions

View File

@ -57,7 +57,7 @@ void ImageLayer::ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSu
mEffectiveTransformForBuffer = mEffectiveTransform;
}
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
}

View File

@ -857,21 +857,31 @@ Layer::DeprecatedGetEffectiveMixBlendMode()
}
void
Layer::ComputeEffectiveTransformForMaskLayer(const Matrix4x4& aTransformToSurface)
Layer::ComputeEffectiveTransformForMaskLayers(const gfx::Matrix4x4& aTransformToSurface)
{
if (mMaskLayer) {
mMaskLayer->mEffectiveTransform = aTransformToSurface;
if (GetMaskLayer()) {
ComputeEffectiveTransformForMaskLayer(GetMaskLayer(), aTransformToSurface);
}
for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
Layer* maskLayer = GetAncestorMaskLayerAt(i);
ComputeEffectiveTransformForMaskLayer(maskLayer, aTransformToSurface);
}
}
/* static */ void
Layer::ComputeEffectiveTransformForMaskLayer(Layer* aMaskLayer, const gfx::Matrix4x4& aTransformToSurface)
{
aMaskLayer->mEffectiveTransform = aTransformToSurface;
#ifdef DEBUG
bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D();
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D();
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
#endif
// The mask layer can have an async transform applied to it in some
// situations, so be sure to use its GetLocalTransform() rather than
// its GetTransform().
mMaskLayer->mEffectiveTransform = mMaskLayer->GetLocalTransform() *
mMaskLayer->mEffectiveTransform;
}
// The mask layer can have an async transform applied to it in some
// situations, so be sure to use its GetLocalTransform() rather than
// its GetTransform().
aMaskLayer->mEffectiveTransform = aMaskLayer->GetLocalTransform() *
aMaskLayer->mEffectiveTransform;
}
RenderTargetRect
@ -1236,9 +1246,9 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
}
if (idealTransform.CanDraw2D()) {
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
} else {
ComputeEffectiveTransformForMaskLayer(Matrix4x4());
ComputeEffectiveTransformForMaskLayers(Matrix4x4());
}
}

View File

@ -1514,9 +1514,11 @@ public:
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) = 0;
/**
* computes the effective transform for a mask layer, if this layer has one
* Computes the effective transform for mask layers, if this layer has any.
*/
void ComputeEffectiveTransformForMaskLayer(const gfx::Matrix4x4& aTransformToSurface);
void ComputeEffectiveTransformForMaskLayers(const gfx::Matrix4x4& aTransformToSurface);
static void ComputeEffectiveTransformForMaskLayer(Layer* aMaskLayer,
const gfx::Matrix4x4& aTransformToSurface);
/**
* Calculate the scissor rect required when rendering this layer.
@ -1832,7 +1834,7 @@ public:
"Residual translation out of range");
mValidRegion.SetEmpty();
}
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
LayerManager::PaintedLayerCreationHint GetCreationHint() const { return mCreationHint; }
@ -2143,7 +2145,7 @@ public:
{
gfx::Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
mEffectiveTransform = SnapTransformTranslation(idealTransform, nullptr);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
protected:
@ -2295,7 +2297,7 @@ public:
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
nullptr)*
SnapTransformTranslation(aTransformToSurface, nullptr);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
protected:

View File

@ -44,7 +44,7 @@ BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSur
if (!idealTransform.CanDraw2D()) {
mEffectiveTransform = idealTransform;
ComputeEffectiveTransformsForChildren(Matrix4x4());
ComputeEffectiveTransformForMaskLayer(Matrix4x4());
ComputeEffectiveTransformForMaskLayers(Matrix4x4());
mUseIntermediateSurface = true;
return;
}
@ -54,7 +54,7 @@ BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSur
// need to apply any compensation using the residual from SnapTransformTranslation.
ComputeEffectiveTransformsForChildren(idealTransform);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
Layer* child = GetFirstChild();
bool hasSingleBlendingChild = false;

View File

@ -86,7 +86,7 @@ public:
mResidualTranslation = gfxPoint(0,0);
mValidRegion.SetEmpty();
}
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
return;
}
PaintedLayer::ComputeEffectiveTransforms(aTransformToSurface);

View File

@ -614,6 +614,18 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer)
// The final clip for the layer is the intersection of these clips.
Maybe<ParentLayerIntRect> asyncClip = aLayer->GetClipRect();
// The transform of a mask layer is relative to the masked layer's parent
// layer. So whenever we apply an async transform to a layer, we need to
// apply that same transform to the layer's own mask layer.
// A layer can also have "ancestor" mask layers for any rounded clips from
// its ancestor scroll frames. A scroll frame mask layer only needs to be
// async transformed for async scrolls of this scroll frame's ancestor
// scroll frames, not for async scrolls of this scroll frame itself.
// In the loop below, we iterate over scroll frames from inside to outside.
// At each iteration, this array contains the layer's ancestor mask layers
// of all scroll frames inside the current one.
nsTArray<Layer*> ancestorMaskLayers;
for (uint32_t i = 0; i < aLayer->GetFrameMetricsCount(); i++) {
AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController(i);
if (!controller) {
@ -676,6 +688,21 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer)
}
}
// Do the same for the ancestor mask layers: ancestorMaskLayers contains
// the ancestor mask layers for scroll frames *inside* the current scroll
// frame, so these are the ones we need to shift by our async transform.
for (Layer* ancestorMaskLayer : ancestorMaskLayers) {
SetShadowTransform(ancestorMaskLayer,
ancestorMaskLayer->GetLocalTransform() * asyncTransform);
}
// Append the ancestor mask layer for this scroll frame to ancestorMaskLayers.
if (metrics.GetMaskLayerIndex()) {
size_t maskLayerIndex = metrics.GetMaskLayerIndex().value();
Layer* ancestorMaskLayer = aLayer->GetAncestorMaskLayerAt(maskLayerIndex);
ancestorMaskLayers.AppendElement(ancestorMaskLayer);
}
combinedAsyncTransformWithoutOverscroll *= asyncTransformWithoutOverscroll;
combinedAsyncTransform *= asyncTransform;
}
@ -692,6 +719,12 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer)
SetShadowTransform(aLayer,
aLayer->GetLocalTransform() * AdjustForClip(combinedAsyncTransform, aLayer));
// Do the same for the layer's own mask layer, if it has one.
if (Layer* maskLayer = aLayer->GetMaskLayer()) {
SetShadowTransform(maskLayer,
maskLayer->GetLocalTransform() * combinedAsyncTransform);
}
const FrameMetrics& bottom = LayerMetricsWrapper::BottommostScrollableMetrics(aLayer);
MOZ_ASSERT(bottom.IsScrollable()); // must be true because hasAsyncTransform is true

View File

@ -143,7 +143,7 @@ ImageLayerComposite::ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransform
mEffectiveTransformForBuffer = mEffectiveTransform;
}
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
CompositableHost*