--- a/gfx/layers/LayerSorter.cpp
+++ b/gfx/layers/LayerSorter.cpp
@@ -73,23 +73,18 @@ static gfxFloat RecoverZDepth(const Matr
* in particular) and this generates the 'correct' looking ordering. For planes
* that truely intersect, then there is no correct ordering and this remains
* unsolved without changing our rendering code.
*/
static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
gfxRect ourRect = aOne->GetEffectiveVisibleRegion().GetBounds();
gfxRect otherRect = aTwo->GetEffectiveVisibleRegion().GetBounds();
- MOZ_ASSERT(aOne->GetParent() && aOne->GetParent()->Extend3DContext() &&
- aTwo->GetParent() && aTwo->GetParent()->Extend3DContext());
- // Effective transform of leaves may had been projected to 2D.
- Matrix4x4 ourTransform =
- aOne->GetLocalTransform() * aOne->GetParent()->GetEffectiveTransform();
- Matrix4x4 otherTransform =
- aTwo->GetLocalTransform() * aTwo->GetParent()->GetEffectiveTransform();
+ Matrix4x4 ourTransform = aOne->GetTransform();
+ Matrix4x4 otherTransform = aTwo->GetTransform();
// Transform both rectangles and project into 2d space.
gfxQuad ourTransformedRect = ourRect.TransformToQuad(ourTransform);
gfxQuad otherTransformedRect = otherRect.TransformToQuad(otherTransform);
gfxRect ourBounds = ourTransformedRect.GetBounds();
gfxRect otherBounds = otherTransformedRect.GetBounds();
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -621,96 +621,37 @@ Layer::GetEffectiveVisibleRegion()
Matrix4x4
Layer::SnapTransformTranslation(const Matrix4x4& aTransform,
Matrix* aResidualTransform)
{
if (aResidualTransform) {
*aResidualTransform = Matrix();
}
- if (!mManager->IsSnappingEffectiveTransforms()) {
- return aTransform;
- }
-
Matrix matrix2D;
Matrix4x4 result;
- if (aTransform.Is2D(&matrix2D) &&
+ if (mManager->IsSnappingEffectiveTransforms() &&
+ aTransform.Is2D(&matrix2D) &&
!matrix2D.HasNonTranslation() &&
matrix2D.HasNonIntegerTranslation()) {
IntPoint snappedTranslation = RoundedToInt(matrix2D.GetTranslation());
Matrix snappedMatrix = Matrix::Translation(snappedTranslation.x,
snappedTranslation.y);
result = Matrix4x4::From2D(snappedMatrix);
if (aResidualTransform) {
// set aResidualTransform so that aResidual * snappedMatrix == matrix2D.
// (I.e., appying snappedMatrix after aResidualTransform gives the
// ideal transform.)
*aResidualTransform =
Matrix::Translation(matrix2D._31 - snappedTranslation.x,
matrix2D._32 - snappedTranslation.y);
}
- return result;
- }
-
- if(aTransform.IsSingular() ||
- (aTransform._14 != 0 || aTransform._24 != 0 || aTransform._34 != 0)) {
- // For a singular transform, there is no reversed matrix, so we
- // don't snap it.
- // For a perspective transform, the content is transformed in
- // non-linear, so we don't snap it too.
- return aTransform;
+ } else {
+ result = aTransform;
}
-
- // Snap for 3D Transforms
-
- Point3D transformedOrigin = aTransform * Point3D();
-
- // Compute the transformed snap by rounding the values of
- // transformed origin.
- IntPoint transformedSnapXY =
- RoundedToInt(Point(transformedOrigin.x, transformedOrigin.y));
- Matrix4x4 inverse = aTransform;
- inverse.Invert();
- // see Matrix4x4::ProjectPoint()
- Float transformedSnapZ =
- inverse._33 == 0 ? 0 : (-(transformedSnapXY.x * inverse._13 +
- transformedSnapXY.y * inverse._23 +
- inverse._43) / inverse._33);
- Point3D transformedSnap =
- Point3D(transformedSnapXY.x, transformedSnapXY.y, transformedSnapZ);
- if (transformedOrigin == transformedSnap) {
- return aTransform;
- }
-
- // Compute the snap from the transformed snap.
- Point3D snap = inverse * transformedSnap;
- if (snap.z > 0.001 || snap.z < -0.001) {
- // Allow some level of accumulated computation error.
- MOZ_ASSERT(inverse._33 == 0.0);
- return aTransform;
- }
-
- // The difference between the origin and snap is the residual transform.
- if (aResidualTransform) {
- // The residual transform is to translate the snap to the origin
- // of the content buffer.
- *aResidualTransform = Matrix::Translation(-snap.x, -snap.y);
- }
-
- // Translate transformed origin to transformed snap since the
- // residual transform would trnslate the snap to the origin.
- Point3D transformedShift = transformedSnap - transformedOrigin;
- result = aTransform;
- result.PostTranslate(transformedShift.x,
- transformedShift.y,
- transformedShift.z);
-
- // For non-2d transform, residual translation could be more than
- // 0.5 pixels for every axis.
-
return result;
}
Matrix4x4
Layer::SnapTransform(const Matrix4x4& aTransform,
const gfxRect& aSnapRect,
Matrix* aResidualTransform)
{
@@ -765,55 +706,40 @@ Layer::MayResample()
ThebesMatrix(transform2d).HasNonIntegerTranslation() ||
AncestorLayerMayChangeTransform(this);
}
RenderTargetIntRect
Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
{
ContainerLayer* container = GetParent();
- ContainerLayer* containerChild = nullptr;
- NS_ASSERTION(GetParent(), "This can't be called on the root!");
-
- // Find the layer creating the 3D context.
- while (container->Extend3DContext()) {
- containerChild = container;
- container = container->GetParent();
- MOZ_ASSERT(container);
- }
-
- // Find the nearest layer with a clip, or this layer.
- // ContainerState::SetupScrollingMetadata() may install a clip on
- // the layer.
- Layer *clipLayer =
- containerChild && containerChild->GetEffectiveClipRect() ?
- containerChild : this;
+ NS_ASSERTION(container, "This can't be called on the root!");
// Establish initial clip rect: it's either the one passed in, or
// if the parent has an intermediate surface, it's the extents of that surface.
RenderTargetIntRect currentClip;
if (container->UseIntermediateSurface()) {
currentClip.SizeTo(container->GetIntermediateSurfaceRect().Size());
} else {
currentClip = aCurrentScissorRect;
}
- if (!clipLayer->GetEffectiveClipRect()) {
+ if (!GetEffectiveClipRect()) {
return currentClip;
}
if (GetVisibleRegion().IsEmpty()) {
// When our visible region is empty, our parent may not have created the
// intermediate surface that we would require for correct clipping; however,
// this does not matter since we are invisible.
return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
}
const RenderTargetIntRect clipRect =
- ViewAs<RenderTargetPixel>(*clipLayer->GetEffectiveClipRect(),
+ ViewAs<RenderTargetPixel>(*GetEffectiveClipRect(),
PixelCastJustification::RenderTargetIsParentLayerForRoot);
if (clipRect.IsEmpty()) {
// We might have a non-translation transform in the container so we can't
// use the code path below.
return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
}
RenderTargetIntRect scissor = clipRect;
@@ -1266,32 +1192,16 @@ ContainerLayer::FillSpecificAttributes(S
aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
mInheritedXScale, mInheritedYScale,
mPresShellResolution, mScaleToResolution,
mEventRegionsOverride,
reinterpret_cast<uint64_t>(mHMDInfo.get()));
}
bool
-ContainerLayer::Creates3DContextWithExtendingChildren()
-{
- if (Extend3DContext()) {
- return false;
- }
- for (Layer* child = GetFirstChild();
- child;
- child = child->GetNextSibling()) {
- if (child->Extend3DContext()) {
- return true;
- }
- }
- return false;
-}
-
-bool
ContainerLayer::HasMultipleChildren()
{
uint32_t count = 0;
for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
const Maybe<ParentLayerIntRect>& clipRect = child->GetEffectiveClipRect();
if (clipRect && clipRect->IsEmpty())
continue;
if (child->GetVisibleRegion().IsEmpty())
@@ -1299,41 +1209,25 @@ ContainerLayer::HasMultipleChildren()
++count;
if (count > 1)
return true;
}
return false;
}
-/**
- * Collect all leaf descendants of the current 3D context.
- */
-void
-ContainerLayer::Collect3DContextLeaves(nsTArray<Layer*>& aToSort)
-{
- for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
- ContainerLayer* container = l->AsContainerLayer();
- if (container && container->Extend3DContext()) {
- container->Collect3DContextLeaves(aToSort);
- } else {
- aToSort.AppendElement(l);
- }
- }
-}
-
void
ContainerLayer::SortChildrenBy3DZOrder(nsTArray<Layer*>& aArray)
{
nsAutoTArray<Layer*, 10> toSort;
for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) {
ContainerLayer* container = l->AsContainerLayer();
- if (container && container->Extend3DContext()) {
- container->Collect3DContextLeaves(toSort);
+ if (container && container->GetContentFlags() & CONTENT_PRESERVE_3D) {
+ toSort.AppendElement(l);
} else {
if (toSort.Length() > 0) {
SortLayersBy3DZOrder(toSort);
aArray.AppendElements(Move(toSort));
// XXX The move analysis gets confused here, because toSort gets moved
// here, and then gets used again outside of the loop. To clarify that
// we realize that the array is going to be empty to the move checker,
// we clear it again here. (This method renews toSort for the move
@@ -1349,43 +1243,39 @@ ContainerLayer::SortChildrenBy3DZOrder(n
}
}
void
ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface)
{
Matrix residual;
Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
-
- // Keep 3D transforms for leaves to keep z-order sorting correct.
- if (!Extend3DContext() && !Is3DContextLeaf()) {
- idealTransform.ProjectTo2D();
- }
+ idealTransform.ProjectTo2D();
+ mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
bool useIntermediateSurface;
if (HasMaskLayers() ||
GetForceIsolatedGroup()) {
useIntermediateSurface = true;
#ifdef MOZ_DUMP_PAINTING
- } else if (gfxUtils::sDumpPaintingIntermediate && !Extend3DContext()) {
+ } else if (gfxUtils::sDumpPaintingIntermediate) {
useIntermediateSurface = true;
#endif
} else {
float opacity = GetEffectiveOpacity();
CompositionOp blendMode = GetEffectiveMixBlendMode();
- if (((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) ||
- (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) {
+ if ((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) {
useIntermediateSurface = true;
} else {
useIntermediateSurface = false;
gfx::Matrix contTransform;
bool checkClipRect = false;
bool checkMaskLayers = false;
- if (!idealTransform.Is2D(&contTransform)) {
+ if (!mEffectiveTransform.Is2D(&contTransform)) {
// In 3D case, always check if we should use IntermediateSurface.
checkClipRect = true;
checkMaskLayers = true;
} else {
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
if (!contTransform.PreservesAxisAlignedRectangles()) {
#else
if (gfx::ThebesMatrix(contTransform).HasNonIntegerTranslation()) {
@@ -1416,29 +1306,16 @@ ContainerLayer::DefaultComputeEffectiveT
useIntermediateSurface = true;
break;
}
}
}
}
}
- if (useIntermediateSurface) {
- mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
- } else {
- mEffectiveTransform = idealTransform;
- }
-
- // For layers extending 3d context, its ideal transform should be
- // applied on children.
- if (!Extend3DContext()) {
- // Without this projection, non-container children would get a 3D
- // transform while 2D is expected.
- idealTransform.ProjectTo2D();
- }
mUseIntermediateSurface = useIntermediateSurface && !GetEffectiveVisibleRegion().IsEmpty();
if (useIntermediateSurface) {
ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
} else {
ComputeEffectiveTransformsForChildren(idealTransform);
}
if (idealTransform.CanDraw2D()) {
@@ -2053,33 +1930,16 @@ Layer::DumpPacket(layerscope::LayersPack
MakeUnique<char[]>(LZ4::maxCompressedSize(mDisplayListLog.Length()));
int compressedSize = LZ4::compress((char*)mDisplayListLog.get(),
mDisplayListLog.Length(),
compressedData.get());
layer->set_displaylistlog(compressedData.get(), compressedSize);
}
}
-bool
-Layer::IsBackfaceHidden()
-{
- if (GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
- Layer* container = AsContainerLayer() ? this : GetParent();
- if (container) {
- // The effective transform can include non-preserve-3d parent
- // transforms, since we don't always require an intermediate.
- if (container->Extend3DContext() || container->Is3DContextLeaf()) {
- return container->GetEffectiveTransform().IsBackfaceVisible();
- }
- return container->GetBaseTransform().IsBackfaceVisible();
- }
- }
- return false;
-}
-
nsAutoPtr<LayerUserData>
Layer::RemoveUserData(void* aKey)
{
nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
return d;
}
void
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -768,17 +768,17 @@ public:
* CONTENT_COMPONENT_ALPHA set.
*/
CONTENT_COMPONENT_ALPHA_DESCENDANT = 0x04,
/**
* If this is set then this layer is part of a preserve-3d group, and should
* be sorted with sibling layers that are also part of the same group.
*/
- CONTENT_EXTEND_3D_CONTEXT = 0x08,
+ CONTENT_PRESERVE_3D = 0x08,
/**
* This indicates that the transform may be changed on during an empty
* transaction where there is no possibility of redrawing the content, so the
* implementation should be ready for that.
*/
CONTENT_MAY_CHANGE_TRANSFORM = 0x10,
/**
@@ -788,23 +788,17 @@ public:
CONTENT_DISABLE_SUBPIXEL_AA = 0x20,
/**
* If this is set then the layer contains content that may look objectionable
* if not handled as an active layer (such as text with an animated transform).
* This is for internal layout/FrameLayerBuilder usage only until flattening
* code is obsoleted. See bug 633097
*/
- CONTENT_DISABLE_FLATTENING = 0x40,
-
- /**
- * This layer is hidden if the backface of the layer is visible
- * to user.
- */
- CONTENT_BACKFACE_HIDDEN = 0x80
+ CONTENT_DISABLE_FLATTENING = 0x40
};
/**
* CONSTRUCTION PHASE ONLY
* This lets layout make some promises about what will be drawn into the
* visible region of the PaintedLayer. This enables internal quality
* and performance optimizations.
*/
void SetContentFlags(uint32_t aFlags)
@@ -1458,36 +1452,16 @@ public:
virtual ShadowableLayer* AsShadowableLayer() { return nullptr; }
// These getters can be used anytime. They return the effective
// values that should be used when drawing this layer to screen,
// accounting for this layer possibly being a shadow.
const Maybe<ParentLayerIntRect>& GetEffectiveClipRect();
const nsIntRegion& GetEffectiveVisibleRegion();
- bool Extend3DContext() {
- return GetContentFlags() & CONTENT_EXTEND_3D_CONTEXT;
- }
- bool Is3DContextLeaf() {
- return !Extend3DContext() && GetParent() &&
- reinterpret_cast<Layer*>(GetParent())->Extend3DContext();
- }
- /**
- * It is true if the user can see the back of the layer and the
- * backface is hidden. The compositor should skip the layer if the
- * result is true.
- */
- bool IsBackfaceHidden();
- bool IsVisible() {
- // For containers extending 3D context, visible region
- // is meaningless, since they are just intermediate result of
- // content.
- return !GetEffectiveVisibleRegion().IsEmpty() || Extend3DContext();
- }
-
/**
* Returns the product of the opacities of this layer and all ancestors up
* to and excluding the nearest ancestor that has UseIntermediateSurface() set.
*/
float GetEffectiveOpacity();
/**
* Returns the blendmode of this layer.
@@ -1878,26 +1852,18 @@ public:
mEffectiveTransform = SnapTransformTranslation(idealTransform,
mAllowResidualTranslation ? &residual : nullptr);
// The residual can only be a translation because SnapTransformTranslation
// only changes the transform if it's a translation
NS_ASSERTION(residual.IsTranslation(),
"Residual transform can only be a translation");
if (!gfx::ThebesPoint(residual.GetTranslation()).WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
mResidualTranslation = gfx::ThebesPoint(residual.GetTranslation());
- DebugOnly<mozilla::gfx::Point> transformedOrig =
- idealTransform * mozilla::gfx::Point();
-#ifdef DEBUG
- DebugOnly<mozilla::gfx::Point> transformed =
- idealTransform * mozilla::gfx::Point(mResidualTranslation.x,
- mResidualTranslation.y) -
- *&transformedOrig;
-#endif
- NS_ASSERTION(-0.5 <= (&transformed)->x && (&transformed)->x < 0.5 &&
- -0.5 <= (&transformed)->y && (&transformed)->y < 0.5,
+ NS_ASSERTION(-0.5 <= mResidualTranslation.x && mResidualTranslation.x < 0.5 &&
+ -0.5 <= mResidualTranslation.y && mResidualTranslation.y < 0.5,
"Residual translation out of range");
mValidRegion.SetEmpty();
}
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
LayerManager::PaintedLayerCreationHint GetCreationHint() const { return mCreationHint; }
@@ -2132,18 +2098,16 @@ public:
}
protected:
friend class ReadbackProcessor;
void DidInsertChild(Layer* aLayer);
void DidRemoveChild(Layer* aLayer);
- void Collect3DContextLeaves(nsTArray<Layer*>& aToSort);
-
ContainerLayer(LayerManager* aManager, void* aImplData);
/**
* A default implementation of ComputeEffectiveTransforms for use by OpenGL
* and D3D.
*/
void DefaultComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface);
@@ -2159,22 +2123,16 @@ protected:
* Loops over the children calling ComputeEffectiveTransforms on them.
*/
void ComputeEffectiveTransformsForChildren(const gfx::Matrix4x4& aTransformToSurface);
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
- /**
- * True for if the container start a new 3D context extended by one
- * or more children.
- */
- bool Creates3DContextWithExtendingChildren();
-
Layer* mFirstChild;
Layer* mLastChild;
float mPreXScale;
float mPreYScale;
// The resolution scale inherited from the parent layer. This will already
// be part of mTransform.
float mInheritedXScale;
float mInheritedYScale;
--- a/gfx/layers/apz/test/reftest/reftest.list
+++ b/gfx/layers/apz/test/reftest/reftest.list
@@ -5,13 +5,13 @@ chaos-mode skip-if(!asyncPan) == async-s
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
# compositor, the border-radius ends of the scrollthumb are going to be a little
# off, hence the fuzzy-if clauses.
-chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,98,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
+chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,77,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-scrollbar-zoom-2-ref.html
# Meta-viewport tag support
chaos-mode skip-if(!asyncZoom) == initial-scale-1.html initial-scale-1-ref.html
--- a/gfx/layers/basic/BasicContainerLayer.cpp
+++ b/gfx/layers/basic/BasicContainerLayer.cpp
@@ -34,42 +34,32 @@ BasicContainerLayer::~BasicContainerLaye
void
BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface)
{
// We push groups for container layers if we need to, which always
// are aligned in device space, so it doesn't really matter how we snap
// containers.
Matrix residual;
Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
- if (!Extend3DContext() && !Is3DContextLeaf()) {
- // For 3D transform leaked from extended parent layer.
- idealTransform.ProjectTo2D();
- }
+ idealTransform.ProjectTo2D();
if (!idealTransform.CanDraw2D()) {
- if (!Extend3DContext() ||
- (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) {
- if (!Creates3DContextWithExtendingChildren()) {
- idealTransform.ProjectTo2D();
- }
- mEffectiveTransform = idealTransform;
- ComputeEffectiveTransformsForChildren(Matrix4x4());
- ComputeEffectiveTransformForMaskLayers(Matrix4x4());
- mUseIntermediateSurface = true;
- return;
- }
-
mEffectiveTransform = idealTransform;
- ComputeEffectiveTransformsForChildren(idealTransform);
- ComputeEffectiveTransformForMaskLayers(idealTransform);
- mUseIntermediateSurface = false;
+ ComputeEffectiveTransformsForChildren(Matrix4x4());
+ ComputeEffectiveTransformForMaskLayers(Matrix4x4());
+ mUseIntermediateSurface = true;
return;
}
- // With 2D transform or extended 3D context.
+ mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
+ // We always pass the ideal matrix down to our children, so there is no
+ // need to apply any compensation using the residual from SnapTransformTranslation.
+ ComputeEffectiveTransformsForChildren(idealTransform);
+
+ ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
Layer* child = GetFirstChild();
bool hasSingleBlendingChild = false;
if (!HasMultipleChildren() && child) {
hasSingleBlendingChild = child->GetMixBlendMode() != CompositionOp::OP_OVER;
}
/* If we have a single childand it is not blending,, it can just inherit our opacity,
@@ -79,30 +69,16 @@ BasicContainerLayer::ComputeEffectiveTra
* Having a mask layer always forces our own push group
* Having a blend mode also always forces our own push group
*/
mUseIntermediateSurface =
GetMaskLayer() ||
GetForceIsolatedGroup() ||
(GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
(GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
-
- if (!Extend3DContext()) {
- idealTransform.ProjectTo2D();
- }
- mEffectiveTransform =
- !mUseIntermediateSurface ?
- idealTransform : SnapTransformTranslation(idealTransform, &residual);
- Matrix4x4 childTransformToSurface =
- (!mUseIntermediateSurface ||
- (mUseIntermediateSurface && !Extend3DContext() /* 2D */)) ?
- idealTransform : Matrix4x4::From2D(residual);
- ComputeEffectiveTransformsForChildren(childTransformToSurface);
-
- ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
bool
BasicContainerLayer::ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect)
{
Matrix transform;
if (!GetEffectiveTransform().CanDraw2D(&transform) ||
ThebesMatrix(transform).HasNonIntegerTranslation())
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -805,25 +805,17 @@ BasicLayerManager::PaintSelfOrChildren(P
aPaintContext.mLayer->GetMaskLayer());
}
} else {
ContainerLayer* container =
static_cast<ContainerLayer*>(aPaintContext.mLayer);
nsAutoTArray<Layer*, 12> children;
container->SortChildrenBy3DZOrder(children);
for (uint32_t i = 0; i < children.Length(); i++) {
- Layer* layer = children.ElementAt(i);
- if (layer->IsBackfaceHidden()) {
- continue;
- }
- if (!layer->AsContainerLayer() && !layer->IsVisible()) {
- continue;
- }
-
- PaintLayer(aGroupTarget, layer, aPaintContext.mCallback,
+ PaintLayer(aGroupTarget, children.ElementAt(i), aPaintContext.mCallback,
aPaintContext.mCallbackData);
if (mTransactionIncomplete)
break;
}
}
}
void
@@ -847,51 +839,16 @@ BasicLayerManager::FlushGroup(PaintLayer
CompositionOp op = GetEffectiveOperator(aPaintContext.mLayer);
AutoSetOperator setOperator(aPaintContext.mTarget, op);
PaintWithMask(aPaintContext.mTarget, aPaintContext.mLayer->GetEffectiveOpacity(),
aPaintContext.mLayer->GetMaskLayer());
}
}
-/**
- * Install the clip applied to the layer on the given gfxContext. The
- * given gfxContext is the buffer that the layer will be painted to.
- */
-static void
-InstallLayerClipPreserves3D(gfxContext* aTarget, Layer* aLayer)
-{
- const Maybe<ParentLayerIntRect> &clipRect = aLayer->GetEffectiveClipRect();
-
- if (!clipRect) {
- return;
- }
-
- Layer* parent = aLayer->GetParent();
- Matrix4x4 transform3d =
- parent && parent->Extend3DContext() ?
- parent->GetEffectiveTransform() :
- Matrix4x4();
- Matrix transform;
- if (!transform3d.CanDraw2D(&transform)) {
- MOZ_CRASH("We should not have a 3D transform that CanDraw2D() is false!");
- return;
- }
- gfxMatrix oldTransform = aTarget->CurrentMatrix();
- transform *= ToMatrix(oldTransform);
- aTarget->SetMatrix(ThebesMatrix(transform));
-
- aTarget->NewPath();
- aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y,
- clipRect->width, clipRect->height));
- aTarget->Clip();
-
- aTarget->SetMatrix(oldTransform);
-}
-
void
BasicLayerManager::PaintLayer(gfxContext* aTarget,
Layer* aLayer,
DrawPaintedLayerCallback aCallback,
void* aCallbackData)
{
MOZ_ASSERT(aTarget);
@@ -921,34 +878,27 @@ BasicLayerManager::PaintLayer(gfxContext
NS_ASSERTION(!container || !aLayer->GetMaskLayer() ||
container->UseIntermediateSurface(),
"ContainerLayer with mask layer should force UseIntermediateSurface");
gfxContextAutoSaveRestore contextSR;
gfxMatrix transform;
// Will return an identity matrix for 3d transforms, and is handled separately below.
bool is2D = paintLayerContext.Setup2DTransform();
- MOZ_ASSERT(is2D || needsGroup || !container ||
- container->Extend3DContext() ||
- container->Is3DContextLeaf(),
- "Must PushGroup for 3d transforms!");
+ MOZ_ASSERT(is2D || needsGroup || !container, "Must PushGroup for 3d transforms!");
- Layer* parent = aLayer->GetParent();
- bool inPreserves3DChain = parent && parent->Extend3DContext();
bool needsSaveRestore =
- needsGroup || clipRect || needsClipToVisibleRegion || !is2D ||
- inPreserves3DChain;
+ needsGroup || clipRect || needsClipToVisibleRegion || !is2D;
if (needsSaveRestore) {
contextSR.SetContext(aTarget);
- // The clips on ancestors on the preserved3d chain should be
- // installed on the aTarget before painting the layer.
- InstallLayerClipPreserves3D(aTarget, aLayer);
- for (Layer* l = parent; l && l->Extend3DContext(); l = l->GetParent()) {
- InstallLayerClipPreserves3D(aTarget, l);
+ if (clipRect) {
+ aTarget->NewPath();
+ aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height));
+ aTarget->Clip();
}
}
paintLayerContext.Apply2DTransform();
const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
// If needsGroup is true, we'll clip to the visible region after we've popped the group
if (needsClipToVisibleRegion && !needsGroup) {
@@ -973,21 +923,16 @@ BasicLayerManager::PaintLayer(gfxContext
&needsClipToVisibleRegion);
PaintSelfOrChildren(paintLayerContext, groupTarget);
aTarget->PopGroupToSource();
FlushGroup(paintLayerContext, needsClipToVisibleRegion);
} else {
PaintSelfOrChildren(paintLayerContext, aTarget);
}
} else {
- if (!needsGroup && container) {
- PaintSelfOrChildren(paintLayerContext, aTarget);
- return;
- }
-
const IntRect& bounds = visibleRegion.GetBounds();
RefPtr<DrawTarget> untransformedDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(bounds.width, bounds.height),
SurfaceFormat::B8G8R8A8);
if (!untransformedDT) {
return;
}
--- a/gfx/layers/client/ClientContainerLayer.h
+++ b/gfx/layers/client/ClientContainerLayer.h
@@ -53,17 +53,17 @@ public:
nsAutoTArray<Layer*, 12> children;
SortChildrenBy3DZOrder(children);
ReadbackProcessor readback;
readback.BuildUpdates(this);
for (uint32_t i = 0; i < children.Length(); i++) {
Layer* child = children.ElementAt(i);
- if (!child->IsVisible()) {
+ if (child->GetEffectiveVisibleRegion().IsEmpty()) {
continue;
}
ToClientLayer(child)->RenderLayerWithReadback(&readback);
if (!ClientManager()->GetRepeatTransaction() &&
!child->GetInvalidRegion().IsEmpty()) {
child->Mutated();
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -191,28 +191,24 @@ ContainerRenderVR(ContainerT* aContainer
gfx::Matrix4x4 origTransform = aContainer->GetEffectiveTransform();
for (uint32_t i = 0; i < children.Length(); i++) {
LayerComposite* layerToRender = static_cast<LayerComposite*>(children.ElementAt(i)->ImplData());
Layer* layer = layerToRender->GetLayer();
uint32_t contentFlags = layer->GetContentFlags();
- if (layer->IsBackfaceHidden()) {
+ if (layer->GetEffectiveVisibleRegion().IsEmpty() &&
+ !layer->AsContainerLayer()) {
continue;
}
- if (!layer->IsVisible() && !layer->AsContainerLayer()) {
- continue;
- }
-
- // We flip between pre-rendered and Gecko-rendered VR based on
- // whether the child layer of this VR container layer has
- // CONTENT_EXTEND_3D_CONTEXT or not.
- if ((contentFlags & Layer::CONTENT_EXTEND_3D_CONTEXT) == 0) {
+ // We flip between pre-rendered and Gecko-rendered VR based on whether
+ // the child layer of this VR container layer has PRESERVE_3D or not.
+ if ((contentFlags & Layer::CONTENT_PRESERVE_3D) == 0) {
// This layer is native VR
DUMP("%p Switching to pre-rendered VR\n", aContainer);
// XXX we still need depth test here, but we have no way of preserving
// depth anyway in native VR layers until we have a way to save them
// from WebGL (and maybe depth video?)
compositor->SetRenderTarget(surface);
aContainer->ReplaceEffectiveTransform(origTransform);
@@ -351,24 +347,20 @@ ContainerPrepare(ContainerT* aContainer,
aContainer->SortChildrenBy3DZOrder(children);
for (uint32_t i = 0; i < children.Length(); i++) {
LayerComposite* layerToRender = static_cast<LayerComposite*>(children.ElementAt(i)->ImplData());
RenderTargetIntRect clipRect = layerToRender->GetLayer()->
CalculateScissorRect(aClipRect);
- if (layerToRender->GetLayer()->IsBackfaceHidden()) {
- continue;
- }
-
// We don't want to skip container layers because otherwise their mPrepared
// may be null which is not allowed.
if (!layerToRender->GetLayer()->AsContainerLayer()) {
- if (!layerToRender->GetLayer()->IsVisible()) {
+ if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer());
continue;
}
if (clipRect.IsEmpty()) {
CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
continue;
}
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -686,17 +686,16 @@ CompositorD3D9::PrepareViewport(const gf
/*
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
* <1.0, -1.0> bottomright)
*/
viewMatrix._11 = 2.0f / aSize.width;
viewMatrix._22 = -2.0f / aSize.height;
viewMatrix._41 = -1.0f;
viewMatrix._42 = 1.0f;
- viewMatrix._33 = 0.0f;
HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
if (FAILED(hr)) {
NS_WARNING("Failed to set projection matrix");
}
}
--- a/layout/base/ActiveLayerTracker.cpp
+++ b/layout/base/ActiveLayerTracker.cpp
@@ -332,17 +332,17 @@ ActiveLayerTracker::IsStyleAnimated(nsDi
}
LayerActivity* layerActivity = GetLayerActivity(aFrame);
if (layerActivity) {
if (layerActivity->RestyleCountForProperty(aProperty) >= 2) {
return true;
}
}
- if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
+ if (aProperty == eCSSProperty_transform && aFrame->Preserves3D()) {
return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
}
return nsLayoutUtils::HasCurrentAnimationsForProperties(aFrame, &aProperty, 1);
}
/* static */ bool
ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame)
{
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -414,17 +414,16 @@ public:
mExclusiveToOneItem(false),
mSingleItemFixedToViewport(false),
mIsCaret(false),
mNeedComponentAlpha(false),
mForceTransparentSurface(false),
mHideAllLayersBelow(false),
mOpaqueForAnimatedGeometryRootParent(false),
mDisableFlattening(false),
- mBackfaceHidden(false),
mImage(nullptr),
mCommonClipCount(-1),
mNewChildLayersIndex(-1)
{}
#ifdef MOZ_DUMP_PAINTING
/**
* Keep track of important decisions for debugging.
@@ -603,22 +602,16 @@ public:
* and the PaintedLayer completely fills the displayport of the scrollframe.
*/
bool mOpaqueForAnimatedGeometryRootParent;
/**
* Set if there is content in the layer that must avoid being flattened.
*/
bool mDisableFlattening;
/**
- * Set if the backface of this region is hidden to the user.
- * Content that backface is hidden should not be draw on the layer
- * with visible backface.
- */
- bool mBackfaceHidden;
- /**
* Stores the pointer to the nsDisplayImage if we want to
* convert this to an ImageLayer.
*/
nsDisplayImageContainer* mImage;
/**
* Stores the clip that we need to apply to the image or, if there is no
* image, a clip for SOME item in the layer. There is no guarantee which
* item's clip will be stored here and mItemClip should not be used to clip
@@ -667,17 +660,16 @@ struct NewLayerEntry {
NewLayerEntry()
: mAnimatedGeometryRoot(nullptr)
, mAnimatedGeometryRootForScrollMetadata(nullptr)
, mFixedPosFrameForLayerData(nullptr)
, mLayerContentsVisibleRect(0, 0, -1, -1)
, mHideAllLayersBelow(false)
, mOpaqueForAnimatedGeometryRootParent(false)
, mPropagateComponentAlphaFlattening(true)
- , mUntransformedVisibleRegion(false)
, mIsCaret(false)
{}
// mLayer is null if the previous entry is for a PaintedLayer that hasn't
// been optimized to some other form (yet).
RefPtr<Layer> mLayer;
const nsIFrame* mAnimatedGeometryRoot;
// For fixed background layers, mAnimatedGeometryRoot is the animated geometry
// root of the viewport frame it's fixed to, but we need to annotate it with
@@ -706,19 +698,16 @@ struct NewLayerEntry {
// When this flag is set, we can treat this opaque region as covering
// content whose animated geometry root is the animated geometry root for
// mAnimatedGeometryRoot->GetParent().
bool mOpaqueForAnimatedGeometryRootParent;
// If true, then the content flags for this layer should contribute
// to our decision to flatten component alpha layers, false otherwise.
bool mPropagateComponentAlphaFlattening;
- // mVisibleRegion is relative to the associated frame before
- // transform.
- bool mUntransformedVisibleRegion;
bool mIsCaret;
};
class PaintedLayerDataTree;
/**
* This is tree node type for PaintedLayerDataTree.
* Each node corresponds to a different animated geometry root, and contains
@@ -764,17 +753,16 @@ public:
/**
* Find a PaintedLayerData in our mPaintedLayerDataStack that aItem can be
* added to. Creates a new PaintedLayerData by calling
* aNewPaintedLayerCallback if necessary.
*/
template<typename NewPaintedLayerCallbackType>
PaintedLayerData* FindPaintedLayerFor(const nsIntRect& aVisibleRect,
- bool aBackfaceHidden,
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
/**
* Find an opaque background color for aRegion. Pulls a color from the parent
* geometry root if appropriate, but only if that color is present underneath
* the whole clip of this node, so that this node's contents can animate or
* move (possibly async) without having to change the background color.
* @param aUnderIndex Searching will start in mPaintedLayerDataStack right
@@ -940,17 +928,16 @@ public:
* Find a PaintedLayerData for aItem. This can either be an existing
* PaintedLayerData from inside a node in our tree, or a new one that gets
* created by a call out to aNewPaintedLayerCallback.
*/
template<typename NewPaintedLayerCallbackType>
PaintedLayerData* FindPaintedLayerFor(const nsIFrame* aAnimatedGeometryRoot,
const nsIntRect& aVisibleRect,
bool aForceOwnLayer,
- bool aBackfaceidden,
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
/**
* Finish everything.
*/
void Finish();
/**
@@ -1146,28 +1133,24 @@ public:
/**
* Check if we are currently inside an inactive layer.
*/
bool IsInInactiveLayer() const {
return mLayerBuilder->GetContainingPaintedLayerData();
}
/**
- * Sets aOuterVisibleRegion as aLayer's visible region.
- * @param aOuterVisibleRegion
- * is in the coordinate space of the container reference frame.
- * @param aLayerContentsVisibleRect, if non-null, is in the layer's own
- * coordinate system.
- * @param aOuterUntransformed is true if the given aOuterVisibleRegion
- * is already untransformed with the matrix of the layer.
+ * Sets aOuterVisibleRegion as aLayer's visible region. aOuterVisibleRegion
+ * is in the coordinate space of the container reference frame.
+ * aLayerContentsVisibleRect, if non-null, is in the layer's own
+ * coordinate system.
*/
void SetOuterVisibleRegionForLayer(Layer* aLayer,
const nsIntRegion& aOuterVisibleRegion,
- const nsIntRect* aLayerContentsVisibleRect = nullptr,
- bool aOuterUntransformed = false) const;
+ const nsIntRect* aLayerContentsVisibleRect = nullptr) const;
/**
* Try to determine whether the PaintedLayer aData has a single opaque color
* covering aRect. If successful, return that color, otherwise return
* NS_RGBA(0,0,0,0).
* If aRect turns out not to intersect any content in the layer,
* *aOutIntersectsLayer will be set to false.
*/
@@ -2411,27 +2394,21 @@ AppUnitsPerDevPixel(nsDisplayItem* aItem
* Set the visible region for aLayer.
* aOuterVisibleRegion is the visible region relative to the parent layer.
* aLayerContentsVisibleRect, if non-null, is a rectangle in the layer's
* own coordinate system to which the layer's visible region is restricted.
* Consumes *aOuterVisibleRegion.
*/
static void
SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion,
- const nsIntRect* aLayerContentsVisibleRect = nullptr,
- bool aOuterUntransformed = false)
+ const nsIntRect* aLayerContentsVisibleRect = nullptr)
{
Matrix4x4 transform = aLayer->GetTransform();
Matrix transform2D;
- if (aOuterUntransformed) {
- if (aLayerContentsVisibleRect) {
- aOuterVisibleRegion->And(*aOuterVisibleRegion,
- *aLayerContentsVisibleRect);
- }
- } else if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) {
+ if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) {
aOuterVisibleRegion->MoveBy(-int(transform2D._31), -int(transform2D._32));
if (aLayerContentsVisibleRect) {
aOuterVisibleRegion->And(*aOuterVisibleRegion, *aLayerContentsVisibleRect);
}
} else {
nsIntRect outerRect = aOuterVisibleRegion->GetBounds();
// if 'transform' is not invertible, then nothing will be displayed
// for the layer, so it doesn't really matter what we do here
@@ -2462,25 +2439,21 @@ SetOuterVisibleRegion(Layer* aLayer, nsI
}
aLayer->SetVisibleRegion(*aOuterVisibleRegion);
}
void
ContainerState::SetOuterVisibleRegionForLayer(Layer* aLayer,
const nsIntRegion& aOuterVisibleRegion,
- const nsIntRect* aLayerContentsVisibleRect,
- bool aOuterUntransformed) const
+ const nsIntRect* aLayerContentsVisibleRect) const
{
nsIntRegion visRegion = aOuterVisibleRegion;
- if (!aOuterUntransformed) {
- visRegion.MoveBy(mParameters.mOffset);
- }
- SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect,
- aOuterUntransformed);
+ visRegion.MoveBy(mParameters.mOffset);
+ SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect);
}
nscolor
ContainerState::FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData,
const nsIntRect& aRect,
bool* aOutIntersectsLayer) const
{
*aOutIntersectsLayer = true;
@@ -2662,34 +2635,31 @@ PaintedLayerDataNode::AddChildNodeFor(co
MakeUnique<PaintedLayerDataNode>(mTree, this, aAnimatedGeometryRoot);
mChildren.AppendElement(Move(child));
return mChildren.LastElement().get();
}
template<typename NewPaintedLayerCallbackType>
PaintedLayerData*
PaintedLayerDataNode::FindPaintedLayerFor(const nsIntRect& aVisibleRect,
- bool aBackfaceHidden,
NewPaintedLayerCallbackType aNewPaintedLayerCallback)
{
if (!mPaintedLayerDataStack.IsEmpty()) {
if (mPaintedLayerDataStack[0].mExclusiveToOneItem) {
MOZ_ASSERT(mPaintedLayerDataStack.Length() == 1);
SetAllDrawingAbove();
MOZ_ASSERT(mPaintedLayerDataStack.IsEmpty());
} else {
PaintedLayerData* lowestUsableLayer = nullptr;
for (auto& data : Reversed(mPaintedLayerDataStack)) {
if (data.mVisibleAboveRegion.Intersects(aVisibleRect)) {
break;
}
MOZ_ASSERT(!data.mExclusiveToOneItem);
- if (data.mBackfaceHidden == aBackfaceHidden) {
- lowestUsableLayer = &data;
- }
+ lowestUsableLayer = &data;
nsIntRegion visibleRegion = data.mVisibleRegion;
// Also check whether the event-regions intersect the visible rect,
// unless we're in an inactive layer, in which case the event-regions
// will be hoisted out into their own layer.
// For performance reasons, we check the intersection with the bounds
// of the event-regions.
if (!mTree.ContState().IsInInactiveLayer() &&
(data.mScaledHitRegionBounds.Intersects(aVisibleRect) ||
@@ -2851,28 +2821,26 @@ PaintedLayerDataTree::AddingOwnLayer(con
}
}
template<typename NewPaintedLayerCallbackType>
PaintedLayerData*
PaintedLayerDataTree::FindPaintedLayerFor(const nsIFrame* aAnimatedGeometryRoot,
const nsIntRect& aVisibleRect,
bool aForceOwnLayer,
- bool aBackfaceHidden,
NewPaintedLayerCallbackType aNewPaintedLayerCallback)
{
const nsIntRect* bounds = aForceOwnLayer ? nullptr : &aVisibleRect;
FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, bounds);
PaintedLayerDataNode* node = EnsureNodeFor(aAnimatedGeometryRoot);
if (aForceOwnLayer) {
node->SetAllDrawingAbove();
}
PaintedLayerData* data =
- node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden,
- aNewPaintedLayerCallback);
+ node->FindPaintedLayerFor(aVisibleRect, aNewPaintedLayerCallback);
data->mExclusiveToOneItem = aForceOwnLayer;
return data;
}
void
PaintedLayerDataTree::FinishPotentiallyIntersectingNodes(const nsIFrame* aAnimatedGeometryRoot,
const nsIntRect* aRect)
{
@@ -3129,28 +3097,16 @@ ContainerState::PrepareColorLayer(Painte
colorLayer->SetClipRect(Nothing());
FLB_LOG_PAINTED_LAYER_DECISION(aData,
" Selected color layer=%p\n", colorLayer.get());
return colorLayer.forget();
}
-static void
-SetBackfaceHiddenForLayer(bool aBackfaceHidden, Layer* aLayer)
-{
- if (aBackfaceHidden) {
- aLayer->SetContentFlags(aLayer->GetContentFlags() |
- Layer::CONTENT_BACKFACE_HIDDEN);
- } else {
- aLayer->SetContentFlags(aLayer->GetContentFlags() &
- ~Layer::CONTENT_BACKFACE_HIDDEN);
- }
-}
-
template<typename FindOpaqueBackgroundColorCallbackType>
void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor)
{
PaintedLayerData* data = &aData;
if (!data->mLayer) {
// No layer was recycled, so we create a new one.
RefPtr<PaintedLayer> paintedLayer = CreatePaintedLayer(data);
@@ -3390,21 +3346,16 @@ void ContainerState::FinishPaintedLayerD
regions.mHitRegion.OrWith(maybeHitRegion);
Matrix mat = layer->GetTransform().As2D();
mat.Invert();
regions.ApplyTranslationAndScale(mat._31, mat._32, mat._11, mat._22);
layer->SetEventRegions(regions);
}
-
- SetBackfaceHiddenForLayer(data->mBackfaceHidden, data->mLayer);
- if (layer != data->mLayer) {
- SetBackfaceHiddenForLayer(data->mBackfaceHidden, layer);
- }
}
static bool
IsItemAreaInWindowOpaqueRegion(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
const nsRect& aComponentAlphaBounds)
{
if (!aItem->Frame()->PresContext()->IsChrome()) {
@@ -3601,17 +3552,16 @@ ContainerState::NewPaintedLayerData(nsDi
PaintedLayerData data;
data.mAnimatedGeometryRoot = aAnimatedGeometryRoot;
data.mAnimatedGeometryRootForScrollMetadata = aAnimatedGeometryRootForScrollMetadata;
data.mAnimatedGeometryRootOffset = aTopLeft;
data.mFixedPosFrameForLayerData =
FindFixedPosFrameForLayerData(aAnimatedGeometryRoot, aShouldFixToViewport);
data.mReferenceFrame = aItem->ReferenceFrame();
data.mSingleItemFixedToViewport = aShouldFixToViewport;
- data.mBackfaceHidden = aItem->Frame()->BackfaceIsHidden();
data.mIsCaret = aItem->GetType() == nsDisplayItem::TYPE_CARET;
data.mNewChildLayersIndex = mNewChildLayers.Length();
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
newLayerEntry->mAnimatedGeometryRootForScrollMetadata = aAnimatedGeometryRootForScrollMetadata;
newLayerEntry->mFixedPosFrameForLayerData = data.mFixedPosFrameForLayerData;
newLayerEntry->mIsCaret = data.mIsCaret;
@@ -4025,18 +3975,17 @@ ContainerState::ProcessDisplayItems(nsDi
if (itemVisibleRect.IsEmpty() &&
!item->ShouldBuildLayerEvenIfInvisible(mBuilder)) {
continue;
}
// 3D-transformed layers don't necessarily draw in the order in which
// they're added to their parent container layer.
bool mayDrawOutOfOrder = itemType == nsDisplayItem::TYPE_TRANSFORM &&
- (item->Frame()->Combines3DTransformWithAncestors() ||
- item->Frame()->Extend3DContext());
+ (item->Frame()->Preserves3D() || item->Frame()->Preserves3DChildren());
// Let mPaintedLayerDataTree know about this item, so that
// FindPaintedLayerFor and FindOpaqueBackgroundColor are aware of this
// item, even though it's not in any PaintedLayerDataStack.
// Ideally we'd only need the "else" case here and have
// mPaintedLayerDataTree figure out the right clip from the animated
// geometry root that we give it, but it can't easily figure about
// overflow:hidden clips on ancestors just by looking at the frame.
@@ -4086,24 +4035,16 @@ ContainerState::ProcessDisplayItems(nsDi
RefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
if (!ownLayer) {
continue;
}
NS_ASSERTION(!ownLayer->AsPaintedLayer(),
"Should never have created a dedicated Painted layer!");
- if (item->BackfaceIsHidden()) {
- ownLayer->SetContentFlags(ownLayer->GetContentFlags() |
- Layer::CONTENT_BACKFACE_HIDDEN);
- } else {
- ownLayer->SetContentFlags(ownLayer->GetContentFlags() &
- ~Layer::CONTENT_BACKFACE_HIDDEN);
- }
-
const nsIFrame* fixedPosFrame =
FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport);
SetFixedPositionLayerData(ownLayer, fixedPosFrame, !shouldFixToViewport);
nsRect invalid;
if (item->IsInvalid(invalid)) {
ownLayer->SetInvalidRectToVisibleRegion();
}
@@ -4158,42 +4099,24 @@ ContainerState::ProcessDisplayItems(nsDi
// nsDisplayTransform::BuildLayer must set layerContentsVisibleRect.
// We rely on this to ensure 3D transforms compute a reasonable
// layer visible region.
NS_ASSERTION(itemType != nsDisplayItem::TYPE_TRANSFORM ||
layerContentsVisibleRect.width >= 0,
"Transform items must set layerContentsVisibleRect!");
if (mLayerBuilder->IsBuildingRetainedLayers()) {
newLayerEntry->mLayerContentsVisibleRect = layerContentsVisibleRect;
- if (itemType == nsDisplayItem::TYPE_TRANSFORM &&
- (item->Frame()->Extend3DContext() ||
- item->Frame()->Combines3DTransformWithAncestors())) {
- // Give untransformed visible region as outer visible region
- // to avoid failure caused by singular transforms.
- newLayerEntry->mUntransformedVisibleRegion = true;
- newLayerEntry->mVisibleRegion =
- item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel);
- } else {
- newLayerEntry->mVisibleRegion = itemVisibleRect;
- }
+ newLayerEntry->mVisibleRegion = itemVisibleRect;
newLayerEntry->mOpaqueRegion = ComputeOpaqueRect(item,
animatedGeometryRoot, fixedPosFrame, itemClip, aList,
&newLayerEntry->mHideAllLayersBelow,
&newLayerEntry->mOpaqueForAnimatedGeometryRootParent);
} else {
- bool useChildrenVisible =
- itemType == nsDisplayItem::TYPE_TRANSFORM &&
- item->Frame()->IsPreserve3DLeaf();
- const nsIntRegion &visible = useChildrenVisible ?
- item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel):
- itemVisibleRect;
-
- SetOuterVisibleRegionForLayer(ownLayer, visible,
- layerContentsVisibleRect.width >= 0 ? &layerContentsVisibleRect : nullptr,
- useChildrenVisible);
+ SetOuterVisibleRegionForLayer(ownLayer, itemVisibleRect,
+ layerContentsVisibleRect.width >= 0 ? &layerContentsVisibleRect : nullptr);
}
if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) {
nsDisplayScrollInfoLayer* scrollItem = static_cast<nsDisplayScrollInfoLayer*>(item);
newLayerEntry->mOpaqueForAnimatedGeometryRootParent = false;
newLayerEntry->mBaseFrameMetrics =
scrollItem->ComputeFrameMetrics(ownLayer, mParameters);
} else if ((itemType == nsDisplayItem::TYPE_SUBDOCUMENT ||
itemType == nsDisplayItem::TYPE_ZOOM ||
@@ -4210,19 +4133,17 @@ ContainerState::ProcessDisplayItems(nsDi
*/
mLayerBuilder->AddLayerDisplayItem(ownLayer, item,
layerState,
topLeft, nullptr);
} else {
bool forceOwnLayer = shouldFixToViewport || IsCaretWithCustomClip(item, itemType);
PaintedLayerData* paintedLayerData =
mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, itemVisibleRect,
- forceOwnLayer,
- item->Frame()->BackfaceIsHidden(),
- [&]() {
+ forceOwnLayer, [&]() {
return NewPaintedLayerData(item, itemVisibleRect, animatedGeometryRoot,
animatedGeometryRootForScrollMetadata,
topLeft, shouldFixToViewport);
});
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
@@ -4887,20 +4808,18 @@ ContainerState::PostprocessRetainedLayer
if (clipRect && opaqueRegionForContainer >= 0 &&
opaqueRegions[opaqueRegionForContainer].mOpaqueRegion.Contains(ParentLayerIntRect::ToUntyped(*clipRect))) {
e->mVisibleRegion.SetEmpty();
} else if (data) {
e->mVisibleRegion.Sub(e->mVisibleRegion, data->mOpaqueRegion);
}
}
- SetOuterVisibleRegionForLayer(e->mLayer,
- e->mVisibleRegion,
- e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr,
- e->mUntransformedVisibleRegion);
+ SetOuterVisibleRegionForLayer(e->mLayer, e->mVisibleRegion,
+ e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr);
PaintedLayer* p = e->mLayer->AsPaintedLayer();
if (p) {
InvalidateVisibleBoundsChangesForScrolledLayer(p);
}
if (!e->mOpaqueRegion.IsEmpty()) {
const nsIFrame* animatedGeometryRootToCover = animatedGeometryRootForOpaqueness;
@@ -5120,17 +5039,17 @@ ChooseScaleAndSetTransform(FrameLayerBui
if (transform.IsSingular()) {
return false;
}
bool canDraw2D = transform.CanDraw2D(&transform2d);
gfxSize scale;
// XXX Should we do something for 3D transforms?
- if (canDraw2D && !aContainerFrame->Combines3DTransformWithAncestors()) {
+ if (canDraw2D) {
// If the container's transform is animated off main thread, fix a suitable scale size
// for animation
if (aContainerItem &&
aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
nsLayoutUtils::HasAnimationsForCompositor(
aContainerFrame, eCSSProperty_transform)) {
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
@@ -5213,20 +5132,18 @@ ChooseScaleAndSetTransform(FrameLayerBui
ContainerLayerParameters(scale.width, scale.height, -offset, aIncomingScale);
if (aTransform) {
aOutgoingScale.mInTransformedSubtree = true;
if (ActiveLayerTracker::IsStyleAnimated(aDisplayListBuilder, aContainerFrame,
eCSSProperty_transform)) {
aOutgoingScale.mInActiveTransformedSubtree = true;
}
}
- if ((aLayerBuilder->IsBuildingRetainedLayers() &&
- (!canDraw2D || transform2d.HasNonIntegerTranslation())) ||
- aContainerFrame->Extend3DContext() ||
- aContainerFrame->Combines3DTransformWithAncestors()) {
+ if (aLayerBuilder->IsBuildingRetainedLayers() &&
+ (!canDraw2D || transform2d.HasNonIntegerTranslation())) {
aOutgoingScale.mDisableSubpixelAntialiasingInDescendants = true;
}
return true;
}
already_AddRefed<ContainerLayer>
FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -100,16 +100,22 @@ SpammyLayoutWarningsEnabled()
Preferences::GetBool("layout.spammy_warnings.enabled", &sValue);
sValueInitialized = true;
}
return sValue;
}
#endif
+static inline nsIFrame*
+GetTransformRootFrame(nsIFrame* aFrame)
+{
+ return nsLayoutUtils::GetTransformRootFrame(aFrame);
+}
+
static inline CSSAngle
MakeCSSAngle(const nsCSSValue& aValue)
{
return CSSAngle(aValue.GetAngleValue(), aValue.GetUnit());
}
static void AddTransformFunctions(nsCSSValueList* aList,
nsStyleContext* aContext,
@@ -570,17 +576,20 @@ nsDisplayListBuilder::AddAnimationsAndTr
if (disp && disp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
perspective = disp->mChildPerspective.GetCoordValue();
}
}
nsPoint origin;
if (aItem) {
origin = aItem->ToReferenceFrame();
} else {
- nsIFrame* referenceFrame = nsLayoutUtils::GetReferenceFrame(aFrame);
+ // transform display items used a reference frame computed from
+ // their GetTransformRootFrame().
+ nsIFrame* referenceFrame =
+ nsLayoutUtils::GetReferenceFrame(GetTransformRootFrame(aFrame));
origin = aFrame->GetOffsetToCrossDoc(referenceFrame);
}
data = TransformData(origin, offsetToTransformOrigin,
offsetToPerspectiveOrigin, bounds, perspective,
devPixelsToAppUnits);
} else if (aProperty == eCSSProperty_opacity) {
data = null_t();
@@ -912,40 +921,30 @@ nsDisplayListBuilder::MarkFramesForDispl
}
}
}
mFramesMarkedForDisplay.AppendElement(e);
MarkOutOfFlowFrameForDisplay(aDirtyFrame, e, aDirtyRect);
}
}
-/**
- * Mark all preserve-3d children with
- * NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO to make sure
- * nsFrame::BuildDisplayListForChild() would visit them. Also compute
- * dirty rect for preserve-3d children.
- *
- * @param aDirtyFrame is the frame to mark children extending context.
- * @param aDirtyRect is the same as the dirty rect of the root of the
- * current 3D context, but be translated relative to
- * the aDirtyFrame.
- */
void
nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect)
{
nsAutoTArray<nsIFrame::ChildList,4> childListArray;
aDirtyFrame->GetChildLists(&childListArray);
nsIFrame::ChildListArrayIterator lists(childListArray);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame *child = childFrames.get();
- if (child->Combines3DTransformWithAncestors()) {
+ if (child->Preserves3D()) {
mFramesMarkedForDisplay.AppendElement(child);
nsRect dirty = aDirtyRect - child->GetOffsetTo(aDirtyFrame);
+
child->Properties().Set(nsDisplayListBuilder::Preserve3DDirtyRectProperty(),
new nsRect(dirty));
MarkFrameForDisplay(child, aDirtyFrame);
}
}
}
}
@@ -1834,28 +1833,25 @@ void nsDisplayList::HitTest(nsDisplayLis
for (int32_t i = aState->mItemBuffer.Length() - 1; i >= itemBufferStart; --i) {
// Pop element off the end of the buffer. We want to shorten the buffer
// so that recursive calls to HitTest have more buffer space.
item = aState->mItemBuffer[i];
aState->mItemBuffer.SetLength(i);
bool snap;
nsRect r = item->GetBounds(aBuilder, &snap).Intersect(aRect);
- bool alwaysIntersect =
- item->Frame()->Combines3DTransformWithAncestors() &&
- item->GetType() == nsDisplayItem::TYPE_TRANSFORM;
- if (alwaysIntersect || item->GetClip().MayIntersect(r)) {
+ if (item->GetClip().MayIntersect(r)) {
nsAutoTArray<nsIFrame*, 16> outFrames;
item->HitTest(aBuilder, aRect, aState, &outFrames);
// For 3d transforms with preserve-3d we add hit frames into the temp list
// so we can sort them later, otherwise we add them directly to the output list.
nsTArray<nsIFrame*> *writeFrames = aOutFrames;
if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
- item->Frame()->Combines3DTransformWithAncestors()) {
+ item->Frame()->Preserves3D()) {
if (outFrames.Length()) {
nsDisplayTransform *transform = static_cast<nsDisplayTransform*>(item);
nsPoint point = aRect.TopLeft();
// A 1x1 rect means a point, otherwise use the center of the rect
if (aRect.width != 1 || aRect.height != 1) {
point = aRect.Center();
}
temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(aBuilder, point)));
@@ -3600,31 +3596,44 @@ nsDisplayWrapList::nsDisplayWrapList(nsD
mList.AppendToTop(aList);
UpdateBounds(aBuilder);
if (!aFrame || !aFrame->IsTransformed()) {
return;
}
- // If we're a transformed frame, then we need to find out if we're inside
- // the nsDisplayTransform or outside of it. Frames inside the transform
- // need mReferenceFrame == mFrame, outside needs the next ancestor
- // reference frame.
- // If we're inside the transform, then the nsDisplayItem constructor
- // will have done the right thing.
- // If we're outside the transform, then we should have only one child
- // (since nsDisplayTransform wraps all actual content), and that child
- // will have the correct reference frame set (since nsDisplayTransform
- // handles this explictly).
- nsDisplayItem *i = mList.GetBottom();
- if (i && (!i->GetAbove() || i->GetType() == TYPE_TRANSFORM) &&
- i->Frame() == mFrame) {
- mReferenceFrame = i->ReferenceFrame();
- mToReferenceFrame = i->ToReferenceFrame();
+ // If the frame is a preserve-3d parent, then we will create transforms
+ // inside this list afterwards (see WrapPreserve3DList in nsFrame.cpp).
+ // In this case we will always be outside of the transform, so share
+ // our parents reference frame.
+ if (aFrame->Preserves3DChildren()) {
+ mReferenceFrame =
+ aBuilder->FindReferenceFrameFor(GetTransformRootFrame(aFrame));
+ mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame);
+ } else {
+ // If we're a transformed frame, then we need to find out if we're inside
+ // the nsDisplayTransform or outside of it. Frames inside the transform
+ // need mReferenceFrame == mFrame, outside needs the next ancestor
+ // reference frame.
+ // If we're inside the transform, then the nsDisplayItem constructor
+ // will have done the right thing.
+ // If we're outside the transform, then we should have only one child
+ // (since nsDisplayTransform wraps all actual content), and that child
+ // will have the correct reference frame set (since nsDisplayTransform
+ // handles this explictly).
+ //
+ // Preserve-3d can cause us to have multiple nsDisplayTransform
+ // children.
+ nsDisplayItem *i = mList.GetBottom();
+ if (i && (!i->GetAbove() || i->GetType() == TYPE_TRANSFORM) &&
+ i->Frame() == mFrame) {
+ mReferenceFrame = i->ReferenceFrame();
+ mToReferenceFrame = i->ToReferenceFrame();
+ }
}
mVisibleRect = aBuilder->GetDirtyRect() +
aBuilder->GetCurrentFrameOffsetToReferenceFrame();
}
nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayItem* aItem)
: nsDisplayItem(aBuilder, aFrame)
@@ -3637,20 +3646,26 @@ nsDisplayWrapList::nsDisplayWrapList(nsD
mList.AppendToTop(aItem);
UpdateBounds(aBuilder);
if (!aFrame || !aFrame->IsTransformed()) {
return;
}
- // See the previous nsDisplayWrapList constructor
- if (aItem->Frame() == aFrame) {
- mReferenceFrame = aItem->ReferenceFrame();
- mToReferenceFrame = aItem->ToReferenceFrame();
+ if (aFrame->Preserves3DChildren()) {
+ mReferenceFrame =
+ aBuilder->FindReferenceFrameFor(GetTransformRootFrame(aFrame));
+ mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame);
+ } else {
+ // See the previous nsDisplayWrapList constructor
+ if (aItem->Frame() == aFrame) {
+ mReferenceFrame = aItem->ReferenceFrame();
+ mToReferenceFrame = aItem->ToReferenceFrame();
+ }
}
mVisibleRect = aBuilder->GetDirtyRect() +
aBuilder->GetCurrentFrameOffsetToReferenceFrame();
}
nsDisplayWrapList::~nsDisplayWrapList() {
mList.DeleteAll();
@@ -4701,37 +4716,34 @@ bool nsDisplayZoom::ComputeVisibility(ns
// detection.
#undef UNIFIED_CONTINUATIONS
#undef DEBUG_HIT
nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
nsIFrame *aFrame, nsDisplayList *aList,
const nsRect& aChildrenVisibleRect,
ComputeTransformFunction aTransformGetter,
- uint32_t aIndex)
+ uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransformGetter(aTransformGetter)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
- , mNoExtendContext(false)
- , mHasPresetTransform(false)
- , mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
+ MOZ_ASSERT(!aFrame->IsTransformed(), "Can't specify a transform getter for a transformed frame!");
Init(aBuilder);
}
void
nsDisplayTransform::SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder)
{
- nsIFrame *outerFrame = nsLayoutUtils::GetCrossDocParentFrame(mFrame);
mReferenceFrame =
- aBuilder->FindReferenceFrameFor(outerFrame);
+ aBuilder->FindReferenceFrameFor(GetTransformRootFrame(mFrame));
mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
mVisibleRect = aBuilder->GetDirtyRect() + mToReferenceFrame;
}
void
nsDisplayTransform::Init(nsDisplayListBuilder* aBuilder)
{
mStoredList.SetClip(aBuilder, DisplayItemClip::NoClip());
@@ -4754,79 +4766,51 @@ nsDisplayTransform::nsDisplayTransform(n
nsIFrame *aFrame, nsDisplayList *aList,
const nsRect& aChildrenVisibleRect,
uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransformGetter(nullptr)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
- , mNoExtendContext(false)
- , mHasPresetTransform(false)
- , mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
SetReferenceFrameToAncestor(aBuilder);
Init(aBuilder);
}
nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
nsIFrame *aFrame, nsDisplayItem *aItem,
const nsRect& aChildrenVisibleRect,
uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aItem)
, mTransformGetter(nullptr)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
- , mNoExtendContext(false)
- , mHasPresetTransform(false)
- , mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
SetReferenceFrameToAncestor(aBuilder);
Init(aBuilder);
}
-nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
- nsIFrame *aFrame, nsDisplayList *aList,
- const nsRect& aChildrenVisibleRect,
- const Matrix4x4& aTransform,
- uint32_t aIndex)
- : nsDisplayItem(aBuilder, aFrame)
- , mStoredList(aBuilder, aFrame, aList)
- , mTransform(aTransform)
- , mTransformGetter(nullptr)
- , mChildrenVisibleRect(aChildrenVisibleRect)
- , mIndex(aIndex)
- , mNoExtendContext(false)
- , mHasPresetTransform(true)
- , mTransformPreserves3DInited(false)
-{
- MOZ_COUNT_CTOR(nsDisplayTransform);
- MOZ_ASSERT(aFrame, "Must have a frame!");
- Init(aBuilder);
-}
-
/* Returns the delta specified by the transform-origin property.
* This is a positive delta, meaning that it indicates the direction to move
* to get from (0, 0) of the frame to the transform origin. This function is
* called off the main thread.
*/
/* static */ Point3D
nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride)
{
NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
- NS_PRECONDITION(aFrame->IsTransformed() ||
- aFrame->StyleDisplay()->BackfaceIsHidden() ||
- aFrame->Combines3DTransformWithAncestors(),
+ NS_PRECONDITION(aFrame->IsTransformed() || aFrame->StyleDisplay()->BackfaceIsHidden(),
"Shouldn't get a delta for an untransformed frame!");
if (!aFrame->IsTransformed()) {
return Point3D();
}
/* For both of the coordinates, if the value of transform is a
* percentage, it's relative to the size of the frame. Otherwise, if it's
@@ -4891,19 +4875,17 @@ nsDisplayTransform::GetDeltaToTransformO
* to get from (0, 0) of the frame to the perspective origin. This function is
* called off the main thread.
*/
/* static */ Point3D
nsDisplayTransform::GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel)
{
NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
- NS_PRECONDITION(aFrame->IsTransformed() ||
- aFrame->StyleDisplay()->BackfaceIsHidden() ||
- aFrame->Combines3DTransformWithAncestors(),
+ NS_PRECONDITION(aFrame->IsTransformed() || aFrame->StyleDisplay()->BackfaceIsHidden(),
"Shouldn't get a delta for an untransformed frame!");
if (!aFrame->IsTransformed()) {
return Point3D();
}
/* For both of the coordinates, if the value of -moz-perspective-origin is a
* percentage, it's relative to the size of the frame. Otherwise, if it's
@@ -4986,61 +4968,43 @@ nsDisplayTransform::FrameTransformProper
Matrix4x4
nsDisplayTransform::GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor)
{
return GetResultingTransformMatrixInternal(aProperties, aOrigin, aAppUnitsPerPixel,
- aBoundsOverride, aOutAncestor, false, false);
+ aBoundsOverride, aOutAncestor, false);
}
Matrix4x4
nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor,
bool aOffsetByOrigin)
{
FrameTransformProperties props(aFrame,
aAppUnitsPerPixel,
aBoundsOverride);
return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel,
aBoundsOverride, aOutAncestor,
- aOffsetByOrigin, false);
-}
-
-Matrix4x4
-nsDisplayTransform::GetResultingTransformMatrixP3D(const nsIFrame* aFrame,
- const nsPoint& aOrigin,
- float aAppUnitsPerPixel,
- const nsRect* aBoundsOverride,
- nsIFrame** aOutAncestor,
- bool aOffsetByOrigin)
-{
- FrameTransformProperties props(aFrame,
- aAppUnitsPerPixel,
- aBoundsOverride);
-
- return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel,
- aBoundsOverride, aOutAncestor,
- aOffsetByOrigin, true);
+ aOffsetByOrigin);
}
Matrix4x4
nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor,
- bool aOffsetByOrigin,
- bool aDoPreserves3D)
+ bool aOffsetByOrigin)
{
const nsIFrame *frame = aProperties.mFrame;
if (aOutAncestor) {
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(frame);
}
// Get the underlying transform matrix:
@@ -5145,36 +5109,35 @@ nsDisplayTransform::GetResultingTransfor
if (aOffsetByOrigin) {
result.PreTranslate(-refBoxOffset);
result.PostTranslate(offsets);
} else {
result.ChangeBasis(offsets);
}
}
- if (aDoPreserves3D && frame && frame->Combines3DTransformWithAncestors()) {
+ if (frame && frame->Preserves3D()) {
// Include the transform set on our parent
NS_ASSERTION(frame->GetParent() &&
frame->GetParent()->IsTransformed() &&
- frame->GetParent()->Extend3DContext(),
+ frame->GetParent()->Preserves3DChildren(),
"Preserve3D mismatch!");
FrameTransformProperties props(frame->GetParent(),
aAppUnitsPerPixel,
nullptr);
// If this frame isn't transformed (but we exist for backface-visibility),
// then we're not a reference frame so no offset to origin will be added. Our
// parent transform however *is* the reference frame, so we pass true for
// aOffsetByOrigin to convert into the correct coordinate space.
Matrix4x4 parent =
GetResultingTransformMatrixInternal(props,
aOrigin - frame->GetPosition(),
aAppUnitsPerPixel, nullptr,
- aOutAncestor, !frame->IsTransformed(),
- aDoPreserves3D);
+ aOutAncestor, !frame->IsTransformed());
result = result * parent;
}
return result;
}
bool
nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder)
@@ -5304,94 +5267,67 @@ nsDisplayTransform::GetTransform()
float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
Point3D newOrigin =
Point3D(NSAppUnitsToFloatPixels(mToReferenceFrame.x, scale),
NSAppUnitsToFloatPixels(mToReferenceFrame.y, scale),
0.0f);
if (mTransformGetter) {
mTransform = mTransformGetter(mFrame, scale);
mTransform.ChangeBasis(newOrigin.x, newOrigin.y, newOrigin.z);
- } else if (!mHasPresetTransform) {
- bool isReference =
- mFrame->IsTransformed() ||
- mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext();
+ } else {
/**
* Passing true as the final argument means that we want to shift the
* coordinates to be relative to our reference frame instead of relative
* to this frame.
* When we have preserve-3d, our reference frame is already guaranteed
* to be an ancestor of the preserve-3d chain, so we only need to do
* this once.
- * For preserve-3d leaf, itself is a refrence frame.
*/
mTransform = GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
scale, nullptr, nullptr,
- isReference);
+ mFrame->IsTransformed());
}
}
return mTransform;
}
-const Matrix4x4&
-nsDisplayTransform::GetAccumulatedPreserved3DTransform()
-{
- // XXX: should go back to fix mTransformGetter.
- if (!mTransformPreserves3DInited) {
- mTransformPreserves3DInited = true;
- if (!mFrame->Combines3DTransformWithAncestors()) {
- mTransformPreserves3D = GetTransform();
- return mTransformPreserves3D;
- }
- float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
- bool isReference =
- mFrame->IsTransformed() ||
- mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext();
- mTransformPreserves3D =
- GetResultingTransformMatrixP3D(mFrame, ToReferenceFrame(), scale,
- nullptr, nullptr, isReference);
- }
- return mTransformPreserves3D;
-}
-
bool
nsDisplayTransform::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
{
- // The visible rect of a Preserves-3D frame is just an intermediate
- // result. It should always build a layer to make sure it is
- // rendering correctly.
- return ShouldPrerender(aBuilder) || mFrame->Combines3DTransformWithAncestors();
+ return ShouldPrerender(aBuilder);
}
already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder,
LayerManager *aManager,
const ContainerLayerParameters& aContainerParameters)
{
- /* For frames without transform, it would not be removed for
- * backface hidden here. But, it would be removed by the init
- * function of nsDisplayTransform.
- */
const Matrix4x4& newTransformMatrix = GetTransform();
+ if (mFrame->StyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
+ newTransformMatrix.IsBackfaceVisible()) {
+ return nullptr;
+ }
+
uint32_t flags = ShouldPrerender(aBuilder) ?
FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS : 0;
flags |= FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR;
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mStoredList.GetChildren(),
aContainerParameters, &newTransformMatrix, flags);
if (!container) {
return nullptr;
}
// Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
// so we never need to explicitely unset this flag.
- if (mFrame->Extend3DContext() && !mNoExtendContext) {
- container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT);
+ if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) {
+ container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
} else {
- container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_EXTEND_3D_CONTEXT);
+ container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_PRESERVE_3D);
}
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, mFrame,
eCSSProperty_transform);
if (ShouldPrerender(aBuilder)) {
container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
/*the value is irrelevant*/nullptr);
@@ -5404,17 +5340,17 @@ already_AddRefed<Layer> nsDisplayTransfo
}
nsDisplayItem::LayerState
nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) {
// If the transform is 3d, or the layer takes part in preserve-3d sorting
// then we *always* want this to be an active layer.
- if (!GetTransform().Is2D() || mFrame->Combines3DTransformWithAncestors()) {
+ if (!GetTransform().Is2D() || mFrame->Preserves3D()) {
return LAYER_ACTIVE_FORCE;
}
// Here we check if the *post-transform* bounds of this item are big enough
// to justify an active layer.
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_transform) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame, eCSSProperty_transform)) {
@@ -5471,17 +5407,17 @@ void nsDisplayTransform::HitTest(nsDispl
* 2. Invert the matrix.
* 3. Use it to transform the rect into the correct space.
* 4. Pass that rect down through to the list's version of HitTest.
*/
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
Matrix4x4 matrix = GetTransform();
- if (!IsFrameVisible(mFrame, GetAccumulatedPreserved3DTransform())) {
+ if (!IsFrameVisible(mFrame, matrix)) {
return;
}
/* We want to go from transformed-space to regular space.
* Thus we have to invert the matrix, which normally does
* the reverse operation (e.g. regular->transformed)
*/
@@ -5548,18 +5484,17 @@ void nsDisplayTransform::HitTest(nsDispl
float
nsDisplayTransform::GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint)
{
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
Matrix4x4 matrix = GetTransform();
- NS_ASSERTION(IsFrameVisible(mFrame, GetAccumulatedPreserved3DTransform()),
- "We can't have hit a frame that isn't visible!");
+ NS_ASSERTION(IsFrameVisible(mFrame, matrix), "We can't have hit a frame that isn't visible!");
Matrix4x4 inverse = matrix;
inverse.Invert();
Point4D point = inverse.ProjectPoint(Point(NSAppUnitsToFloatPixels(aPoint.x, factor),
NSAppUnitsToFloatPixels(aPoint.y, factor)));
NS_ASSERTION(point.HasPositiveWCoord(), "Why are we trying to get the depth for a point we didn't hit?");
Point point2d = point.As2DPoint();
@@ -5568,69 +5503,25 @@ nsDisplayTransform::GetHitDepthAtPoint(n
return transformed.z;
}
/* The bounding rectangle for the object is the overflow rectangle translated
* by the reference point.
*/
nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap)
{
- /* For some cases, the transform would make an empty bounds, but it
- * may be turned back again to get a non-empty bounds. We should
- * not depend on transforming bounds level by level.
- *
- * Here, it applies accumulated transforms on the leaf frames of the
- * 3d rendering context, and track and accmulate bounds at
- * nsDisplayListBuilder.
- */
- nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
- Maybe<nsDisplayListBuilder::AutoAccumulateRect> accRect;
- bool startPreserves3D =
- mFrame->Extend3DContext() && !mFrame->Combines3DTransformWithAncestors();
-
- if (!mFrame->Combines3DTransformWithAncestors()) {
- accTransform.StartRoot();
- }
-
- accTransform.Accumulate(GetTransform());
- if (startPreserves3D) {
- accRect.emplace(aBuilder);
- }
-
- /* For Preserves3D, it is bounds of only children as leaf frames.
- * For non-leaf frames, their bounds are accumulated and kept at
- * nsDisplayListBuilder.
- */
nsRect untransformedBounds = MaybePrerender() ?
mFrame->GetVisualOverflowRectRelativeToSelf() :
mStoredList.GetBounds(aBuilder, aSnap);
*aSnap = false;
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
- nsRect rect =
- nsLayoutUtils::MatrixTransformRect(untransformedBounds,
- accTransform.GetCurrentTransform(),
- factor);
-
- if (mFrame->Combines3DTransformWithAncestors()) {
- if (!mFrame->Extend3DContext() &&
- !aBuilder->GetAccumulatedRectLevels()) {
- // For preserve-3d, only leaf frames and frames start
- // preserve-3d chain have non-empty bounds.
- return rect;
- }
- aBuilder->AccumulateRect(rect);
- return nsRect();
- }
-
- if (startPreserves3D) {
- rect.UnionRect(rect, aBuilder->GetAccumulatedRect());
- }
-
- return rect;
+ return nsLayoutUtils::MatrixTransformRect(untransformedBounds,
+ GetTransform(),
+ factor);
}
/* The transform is opaque iff the transform consists solely of scales and
* translations and if the underlying content is opaque. Thus if the transform
* is of the form
*
* |a c e|
* |b d f|
@@ -5746,59 +5637,52 @@ nsDisplayTransform::TryMerge(nsDisplayLi
* @param aBoundsOverride (optional) Force the frame bounds to be the
* specified bounds.
* @return The smallest rectangle containing the image of the transformed
* rectangle.
*/
nsRect nsDisplayTransform::TransformRect(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
- const nsRect* aBoundsOverride,
- bool aPreserves3D)
+ const nsRect* aBoundsOverride)
{
NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
return nsLayoutUtils::MatrixTransformRect
(aUntransformedBounds,
- (aPreserves3D ?
- GetResultingTransformMatrixP3D(aFrame, aOrigin, factor,
- aBoundsOverride) :
- GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride)),
+ GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride),
factor);
}
nsRect nsDisplayTransform::TransformRectOut(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
const nsRect* aBoundsOverride)
{
NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
return nsLayoutUtils::MatrixTransformRectOut
(aUntransformedBounds,
- GetResultingTransformMatrixP3D(aFrame, aOrigin, factor, aBoundsOverride),
+ GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride),
factor);
}
bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
- nsRect *aOutRect,
- bool aPreserves3D)
+ nsRect *aOutRect)
{
NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
- Matrix4x4 transform = aPreserves3D ?
- GetResultingTransformMatrixP3D(aFrame, aOrigin, factor, nullptr) :
- GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr);
+ Matrix4x4 transform = GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr);
if (transform.IsSingular()) {
return false;
}
Rect result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -111,62 +111,25 @@ typedef mozilla::EnumSet<mozilla::gfx::C
* nsIFrame::BuildDisplayList.
* It contains the parameters that don't change from frame to frame and manages
* the display list memory using a PLArena. It also establishes the reference
* coordinate system for all display list items. Some of the parameters are
* available from the prescontext/presshell, but we copy them into the builder
* for faster/more convenient access.
*/
class nsDisplayListBuilder {
- /**
- * This manages status of a 3d context to collect visible rects of
- * descendants and passing a dirty rect.
- *
- * Since some transforms maybe singular, passing visible rects or
- * the dirty rect level by level from parent to children may get a
- * wrong result, being different from the result of appling with
- * effective transform directly.
- *
- * nsFrame::BuildDisplayListForStackingContext() uses
- * AutoPreserves3DContext to install an instance on the builder.
- *
- * \see AutoAccumulateTransform, AutoAccumulateRect,
- * AutoPreserves3DContext, Accumulate, GetCurrentTransform,
- * StartRoot.
- */
- class Preserves3DContext {
- public:
- typedef mozilla::gfx::Matrix4x4 Matrix4x4;
-
- Preserves3DContext() {}
- Preserves3DContext(const Preserves3DContext &aOther)
- : mAccumulatedTransform()
- , mAccumulatedRect()
- , mAccumulatedRectLevels(0)
- , mDirtyRect(aOther.mDirtyRect) {}
-
- // Accmulate transforms of ancestors on the preserves-3d chain.
- Matrix4x4 mAccumulatedTransform;
- // Accmulate visible rect of descendants in the preserves-3d context.
- nsRect mAccumulatedRect;
- // How far this frame is from the root of the current 3d context.
- int mAccumulatedRectLevels;
- nsRect mDirtyRect;
- };
-
public:
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
typedef mozilla::DisplayItemClip DisplayItemClip;
typedef mozilla::DisplayListClipState DisplayListClipState;
typedef nsIWidget::ThemeGeometry ThemeGeometry;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
- typedef mozilla::gfx::Matrix4x4 Matrix4x4;
/**
* @param aReferenceFrame the frame at the root of the subtree; its origin
* is the origin of the reference coordinate system for this display list
* @param aMode encodes what the builder is being used for.
* @param aBuildCaret whether or not we should include the caret in any
* display lists that we make.
*/
@@ -770,96 +733,16 @@ public:
mBuilder->mCurrentScrollbarTarget = FrameMetrics::NULL_SCROLL_ID;
mBuilder->mCurrentScrollbarFlags = 0;
mBuilder->mCurrentScrollbarWillHaveLayer = false;
}
private:
nsDisplayListBuilder* mBuilder;
};
- /**
- * A helper class to track current effective transform for items.
- *
- * For frames that is Combines3DTransformWithAncestors(), we need to
- * apply all transforms of ancestors on the same preserves3D chain
- * on the bounds of current frame to the coordination of the 3D
- * context root. The 3D context root computes it's bounds from
- * these transformed bounds.
- */
- class AutoAccumulateTransform;
- friend class AutoAccumulateTransform;
- class AutoAccumulateTransform {
- public:
- typedef mozilla::gfx::Matrix4x4 Matrix4x4;
-
- explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder)
- : mBuilder(aBuilder)
- , mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {}
-
- ~AutoAccumulateTransform() {
- mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform;
- }
-
- void Accumulate(const Matrix4x4& aTransform) {
- mBuilder->mPreserves3DCtx.mAccumulatedTransform =
- aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform;
- }
-
- const Matrix4x4& GetCurrentTransform() {
- return mBuilder->mPreserves3DCtx.mAccumulatedTransform;
- }
-
- void StartRoot() {
- mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4();
- }
-
- private:
- nsDisplayListBuilder* mBuilder;
- Matrix4x4 mSavedTransform;
- };
-
- /**
- * A helper class to collect bounds rects of descendants.
- *
- * For a 3D context root, it's bounds is computed from the bounds of
- * descendants. If we transform bounds frame by frame applying
- * transforms, the bounds may turn to empty for any singular
- * transform on the path, but it is not empty for the accumulated
- * transform.
- */
- class AutoAccumulateRect;
- friend class AutoAccumulateRect;
- class AutoAccumulateRect {
- public:
- explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder)
- : mBuilder(aBuilder)
- , mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) {
- aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect();
- aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++;
- }
- ~AutoAccumulateRect() {
- mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect;
- mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--;
- }
-
- private:
- nsDisplayListBuilder* mBuilder;
- nsRect mSavedRect;
- };
-
- void AccumulateRect(const nsRect& aRect) {
- mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect, aRect);
- }
- const nsRect& GetAccumulatedRect() {
- return mPreserves3DCtx.mAccumulatedRect;
- }
- int GetAccumulatedRectLevels() {
- return mPreserves3DCtx.mAccumulatedRectLevels;
- }
-
// Helpers for tables
nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
struct OutOfFlowDisplayData {
OutOfFlowDisplayData(const DisplayItemClip& aContainingBlockClip,
const nsRect &aDirtyRect)
: mContainingBlockClip(aContainingBlockClip)
@@ -1011,56 +894,16 @@ public:
/**
* Retrieve the stored dirty rect for the scrolled contents of aScrollableFrame.
* @param aScrollableFrame the scroll frame
* @return the dirty rect, relative to aScrollableFrame's *reference frame*
*/
nsRect GetDirtyRectForScrolledContents(const nsIFrame* aScrollableFrame) const;
- /**
- * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
- *
- * mPreserves3DCtx is used by class AutoAccumulateTransform &
- * AutoAccumulateRect to passing data between frames in the 3D
- * context. If a frame create a new 3D context, it should restore
- * the value of mPreserves3DCtx before returning back to the parent.
- * This class do it for the users.
- */
- class AutoPreserves3DContext;
- friend class AutoPreserves3DContext;
- class AutoPreserves3DContext {
- public:
- explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder)
- : mBuilder(aBuilder)
- , mSavedCtx(aBuilder->mPreserves3DCtx) {}
- ~AutoPreserves3DContext() {
- mBuilder->mPreserves3DCtx = mSavedCtx;
- }
-
- private:
- nsDisplayListBuilder* mBuilder;
- Preserves3DContext mSavedCtx;
- };
-
- const nsRect GetPreserves3DDirtyRect(const nsIFrame *aFrame) const {
- nsRect dirty = mPreserves3DCtx.mDirtyRect;
- // Translate the dirty rect to make it positioned relative to the
- // origin of aFrame.
- const nsIFrame *rootPreserves3D = aFrame;
- while (rootPreserves3D && rootPreserves3D->Combines3DTransformWithAncestors()) {
- dirty.MoveBy(-rootPreserves3D->GetPosition());
- rootPreserves3D = rootPreserves3D->GetParent();
- }
- return dirty;
- }
- void SetPreserves3DDirtyRect(const nsRect &aDirtyRect) {
- mPreserves3DCtx.mDirtyRect = aDirtyRect;
- }
-
private:
void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
const nsRect& aDirtyRect);
struct PresShellState {
nsIPresShell* mPresShell;
nsIFrame* mCaretFrame;
nsRect mCaretRect;
@@ -1154,17 +997,16 @@ private:
nsDisplayList* mPendingScrollInfoItems;
nsDisplayList* mCommittedScrollInfoItems;
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
Mode mMode;
ViewID mCurrentScrollParentId;
ViewID mCurrentScrollbarTarget;
uint32_t mCurrentScrollbarFlags;
BlendModeSet mContainedBlendModes;
- Preserves3DContext mPreserves3DCtx;
bool mIsBuildingScrollbar;
bool mCurrentScrollbarWillHaveLayer;
bool mBuildCaret;
bool mIgnoreSuppression;
bool mHadToIgnoreSuppression;
bool mIsAtRootOfPseudoStackingContext;
bool mIncludeAllOutOfFlows;
bool mDescendIntoSubdocuments;
@@ -1731,20 +1573,16 @@ public:
DisplayItemClip temp = *mClip;
temp.IntersectWith(aClip);
SetClip(aBuilder, temp);
} else {
SetClip(aBuilder, aClip);
}
}
- bool BackfaceIsHidden() {
- return mFrame->StyleDisplay()->BackfaceIsHidden();
- }
-
protected:
friend class nsDisplayList;
nsDisplayItem() { mAbove = nullptr; }
nsIFrame* mFrame;
const DisplayItemClip* mClip;
// Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
@@ -3602,40 +3440,16 @@ private:
* INVARIANT: The wrapped frame is transformed or we supplied a transform getter
* function.
* INVARIANT: The wrapped frame is non-null.
*/
class nsDisplayTransform: public nsDisplayItem
{
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
typedef mozilla::gfx::Point3D Point3D;
-
- /*
- * Avoid doing UpdateBounds() during construction.
- */
- class StoreList : public nsDisplayWrapList {
- public:
- StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
- nsDisplayList* aList) :
- nsDisplayWrapList(aBuilder, aFrame, aList) {}
- StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
- nsDisplayItem* aItem) :
- nsDisplayWrapList(aBuilder, aFrame, aItem) {}
- virtual ~StoreList() {}
-
- virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {}
- virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
- bool* aSnap) override {
- // The bounds should not be computed until now, because we don't
- // get accmulated transform before.
- nsDisplayWrapList::UpdateBounds(aBuilder);
- return nsDisplayWrapList::GetBounds(aBuilder, aSnap);
- }
- };
-
public:
/**
* Returns a matrix (in pixels) for the current frame. The matrix should be relative to
* the current frame's coordinate space.
*
* @param aFrame The frame to compute the transform for.
* @param aAppUnitsPerPixel The number of app units per graphics unit.
*/
@@ -3648,19 +3462,16 @@ public:
nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
uint32_t aIndex = 0);
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayItem *aItem, const nsRect& aChildrenVisibleRect,
uint32_t aIndex = 0);
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0);
- nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
- nsDisplayList *aList, const nsRect& aChildrenVisibleRect,
- const Matrix4x4& aTransform, uint32_t aIndex = 0);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayTransform()
{
MOZ_COUNT_DTOR(nsDisplayTransform);
}
#endif
@@ -3717,21 +3528,16 @@ public:
return mChildrenVisibleRect;
}
enum {
INDEX_MAX = UINT32_MAX >> nsDisplayItem::TYPE_BITS
};
const Matrix4x4& GetTransform();
- /**
- * Return the transform that is aggregation of all transform on the
- * preserves3d chain.
- */
- const Matrix4x4& GetAccumulatedPreserved3DTransform();
float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint);
/**
* TransformRect takes in as parameters a rectangle (in aFrame's coordinate
* space) and returns the smallest rectangle (in aFrame's coordinate space)
* containing the transformed image of that rectangle. That is, it takes
* the four corners of the rectangle, transforms them according to the
@@ -3746,33 +3552,31 @@ public:
* coordinate space.
* @param aBoundsOverride (optional) Rather than using the frame's computed
* bounding rect as frame bounds, use this rectangle instead. Pass
* nullptr (or nothing at all) to use the default.
*/
static nsRect TransformRect(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
- const nsRect* aBoundsOverride = nullptr,
- bool aPreserves3D = true);
+ const nsRect* aBoundsOverride = nullptr);
static nsRect TransformRectOut(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
const nsRect* aBoundsOverride = nullptr);
/* UntransformRect is like TransformRect, except that it inverts the
* transform.
*/
static bool UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
- nsRect *aOutRect,
- bool aPreserves3D = true);
+ nsRect *aOutRect);
bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
nsRect* aOutRect);
static Point3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride);
@@ -3832,22 +3636,16 @@ public:
const nsRect* aBoundsOverride = nullptr,
nsIFrame** aOutAncestor = nullptr,
bool aOffsetByOrigin = false);
static Matrix4x4 GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride = nullptr,
nsIFrame** aOutAncestor = nullptr);
- static Matrix4x4 GetResultingTransformMatrixP3D(const nsIFrame* aFrame,
- const nsPoint& aOrigin,
- float aAppUnitsPerPixel,
- const nsRect* aBoundsOverride = nullptr,
- nsIFrame** aOutAncestor = nullptr,
- bool aOffsetByOrigin = false);
/**
* Return true when we should try to prerender the entire contents of the
* transformed frame even when it's not completely visible (yet).
*/
static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
bool aLogAnimations = false);
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
@@ -3860,53 +3658,35 @@ public:
/**
* Check if this element will be prerendered. This must be done after the
* display list has been fully built.
*/
bool ShouldPrerender(nsDisplayListBuilder* aBuilder);
virtual void WriteDebugInfo(std::stringstream& aStream) override;
- // Force the layer created for this item not to extend 3D context.
- // See nsIFrame::BuildDisplayListForStackingContext()
- void SetNoExtendContext() { mNoExtendContext = true; }
-
private:
void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
void Init(nsDisplayListBuilder* aBuilder);
static Matrix4x4 GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor,
- bool aOffsetByOrigin,
- bool aDoPreserves3D);
-
- StoreList mStoredList;
+ bool aOffsetByOrigin);
+
+ nsDisplayWrapList mStoredList;
Matrix4x4 mTransform;
- // Accumulated transform of ancestors on the preserves-3d chain.
- Matrix4x4 mTransformPreserves3D;
ComputeTransformFunction mTransformGetter;
nsRect mChildrenVisibleRect;
uint32_t mIndex;
// We wont know if we pre-render until the layer building phase where we can
// check layers will-change budget.
bool mMaybePrerender;
- // Be forced not to extend 3D context. Since we don't create a
- // transform item, a container layer, for every frames in a
- // preserves3d context, the transform items of a child preserves3d
- // context may extend the parent context not intented if the root of
- // the child preserves3d context doesn't create a transform item.
- // With this flags, we force the item not extending 3D context.
- bool mNoExtendContext;
- // mTransform have been presetted by the constructor.
- bool mHasPresetTransform;
- // True if mTransformPreserves3D have been initialized.
- bool mTransformPreserves3DInited;
};
/**
* This class adds basic support for limiting the rendering (in the inline axis
* of the writing mode) to the part inside the specified edges. It's a base
* class for the display item classes that do the actual work.
* The two members, mVisIStartEdge and mVisIEndEdge, are relative to the edges
* of the frame's scrollable overflow rectangle and are the amount to suppress
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2407,17 +2407,17 @@ nsLayoutUtils::GetTransformToAncestor(ns
{
nsIFrame* parent;
Matrix4x4 ctm;
if (aFrame == aAncestor) {
return ctm;
}
ctm = aFrame->GetTransformMatrix(aAncestor, &parent);
while (parent && parent != aAncestor) {
- if (!parent->Extend3DContext()) {
+ if (!parent->Preserves3DChildren()) {
ctm.ProjectTo2D();
}
ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent);
}
return ctm;
}
gfxSize
@@ -2444,17 +2444,17 @@ GetTransformToAncestorExcludingAnimated(
if (ActiveLayerTracker::IsScaleSubjectToAnimation(aFrame)) {
return ctm;
}
ctm = aFrame->GetTransformMatrix(aAncestor, &parent);
while (parent && parent != aAncestor) {
if (ActiveLayerTracker::IsScaleSubjectToAnimation(parent)) {
return Matrix4x4();
}
- if (!parent->Extend3DContext()) {
+ if (!parent->Preserves3DChildren()) {
ctm.ProjectTo2D();
}
ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent);
}
return ctm;
}
gfxSize
@@ -2669,17 +2669,17 @@ nsLayoutUtils::ClampRectToScrollFrames(n
}
bool
nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
Matrix4x4* aTransform)
{
// FIXME/bug 796690: we can sometimes compute a transform in these
// cases, it just increases complexity considerably. Punt for now.
- if (aFrame->Extend3DContext() || aFrame->HasTransformGetter()) {
+ if (aFrame->Preserves3DChildren() || aFrame->HasTransformGetter()) {
return false;
}
nsIFrame* root = nsLayoutUtils::GetDisplayRootFrame(aFrame);
if (root->HasAnyStateBits(NS_FRAME_UPDATE_LAYER_TREE)) {
// Content may have been invalidated, so we can't reliably compute
// the "layer transform" in general.
return false;
@@ -6635,27 +6635,37 @@ nsLayoutUtils::GetDisplayRootFrame(nsIFr
}
}
/* static */ nsIFrame*
nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame)
{
nsIFrame *f = aFrame;
for (;;) {
- if (f->IsTransformed() || f->IsPreserve3DLeaf() || IsPopup(f)) {
+ if (f->IsTransformed() || IsPopup(f)) {
return f;
}
nsIFrame* parent = GetCrossDocParentFrame(f);
if (!parent) {
return f;
}
f = parent;
}
}
+/* static */ nsIFrame*
+nsLayoutUtils::GetTransformRootFrame(nsIFrame* aFrame)
+{
+ nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
+ while (parent && parent->Preserves3DChildren()) {
+ parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
+ }
+ return parent;
+}
+
/* static */ uint32_t
nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
const nsStyleFont* aStyleFont,
const nsStyleText* aStyleText,
nscoord aLetterSpacing)
{
uint32_t result = 0;
if (aLetterSpacing != 0) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1956,28 +1956,40 @@ public:
/**
* Find the nearest "display root". This is the nearest enclosing
* popup frame or the root prescontext's root frame.
*/
static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame);
/**
* Get the reference frame that would be used when constructing a
- * display item for this frame. Rather than using their own frame
- * as a reference frame.)
+ * display item for this frame. (Note, however, that
+ * nsDisplayTransform use the reference frame appropriate for their
+ * GetTransformRootFrame(), rather than using their own frame as a
+ * reference frame.)
*
* This duplicates some of the logic of GetDisplayRootFrame above and
* of nsDisplayListBuilder::FindReferenceFrameFor.
*
* If you have an nsDisplayListBuilder, you should get the reference
* frame from it instead of calling this.
*/
static nsIFrame* GetReferenceFrame(nsIFrame* aFrame);
/**
+ * Get the parent of this frame, except if that parent is part of a
+ * preserve-3d hierarchy, get the parent of the root of the
+ * preserve-3d hierarchy.
+ *
+ * (This is used as the starting point for reference frame computation
+ * for nsDisplayTransform display items.)
+ */
+ static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame);
+
+ /**
* Get textrun construction flags determined by a given style; in particular
* some combination of:
* -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use
* -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
* and prefs indicate we should be optimizing for speed over quality
*/
static uint32_t GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
const nsStyleFont* aStyleFont,
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -5718,17 +5718,17 @@ PresShell::MarkImagesInSubtreeVisible(ns
if (usingDisplayport) {
rect = displayPort;
} else {
rect = rect.Intersect(scrollFrame->GetScrollPortRect());
}
rect = scrollFrame->ExpandRectToNearlyVisible(rect);
}
- bool preserves3DChildren = aFrame->Extend3DContext();
+ bool preserves3DChildren = aFrame->Preserves3DChildren();
// we assume all images in popups are visible elsewhere, so we skip them here
const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList |
nsIFrame::kSelectPopupList);
for (nsIFrame::ChildListIterator childLists(aFrame);
!childLists.IsDone(); childLists.Next()) {
if (skip.Contains(childLists.CurrentID())) {
continue;
@@ -5736,17 +5736,17 @@ PresShell::MarkImagesInSubtreeVisible(ns
for (nsIFrame* child : childLists.CurrentList()) {
nsRect r = rect - child->GetPosition();
if (!r.IntersectRect(r, child->GetVisualOverflowRect())) {
continue;
}
if (child->IsTransformed()) {
// for children of a preserve3d element we just pass down the same dirty rect
- if (!preserves3DChildren || !child->Combines3DTransformWithAncestors()) {
+ if (!preserves3DChildren || !child->Preserves3D()) {
const nsRect overflow = child->GetVisualOverflowRectRelativeToSelf();
nsRect out;
if (nsDisplayTransform::UntransformRect(r, overflow, child, nsPoint(0,0), &out)) {
r = out;
} else {
r.SetEmpty();
}
}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1116,17 +1116,17 @@ nsIFrame::HasOpacityInternal(float aThre
bool
nsIFrame::IsSVGTransformed(gfx::Matrix *aOwnTransforms,
gfx::Matrix *aFromParentTransforms) const
{
return false;
}
bool
-nsIFrame::Extend3DContext() const
+nsIFrame::Preserves3DChildren() const
{
const nsStyleDisplay* disp = StyleDisplay();
if (disp->mTransformStyle != NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
!IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
return false;
}
// If we're all scroll frame, then all descendants will be clipped, so we can't preserve 3d.
@@ -1136,19 +1136,19 @@ nsIFrame::Extend3DContext() const
nsRect temp;
return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
!GetClipPropClipRect(disp, &temp, GetSize()) &&
!nsSVGIntegrationUtils::UsingEffectsForFrame(this);
}
bool
-nsIFrame::Combines3DTransformWithAncestors() const
-{
- if (!GetParent() || !GetParent()->Extend3DContext()) {
+nsIFrame::Preserves3D() const
+{
+ if (!GetParent() || !GetParent()->Preserves3DChildren()) {
return false;
}
return StyleDisplay()->HasTransform(this) || StyleDisplay()->BackfaceIsHidden();
}
bool
nsIFrame::HasPerspective() const
{
@@ -1782,22 +1782,136 @@ DisplayDebugBorders(nsDisplayListBuilder
aFrame->PresContext()->PresShell()->GetDrawEventTargetFrame() == aFrame) {
aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(aBuilder, aFrame, PaintEventTargetBorder, "EventTargetBorder",
nsDisplayItem::TYPE_EVENT_TARGET_BORDER));
}
}
#endif
+static nsresult
+WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder,
+ nsDisplayList *aList, nsDisplayList *aOutput,
+ uint32_t& aIndex, nsDisplayList* aTemp)
+{
+ if (aIndex > nsDisplayTransform::INDEX_MAX) {
+ return NS_OK;
+ }
+
+ nsresult rv = NS_OK;
+ while (nsDisplayItem *item = aList->RemoveBottom()) {
+ nsIFrame *childFrame = item->Frame();
+
+ // We accumulate sequential items that aren't transforms into the 'temp' list
+ // and then flush this list into aOutput by wrapping the whole lot with a single
+ // nsDisplayTransform.
+
+ if (childFrame->GetParent() &&
+ (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) {
+ switch (item->GetType()) {
+ case nsDisplayItem::TYPE_TRANSFORM: {
+ if (!aTemp->IsEmpty()) {
+ // Flush current aTemp contents
+ aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
+ aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
+ }
+ // Override item's clipping with our current clip state (if any). Since we're
+ // bubbling up a preserve-3d transformed child to a preserve-3d parent,
+ // we can be sure the child doesn't have clip state of its own.
+ NS_ASSERTION(!item->GetClip().HasClip(), "Unexpected clip on item");
+ const DisplayItemClip* clip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder);
+ if (clip) {
+ item->SetClip(aBuilder, *clip);
+ }
+ aOutput->AppendToTop(item);
+ break;
+ }
+ case nsDisplayItem::TYPE_WRAP_LIST: {
+ nsDisplayWrapList *list = static_cast<nsDisplayWrapList*>(item);
+ rv = WrapPreserve3DListInternal(aFrame, aBuilder,
+ list->GetChildren(), aOutput, aIndex, aTemp);
+ list->~nsDisplayWrapList();
+ break;
+ }
+ case nsDisplayItem::TYPE_OPACITY: {
+ if (!aTemp->IsEmpty()) {
+ // Flush current aTemp contents
+ aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
+ aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
+ }
+ nsDisplayOpacity *opacity = static_cast<nsDisplayOpacity*>(item);
+ nsDisplayList output;
+ // Call GetChildren, not GetSameCoordinateSystemChildren, because
+ // the preserve-3d children of 'opacity' are temporarily not in the
+ // same coordinate system as the opacity --- until this wrapping is done.
+ rv = WrapPreserve3DListInternal(aFrame, aBuilder,
+ opacity->GetChildren(), &output, aIndex, aTemp);
+ if (!aTemp->IsEmpty()) {
+ output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
+ aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
+ }
+
+ opacity->SetVisibleRect(output.GetVisibleRect());
+ opacity->SetReferenceFrame(output.GetBottom()->ReferenceFrame());
+ opacity->GetChildren()->AppendToTop(&output);
+ opacity->UpdateBounds(aBuilder);
+ aOutput->AppendToTop(item);
+ break;
+ }
+ default: {
+ if (childFrame->StyleDisplay()->BackfaceIsHidden()) {
+ if (!aTemp->IsEmpty()) {
+ aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
+ aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
+ }
+
+ aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
+ childFrame, item, item->GetVisibleRect(), aIndex++));
+ } else {
+ aTemp->AppendToTop(item);
+ }
+ break;
+ }
+ }
+ } else {
+ aTemp->AppendToTop(item);
+ }
+
+ if (NS_FAILED(rv) || !item || aIndex > nsDisplayTransform::INDEX_MAX)
+ return rv;
+ }
+
+ return NS_OK;
+}
+
static bool
IsScrollFrameActive(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
{
return aScrollableFrame && aScrollableFrame->IsScrollingActive(aBuilder);
}
+static nsresult
+WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
+ nsDisplayList *aList)
+{
+ uint32_t index = 0;
+ nsDisplayList temp;
+ nsDisplayList output;
+ nsresult rv = WrapPreserve3DListInternal(aFrame, aBuilder, aList, &output,
+ index, &temp);
+
+ if (!temp.IsEmpty()) {
+ output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame,
+ &temp, temp.GetVisibleRect(), index++));
+ }
+
+ aList->AppendToTop(&output);
+ return rv;
+}
+
class AutoSaveRestoreBlendMode
{
nsDisplayListBuilder& mBuilder;
EnumSet<gfx::CompositionOp> mSavedBlendModes;
public:
explicit AutoSaveRestoreBlendMode(nsDisplayListBuilder& aBuilder)
: mBuilder(aBuilder)
, mSavedBlendModes(aBuilder.ContainedBlendModes())
@@ -1933,55 +2047,40 @@ nsIFrame::BuildDisplayListForStackingCon
return;
}
}
if (disp->mWillChangeBitField != 0) {
aBuilder->AddToWillChangeBudget(this, GetSize());
}
- Maybe<nsDisplayListBuilder::AutoPreserves3DContext> autoPreserves3DContext;
- if (Extend3DContext() && !Combines3DTransformWithAncestors()) {
- // Start a new preserves3d context to keep informations on
- // nsDisplayListBuilder.
- autoPreserves3DContext.emplace(aBuilder);
- // Save dirty rect on the builder to avoid being distorted for
- // multiple transforms along the chain.
- aBuilder->SetPreserves3DDirtyRect(aDirtyRect);
- }
-
- // For preserves3d, use the dirty rect already installed on the
- // builder, since aDirtyRect maybe distorted for transforms along
- // the chain.
nsRect dirtyRect = aDirtyRect;
bool inTransform = aBuilder->IsInTransform();
bool isTransformed = IsTransformed();
// reset blend mode so we can keep track if this stacking context needs have
// a nsDisplayBlendContainer. Set the blend mode back when the routine exits
// so we keep track if the parent stacking context needs a container too.
AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder);
aBuilder->SetContainsBlendModes(BlendModeSet());
nsRect dirtyRectOutsideTransform = dirtyRect;
if (isTransformed) {
const nsRect overflow = GetVisualOverflowRectRelativeToSelf();
if (aBuilder->IsForPainting() &&
- (nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder,
- this) ||
- Extend3DContext() || Combines3DTransformWithAncestors())) {
+ nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) {
dirtyRect = overflow;
} else {
- if (overflow.IsEmpty()) {
+ if (overflow.IsEmpty() && !Preserves3DChildren()) {
return;
}
nsRect untransformedDirtyRect;
if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this,
- nsPoint(0,0), &untransformedDirtyRect, false)) {
+ nsPoint(0,0), &untransformedDirtyRect)) {
dirtyRect = untransformedDirtyRect;
} else {
NS_WARNING("Unable to untransform dirty rect!");
// This should only happen if the transform is singular, in which case nothing is visible anyway
dirtyRect.SetEmpty();
}
}
inTransform = true;
@@ -2033,21 +2132,20 @@ nsIFrame::BuildDisplayListForStackingCon
nsRect clipPropClip;
if (ApplyClipPropClipping(aBuilder, this, disp, &clipPropClip,
nestedClipState)) {
dirtyRect.IntersectRect(dirtyRect, clipPropClip);
}
MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect);
- // Extend3DContext() also guarantees that applyAbsPosClipping and usingSVGEffects are false
+ // Preserve3DChildren() also guarantees that applyAbsPosClipping and usingSVGEffects are false
// We only modify the preserve-3d rect if we are the top of a preserve-3d heirarchy
- if (Extend3DContext()) {
- nsRect dirty = aBuilder->GetPreserves3DDirtyRect(this);
- aBuilder->MarkPreserve3DFramesForDisplayList(this, dirty);
+ if (Preserves3DChildren()) {
+ aBuilder->MarkPreserve3DFramesForDisplayList(this, aDirtyRect);
}
if (aBuilder->IsBuildingLayerEventRegions()) {
nsDisplayLayerEventRegions* eventRegions =
new (aBuilder) nsDisplayLayerEventRegions(aBuilder, this);
eventRegions->AddFrame(aBuilder, this);
aBuilder->SetLayerEventRegions(eventRegions);
set.BorderBackground()->AppendNewToTop(eventRegions);
@@ -2163,69 +2261,26 @@ nsIFrame::BuildDisplayListForStackingCon
if (isTransformed && !resultList.IsEmpty()) {
// Restore clip state now so nsDisplayTransform is clipped properly.
clipState.Restore();
// Revert to the dirtyrect coming in from the parent, without our transform
// taken into account.
buildingDisplayList.SetDirtyRect(dirtyRectOutsideTransform);
// Revert to the outer reference frame and offset because all display
// items we create from now on are outside the transform.
- nsPoint toOuterReferenceFrame;
const nsIFrame* outerReferenceFrame =
- aBuilder->FindReferenceFrameFor(GetParent(), &toOuterReferenceFrame);
+ aBuilder->FindReferenceFrameFor(nsLayoutUtils::GetTransformRootFrame(this));
buildingDisplayList.SetReferenceFrameAndCurrentOffset(outerReferenceFrame,
GetOffsetToCrossDoc(outerReferenceFrame));
- nsDisplayTransform *transformItem =
- new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList, dirtyRect);
- resultList.AppendNewToTop(transformItem);
-
- /*
- * Create an additional transform item as a separator layer
- * between current and parent's 3D context if necessary.
- *
- * Separator layers avoid improperly exteding 3D context by
- * children.
- */
- {
- bool needAdditionalTransform = false;
- if (Extend3DContext()) {
- if (outerReferenceFrame->Extend3DContext()) {
- for (nsIFrame *f = nsLayoutUtils::GetCrossDocParentFrame(this);
- f && f != outerReferenceFrame && !f->IsTransformed();
- f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
- if (!f->Extend3DContext()) {
- // The first one with transform in it's 3D context chain,
- // and it is different 3D context with the outer reference
- // frame.
- needAdditionalTransform = true;
- break;
- }
- }
- }
- } else if (outerReferenceFrame->Extend3DContext() &&
- outerReferenceFrame != nsLayoutUtils::GetCrossDocParentFrame(this)) {
- // The content should be transformed and drawn on a buffer,
- // then tranformed and drawn again for outerReferenceFrame.
- // So, a separator layer is required.
- needAdditionalTransform = true;
- }
- if (needAdditionalTransform) {
- nsRect sepDirty = dirtyRectOutsideTransform;
- // The separator item is with ID transform and is out of this
- // frame, so it is in the coordination of the outer reference
- // frame. Here translate the dirty rect back.
- sepDirty.MoveBy(toOuterReferenceFrame);
- nsDisplayTransform *sepIdItem =
- new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList,
- sepDirty,
- Matrix4x4(), 1);
- sepIdItem->SetNoExtendContext();
- resultList.AppendNewToTop(sepIdItem);
- }
+ if (Preserves3DChildren()) {
+ WrapPreserve3DList(this, aBuilder, &resultList);
+ } else {
+ resultList.AppendNewToTop(
+ new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList, dirtyRect));
}
}
/* If we're doing VR rendering, then we need to wrap everything in a nsDisplayVR
*/
if (vrHMDInfo && !resultList.IsEmpty()) {
resultList.AppendNewToTop(
new (aBuilder) nsDisplayVR(aBuilder, this, &resultList, vrHMDInfo));
@@ -2358,17 +2413,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
} else {
// The out-of-flow frame did not intersect the dirty area. We may still
// need to traverse into it, since it may contain placeholders we need
// to enter to reach other out-of-flow frames that are visible.
dirty.SetEmpty();
}
pseudoStackingContext = true;
}
- if (child->Combines3DTransformWithAncestors()) {
+ if (child->Preserves3D()) {
nsRect* savedDirty = static_cast<nsRect*>
(child->Properties().Get(nsDisplayListBuilder::Preserve3DDirtyRectProperty()));
if (savedDirty) {
dirty = *savedDirty;
} else {
dirty.SetEmpty();
}
}
@@ -5805,20 +5860,20 @@ nsIFrame::ListGeneric(nsACString& aTo, c
aTo += nsPrintfCString(" [state=%016llx]", (unsigned long long)mState);
}
if (IsTransformed()) {
aTo += nsPrintfCString(" transformed");
}
if (ChildrenHavePerspective()) {
aTo += nsPrintfCString(" perspective");
}
- if (Extend3DContext()) {
+ if (Preserves3DChildren()) {
aTo += nsPrintfCString(" preserves-3d-children");
}
- if (Combines3DTransformWithAncestors()) {
+ if (Preserves3D()) {
aTo += nsPrintfCString(" preserves-3d");
}
if (mContent) {
aTo += nsPrintfCString(" [content=%p]", static_cast<void*>(mContent));
}
aTo += nsPrintfCString(" [sc=%p", static_cast<void*>(mStyleContext));
if (mStyleContext) {
nsIAtom* pseudoTag = mStyleContext->GetPseudo();
@@ -7462,39 +7517,39 @@ UnionBorderBoxes(nsIFrame* aFrame, bool
if (skip.Contains(childLists.CurrentID())) {
continue;
}
nsFrameList children = childLists.CurrentList();
for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) {
nsIFrame* child = e.get();
// Note that passing |true| for aApplyTransform when
- // child->Combines3DTransformWithAncestors() is incorrect if our
- // aApplyTransform is false... but the opposite would be as
- // well. This is because elements within a preserve-3d scene
- // are always transformed up to the top of the scene. This
- // means we don't have a mechanism for getting a transform up to
- // an intermediate point within the scene. We choose to
- // over-transform rather than under-transform because this is
- // consistent with other overflow areas.
+ // child->Preserves3D() is incorrect if our aApplyTransform is
+ // false... but the opposite would be as well. This is because
+ // elements within a preserve-3d scene are always transformed up
+ // to the top of the scene. This means we don't have a
+ // mechanism for getting a transform up to an intermediate point
+ // within the scene. We choose to over-transform rather than
+ // under-transform because this is consistent with other
+ // overflow areas.
nsRect childRect = UnionBorderBoxes(child, true) +
child->GetPosition();
if (hasClipPropClip) {
// Intersect with the clip before transforming.
childRect.IntersectRect(childRect, clipPropClipRect);
}
// Note that we transform each child separately according to
// aFrame's transform, and then union, which gives a different
// (smaller) result from unioning and then transforming the
// union. This doesn't match the way we handle overflow areas
// with 2-D transforms, though it does match the way we handle
// overflow areas in preserve-3d 3-D scenes.
- if (doTransform && !child->Combines3DTransformWithAncestors()) {
+ if (doTransform && !child->Preserves3D()) {
childRect = nsDisplayTransform::TransformRect(childRect, aFrame,
nsPoint(0, 0), &bounds);
}
u.UnionRectEdges(u, childRect);
}
}
return u;
@@ -7553,17 +7608,17 @@ ComputeAndIncludeOutlineArea(nsIFrame* a
// UnionBorderBoxes for some of the subtlety here.
for (nsIFrame *f = frameForArea, *parent = f->GetParent();
/* see middle of loop */;
f = parent, parent = f->GetParent()) {
r += f->GetPosition();
if (parent == aFrame) {
break;
}
- if (parent->IsTransformed() && !f->Combines3DTransformWithAncestors()) {
+ if (parent->IsTransformed() && !f->Preserves3D()) {
r = nsDisplayTransform::TransformRect(r, parent, nsPoint(0, 0));
}
}
innerRect.UnionRect(innerRect, r);
}
}
@@ -7601,17 +7656,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
nsSize aNewSize, nsSize* aOldSize)
{
NS_ASSERTION(FrameMaintainsOverflow(),
"Don't call - overflow rects not maintained on these SVG frames");
nsRect bounds(nsPoint(0, 0), aNewSize);
// Store the passed in overflow area if we are a preserve-3d frame or we have
// a transform, and it's not just the frame bounds.
- if (Combines3DTransformWithAncestors() || IsTransformed()) {
+ if (Preserves3D() || IsTransformed()) {
if (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
!aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds)) {
nsOverflowAreas* initial =
static_cast<nsOverflowAreas*>(Properties().Get(nsIFrame::InitialOverflowProperty()));
if (!initial) {
Properties().Set(nsIFrame::InitialOverflowProperty(),
new nsOverflowAreas(aOverflowAreas));
} else if (initial != &aOverflowAreas) {
@@ -7714,17 +7769,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
* ensured us we'll use.
*/
nsRect newBounds(nsPoint(0, 0), aNewSize);
// Transform affects both overflow areas.
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
}
- if (Extend3DContext()) {
+ if (Preserves3DChildren()) {
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
} else if (sizeChanged && ChildrenHavePerspective()) {
RecomputePerspectiveChildrenOverflow(this, &newBounds);
}
} else {
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
if (ChildrenHavePerspective() && sizeChanged) {
nsRect newBounds(nsPoint(0, 0), aNewSize);
@@ -7804,19 +7859,19 @@ RecomputePreserve3DChildrenOverflow(nsIF
nsIFrame::ChildListIterator lists(aFrame);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
if (!child->FrameMaintainsOverflow()) {
continue; // frame does not maintain overflow rects
}
- if (child->Extend3DContext()) {
+ if (child->Preserves3DChildren()) {
RecomputePreserve3DChildrenOverflow(child, nullptr);
- } else if (child->Combines3DTransformWithAncestors()) {
+ } else if (child->Preserves3D()) {
nsOverflowAreas* overflow =
static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
nsRect bounds(nsPoint(0, 0), child->GetSize());
if (overflow) {
nsOverflowAreas overflowCopy = *overflow;
child->FinishAndStoreOverflow(overflowCopy, bounds.Size());
} else {
nsOverflowAreas boundsOverflow;
@@ -7852,33 +7907,33 @@ nsIFrame::ComputePreserve3DChildrenOverf
{
// When we are preserving 3d we need to iterate over all children separately.
// If the child also preserves 3d then their overflow will already been in our
// coordinate space, otherwise we need to transform.
// If we're the top frame in a preserve 3d chain then we need to recalculate the overflow
// areas of all our children since they will have used our size/offset which was invalid at
// the time.
- if (!Combines3DTransformWithAncestors()) {
+ if (!Preserves3D()) {
RecomputePreserve3DChildrenOverflow(this, &aBounds);
}
nsRect childVisual;
nsRect childScrollable;
nsIFrame::ChildListIterator lists(this);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
nsPoint offset = child->GetPosition();
nsRect visual = child->GetVisualOverflowRect();
nsRect scrollable = child->GetScrollableOverflowRect();
visual.MoveBy(offset);
scrollable.MoveBy(offset);
- if (child->Combines3DTransformWithAncestors()) {
+ if (child->Preserves3D()) {
childVisual = childVisual.Union(visual);
childScrollable = childScrollable.Union(scrollable);
} else {
childVisual =
childVisual.Union(nsDisplayTransform::TransformRect(visual,
this, nsPoint(0,0), &aBounds));
childScrollable =
childScrollable.Union(nsDisplayTransform::TransformRect(scrollable,
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1242,32 +1242,28 @@ public:
* aOwnTransforms will be set to these transforms. If aFromParentTransforms
* is non-null and the frame has an SVG parent with children-only transforms,
* then aFromParentTransforms will be set to these transforms.
*/
virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
Matrix *aFromParentTransforms = nullptr) const;
/**
- * Returns whether this frame will attempt to extend the 3d transforms of its
+ * Returns whether this frame will attempt to preserve the 3d transforms of its
* children. This requires transform-style: preserve-3d, as well as no clipping
* or svg effects.
*/
- bool Extend3DContext() const;
+ bool Preserves3DChildren() const;
/**
- * Returns whether this frame has a parent that Extend3DContext() and has
+ * Returns whether this frame has a parent that Preserves3DChildren() and has
* its own transform (or hidden backface) to be combined with the parent's
* transform.
*/
- bool Combines3DTransformWithAncestors() const;
-
- bool IsPreserve3DLeaf() const {
- return Combines3DTransformWithAncestors() && !Extend3DContext();
- }
+ bool Preserves3D() const;
bool HasPerspective() const;
bool ChildrenHavePerspective() const;
// Calculate the overflow size of all child frames, taking preserve-3d into account
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
@@ -3038,20 +3034,16 @@ NS_PTR_TO_INT32(frame->Properties().Get(
/**
* Returns the content node within the anonymous content that this frame
* generated and which corresponds to the specified pseudo-element type,
* or nullptr if there is no such anonymous content.
*/
virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType);
- bool BackfaceIsHidden() {
- return StyleDisplay()->BackfaceIsHidden();
- }
-
protected:
// Members
nsRect mRect;
nsIContent* mContent;
nsStyleContext* mStyleContext;
private:
nsContainerFrame* mParent;
nsIFrame* mNextSibling; // doubly-linked list of frames
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1654,17 +1654,17 @@ fuzzy-if(Android&&AndroidVersion>=15,8,3
== 630835-1.html about:blank
== 631352-1.html 631352-1-ref.html
skip-if(!haveTestPlugin) skip-if(B2G||Mulet) fails-if(Android) fuzzy-if(winWidget&&!layersGPUAccelerated,102,535) == 632423-1.html 632423-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(Android||B2G||Mulet) random-if(winWidget) == 632781-verybig.html 632781-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== 632781-normalsize.html 632781-ref.html
fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,559) == 633344-1.html 633344-1-ref.html # bug 1103623
== 634232-1.html 634232-1-ref.html
fails-if(Android&&AndroidVersion<17&&AndroidVersion!=10) == 635302-1.html 635302-1-ref.html
-fuzzy(1,68) fuzzy-if(gtkWidget,1,70) skip-if(B2G||Mulet) fails-if(Android) == 635373-1.html 635373-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
+fuzzy(1,68) skip-if(B2G||Mulet) fails-if(Android) == 635373-1.html 635373-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,20,118) == 635373-2.html 635373-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,20,116) == 635373-3.html 635373-3-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == 635639-1.html 635639-1-ref.html
HTTP(..) == 635639-2.html 635639-2-ref.html
random == 637597-1.html 637597-1-ref.html # bug 637597 was never really fixed!
fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-1.html 637852-1-ref.html
fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-2.html 637852-2-ref.html
fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-3.html 637852-3-ref.html
@@ -1880,53 +1880,53 @@ skip-if(!B2G) == 1133905-3.html 1133905-
skip-if(!B2G) == 1133905-4.html 1133905-ref.html
skip-if(!B2G) == 1133905-5.html 1133905-ref.html
skip-if(!B2G) == 1133905-6.html 1133905-ref.html
skip-if(!B2G) == 1133905-1-v.html 1133905-ref-v.html
skip-if(!B2G) == 1133905-2-v.html 1133905-ref-v.html
skip-if(!B2G) == 1133905-3-v.html 1133905-ref-v.html
skip-if(!B2G) == 1133905-4-v.html 1133905-ref-v.html
skip-if(!B2G) fuzzy-if(B2G,61,336) == 1133905-5-v.html 1133905-ref-v.html
-skip-if(!B2G) fuzzy-if(B2G,77,287) == 1133905-6-v.html 1133905-ref-v.html
+skip-if(!B2G) fuzzy-if(B2G,61,480) == 1133905-6-v.html 1133905-ref-v.html
skip-if(!B2G) == 1133905-1-h.html 1133905-ref-h.html
skip-if(!B2G) == 1133905-2-h.html 1133905-ref-h.html
skip-if(!B2G) == 1133905-3-h.html 1133905-ref-h.html
skip-if(!B2G) == 1133905-4-h.html 1133905-ref-h.html
skip-if(!B2G) == 1133905-5-h.html 1133905-ref-h.html
skip-if(!B2G) == 1133905-6-h.html 1133905-ref-h.html
skip-if(!B2G) == 1133905-1-vh.html 1133905-ref-vh.html
skip-if(!B2G) == 1133905-2-vh.html 1133905-ref-vh.html
skip-if(!B2G) == 1133905-3-vh.html 1133905-ref-vh.html
skip-if(!B2G) == 1133905-4-vh.html 1133905-ref-vh.html
skip-if(!B2G) fuzzy-if(B2G,102,720) == 1133905-5-vh.html 1133905-ref-vh.html
-skip-if(!B2G) fuzzy-if(B2G,102,945) == 1133905-6-vh.html 1133905-ref-vh.html
+skip-if(!B2G) fuzzy-if(B2G,101,1138) == 1133905-6-vh.html 1133905-ref-vh.html
skip-if(!B2G) == 1133905-1-rtl.html 1133905-ref-rtl.html
skip-if(!B2G) == 1133905-2-rtl.html 1133905-ref-rtl.html
skip-if(!B2G) == 1133905-3-rtl.html 1133905-ref-rtl.html
skip-if(!B2G) == 1133905-4-rtl.html 1133905-ref-rtl.html
skip-if(!B2G) == 1133905-5-rtl.html 1133905-ref-rtl.html
skip-if(!B2G) == 1133905-6-rtl.html 1133905-ref-rtl.html
-skip-if(!B2G) fuzzy-if(B2G,20,177) == 1133905-1-v-rtl.html 1133905-ref-v-rtl.html
-skip-if(!B2G) fuzzy-if(B2G,20,174) == 1133905-2-v-rtl.html 1133905-ref-v-rtl.html
+skip-if(!B2G) fuzzy-if(B2G,23,175) == 1133905-1-v-rtl.html 1133905-ref-v-rtl.html
+skip-if(!B2G) fuzzy-if(B2G,18,175) == 1133905-2-v-rtl.html 1133905-ref-v-rtl.html
skip-if(!B2G) fuzzy-if(B2G,64,181) == 1133905-3-v-rtl.html 1133905-ref-v-rtl.html
skip-if(!B2G) == 1133905-4-v-rtl.html 1133905-ref-v-rtl.html
skip-if(!B2G) fuzzy-if(B2G,33,180) == 1133905-5-v-rtl.html 1133905-ref-v-rtl.html
-skip-if(!B2G) fuzzy-if(B2G,77,219) == 1133905-6-v-rtl.html 1133905-ref-v-rtl.html
+skip-if(!B2G) fuzzy-if(B2G,62,222) == 1133905-6-v-rtl.html 1133905-ref-v-rtl.html
skip-if(!B2G) == 1133905-1-h-rtl.html 1133905-ref-h-rtl.html
skip-if(!B2G) == 1133905-2-h-rtl.html 1133905-ref-h-rtl.html
skip-if(!B2G) == 1133905-3-h-rtl.html 1133905-ref-h-rtl.html
skip-if(!B2G) == 1133905-4-h-rtl.html 1133905-ref-h-rtl.html
skip-if(!B2G) == 1133905-5-h-rtl.html 1133905-ref-h-rtl.html
skip-if(!B2G) == 1133905-6-h-rtl.html 1133905-ref-h-rtl.html
-skip-if(!B2G) fuzzy-if(B2G,20,177) == 1133905-1-vh-rtl.html 1133905-ref-vh-rtl.html
-skip-if(!B2G) fuzzy-if(B2G,62,176) == 1133905-2-vh-rtl.html 1133905-ref-vh-rtl.html
+skip-if(!B2G) fuzzy-if(B2G,23,175) == 1133905-1-vh-rtl.html 1133905-ref-vh-rtl.html
+skip-if(!B2G) fuzzy-if(B2G,62,175) == 1133905-2-vh-rtl.html 1133905-ref-vh-rtl.html
skip-if(!B2G) fuzzy-if(B2G,23,176) == 1133905-3-vh-rtl.html 1133905-ref-vh-rtl.html
skip-if(!B2G) == 1133905-4-vh-rtl.html 1133905-ref-vh-rtl.html
skip-if(!B2G) fuzzy-if(B2G,102,577) == 1133905-5-vh-rtl.html 1133905-ref-vh-rtl.html
-skip-if(!B2G) fuzzy-if(B2G,102,877) == 1133905-6-vh-rtl.html 1133905-ref-vh-rtl.html
+skip-if(!B2G) fuzzy-if(B2G,101,887) == 1133905-6-vh-rtl.html 1133905-ref-vh-rtl.html
skip-if(B2G||Mulet) == 1150021-1.xul 1150021-1-ref.xul
== 1151145-1.html 1151145-1-ref.html
== 1151306-1.html 1151306-1-ref.html
== 1153845-1.html 1153845-1-ref.html
== 1155828-1.html 1155828-1-ref.html
== 1156129-1.html 1156129-1-ref.html
== 1169331-1.html 1169331-1-ref.html
fuzzy(1,74) fuzzy-if(gtkWidget,6,79) == 1174332-1.html 1174332-1-ref.html
--- a/layout/reftests/outline/reftest.list
+++ b/layout/reftests/outline/reftest.list
@@ -1,12 +1,12 @@
== outline-and-box-shadow.html outline-and-box-shadow-ref.html
== outline-and-3d-transform-1a.html outline-and-3d-transform-1-ref.html
== outline-and-3d-transform-1b.html outline-and-3d-transform-1-ref.html
-fuzzy-if(Android,255,356) fuzzy-if(d2d,16,96) fuzzy-if(cocoaWidget,255,120) fuzzy-if(B2G,128,60) fuzzy-if(gtkWidget,128,120) fuzzy-if(winWidget,255,120) == outline-and-3d-transform-2.html outline-and-3d-transform-2-ref.html
+fuzzy-if(d2d,16,96) == outline-and-3d-transform-2.html outline-and-3d-transform-2-ref.html
== outline-overflow-block-abspos.html outline-overflow-block-ref.html
== outline-overflow-block-float.html outline-overflow-block-ref.html
== outline-overflow-inlineblock-abspos.html outline-overflow-inlineblock-ref.html
== outline-overflow-inlineblock-float.html outline-overflow-inlineblock-ref.html
pref(layout.css.outline-style-auto.enabled,true) skip-if((!gtkWidget&&!winWidget&&!cocoaWidget)||Mulet) == outline-auto-001.html outline-auto-001-ref.html # only works on platforms that supports NS_THEME_FOCUS_OUTLINE # bug 1141511: Disable some gtkWidget-dependant reftests on Mulet
pref(layout.css.outline-style-auto.enabled,false) == outline-auto-001.html outline-auto-001-solid-ref.html
== outline-initial-1a.html outline-initial-1-ref.html
== outline-initial-1b.html outline-initial-1-ref.html
deleted file mode 100644
--- a/layout/reftests/transform-3d/preserves3d-nested-ref.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML>
-<title>preserve-3d consequence nested context</title>
-<style>
-.rect {
- width: 100px;
- height: 100px;
-}
-
-#outeri {
- transform-style: preserve-3d;
- transform: rotateX(45deg);
-}
-
-#rect1 {
- background-color: green;
-}
-
-#rect2 {
- transform: translate(50px, 50px);
- background-color: pink;
-}
-
-#inneri {
- transform: rotateX(45deg);
-}
-
-#rect3 {
- background-color: red;
-}
-
-</style>
-<body>
- <div id="outer">
- <div id="outeri">
- <div id="rect1" class="rect"></div>
- <div id="rect2" class="rect"></div>
- <div id="inner">
- <div id="inneri">
- <div id="rect3" class="rect"></div>
- </div>
- </div>
- </div>
- </div>
-</body>
deleted file mode 100644
--- a/layout/reftests/transform-3d/preserves3d-nested.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<title>preserve-3d consequence nested context</title>
-<style>
-.rect {
- width: 100px;
- height: 100px;
- background-color: green;
-}
-
-#outeri {
- transform-style: preserve-3d;
- transform: rotateX(45deg);
-}
-
-#inner {
- transform: rotateX(0deg);
-}
-
-#inneri {
- transform-style: preserve-3d;
- transform: rotateX(45deg);
-}
-
-#rect2 {
- transform: translate(50px, 50px);
- background-color: pink;
-}
-
-#rect3 {
- background-color: red;
-}
-
-</style>
-<body>
- <div id="outer">
- <div id="outeri">
- <div id="rect1" class="rect"></div>
- <div id="rect2" class="rect"></div>
- <div id="inner">
- <div id="inneri">
- <div id="rect3" class="rect"></div>
- </div>
- </div>
- </div>
- </div>
-</body>
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -6,26 +6,26 @@
# Check that the perspectve() transform function results in some visual changes
!= rotatex-perspective-1a.html rotatex-1-ref.html
# Check that -moz-perspective results in visual changes to child transformed elements
!= rotatex-perspective-1b.html rotatex-1-ref.html
# -moz-perspective should only apply to child elements
== rotatex-perspective-1c.html rotatex-1-ref.html
== rotatex-perspective-3a.html rotatex-perspective-3-ref.html
== scalez-1a.html scalez-1-ref.html
-fuzzy-if(gtkWidget||winWidget,8,376) fuzzy-if(Android,8,441) fuzzy-if(cocoaWidget,17,4) == preserve3d-1a.html preserve3d-1-ref.html
+fuzzy-if(cocoaWidget,17,4) == preserve3d-1a.html preserve3d-1-ref.html
== preserve3d-1b.html about:blank
== preserve3d-clipped.html about:blank
== preserve3d-2a.html preserve3d-2-ref.html
== preserve3d-2b.html preserve3d-2-ref.html
== preserve3d-2c.html preserve3d-2-ref.html
== preserve3d-2d.html preserve3d-2-ref.html
-fuzzy(4,100) == preserve3d-3a.html preserve3d-3-ref.html
+== preserve3d-3a.html preserve3d-3-ref.html
skip-if(B2G||Mulet) == preserve3d-4a.html green-rect.html # Initial mulet triage: parity with B2G/B2G Desktop
-fuzzy-if(gtkWidget,4,200) fuzzy-if(Android&&AndroidVersion>=15,4,300) == preserve3d-5a.html preserve3d-5-ref.html
+fuzzy-if(Android&&AndroidVersion>=15,4,300) == preserve3d-5a.html preserve3d-5-ref.html
== scale3d-z.html scalez-1-ref.html
fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fuzzy-if(OSX>=1008,224,924) == scale3d-all.html scale3d-1-ref.html # subpixel AA
fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fuzzy-if(OSX>=1008,224,924) == scale3d-all-separate.html scale3d-1-ref.html # subpixel AA
== scale3d-xz.html scale3d-1-ref.html
== translatez-1a.html translatez-1-ref.html
!= translatez-1b.html translatez-1-ref.html
== translate3d-1a.html translate3d-1-ref.html
== matrix3d-1a.html matrix3d-1-ref.html
@@ -59,12 +59,11 @@ fuzzy-if(winWidget&&!layersGPUAccelerate
fails-if(!layersGPUAccelerated) == 1035611-1.html 1035611-1-ref.html # Bug 1072898 for !layersGPUAccelerated failures
!= 1157984-1.html about:blank # Bug 1157984
fuzzy(3,99) == animate-cube-radians.html animate-cube-radians-ref.html # subpixel AA
fuzzy(3,99) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated,16,6) fuzzy-if(Mulet,16,9) == animate-cube-radians-zoom.html animate-cube-radians-zoom-ref.html
!= animate-cube-radians-ref.html animate-cube-radians-zoom-ref.html
fuzzy(3,99) == animate-cube-degrees.html animate-cube-degrees-ref.html # subpixel AA
== animate-cube-degrees-zoom.html animate-cube-degrees-zoom-ref.html
!= animate-cube-degrees-ref.html animate-cube-degrees-zoom-ref.html
-fuzzy-if(B2G,15,100) fuzzy-if(Android,100,100) fuzzy-if(winWidget,90,200) fuzzy-if(B2G,88,100) fuzzy-if(cocoaWidget,90,100) fuzzy-if(gtkWidget,80,200) == preserves3d-nested.html preserves3d-nested-ref.html
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
== animate-backface-hidden.html about:blank
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -463,28 +463,28 @@ AnimationCollection::CanAnimatePropertyO
message.AppendLiteral("Performance warning: Async animation of geometric property '");
message.Append(nsCSSProps::GetStringValue(aProperty));
message.AppendLiteral("' is disabled");
LogAsyncAnimationFailure(message, aElement);
}
return false;
}
if (aProperty == eCSSProperty_transform) {
- if (frame->Combines3DTransformWithAncestors() ||
- frame->Extend3DContext()) {
+ if (frame->Preserves3D() ||
+ frame->Preserves3DChildren()) {
if (shouldLog) {
nsCString message;
message.AppendLiteral("Gecko bug: Async animation of 'preserve-3d' transforms is not supported. See bug 779598");
LogAsyncAnimationFailure(message, aElement);
}
return false;
}
// Note that testing BackfaceIsHidden() is not a sufficient test for
// what we need for animating backface-visibility correctly if we
- // remove the above test for Extend3DContext(); that would require
+ // remove the above test for Preserves3DChildren(); that would require
// looking at backface-visibility on descendants as well.
if (frame->StyleDisplay()->BackfaceIsHidden()) {
if (shouldLog) {
nsCString message;
message.AppendLiteral("Gecko bug: Async animation of 'backface-visibility: hidden' transforms is not supported. See bug 1186204.");
LogAsyncAnimationFailure(message, aElement);
}
return false;