Bug 1338997 - Ensure that the transformation matrices are invertible r=mattwoodrow
authorMiko Mynttinen <mikokm@gmail.com>
Thu, 23 Feb 2017 20:42:10 +0100
changeset 374110 370364bfc2b5a266e67b63fab5eb9f800220601b
parent 374109 c2fbddc3469aeb1e47c33f37eeeea8352c01afd7
child 374111 f30e28369136fcb28dddcd55a94d98e2816009e9
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1338997
milestone54.0a1
Bug 1338997 - Ensure that the transformation matrices are invertible r=mattwoodrow MozReview-Commit-ID: A5nHNcnkrNN
gfx/2d/Polygon.h
gfx/layers/Layers.cpp
gfx/layers/composite/ContainerLayerComposite.cpp
--- a/gfx/2d/Polygon.h
+++ b/gfx/2d/Polygon.h
@@ -33,17 +33,20 @@ ClipHomogeneous(const nsTArray<Point4DTy
 {
   nsTArray<Point4DTyped<Units>> outPoints;
 
   const size_t pointCount = aPoints.Length();
   for (size_t i = 0; i < pointCount; ++i) {
     const Point4DTyped<Units>& first = aPoints[i];
     const Point4DTyped<Units>& second = aPoints[(i + 1) % pointCount];
 
-    MOZ_ASSERT(first.w != 0.0f || second.w != 0.0f);
+    if (!first.w || !second.w) {
+      // Skip edges at infinity.
+      continue;
+    }
 
     if (first.w > 0.0f) {
       outPoints.AppendElement(first);
     }
 
     if ((first.w <= 0.0f) ^ (second.w <= 0.0f)) {
       outPoints.AppendElement(CalculateEdgeIntersect(first, second));
     }
@@ -294,16 +297,18 @@ public:
   void TransformToLayerSpace(const Matrix4x4Typed<Units, Units>& aTransform)
   {
     TransformPoints(aTransform, true);
     mNormal = DefaultNormal();
   }
 
   void TransformToScreenSpace(const Matrix4x4Typed<Units, Units>& aTransform)
   {
+    MOZ_ASSERT(!aTransform.IsSingular());
+
     TransformPoints(aTransform, false);
     mPoints = ClipHomogeneous(mPoints);
 
     // Normal vectors should be transformed using inverse transpose.
     mNormal = aTransform.Inverse().Transpose().TransformPoint(mNormal);
   }
 
 private:
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -1154,18 +1154,24 @@ SortLayersWithBSPTree(nsTArray<Layer*>& 
   for (Layer* layer : aArray) {
     // Ignore invisible layers.
     if (!layer->IsVisible()) {
       continue;
     }
 
     const gfx::IntRect& bounds =
       layer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
+
     const gfx::Matrix4x4& transform = layer->GetEffectiveTransform();
 
+    if (transform.IsSingular()) {
+      // Transform cannot be inverted.
+      continue;
+    }
+
     gfx::Polygon polygon = gfx::Polygon::FromRect(gfx::Rect(bounds));
 
     // Transform the polygon to screen space.
     polygon.TransformToScreenSpace(transform);
 
     if (polygon.GetPoints().Length() >= 3) {
       inputLayers.push_back(LayerPolygon(layer, Move(polygon)));
     }
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -137,17 +137,24 @@ TransformLayerGeometry(Layer* aLayer, Ma
 
   // Collect all parent transforms.
   while (parent != nullptr && !parent->Is3DContextLeaf()) {
     transform = transform * parent->GetLocalTransform();
     parent = parent->GetParent();
   }
 
   // Transform the geometry to the parent 3D context leaf coordinate space.
-  aGeometry->TransformToScreenSpace(transform.ProjectTo2D().Inverse());
+  transform = transform.ProjectTo2D();
+
+  if (!transform.IsSingular()) {
+    aGeometry->TransformToScreenSpace(transform.Inverse());
+  } else {
+    // Discard the geometry since the result might not be correct.
+    aGeometry.reset();
+  }
 }
 
 
 template<class ContainerT>
 static gfx::IntRect ContainerVisibleRect(ContainerT* aContainer)
 {
   gfx::IntRect surfaceRect = aContainer->GetLocalVisibleRegion().ToUnknownRegion().GetBounds();
   return surfaceRect;