Migrate from MathUtil::inverse() to gfx::Transform::GetInverse()

BUG=159972, 163769

Review URL: https://codereview.chromium.org/11644008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175363 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/cc/direct_renderer.cc b/cc/direct_renderer.cc
index 70522f2f..e96cc417 100644
--- a/cc/direct_renderer.cc
+++ b/cc/direct_renderer.cc
@@ -185,9 +185,12 @@
     if (frame.rootDamageRect == frame.rootRenderPass->output_rect)
         return renderPassScissor;
 
-    gfx::Transform inverseTransform = MathUtil::inverse(frame.currentRenderPass->transform_to_root_target);
-    gfx::RectF damageRectInRenderPassSpace = MathUtil::projectClippedRect(inverseTransform, frame.rootDamageRect);
-    renderPassScissor.Intersect(damageRectInRenderPassSpace);
+    gfx::Transform inverseTransform(gfx::Transform::kSkipInitialization);
+    if (frame.currentRenderPass->transform_to_root_target.GetInverse(&inverseTransform)) {
+        // Only intersect inverse-projected damage if the transform is invertible.
+        gfx::RectF damageRectInRenderPassSpace = MathUtil::projectClippedRect(inverseTransform, frame.rootDamageRect);
+        renderPassScissor.Intersect(damageRectInRenderPassSpace);
+    }
 
     return renderPassScissor;
 }
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index 8f03721..54eef96e 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -521,10 +521,10 @@
     gfx::Transform contentsDeviceTransform = MathUtil::to2dTransform(frame.windowMatrix * frame.projectionMatrix * quadRectMatrix);
 
     // Can only draw surface if device matrix is invertible.
-    if (!contentsDeviceTransform.IsInvertible())
+    gfx::Transform contentsDeviceTransformInverse(gfx::Transform::kSkipInitialization);
+    if (!contentsDeviceTransform.GetInverse(&contentsDeviceTransformInverse))
         return;
 
-    gfx::Transform contentsDeviceTransformInverse = MathUtil::inverse(contentsDeviceTransform);
     scoped_ptr<ScopedResource> backgroundTexture = drawBackgroundFilters(
         frame, quad, contentsDeviceTransform, contentsDeviceTransformInverse);
 
@@ -861,8 +861,11 @@
         LayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
 
         // Map device space quad to local space. deviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project.
-        gfx::Transform deviceTransformInverse = MathUtil::inverse(deviceTransform);
-        localQuad = MathUtil::mapQuad(deviceTransformInverse, deviceQuad.ToQuadF(), clipped);
+        // We should have already checked that the transform was uninvertible above.
+        gfx::Transform inverseDeviceTransform(gfx::Transform::kSkipInitialization);
+        bool didInvert = deviceTransform.GetInverse(&inverseDeviceTransform);
+        DCHECK(didInvert);
+        localQuad = MathUtil::mapQuad(inverseDeviceTransform, deviceQuad.ToQuadF(), clipped);
 
         // We should not DCHECK(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become
         // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case.
