Bug 1306107 - Stop calling ProjectTo2D() for leaf basic layers. r=mattwoodrow
authorThinker K.F. Li <thinker@codemud.net>
Mon, 07 Nov 2016 01:45:00 -0500
changeset 348121 a0ff94cf57e7a15c359dd8b343b5f2f3f8fcd0b1
parent 348120 eab190f5dc945bbc9a09bfd776ccba99a9d81496
child 348122 3303f8ce11f9ea33eb67a760f8d03f531d1ae8b9
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1306107
milestone52.0a1
Bug 1306107 - Stop calling ProjectTo2D() for leaf basic layers. r=mattwoodrow
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicContainerLayer.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -599,35 +599,41 @@ Layer::SnapTransformTranslation(const Ma
     *aResidualTransform = Matrix();
   }
 
   if (!mManager->IsSnappingEffectiveTransforms()) {
     return aTransform;
   }
 
   Matrix matrix2D;
-  Matrix4x4 result;
   if (aTransform.CanDraw2D(&matrix2D) &&
       !matrix2D.HasNonTranslation() &&
       matrix2D.HasNonIntegerTranslation()) {
     auto snappedTranslation = IntPoint::Round(matrix2D.GetTranslation());
     Matrix snappedMatrix = Matrix::Translation(snappedTranslation.x,
                                                snappedTranslation.y);
-    result = Matrix4x4::From2D(snappedMatrix);
+    Matrix4x4 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;
   }
 
+  return SnapTransformTranslation3D(aTransform, aResidualTransform);
+}
+
+Matrix4x4
+Layer::SnapTransformTranslation3D(const Matrix4x4& aTransform,
+                                  Matrix* aResidualTransform)
+{
   if(aTransform.IsSingular() ||
      aTransform.HasPerspectiveComponent() ||
      aTransform.HasNonTranslation() ||
      !aTransform.HasNonIntegerTranslation()) {
     // 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.
@@ -667,17 +673,17 @@ Layer::SnapTransformTranslation(const Ma
     // 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;
+  Matrix4x4 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;
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1816,16 +1816,18 @@ protected:
    * layer's content can be rendered unpredictably (jiggling) as the scale
    * interacts with the snapping of the translation, especially with animated
    * transforms.
    * @param aResidualTransform a transform to apply before the result transform
    * in order to get the results to completely match aTransform.
    */
   gfx::Matrix4x4 SnapTransformTranslation(const gfx::Matrix4x4& aTransform,
                                           gfx::Matrix* aResidualTransform);
+  gfx::Matrix4x4 SnapTransformTranslation3D(const gfx::Matrix4x4& aTransform,
+                                            gfx::Matrix* aResidualTransform);
   /**
    * See comment for SnapTransformTranslation.
    * This function implements type 2 snapping. If aTransform is a translation
    * and/or scale, transform aSnapRect by aTransform, snap to pixel boundaries,
    * and return the transform that maps aSnapRect to that rect. Otherwise
    * just return aTransform.
    * @param aSnapRect a rectangle whose edges should be snapped to pixel
    * boundaries in the destination surface.
--- a/gfx/layers/basic/BasicContainerLayer.cpp
+++ b/gfx/layers/basic/BasicContainerLayer.cpp
@@ -32,28 +32,33 @@ 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.
+  Matrix4x4 transformToSurface = aTransformToSurface;
+  bool participate3DCtx = Extend3DContext() || Is3DContextLeaf();
+  if (!participate3DCtx &&
+      GetContentFlags() & CONTENT_BACKFACE_HIDDEN) {
+    // For backface-hidden layers
+    transformToSurface.ProjectTo2D();
+  }
+  Matrix4x4 idealTransform = GetLocalTransform() * transformToSurface;
+  if (!participate3DCtx &&
+      !(GetContentFlags() & CONTENT_BACKFACE_HIDDEN)) {
+    // For non-backface-hidden layers,
+    // 3D components are required to handle CONTENT_BACKFACE_HIDDEN.
     idealTransform.ProjectTo2D();
   }
 
   if (!idealTransform.CanDraw2D()) {
-    if (!Extend3DContext() ||
-        (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) {
-      if (!Creates3DContextWithExtendingChildren()) {
-        idealTransform.ProjectTo2D();
-      }
+    if (!Extend3DContext()) {
       mEffectiveTransform = idealTransform;
       ComputeEffectiveTransformsForChildren(Matrix4x4());
       ComputeEffectiveTransformForMaskLayers(Matrix4x4());
       mUseIntermediateSurface = true;
       return;
     }
 
     mEffectiveTransform = idealTransform;
@@ -79,22 +84,22 @@ BasicContainerLayer::ComputeEffectiveTra
    * Having a blend mode also always forces our own push group
    */
   mUseIntermediateSurface =
     GetMaskLayer() ||
     GetForceIsolatedGroup() ||
     (GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) ||
     (GetEffectiveOpacity() != 1.0 && ((HasMultipleChildren() && !Extend3DContext()) || hasSingleBlendingChild));
 
-  if (!Extend3DContext()) {
-    idealTransform.ProjectTo2D();
-  }
   mEffectiveTransform =
     !mUseIntermediateSurface ?
-    idealTransform : SnapTransformTranslation(idealTransform, &residual);
+    idealTransform :
+    (!(GetContentFlags() & CONTENT_BACKFACE_HIDDEN) ?
+     SnapTransformTranslation(idealTransform, &residual) :
+     SnapTransformTranslation3D(idealTransform, &residual));
   Matrix4x4 childTransformToSurface =
     (!mUseIntermediateSurface ||
      (mUseIntermediateSurface && !Extend3DContext() /* 2D */)) ?
     idealTransform : Matrix4x4::From2D(residual);
   ComputeEffectiveTransformsForChildren(childTransformToSurface);
 
   ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
 }