diff --git a/cc/layer_impl.cc b/cc/layer_impl.cc
index d0eafe3..4ab99895 100644
--- a/cc/layer_impl.cc
+++ b/cc/layer_impl.cc
@@ -245,7 +245,14 @@
 
     if (!nonFastScrollableRegion().IsEmpty()) {
         bool clipped = false;
-        gfx::PointF hitTestPointInContentSpace = MathUtil::projectPoint(MathUtil::inverse(screenSpaceTransform()), screenSpacePoint, clipped);
+        gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization);
+        if (!screenSpaceTransform().GetInverse(&inverseScreenSpaceTransform)) {
+            // TODO(shawnsingh): We shouldn't be applying a projection if screen space
+            // transform is uninvertible here. Perhaps we should be returning
+            // ScrollOnMainThread in this case?
+        }
+
+        gfx::PointF hitTestPointInContentSpace = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, clipped);
         gfx::PointF hitTestPointInLayerSpace = gfx::ScalePoint(hitTestPointInContentSpace, 1 / contentsScaleX(), 1 / contentsScaleY());
         if (!clipped && nonFastScrollableRegion().Contains(gfx::ToRoundedPoint(hitTestPointInLayerSpace))) {
             TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed nonFastScrollableRegion");
diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc
index b85429e..390f001 100644
--- a/cc/layer_tree_host.cc
+++ b/cc/layer_tree_host.cc
@@ -780,7 +780,12 @@
 
     // Scale to screen space before applying implTransform inverse.
     gfx::PointF zoomedScreenspacePoint = gfx::ScalePoint(zoomedViewportPoint, deviceScaleFactor());
-    gfx::Transform inverseImplTransform = MathUtil::inverse(m_implTransform);
+
+    gfx::Transform inverseImplTransform(gfx::Transform::kSkipInitialization);
+    if (!m_implTransform.GetInverse(&inverseImplTransform)) {
+        // TODO(shawnsingh): Either we need to handle uninvertible transforms
+        // here, or DCHECK that the transform is invertible.
+    }
 
     bool wasClipped = false;
     gfx::PointF unzoomedScreenspacePoint = MathUtil::projectPoint(inverseImplTransform, zoomedScreenspacePoint, wasClipped);
diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc
index 2210894..feba747 100644
--- a/cc/layer_tree_host_common.cc
+++ b/cc/layer_tree_host_common.cc
@@ -56,7 +56,12 @@
     // This bounding rectangle may be larger than it needs to be (being
     // axis-aligned), but is a reasonable filter on the space to consider.
     // Non-invertible transforms will create an empty rect here.
-    const gfx::Transform surfaceToLayer = MathUtil::inverse(transform);
+
+    gfx::Transform surfaceToLayer(gfx::Transform::kSkipInitialization);
+    if (!transform.GetInverse(&surfaceToLayer)) {
+        // TODO(shawnsingh): Either we need to handle uninvertible transforms
+        // here, or DCHECK that the transform is invertible.
+    }
     gfx::Rect layerRect = gfx::ToEnclosingRect(MathUtil::projectClippedRect(surfaceToLayer, gfx::RectF(minimalSurfaceRect)));
     layerRect.Intersect(layerBoundRect);
     return layerRect;
@@ -331,7 +336,13 @@
 
     gfx::Transform scrollCompensationForThisLayer = partialLayerOriginTransform; // Step 3
     scrollCompensationForThisLayer.Translate(scrollingLayer->scrollDelta().x(), scrollingLayer->scrollDelta().y()); // Step 2
-    scrollCompensationForThisLayer.PreconcatTransform(MathUtil::inverse(partialLayerOriginTransform)); // Step 1
+
+    gfx::Transform inversePartialLayerOriginTransform(gfx::Transform::kSkipInitialization);
+    if (!partialLayerOriginTransform.GetInverse(&inversePartialLayerOriginTransform)) {
+        // TODO(shawnsingh): Either we need to handle uninvertible transforms
+        // here, or DCHECK that the transform is invertible.
+    }
+    scrollCompensationForThisLayer.PreconcatTransform(inversePartialLayerOriginTransform); // Step 1
     return scrollCompensationForThisLayer;
 }
 
@@ -383,8 +394,14 @@
     //  Step 1 (right-most in the math): transform from the new surface to the original ancestor surface
     //  Step 2: apply the scroll compensation
     //  Step 3: transform back to the new surface.
-    if (layer->renderSurface() && !nextScrollCompensationMatrix.IsIdentity())
-        nextScrollCompensationMatrix = MathUtil::inverse(layer->renderSurface()->drawTransform()) * nextScrollCompensationMatrix * layer->renderSurface()->drawTransform();
+    if (layer->renderSurface() && !nextScrollCompensationMatrix.IsIdentity()) {
+        gfx::Transform inverseSurfaceDrawTransform(gfx::Transform::kSkipInitialization);
+        if (!layer->renderSurface()->drawTransform().GetInverse(&inverseSurfaceDrawTransform)) {
+            // TODO(shawnsingh): Either we need to handle uninvertible transforms
+            // here, or DCHECK that the transform is invertible.
+        }
+        nextScrollCompensationMatrix = inverseSurfaceDrawTransform * nextScrollCompensationMatrix * layer->renderSurface()->drawTransform();
+    }
 
     return nextScrollCompensationMatrix;
 }
@@ -746,7 +763,13 @@
         renderSurface->setIsClipped(ancestorClipsSubtree);
         if (ancestorClipsSubtree) {
             renderSurface->setClipRect(clipRectFromAncestor);
-            clipRectForSubtreeInDescendantSpace = gfx::ToEnclosingRect(MathUtil::projectClippedRect(MathUtil::inverse(renderSurface->drawTransform()), renderSurface->clipRect()));
+
+            gfx::Transform inverseSurfaceDrawTransform(gfx::Transform::kSkipInitialization);
+            if (!renderSurface->drawTransform().GetInverse(&inverseSurfaceDrawTransform)) {
+                // TODO(shawnsingh): Either we need to handle uninvertible transforms
+                // here, or DCHECK that the transform is invertible.
+            }
+            clipRectForSubtreeInDescendantSpace = gfx::ToEnclosingRect(MathUtil::projectClippedRect(inverseSurfaceDrawTransform, renderSurface->clipRect()));
         } else {
             renderSurface->setClipRect(gfx::Rect());
             clipRectForSubtreeInDescendantSpace = clipRectFromAncestorInDescendantSpace;
@@ -1008,12 +1031,13 @@
 static bool pointHitsRect(const gfx::PointF& screenSpacePoint, const gfx::Transform& localSpaceToScreenSpaceTransform, gfx::RectF localSpaceRect)
 {
     // If the transform is not invertible, then assume that this point doesn't hit this rect.
-    if (!localSpaceToScreenSpaceTransform.IsInvertible())
+    gfx::Transform inverseLocalSpaceToScreenSpace(gfx::Transform::kSkipInitialization);
+    if (!localSpaceToScreenSpaceTransform.GetInverse(&inverseLocalSpaceToScreenSpace))
         return false;
 
     // Transform the hit test point from screen space to the local space of the given rect.
     bool clipped = false;
-    gfx::PointF hitTestPointInLocalSpace = MathUtil::projectPoint(MathUtil::inverse(localSpaceToScreenSpaceTransform), screenSpacePoint, clipped);
+    gfx::PointF hitTestPointInLocalSpace = MathUtil::projectPoint(inverseLocalSpaceToScreenSpace, screenSpacePoint, clipped);
 
     // If projectPoint could not project to a valid value, then we assume that this point doesn't hit this rect.
     if (clipped)
@@ -1025,12 +1049,13 @@
 static bool pointHitsRegion(gfx::PointF screenSpacePoint, const gfx::Transform& screenSpaceTransform, const Region& layerSpaceRegion, float layerContentScaleX, float layerContentScaleY)
 {
     // If the transform is not invertible, then assume that this point doesn't hit this region.
-    if (!screenSpaceTransform.IsInvertible())
+    gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization);
+    if (!screenSpaceTransform.GetInverse(&inverseScreenSpaceTransform))
         return false;
 
     // Transform the hit test point from screen space to the local space of the given region.
     bool clipped = false;
-    gfx::PointF hitTestPointInContentSpace = MathUtil::projectPoint(MathUtil::inverse(screenSpaceTransform), screenSpacePoint, clipped);
+    gfx::PointF hitTestPointInContentSpace = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, clipped);
     gfx::PointF hitTestPointInLayerSpace = gfx::ScalePoint(hitTestPointInContentSpace, 1 / layerContentScaleX, 1 / layerContentScaleY);
 
     // If projectPoint could not project to a valid value, then we assume that this point doesn't hit this region.
diff --git a/cc/layer_tree_host_common_unittest.cc b/cc/layer_tree_host_common_unittest.cc
index 25ff83d..9d5a190 100644
--- a/cc/layer_tree_host_common_unittest.cc
+++ b/cc/layer_tree_host_common_unittest.cc
@@ -209,7 +209,7 @@
     // Case 6: The layer transform should occur with respect to the anchor point.
     gfx::Transform translationToAnchor;
     translationToAnchor.Translate(5, 0);
-    gfx::Transform expectedResult = translationToAnchor * layerTransform * MathUtil::inverse(translationToAnchor);
+    gfx::Transform expectedResult = translationToAnchor * layerTransform * inverse(translationToAnchor);
     setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, gfx::PointF(0.5, 0), gfx::PointF(0, 0), gfx::Size(10, 12), false);
     executeCalculateDrawProperties(root.get());
     EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->drawTransform());
@@ -218,7 +218,7 @@
     // Case 7: Verify that position pre-multiplies the layer transform.
     //         The current implementation of calculateDrawProperties does this implicitly, but it is
     //         still worth testing to detect accidental regressions.
-    expectedResult = positionTransform * translationToAnchor * layerTransform * MathUtil::inverse(translationToAnchor);
+    expectedResult = positionTransform * translationToAnchor * layerTransform * inverse(translationToAnchor);
     setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, gfx::PointF(0.5, 0), gfx::PointF(0, 1.2f), gfx::Size(10, 12), false);
     executeCalculateDrawProperties(root.get());
     EXPECT_TRANSFORMATION_MATRIX_EQ(expectedResult, layer->drawTransform());
@@ -266,7 +266,7 @@
     parentLayerTransform.Scale3d(2, 2, 1);
     gfx::Transform parentTranslationToAnchor;
     parentTranslationToAnchor.Translate(2.5, 3);
-    gfx::Transform parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * MathUtil::inverse(parentTranslationToAnchor);
+    gfx::Transform parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * inverse(parentTranslationToAnchor);
     setLayerPropertiesForTesting(parent.get(), parentLayerTransform, identityMatrix, gfx::PointF(0.25, 0.25), gfx::PointF(0, 0), gfx::Size(10, 12), false);
     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, gfx::PointF(0, 0), gfx::PointF(0, 0), gfx::Size(16, 18), false);
     setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, gfx::PointF(0, 0), gfx::PointF(0, 0), gfx::Size(76, 78), false);
@@ -285,8 +285,8 @@
     gfx::Transform parentTranslationToCenter;
     parentTranslationToCenter.Translate(5, 6);
     // Sublayer matrix is applied to the center of the parent layer.
-    parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * MathUtil::inverse(parentTranslationToAnchor)
-            * parentTranslationToCenter * parentSublayerMatrix * MathUtil::inverse(parentTranslationToCenter);
+    parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * inverse(parentTranslationToAnchor)
+            * parentTranslationToCenter * parentSublayerMatrix * inverse(parentTranslationToCenter);
     gfx::Transform flattenedCompositeTransform = MathUtil::to2dTransform(parentCompositeTransform);
     setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, gfx::PointF(0.25, 0.25), gfx::PointF(0, 0), gfx::Size(10, 12), false);
     setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, gfx::PointF(0, 0), gfx::PointF(0, 0), gfx::Size(16, 18), false);
@@ -335,12 +335,12 @@
     parentSublayerMatrix.Scale3d(0.9, 1, 3.3);
     gfx::Transform parentTranslationToCenter;
     parentTranslationToCenter.Translate(50, 60);
-    gfx::Transform parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * MathUtil::inverse(parentTranslationToAnchor)
-            * parentTranslationToCenter * parentSublayerMatrix * MathUtil::inverse(parentTranslationToCenter);
+    gfx::Transform parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * inverse(parentTranslationToAnchor)
+            * parentTranslationToCenter * parentSublayerMatrix * inverse(parentTranslationToCenter);
     gfx::Vector2dF parentCompositeScale = MathUtil::computeTransform2dScaleComponents(parentCompositeTransform, 1.f);
     gfx::Transform surfaceSublayerTransform;
     surfaceSublayerTransform.Scale(parentCompositeScale.x(), parentCompositeScale.y());
-    gfx::Transform surfaceSublayerCompositeTransform = parentCompositeTransform * MathUtil::inverse(surfaceSublayerTransform);
+    gfx::Transform surfaceSublayerCompositeTransform = parentCompositeTransform * inverse(surfaceSublayerTransform);
 
     // Child's render surface should not exist yet.
     ASSERT_FALSE(child->renderSurface());
@@ -394,8 +394,8 @@
     parentSublayerMatrix.Scale3d(10, 10, 3.3);
     gfx::Transform parentTranslationToCenter;
     parentTranslationToCenter.Translate(5, 6);
-    gfx::Transform parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * MathUtil::inverse(parentTranslationToAnchor)
-            * parentTranslationToCenter * parentSublayerMatrix * MathUtil::inverse(parentTranslationToCenter);
+    gfx::Transform parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * inverse(parentTranslationToAnchor)
+            * parentTranslationToCenter * parentSublayerMatrix * inverse(parentTranslationToCenter);
     gfx::Transform childTranslationToCenter;
     childTranslationToCenter.Translate(8, 9);
     gfx::Transform replicaLayerTransform;
@@ -403,7 +403,7 @@
     gfx::Vector2dF parentCompositeScale = MathUtil::computeTransform2dScaleComponents(parentCompositeTransform, 1.f);
     gfx::Transform surfaceSublayerTransform;
     surfaceSublayerTransform.Scale(parentCompositeScale.x(), parentCompositeScale.y());
-    gfx::Transform replicaCompositeTransform = parentCompositeTransform * replicaLayerTransform * MathUtil::inverse(surfaceSublayerTransform);
+    gfx::Transform replicaCompositeTransform = parentCompositeTransform * replicaLayerTransform * inverse(surfaceSublayerTransform);
 
     // Child's render surface should not exist yet.
     ASSERT_FALSE(child->renderSurface());
@@ -481,9 +481,9 @@
     gfx::Transform replicaLayerTransform;
     replicaLayerTransform.Scale3d(-2, 5, 1);
 
-    gfx::Transform A = translationToAnchor * layerTransform * MathUtil::inverse(translationToAnchor);
-    gfx::Transform B = translationToCenter * sublayerTransform * MathUtil::inverse(translationToCenter);
-    gfx::Transform R = A * translationToAnchor * replicaLayerTransform * MathUtil::inverse(translationToAnchor);
+    gfx::Transform A = translationToAnchor * layerTransform * inverse(translationToAnchor);
+    gfx::Transform B = translationToCenter * sublayerTransform * inverse(translationToCenter);
+    gfx::Transform R = A * translationToAnchor * replicaLayerTransform * inverse(translationToAnchor);
 
     gfx::Vector2dF surface1ParentTransformScale = MathUtil::computeTransform2dScaleComponents(A * B, 1.f);
     gfx::Transform surface1SublayerTransform;
@@ -492,7 +492,7 @@
     // SS1 = transform given to the subtree of renderSurface1
     gfx::Transform SS1 = surface1SublayerTransform;
     // S1 = transform to move from renderSurface1 pixels to the layer space of the owning layer
-    gfx::Transform S1 = MathUtil::inverse(surface1SublayerTransform);
+    gfx::Transform S1 = inverse(surface1SublayerTransform);
 
     gfx::Vector2dF surface2ParentTransformScale = MathUtil::computeTransform2dScaleComponents(SS1 * A * B, 1.f);
     gfx::Transform surface2SublayerTransform;
@@ -501,7 +501,7 @@
     // SS2 = transform given to the subtree of renderSurface2
     gfx::Transform SS2 = surface2SublayerTransform;
     // S2 = transform to move from renderSurface2 pixels to the layer space of the owning layer
-    gfx::Transform S2 = MathUtil::inverse(surface2SublayerTransform);
+    gfx::Transform S2 = inverse(surface2SublayerTransform);
 
     setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(0, 0), gfx::Size(10, 10), false);
     setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(0, 0), gfx::Size(10, 10), false);
@@ -1083,7 +1083,7 @@
     // the correct space. This test will fail if the rotation/inverse are backwards, too,
     // so it requires perfect order of operations.
     expectedGreatGrandChildTransform.MakeIdentity();
-    expectedGreatGrandChildTransform.PreconcatTransform(MathUtil::inverse(rotationAboutZ));
+    expectedGreatGrandChildTransform.PreconcatTransform(inverse(rotationAboutZ));
     expectedGreatGrandChildTransform.Translate(10, 30); // explicit canceling out the scrollDelta that gets embedded in the fixed position layer's surface.
     expectedGreatGrandChildTransform.PreconcatTransform(rotationAboutZ);
 
@@ -1191,7 +1191,7 @@
     compoundDrawTransform.PreconcatTransform(rotationAboutZ); // rotation of greatGrandChild
 
     expectedFixedPositionChildTransform.MakeIdentity();
-    expectedFixedPositionChildTransform.PreconcatTransform(MathUtil::inverse(compoundDrawTransform));
+    expectedFixedPositionChildTransform.PreconcatTransform(inverse(compoundDrawTransform));
     expectedFixedPositionChildTransform.Translate(10, 30); // explicit canceling out the scrollDelta that gets embedded in the fixed position layer's surface.
     expectedFixedPositionChildTransform.PreconcatTransform(compoundDrawTransform);
 
@@ -1325,7 +1325,7 @@
     // affected by the scrollDelta, so its drawTransform needs to explicitly
     // inverse-compensate for the scroll that's embedded in the target surface.
     gfx::Transform expectedGrandChildTransform;
-    expectedGrandChildTransform.PreconcatTransform(MathUtil::inverse(rotationByZ));
+    expectedGrandChildTransform.PreconcatTransform(inverse(rotationByZ));
     expectedGrandChildTransform.Translate(10, 20); // explicit canceling out the scrollDelta that gets embedded in the fixed position layer's surface.
     expectedGrandChildTransform.PreconcatTransform(rotationByZ);
 
@@ -2064,7 +2064,7 @@
     // testing the intended scenario.
     bool clipped = false;
     gfx::RectF clippedRect = MathUtil::mapClippedRect(layerToSurfaceTransform, layerContentRect);
-    MathUtil::projectQuad(MathUtil::inverse(layerToSurfaceTransform), gfx::QuadF(clippedRect), clipped);
+    MathUtil::projectQuad(inverse(layerToSurfaceTransform), gfx::QuadF(clippedRect), clipped);
     ASSERT_TRUE(clipped);
 
     // Only the corner of the layer is not visible on the surface because of being
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc
index 456fa01..7ce1bf14 100644
--- a/cc/layer_tree_host_impl.cc
+++ b/cc/layer_tree_host_impl.cc
@@ -489,8 +489,6 @@
     // doesn't have any bounds and so can't generate this itself.
     // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
 
-    DCHECK(rootLayer->screenSpaceTransform().IsInvertible());
-
     gfx::Rect rootTargetRect = rootLayer->renderSurface()->contentRect();
     float opacity = 1;
     SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadState::Create());
@@ -502,10 +500,13 @@
                             opacity);
 
     AppendQuadsData appendQuadsData;
-    gfx::Transform transformToLayerSpace = MathUtil::inverse(rootLayer->screenSpaceTransform());
+
+    gfx::Transform transformToLayerSpace(gfx::Transform::kSkipInitialization);
+    bool didInvert = rootLayer->screenSpaceTransform().GetInverse(&transformToLayerSpace);
+    DCHECK(didInvert);
     for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects.next()) {
         // The root layer transform is composed of translations and scales only,
-        // no perspective, so mapping is sufficient.
+        // no perspective, so mapping is sufficient (as opposed to projecting).
         gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fillRects.rect());
         // Skip the quad culler and just append the quads directly to avoid
         // occlusion checks.
@@ -1257,7 +1258,11 @@
     // Layers with non-invertible screen space transforms should not have passed the scroll hit
     // test in the first place.
     DCHECK(layerImpl.screenSpaceTransform().IsInvertible());
-    gfx::Transform inverseScreenSpaceTransform = MathUtil::inverse(layerImpl.screenSpaceTransform());
+    gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization);
+    bool didInvert = layerImpl.screenSpaceTransform().GetInverse(&inverseScreenSpaceTransform);
+    // TODO: With the advent of impl-side crolling for non-root layers, we may
+    // need to explicitly handle uninvertible transforms here.
+    DCHECK(didInvert);
 
     gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewportToScreenSpace);
 
diff --git a/cc/math_util.cc b/cc/math_util.cc
index 38b609b..8796504e 100644
--- a/cc/math_util.cc
+++ b/cc/math_util.cc
@@ -422,18 +422,6 @@
     transform->PreconcatTransform(composite);
 }
 
-gfx::Transform MathUtil::inverse(const gfx::Transform& transform)
-{
-    gfx::Transform result;
-    bool invertedSuccessfully = transform.GetInverse(&result);
-
-    if (invertedSuccessfully)
-        return result;
-
-    // If transform was un-invertible, then just return identity.
-    return gfx::Transform();
-}
-
 gfx::Transform MathUtil::to2dTransform(const gfx::Transform& transform)
 {
     gfx::Transform result = transform;
diff --git a/cc/math_util.h b/cc/math_util.h
index d47c80a7..a3a6016 100644
--- a/cc/math_util.h
+++ b/cc/math_util.h
@@ -121,7 +121,6 @@
     // TODO(shawnsingh, vollick) we should phase out as much as possible of
     // these temporary functions, putting functionality into gfx::Transform.
     static void rotateEulerAngles(gfx::Transform*, double eulerX, double eulerY, double eulerZ);
-    static gfx::Transform inverse(const gfx::Transform&);
     static gfx::Transform to2dTransform(const gfx::Transform&);
     // Note carefully: the args here are labeled as per Webcore indexing conventions.
     static gfx::Transform createGfxTransform(double m11, double m12, double m13, double m14,
diff --git a/cc/math_util_unittest.cc b/cc/math_util_unittest.cc
index 0aa0523..6dc2ced7 100644
--- a/cc/math_util_unittest.cc
+++ b/cc/math_util_unittest.cc
@@ -325,51 +325,6 @@
     EXPECT_ROW4_EQ(13, 17, 21, 25, B);
 }
 
-TEST(MathUtilGfxTransformTest, verifyMatrixInversion)
-{
-    // Invert a translation
-    gfx::Transform translation;
-    translation.Translate3d(2, 3, 4);
-    EXPECT_TRUE(translation.IsInvertible());
-
-    gfx::Transform inverseTranslation = MathUtil::inverse(translation);
-    EXPECT_ROW1_EQ(1, 0, 0, -2, inverseTranslation);
-    EXPECT_ROW2_EQ(0, 1, 0, -3, inverseTranslation);
-    EXPECT_ROW3_EQ(0, 0, 1, -4, inverseTranslation);
-    EXPECT_ROW4_EQ(0, 0, 0,  1, inverseTranslation);
-
-    // Note that inversion should not have changed the original matrix.
-    EXPECT_ROW1_EQ(1, 0, 0, 2, translation);
-    EXPECT_ROW2_EQ(0, 1, 0, 3, translation);
-    EXPECT_ROW3_EQ(0, 0, 1, 4, translation);
-    EXPECT_ROW4_EQ(0, 0, 0, 1, translation);
-
-    // Invert a non-uniform scale
-    gfx::Transform scale;
-    scale.Scale3d(4, 10, 100);
-    EXPECT_TRUE(scale.IsInvertible());
-
-    gfx::Transform inverseScale = MathUtil::inverse(scale);
-    EXPECT_ROW1_EQ(0.25,   0,    0, 0, inverseScale);
-    EXPECT_ROW2_EQ(0,    .1f,    0, 0, inverseScale);
-    EXPECT_ROW3_EQ(0,      0, .01f, 0, inverseScale);
-    EXPECT_ROW4_EQ(0,      0,    0, 1, inverseScale);
-
-    // Try to invert a matrix that is not invertible.
-    // The inverse() function should simply return an identity matrix.
-    gfx::Transform notInvertible;
-    notInvertible.matrix().setDouble(0, 0, 0);
-    notInvertible.matrix().setDouble(1, 1, 0);
-    notInvertible.matrix().setDouble(2, 2, 0);
-    notInvertible.matrix().setDouble(3, 3, 0);
-    EXPECT_FALSE(notInvertible.IsInvertible());
-
-    gfx::Transform inverseOfNotInvertible;
-    initializeTestMatrix(&inverseOfNotInvertible); // initialize this to something non-identity, to make sure that assignment below actually took place.
-    inverseOfNotInvertible = MathUtil::inverse(notInvertible);
-    EXPECT_TRUE(inverseOfNotInvertible.IsIdentity());
-}
-
 TEST(MathUtilGfxTransformTest, verifyTo2DTransform)
 {
     gfx::Transform A;
diff --git a/cc/occlusion_tracker.cc b/cc/occlusion_tracker.cc
index e71c6785..c053fda 100644
--- a/cc/occlusion_tracker.cc
+++ b/cc/occlusion_tracker.cc
@@ -54,7 +54,7 @@
 template<typename RenderSurfaceType>
 static gfx::Rect screenSpaceClipRectInTargetSurface(const RenderSurfaceType* targetSurface, gfx::Rect screenSpaceClipRect)
 {
-    gfx::Transform inverseScreenSpaceTransform;
+    gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization);
     if (!targetSurface->screenSpaceTransform().GetInverse(&inverseScreenSpaceTransform))
         return targetSurface->contentRect();
 
@@ -124,7 +124,7 @@
     bool enteringSubtreeThatMovesPixels = newAncestorThatMovesPixels && newAncestorThatMovesPixels != oldAncestorThatMovesPixels;
 
     bool haveTransformFromScreenToNewTarget = false;
-    gfx::Transform inverseNewTargetScreenSpaceTransform;
+    gfx::Transform inverseNewTargetScreenSpaceTransform(gfx::Transform::kSkipInitialization); // Note carefully, not used if screen space transform is uninvertible.
     if (surfaceTransformsToScreenKnown(newTarget->renderSurface()))
         haveTransformFromScreenToNewTarget = newTarget->renderSurface()->screenSpaceTransform().GetInverse(&inverseNewTargetScreenSpaceTransform);
 
@@ -353,7 +353,7 @@
     DCHECK(renderTarget->renderSurface());
     DCHECK(renderTarget == m_stack.back().target);
 
-    gfx::Transform inverseDrawTransform;
+    gfx::Transform inverseDrawTransform(gfx::Transform::kSkipInitialization);
     if (!drawTransform.GetInverse(&inverseDrawTransform))
         return false;
 
@@ -396,7 +396,7 @@
     DCHECK(renderTarget->renderSurface());
     DCHECK(renderTarget == m_stack.back().target);
 
-    gfx::Transform inverseDrawTransform;
+    gfx::Transform inverseDrawTransform(gfx::Transform::kSkipInitialization);
     if (!drawTransform.GetInverse(&inverseDrawTransform))
         return contentRect;
 
@@ -445,7 +445,7 @@
         return contentRect;
 
     gfx::Transform drawTransform = forReplica ? surface->replicaDrawTransform() : surface->drawTransform();
-    gfx::Transform inverseDrawTransform;
+    gfx::Transform inverseDrawTransform(gfx::Transform::kSkipInitialization);
     if (!drawTransform.GetInverse(&inverseDrawTransform))
         return contentRect;
 
diff --git a/cc/test/geometry_test_utils.cc b/cc/test/geometry_test_utils.cc
index bed04c4..385dbaca2 100644
--- a/cc/test/geometry_test_utils.cc
+++ b/cc/test/geometry_test_utils.cc
@@ -4,6 +4,7 @@
 
 #include "cc/test/geometry_test_utils.h"
 
+#include "base/logging.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebTransformationMatrix.h"
 #include "ui/gfx/transform.h"
@@ -56,4 +57,12 @@
     EXPECT_FLOAT_EQ((expected).matrix().getDouble(3, 3), (actual).matrix().getDouble(3, 3));
 }
 
+gfx::Transform inverse(const gfx::Transform& transform)
+{
+    gfx::Transform result(gfx::Transform::kSkipInitialization);
+    bool invertedSuccessfully = transform.GetInverse(&result);
+    DCHECK(invertedSuccessfully);
+    return result;
+}
+
 }  // namespace cc
diff --git a/cc/test/geometry_test_utils.h b/cc/test/geometry_test_utils.h
index 30260c1..0bcb99e 100644
--- a/cc/test/geometry_test_utils.h
+++ b/cc/test/geometry_test_utils.h
@@ -73,6 +73,10 @@
         cc::ExpectTransformationMatrixEq(expected, actual);          \
     }
 
+// Should be used in test code only, for convenience. Production code should use
+// the gfx::Transform::GetInverse() API.
+gfx::Transform inverse(const gfx::Transform& transform);
+
 }  // namespace cc
 
 #endif  // CC_TEST_GEOMETRY_TEST_UTILS_H_
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc
index a4a4e64..c2b6ba2 100644
--- a/ui/gfx/transform.cc
+++ b/ui/gfx/transform.cc
@@ -245,7 +245,14 @@
 }
 
 bool Transform::GetInverse(Transform* transform) const {
-  return matrix_.invert(&transform->matrix_);
+  if (!matrix_.invert(&transform->matrix_)) {
+    // Initialize the return value to identity if this matrix turned
+    // out to be un-invertible.
+    transform->MakeIdentity();
+    return false;
+  }
+
+  return true;
 }
 
 void Transform::Transpose() {
diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h
index 6cd10b1..95de30f 100644
--- a/ui/gfx/transform.h
+++ b/ui/gfx/transform.h
@@ -22,7 +22,17 @@
 // copy/assign.
 class UI_EXPORT Transform {
  public:
+
+  enum SkipInitialization {
+    kSkipInitialization
+  };
+
   Transform() : matrix_(SkMatrix44::kIdentity_Constructor) {}
+
+  // Skips initializing this matrix to avoid overhead, when we know it will be
+  // initialized before use.
+  Transform(SkipInitialization)
+      : matrix_(SkMatrix44::kUninitialized_Constructor) {}
   Transform(const Transform& rhs) : matrix_(rhs.matrix_) {}
   // Initialize with the concatenation of lhs * rhs.
   Transform(const Transform& lhs, const Transform& rhs)
diff --git a/ui/gfx/transform_unittest.cc b/ui/gfx/transform_unittest.cc
index 31892c3..1984fea 100644
--- a/ui/gfx/transform_unittest.cc
+++ b/ui/gfx/transform_unittest.cc
@@ -1182,6 +1182,63 @@
   EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
 }
 
+TEST(XFormTest, verifyMatrixInversion)
+{
+  {
+    // Invert a translation
+    gfx::Transform translation;
+    translation.Translate3d(2, 3, 4);
+    EXPECT_TRUE(translation.IsInvertible());
+
+    gfx::Transform inverse_translation;
+    bool is_invertible = translation.GetInverse(&inverse_translation);
+    EXPECT_TRUE(is_invertible);
+    EXPECT_ROW1_EQ(1, 0, 0, -2, inverse_translation);
+    EXPECT_ROW2_EQ(0, 1, 0, -3, inverse_translation);
+    EXPECT_ROW3_EQ(0, 0, 1, -4, inverse_translation);
+    EXPECT_ROW4_EQ(0, 0, 0,  1, inverse_translation);
+  }
+
+  {
+    // Invert a non-uniform scale
+    gfx::Transform scale;
+    scale.Scale3d(4, 10, 100);
+    EXPECT_TRUE(scale.IsInvertible());
+
+    gfx::Transform inverse_scale;
+    bool is_invertible = scale.GetInverse(&inverse_scale);
+    EXPECT_TRUE(is_invertible);
+    EXPECT_ROW1_EQ(0.25,   0,    0, 0, inverse_scale);
+    EXPECT_ROW2_EQ(0,    .1f,    0, 0, inverse_scale);
+    EXPECT_ROW3_EQ(0,      0, .01f, 0, inverse_scale);
+    EXPECT_ROW4_EQ(0,      0,    0, 1, inverse_scale);
+  }
+
+  {
+    // Try to invert a matrix that is not invertible.
+    // The inverse() function should reset the output matrix to identity.
+    gfx::Transform uninvertible;
+    uninvertible.matrix().setDouble(0, 0, 0);
+    uninvertible.matrix().setDouble(1, 1, 0);
+    uninvertible.matrix().setDouble(2, 2, 0);
+    uninvertible.matrix().setDouble(3, 3, 0);
+    EXPECT_FALSE(uninvertible.IsInvertible());
+
+    gfx::Transform inverse_of_uninvertible;
+
+    // Add a scale just to more easily ensure that inverse_of_uninvertible is
+    // reset to identity.
+    inverse_of_uninvertible.Scale3d(4, 10, 100);
+
+    bool is_invertible = uninvertible.GetInverse(&inverse_of_uninvertible);
+    EXPECT_FALSE(is_invertible);
+    EXPECT_TRUE(inverse_of_uninvertible.IsIdentity());
+    EXPECT_ROW1_EQ(1, 0, 0, 0, inverse_of_uninvertible);
+    EXPECT_ROW2_EQ(0, 1, 0, 0, inverse_of_uninvertible);
+    EXPECT_ROW3_EQ(0, 0, 1, 0, inverse_of_uninvertible);
+    EXPECT_ROW4_EQ(0, 0, 0, 1, inverse_of_uninvertible);
+  }
+}
 
 }  // namespace