Back out bug 779001, bug 746883, bug 778595, bug 776803, bug 7118849
authorNicholas Cameron <ncameron@mozilla.com>
Tue, 31 Jul 2012 18:17:23 +1200
changeset 102802 f7e6da69186d54357e06d8488ff3f301f21ff442
parent 102783 e4baff472b7f0d5ffe63e3a55c250566e9548307
child 102803 cda1c40da9868d14756ebf702d40f4783b3866d0
push id18
push usershu@rfrn.org
push dateMon, 06 Aug 2012 22:42:45 +0000
bugs779001, 746883, 778595, 776803, 7118849
milestone17.0a1
Back out bug 779001, bug 746883, bug 778595, bug 776803, bug 7118849
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/canvas/test/test_canvas.html
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/skia/patches/0016-Bug-718849-Radial-gradients.patch
gfx/skia/patches/README
gfx/skia/src/effects/SkGradientShader.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
layout/reftests/bugs/reftest.list
layout/reftests/css-gradients/reftest.list
layout/reftests/svg/reftest.list
layout/tools/reftest/reftest.js
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -547,17 +547,18 @@ PRUint8 (*nsCanvasRenderingContext2DAzur
 PRUint8 (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nullptr;
 
 namespace mozilla {
 namespace dom {
 
 bool
 AzureCanvasEnabled()
 {
-  return gfxPlatform::GetPlatform()->SupportsAzureCanvas();
+  BackendType dontCare;
+  return gfxPlatform::GetPlatform()->SupportsAzureCanvas(dontCare);
 }
 
 }
 }
 
 nsresult
 NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
 {
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -39,41 +39,41 @@ function IsMacOSX10_5orOlder() {
 }
 
 
 function IsAzureEnabled() {
   var enabled = false;
 
   try {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
+    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
     enabled = (backend != "none");
   } catch (e) { }
 
   return enabled;
 }
 
 function IsAzureSkia() {
   var enabled = false;
   
   try {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
+    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
     enabled = (backend == "skia");
   } catch (e) { }
 
   return enabled;
 }
 
 function IsAzureCairo() {
   var enabled = false;
   
   try {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
+    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
     enabled = (backend == "cairo");
   } catch (e) { }
 
   return enabled;
 }
 
 </script>
 <!-- Includes all the tests in the content/canvas/tests except for test_bug397524.html -->
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -479,20 +479,21 @@ LayerManagerD3D10::CreateOptimalMaskSurf
   return CreateOptimalSurface(aSize, gfxASurface::ImageFormatARGB32);
 }
 
 
 TemporaryRef<DrawTarget>
 LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
                                     SurfaceFormat aFormat)
 {
+  BackendType backend;
   if ((aFormat != FORMAT_B8G8R8A8 &&
        aFormat != FORMAT_B8G8R8X8) ||
-       !gfxPlatform::GetPlatform()->SupportsAzureCanvas() ||
-       gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() != BACKEND_DIRECT2D) {
+       !gfxPlatform::GetPlatform()->SupportsAzureCanvas(backend) ||
+       backend != BACKEND_DIRECT2D) {
     return LayerManager::CreateDrawTarget(aSize, aFormat);
   }
 
   nsRefPtr<ID3D10Texture2D> texture;
   
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   
deleted file mode 100644
--- a/gfx/skia/patches/0016-Bug-718849-Radial-gradients.patch
+++ /dev/null
@@ -1,400 +0,0 @@
-# HG changeset patch
-# User Matt Woodrow <mwoodrow@mozilla.com>
-# Date 1339988782 -43200
-# Node ID 1e9dae659ee6c992f719fd4136efbcc5410ded37
-# Parent 946750f6d95febd199fb7b748e9d2c48fd01c8a6
-[mq]: skia-windows-gradients
-
-diff --git a/gfx/skia/src/effects/SkGradientShader.cpp b/gfx/skia/src/effects/SkGradientShader.cpp
---- a/gfx/skia/src/effects/SkGradientShader.cpp
-+++ b/gfx/skia/src/effects/SkGradientShader.cpp
-@@ -847,16 +847,19 @@ bool Linear_Gradient::setContext(const S
-         fFlags |= SkShader::kConstInY32_Flag;
-         if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
-             // only claim this if we do have a 16bit mode (i.e. none of our
-             // colors have alpha), and if we are not dithering (which obviously
-             // is not const in Y).
-             fFlags |= SkShader::kConstInY16_Flag;
-         }
-     }
-+    if (fStart == fEnd) {
-+        fFlags &= ~kOpaqueAlpha_Flag;
-+    }
-     return true;
- }
- 
- #define NO_CHECK_ITER               \
-     do {                            \
-     unsigned fi = fx >> Gradient_Shader::kCache32Shift; \
-     SkASSERT(fi <= 0xFF);           \
-     fx += dx;                       \
-@@ -976,16 +979,21 @@ void Linear_Gradient::shadeSpan(int x, i
-     TileProc            proc = fTileProc;
-     const SkPMColor* SK_RESTRICT cache = this->getCache32();
- #ifdef USE_DITHER_32BIT_GRADIENT
-     int                 toggle = ((x ^ y) & 1) * kDitherStride32;
- #else
-     int toggle = 0;
- #endif
- 
-+    if (fStart == fEnd) {
-+        sk_bzero(dstC, count * sizeof(*dstC));
-+        return;
-+    }
-+
-     if (fDstToIndexClass != kPerspective_MatrixClass) {
-         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
-                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
- 
-         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
-             SkFixed dxStorage[1];
-             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
-@@ -1169,16 +1177,21 @@ void Linear_Gradient::shadeSpan16(int x,
-     SkASSERT(count > 0);
- 
-     SkPoint             srcPt;
-     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
-     TileProc            proc = fTileProc;
-     const uint16_t* SK_RESTRICT cache = this->getCache16();
-     int                 toggle = ((x ^ y) & 1) * kDitherStride16;
- 
-+    if (fStart == fEnd) {
-+        sk_bzero(dstC, count * sizeof(*dstC));
-+        return;
-+    }
-+
-     if (fDstToIndexClass != kPerspective_MatrixClass) {
-         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
-                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
- 
-         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
-             SkFixed dxStorage[1];
-             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
-@@ -1739,21 +1752,25 @@ void Radial_Gradient::shadeSpan(int x, i
-    possible circles on which the point may fall.  Solving for t yields
-    the gradient value to use.
- 
-    If a<0, the start circle is entirely contained in the
-    end circle, and one of the roots will be <0 or >1 (off the line
-    segment).  If a>0, the start circle falls at least partially
-    outside the end circle (or vice versa), and the gradient
-    defines a "tube" where a point may be on one circle (on the
--   inside of the tube) or the other (outside of the tube).  We choose
--   one arbitrarily.
-+   inside of the tube) or the other (outside of the tube). We choose
-+   the one with the highest t value, as long as the radius that it 
-+   corresponds to is >=0. In the case where neither root has a positive
-+   radius, we don't draw anything.
- 
-+   XXXmattwoodrow: I've removed this for now since it breaks
-+   down when Dr == 0. Is there something else we can do instead?
-    In order to keep the math to within the limits of fixed point,
--   we divide the entire quadratic by Dr^2, and replace
-+   we divide the entire quadratic by Dr, and replace
-    (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
- 
-    [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
-    + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
-    + [x'^2 + y'^2 - Sr^2/Dr^2] = 0
- 
-    (x' and y' are computed by appending the subtract and scale to the
-    fDstToIndex matrix in the constructor).
-@@ -1763,99 +1780,122 @@ void Radial_Gradient::shadeSpan(int x, i
-    x' and y', if x and y are linear in the span, 'B' can be computed
-    incrementally with a simple delta (db below).  If it is not (e.g.,
-    a perspective projection), it must be computed in the loop.
- 
- */
- 
- namespace {
- 
--inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
--                                SkScalar sr2d2, SkScalar foura,
--                                SkScalar oneOverTwoA, bool posRoot) {
-+inline bool two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
-+                             SkScalar sr2d2, SkScalar foura,
-+                             SkScalar oneOverTwoA, SkScalar diffRadius, 
-+                             SkScalar startRadius, SkFixed& t) {
-     SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
-     if (0 == foura) {
--        return SkScalarToFixed(SkScalarDiv(-c, b));
-+        SkScalar result = SkScalarDiv(-c, b);
-+        if (result * diffRadius + startRadius >= 0) {
-+            t = SkScalarToFixed(result);
-+            return true;
-+        }
-+        return false;
-     }
- 
-     SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
-     if (discrim < 0) {
--        discrim = -discrim;
-+        return false;
-     }
-     SkScalar rootDiscrim = SkScalarSqrt(discrim);
--    SkScalar result;
--    if (posRoot) {
--        result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
--    } else {
--        result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
-+
-+    // Make sure the results corresponds to a positive radius.
-+    SkScalar result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
-+    if (result * diffRadius + startRadius >= 0) {
-+        t = SkScalarToFixed(result);
-+        return true;
-     }
--    return SkScalarToFixed(result);
-+    result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
-+    if (result * diffRadius + startRadius >= 0) {
-+        t = SkScalarToFixed(result);
-+        return true;
-+    }
-+
-+    return false;
- }
- 
- typedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx,
-         SkScalar fy, SkScalar dy,
-         SkScalar b, SkScalar db,
--        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
-+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
-+        SkScalar fDiffRadius, SkScalar fRadius1,
-         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-         int count);
- 
- void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
-         SkScalar fy, SkScalar dy,
-         SkScalar b, SkScalar db,
--        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
-+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
-+        SkScalar fDiffRadius, SkScalar fRadius1,
-         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-         int count) {
-     for (; count > 0; --count) {
--        SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
--                                     fOneOverTwoA, posRoot);
--
--        if (t < 0) {
-+        SkFixed t;
-+        if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-+          *(dstC++) = 0;
-+        } else if (t < 0) {
-             *dstC++ = cache[-1];
-         } else if (t > 0xFFFF) {
-             *dstC++ = cache[Gradient_Shader::kCache32Count * 2];
-         } else {
-             SkASSERT(t <= 0xFFFF);
-             *dstC++ = cache[t >> Gradient_Shader::kCache32Shift];
-         }
- 
-         fx += dx;
-         fy += dy;
-         b += db;
-     }
- }
- void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
-         SkScalar fy, SkScalar dy,
-         SkScalar b, SkScalar db,
--        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
-+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
-+        SkScalar fDiffRadius, SkScalar fRadius1,
-         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-         int count) {
-     for (; count > 0; --count) {
--        SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
--                                     fOneOverTwoA, posRoot);
--        SkFixed index = mirror_tileproc(t);
--        SkASSERT(index <= 0xFFFF);
--        *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
-+        SkFixed t;
-+        if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-+          *(dstC++) = 0;
-+        } else {
-+          SkFixed index = mirror_tileproc(t);
-+          SkASSERT(index <= 0xFFFF);
-+          *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
-+        }
-         fx += dx;
-         fy += dy;
-         b += db;
-     }
- }
- 
- void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
-         SkScalar fy, SkScalar dy,
-         SkScalar b, SkScalar db,
--        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
-+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, 
-+        SkScalar fDiffRadius, SkScalar fRadius1,
-         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-         int count) {
-     for (; count > 0; --count) {
--        SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
--                                     fOneOverTwoA, posRoot);
--        SkFixed index = repeat_tileproc(t);
--        SkASSERT(index <= 0xFFFF);
--        *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
-+        SkFixed t;
-+        if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-+          *(dstC++) = 0;
-+        } else {
-+          SkFixed index = repeat_tileproc(t);
-+          SkASSERT(index <= 0xFFFF);
-+          *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
-+        }
-         fx += dx;
-         fy += dy;
-         b += db;
-     }
- }
- 
- 
- 
-@@ -1935,17 +1975,16 @@ public:
-           sk_bzero(dstC, count * sizeof(*dstC));
-           return;
-         }
-         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
-         TileProc            proc = fTileProc;
-         const SkPMColor* SK_RESTRICT cache = this->getCache32();
- 
-         SkScalar foura = fA * 4;
--        bool posRoot = fDiffRadius < 0;
-         if (fDstToIndexClass != kPerspective_MatrixClass) {
-             SkPoint srcPt;
-             dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
-                                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-             SkScalar dx, fx = srcPt.fX;
-             SkScalar dy, fy = srcPt.fY;
- 
-             if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
-@@ -1954,60 +1993,69 @@ public:
-                 dx = SkFixedToScalar(fixedX);
-                 dy = SkFixedToScalar(fixedY);
-             } else {
-                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
-                 dx = fDstToIndex.getScaleX();
-                 dy = fDstToIndex.getSkewY();
-             }
-             SkScalar b = (SkScalarMul(fDiff.fX, fx) +
--                         SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
-+                          SkScalarMul(fDiff.fY, fy) - fStartRadius * fDiffRadius) * 2;
-             SkScalar db = (SkScalarMul(fDiff.fX, dx) +
-                           SkScalarMul(fDiff.fY, dy)) * 2;
- 
-             TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat;
-             if (proc == clamp_tileproc) {
-                 shadeProc = shadeSpan_twopoint_clamp;
-             } else if (proc == mirror_tileproc) {
-                 shadeProc = shadeSpan_twopoint_mirror;
-             } else {
-                 SkASSERT(proc == repeat_tileproc);
-             }
-             (*shadeProc)(fx, dx, fy, dy, b, db,
--                         fSr2D2, foura, fOneOverTwoA, posRoot,
-+                         fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1,
-                          dstC, cache, count);
-         } else {    // perspective case
-             SkScalar dstX = SkIntToScalar(x);
-             SkScalar dstY = SkIntToScalar(y);
-             for (; count > 0; --count) {
-                 SkPoint             srcPt;
-                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
-                 SkScalar fx = srcPt.fX;
-                 SkScalar fy = srcPt.fY;
-                 SkScalar b = (SkScalarMul(fDiff.fX, fx) +
-                              SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
--                SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
--                                             fOneOverTwoA, posRoot);
--                SkFixed index = proc(t);
--                SkASSERT(index <= 0xFFFF);
--                *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
-+                SkFixed t;
-+                if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-+                  *(dstC++) = 0;
-+                } else {
-+                  SkFixed index = proc(t);
-+                  SkASSERT(index <= 0xFFFF);
-+                  *dstC++ = cache[index >> (16 - kCache32Bits)];
-+                }
-                 dstX += SK_Scalar1;
-             }
-         }
-     }
- 
-     virtual bool setContext(const SkBitmap& device,
-                             const SkPaint& paint,
-                             const SkMatrix& matrix) SK_OVERRIDE {
-         if (!this->INHERITED::setContext(device, paint, matrix)) {
-             return false;
-         }
- 
-         // we don't have a span16 proc
-         fFlags &= ~kHasSpan16_Flag;
-+
-+        // If we might end up wanting to draw nothing as part of the gradient
-+        // then we should mark ourselves as not being opaque.
-+        if (fA >= 0 || (fDiffRadius == 0 && fCenter1 == fCenter2)) {
-+            fFlags &= ~kOpaqueAlpha_Flag;
-+        }
-         return true;
-     }
- 
-     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Two_Point_Radial_Gradient)
- 
- protected:
-     Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
-             : INHERITED(buffer),
-@@ -2033,26 +2081,22 @@ private:
-     const SkScalar fRadius1;
-     const SkScalar fRadius2;
-     SkPoint fDiff;
-     SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
- 
-     void init() {
-         fDiff = fCenter1 - fCenter2;
-         fDiffRadius = fRadius2 - fRadius1;
--        SkScalar inv = SkScalarInvert(fDiffRadius);
--        fDiff.fX = SkScalarMul(fDiff.fX, inv);
--        fDiff.fY = SkScalarMul(fDiff.fY, inv);
--        fStartRadius = SkScalarMul(fRadius1, inv);
-+        fStartRadius = fRadius1;
-         fSr2D2 = SkScalarSquare(fStartRadius);
--        fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
-+        fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SkScalarSquare(fDiffRadius);
-         fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0;
- 
-         fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
--        fPtsToUnit.postScale(inv, inv);
-     }
- };
- 
- ///////////////////////////////////////////////////////////////////////////////
- 
- class Sweep_Gradient : public Gradient_Shader {
- public:
-     Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
-@@ -2488,16 +2532,20 @@ SkShader* SkGradientShader::CreateTwoPoi
-                                                  int colorCount,
-                                                  SkShader::TileMode mode,
-                                                  SkUnitMapper* mapper) {
-     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
-         return NULL;
-     }
-     EXPAND_1_COLOR(colorCount);
- 
-+    if (start == end && startRadius == 0) {
-+        return CreateRadial(start, endRadius, colors, pos, colorCount, mode, mapper);
-+    }
-+
-     return SkNEW_ARGS(Two_Point_Radial_Gradient,
-                       (start, startRadius, end, endRadius, colors, pos,
-                        colorCount, mode, mapper));
- }
- 
- SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
-                                         const SkColor colors[],
-                                         const SkScalar pos[],
--- a/gfx/skia/patches/README
+++ b/gfx/skia/patches/README
@@ -13,9 +13,8 @@ 0007-Bug-719872-Old-Android-FontHost.pat
 0008-Bug-687188-Skia-radial-gradients.patch
 0009-Bug-755869-FreeBSD-Hurd.patch
 0010-Bug-689069-ARM-Opts.patch
 0011-Bug-719575-Fix-clang-build.patch
 0012-Bug-759683-make-ssse3-conditional.patch
 0013-Bug-761890-fonts.patch
 0014-Bug-765038-Fix-clang-build.patch
 0015-Bug-766017-warnings.patch
-0016-Bug-718849-Radial-Gradients.patch
--- a/gfx/skia/src/effects/SkGradientShader.cpp
+++ b/gfx/skia/src/effects/SkGradientShader.cpp
@@ -847,19 +847,16 @@ bool Linear_Gradient::setContext(const S
         fFlags |= SkShader::kConstInY32_Flag;
         if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
             // only claim this if we do have a 16bit mode (i.e. none of our
             // colors have alpha), and if we are not dithering (which obviously
             // is not const in Y).
             fFlags |= SkShader::kConstInY16_Flag;
         }
     }
-    if (fStart == fEnd) {
-        fFlags &= ~kOpaqueAlpha_Flag;
-    }
     return true;
 }
 
 #define NO_CHECK_ITER               \
     do {                            \
     unsigned fi = fx >> Gradient_Shader::kCache32Shift; \
     SkASSERT(fi <= 0xFF);           \
     fx += dx;                       \
@@ -979,21 +976,16 @@ void Linear_Gradient::shadeSpan(int x, i
     TileProc            proc = fTileProc;
     const SkPMColor* SK_RESTRICT cache = this->getCache32();
 #ifdef USE_DITHER_32BIT_GRADIENT
     int                 toggle = ((x ^ y) & 1) * kDitherStride32;
 #else
     int toggle = 0;
 #endif
 
-    if (fStart == fEnd) {
-        sk_bzero(dstC, count * sizeof(*dstC));
-        return;
-    }
-
     if (fDstToIndexClass != kPerspective_MatrixClass) {
         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
 
         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
             SkFixed dxStorage[1];
             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
@@ -1177,21 +1169,16 @@ void Linear_Gradient::shadeSpan16(int x,
     SkASSERT(count > 0);
 
     SkPoint             srcPt;
     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
     TileProc            proc = fTileProc;
     const uint16_t* SK_RESTRICT cache = this->getCache16();
     int                 toggle = ((x ^ y) & 1) * kDitherStride16;
 
-    if (fStart == fEnd) {
-        sk_bzero(dstC, count * sizeof(*dstC));
-        return;
-    }
-
     if (fDstToIndexClass != kPerspective_MatrixClass) {
         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
                              SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
         SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
 
         if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
             SkFixed dxStorage[1];
             (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL);
@@ -1752,25 +1739,21 @@ void Radial_Gradient::shadeSpan(int x, i
    possible circles on which the point may fall.  Solving for t yields
    the gradient value to use.
 
    If a<0, the start circle is entirely contained in the
    end circle, and one of the roots will be <0 or >1 (off the line
    segment).  If a>0, the start circle falls at least partially
    outside the end circle (or vice versa), and the gradient
    defines a "tube" where a point may be on one circle (on the
-   inside of the tube) or the other (outside of the tube). We choose
-   the one with the highest t value, as long as the radius that it 
-   corresponds to is >=0. In the case where neither root has a positive
-   radius, we don't draw anything.
+   inside of the tube) or the other (outside of the tube).  We choose
+   one arbitrarily.
 
-   XXXmattwoodrow: I've removed this for now since it breaks
-   down when Dr == 0. Is there something else we can do instead?
    In order to keep the math to within the limits of fixed point,
-   we divide the entire quadratic by Dr, and replace
+   we divide the entire quadratic by Dr^2, and replace
    (x - Sx)/Dr with x' and (y - Sy)/Dr with y', giving
 
    [Dx^2 / Dr^2 + Dy^2 / Dr^2 - 1)] * t^2
    + 2 * [x' * Dx / Dr + y' * Dy / Dr - Sr / Dr] * t
    + [x'^2 + y'^2 - Sr^2/Dr^2] = 0
 
    (x' and y' are computed by appending the subtract and scale to the
    fDstToIndex matrix in the constructor).
@@ -1780,122 +1763,99 @@ void Radial_Gradient::shadeSpan(int x, i
    x' and y', if x and y are linear in the span, 'B' can be computed
    incrementally with a simple delta (db below).  If it is not (e.g.,
    a perspective projection), it must be computed in the loop.
 
 */
 
 namespace {
 
-inline bool two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
-                             SkScalar sr2d2, SkScalar foura,
-                             SkScalar oneOverTwoA, SkScalar diffRadius, 
-                             SkScalar startRadius, SkFixed& t) {
+inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
+                                SkScalar sr2d2, SkScalar foura,
+                                SkScalar oneOverTwoA, bool posRoot) {
     SkScalar c = SkScalarSquare(fx) + SkScalarSquare(fy) - sr2d2;
     if (0 == foura) {
-        SkScalar result = SkScalarDiv(-c, b);
-        if (result * diffRadius + startRadius >= 0) {
-            t = SkScalarToFixed(result);
-            return true;
-        }
-        return false;
+        return SkScalarToFixed(SkScalarDiv(-c, b));
     }
 
     SkScalar discrim = SkScalarSquare(b) - SkScalarMul(foura, c);
     if (discrim < 0) {
-        return false;
+        discrim = -discrim;
     }
     SkScalar rootDiscrim = SkScalarSqrt(discrim);
-
-    // Make sure the results corresponds to a positive radius.
-    SkScalar result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
-    if (result * diffRadius + startRadius >= 0) {
-        t = SkScalarToFixed(result);
-        return true;
+    SkScalar result;
+    if (posRoot) {
+        result = SkScalarMul(-b + rootDiscrim, oneOverTwoA);
+    } else {
+        result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
     }
-    result = SkScalarMul(-b - rootDiscrim, oneOverTwoA);
-    if (result * diffRadius + startRadius >= 0) {
-        t = SkScalarToFixed(result);
-        return true;
-    }
-
-    return false;
+    return SkScalarToFixed(result);
 }
 
 typedef void (* TwoPointRadialShadeProc)(SkScalar fx, SkScalar dx,
         SkScalar fy, SkScalar dy,
         SkScalar b, SkScalar db,
-        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
-        SkScalar fDiffRadius, SkScalar fRadius1,
+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
         int count);
 
 void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
         SkScalar fy, SkScalar dy,
         SkScalar b, SkScalar db,
-        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
-        SkScalar fDiffRadius, SkScalar fRadius1,
+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
         int count) {
     for (; count > 0; --count) {
-        SkFixed t;
-        if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-          *(dstC++) = 0;
-        } else if (t < 0) {
+        SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
+                                     fOneOverTwoA, posRoot);
+
+        if (t < 0) {
             *dstC++ = cache[-1];
         } else if (t > 0xFFFF) {
             *dstC++ = cache[Gradient_Shader::kCache32Count * 2];
         } else {
             SkASSERT(t <= 0xFFFF);
             *dstC++ = cache[t >> Gradient_Shader::kCache32Shift];
         }
 
         fx += dx;
         fy += dy;
         b += db;
     }
 }
 void shadeSpan_twopoint_mirror(SkScalar fx, SkScalar dx,
         SkScalar fy, SkScalar dy,
         SkScalar b, SkScalar db,
-        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA,
-        SkScalar fDiffRadius, SkScalar fRadius1,
+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
         int count) {
     for (; count > 0; --count) {
-        SkFixed t;
-        if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-          *(dstC++) = 0;
-        } else {
-          SkFixed index = mirror_tileproc(t);
-          SkASSERT(index <= 0xFFFF);
-          *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
-        }
+        SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
+                                     fOneOverTwoA, posRoot);
+        SkFixed index = mirror_tileproc(t);
+        SkASSERT(index <= 0xFFFF);
+        *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
         fx += dx;
         fy += dy;
         b += db;
     }
 }
 
 void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
         SkScalar fy, SkScalar dy,
         SkScalar b, SkScalar db,
-        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, 
-        SkScalar fDiffRadius, SkScalar fRadius1,
+        SkScalar fSr2D2, SkScalar foura, SkScalar fOneOverTwoA, bool posRoot,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
         int count) {
     for (; count > 0; --count) {
-        SkFixed t;
-        if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-          *(dstC++) = 0;
-        } else {
-          SkFixed index = repeat_tileproc(t);
-          SkASSERT(index <= 0xFFFF);
-          *dstC++ = cache[index >> (16 - Gradient_Shader::kCache32Shift)];
-        }
+        SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
+                                     fOneOverTwoA, posRoot);
+        SkFixed index = repeat_tileproc(t);
+        SkASSERT(index <= 0xFFFF);
+        *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
         fx += dx;
         fy += dy;
         b += db;
     }
 }
 
 
 
@@ -1975,16 +1935,17 @@ public:
           sk_bzero(dstC, count * sizeof(*dstC));
           return;
         }
         SkMatrix::MapXYProc dstProc = fDstToIndexProc;
         TileProc            proc = fTileProc;
         const SkPMColor* SK_RESTRICT cache = this->getCache32();
 
         SkScalar foura = fA * 4;
+        bool posRoot = fDiffRadius < 0;
         if (fDstToIndexClass != kPerspective_MatrixClass) {
             SkPoint srcPt;
             dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
                                  SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
             SkScalar dx, fx = srcPt.fX;
             SkScalar dy, fy = srcPt.fY;
 
             if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
@@ -1993,69 +1954,60 @@ public:
                 dx = SkFixedToScalar(fixedX);
                 dy = SkFixedToScalar(fixedY);
             } else {
                 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
                 dx = fDstToIndex.getScaleX();
                 dy = fDstToIndex.getSkewY();
             }
             SkScalar b = (SkScalarMul(fDiff.fX, fx) +
-                          SkScalarMul(fDiff.fY, fy) - fStartRadius * fDiffRadius) * 2;
+                         SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
             SkScalar db = (SkScalarMul(fDiff.fX, dx) +
                           SkScalarMul(fDiff.fY, dy)) * 2;
 
             TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat;
             if (proc == clamp_tileproc) {
                 shadeProc = shadeSpan_twopoint_clamp;
             } else if (proc == mirror_tileproc) {
                 shadeProc = shadeSpan_twopoint_mirror;
             } else {
                 SkASSERT(proc == repeat_tileproc);
             }
             (*shadeProc)(fx, dx, fy, dy, b, db,
-                         fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1,
+                         fSr2D2, foura, fOneOverTwoA, posRoot,
                          dstC, cache, count);
         } else {    // perspective case
             SkScalar dstX = SkIntToScalar(x);
             SkScalar dstY = SkIntToScalar(y);
             for (; count > 0; --count) {
                 SkPoint             srcPt;
                 dstProc(fDstToIndex, dstX, dstY, &srcPt);
                 SkScalar fx = srcPt.fX;
                 SkScalar fy = srcPt.fY;
                 SkScalar b = (SkScalarMul(fDiff.fX, fx) +
                              SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
-                SkFixed t;
-                if (!two_point_radial(b, fx, fy, fSr2D2, foura, fOneOverTwoA, fDiffRadius, fRadius1, t)) {
-                  *(dstC++) = 0;
-                } else {
-                  SkFixed index = proc(t);
-                  SkASSERT(index <= 0xFFFF);
-                  *dstC++ = cache[index >> (16 - kCache32Bits)];
-                }
+                SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
+                                             fOneOverTwoA, posRoot);
+                SkFixed index = proc(t);
+                SkASSERT(index <= 0xFFFF);
+                *dstC++ = cache[index >> Gradient_Shader::kCache32Shift];
                 dstX += SK_Scalar1;
             }
         }
     }
 
     virtual bool setContext(const SkBitmap& device,
                             const SkPaint& paint,
                             const SkMatrix& matrix) SK_OVERRIDE {
         if (!this->INHERITED::setContext(device, paint, matrix)) {
             return false;
         }
 
         // we don't have a span16 proc
         fFlags &= ~kHasSpan16_Flag;
-
-        // If we might end up wanting to draw nothing as part of the gradient
-        // then we should mark ourselves as not being opaque.
-        if (fA >= 0 || (fDiffRadius == 0 && fCenter1 == fCenter2)) {
-            fFlags &= ~kOpaqueAlpha_Flag;
-        }
         return true;
     }
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Two_Point_Radial_Gradient)
 
 protected:
     Two_Point_Radial_Gradient(SkFlattenableReadBuffer& buffer)
             : INHERITED(buffer),
@@ -2081,22 +2033,26 @@ private:
     const SkScalar fRadius1;
     const SkScalar fRadius2;
     SkPoint fDiff;
     SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
 
     void init() {
         fDiff = fCenter1 - fCenter2;
         fDiffRadius = fRadius2 - fRadius1;
-        fStartRadius = fRadius1;
+        SkScalar inv = SkScalarInvert(fDiffRadius);
+        fDiff.fX = SkScalarMul(fDiff.fX, inv);
+        fDiff.fY = SkScalarMul(fDiff.fY, inv);
+        fStartRadius = SkScalarMul(fRadius1, inv);
         fSr2D2 = SkScalarSquare(fStartRadius);
-        fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SkScalarSquare(fDiffRadius);
+        fA = SkScalarSquare(fDiff.fX) + SkScalarSquare(fDiff.fY) - SK_Scalar1;
         fOneOverTwoA = fA ? SkScalarInvert(fA * 2) : 0;
 
         fPtsToUnit.setTranslate(-fCenter1.fX, -fCenter1.fY);
+        fPtsToUnit.postScale(inv, inv);
     }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
 
 class Sweep_Gradient : public Gradient_Shader {
 public:
     Sweep_Gradient(SkScalar cx, SkScalar cy, const SkColor colors[],
@@ -2532,20 +2488,16 @@ SkShader* SkGradientShader::CreateTwoPoi
                                                  int colorCount,
                                                  SkShader::TileMode mode,
                                                  SkUnitMapper* mapper) {
     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
     EXPAND_1_COLOR(colorCount);
 
-    if (start == end && startRadius == 0) {
-        return CreateRadial(start, endRadius, colors, pos, colorCount, mode, mapper);
-    }
-
     return SkNEW_ARGS(Two_Point_Radial_Gradient,
                       (start, startRadius, end, endRadius, colors, pos,
                        colorCount, mode, mapper));
 }
 
 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
                                         const SkColor colors[],
                                         const SkScalar pos[],
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -208,17 +208,17 @@ static const char *gPrefLangNames[] = {
     "x-knda",
     "x-sinh",
     "x-tibt",
     "x-unicode",
     "x-user-def"
 };
 
 gfxPlatform::gfxPlatform()
-  : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
+  : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureCanvasBackendInfo)
 {
     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
 #ifdef MOZ_GRAPHITE
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
@@ -670,72 +670,76 @@ gfxPlatform::GetThebesSurfaceForDrawTarg
   surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
 
   return surf.forget();
 }
 
 RefPtr<DrawTarget>
 gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
 {
-  if (!SupportsAzureCanvas()) {
+  BackendType backend;
+  if (!SupportsAzureCanvas(backend)) {
     return NULL;
   }
 
   // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
   // create the best offscreen surface for the current system and situation. We
   // can easily take advantage of this for the Cairo backend, so that's what we
   // do.
   // mozilla::gfx::Factory can get away without having all this knowledge for
   // now, but this might need to change in the future (using
   // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
   // backends).
   if (aBackend == BACKEND_CAIRO) {
     nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(ThebesIntSize(aSize),
                                                         ContentForFormat(aFormat));
-    if (!surf || surf->CairoStatus()) {
+    if (!surf) {
       return NULL;
     }
 
     return CreateDrawTargetForSurface(surf, aSize);
   } else {
     return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
   }
 }
 
 RefPtr<DrawTarget>
 gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
 {
-  if (!SupportsAzureCanvas()) {
+  BackendType backend;
+  if (!SupportsAzureCanvas(backend)) {
     return NULL;
   }
 
-  RefPtr<DrawTarget> target = CreateDrawTargetForBackend(mPreferredCanvasBackend, aSize, aFormat);
+  RefPtr<DrawTarget> target = CreateDrawTargetForBackend(backend, aSize, aFormat);
   if (target ||
       mFallbackCanvasBackend == BACKEND_NONE) {
     return target;
   }
 
   return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
 }
 
 
 RefPtr<DrawTarget>
 gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
 {
-  if (!SupportsAzureCanvas()) {
+  BackendType backend;
+  if (!SupportsAzureCanvas(backend)) {
     return NULL;
   }
-  return Factory::CreateDrawTargetForData(mPreferredCanvasBackend, aData, aSize, aStride, aFormat);
+  return Factory::CreateDrawTargetForData(backend, aData, aSize, aStride, aFormat); 
 }
 
 bool
-gfxPlatform::SupportsAzureCanvas()
+gfxPlatform::SupportsAzureCanvas(BackendType& aBackend)
 {
   NS_ASSERTION(mFallbackCanvasBackend == BACKEND_NONE || mPreferredCanvasBackend != BACKEND_NONE,
                "fallback backend with no preferred backend");
+  aBackend = mPreferredCanvasBackend;
   return mPreferredCanvasBackend != BACKEND_NONE;
 }
 
 /* static */ BackendType
 gfxPlatform::BackendTypeForName(const nsCString& aName)
 {
   if (aName.EqualsLiteral("cairo"))
     return BACKEND_CAIRO;
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -190,26 +190,22 @@ public:
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateOffscreenDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize, 
                               int32_t aStride, mozilla::gfx::SurfaceFormat aFormat);
 
-    bool SupportsAzureCanvas();
+    // aBackend will be set to the preferred backend for Azure canvas
+    bool SupportsAzureCanvas(mozilla::gfx::BackendType& aBackend);
 
-    void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
-      aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
-      aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend));
-      aObj.DefineProperty("AzureContentBackend", GetBackendName(GetContentBackend()));
-    }
-
-    mozilla::gfx::BackendType GetPreferredCanvasBackend() {
-      return mPreferredCanvasBackend;
+    // aObj will contain the preferred backend for Azure canvas
+    void GetAzureCanvasBackendInfo(mozilla::widget::InfoObject &aObj) {
+      aObj.DefineProperty("AzureBackend", GetBackendName(mPreferredCanvasBackend));
     }
 
     /*
      * Font bits
      */
 
     virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
 
@@ -475,22 +471,17 @@ protected:
      * by the gfx.canvas.azure.backends pref.
      */
     void InitCanvasBackend(PRUint32 aBackendBitmask);
     /**
      * returns the first backend named in the pref gfx.canvas.azure.backends
      * which is a component of aBackendBitmask, a bitmask of backend types
      */
     static mozilla::gfx::BackendType GetCanvasBackendPref(PRUint32 aBackendBitmask);
-    static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
-
-    virtual mozilla::gfx::BackendType GetContentBackend()
-    {
-      return mozilla::gfx::BACKEND_NONE;
-    }
+    static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
 
     PRInt8  mAllowDownloadableFonts;
     PRInt8  mDownloadableFontsSanitize;
 #ifdef MOZ_GRAPHITE
     PRInt8  mGraphiteShapingEnabled;
 #endif
 
     PRInt8  mBidiNumeralOption;
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -740,20 +740,18 @@ gfxWindowsPlatform::CreateOffscreenSurfa
         surf = new gfxWindowsSurface(size, OptimalFormatForContent(contentType));
 #endif
 
 #ifdef CAIRO_HAS_D2D_SURFACE
     if (mRenderMode == RENDER_DIRECT2D)
         surf = new gfxD2DSurface(size, OptimalFormatForContent(contentType));
 #endif
 
-    if (surf == nullptr
-        || surf->CairoStatus()) {
+    if (surf == nullptr)
         surf = new gfxImageSurface(size, OptimalFormatForContent(contentType));
-    }
 
     NS_IF_ADDREF(surf);
 
     return surf;
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -237,23 +237,16 @@ public:
     cairo_device_t *GetD2DDevice() { return mD2DDevice; }
     ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; }
 #endif
 
     static bool IsOptimus();
     static bool IsRunningInWindows8Metro();
 
 protected:
-    virtual mozilla::gfx::BackendType GetContentBackend()
-    {
-      return UseAzureContentDrawing() && mRenderMode == RENDER_DIRECT2D ?
-               mozilla::gfx::BACKEND_DIRECT2D :
-               mozilla::gfx::BACKEND_NONE;
-    }
-
     RenderMode mRenderMode;
 
     PRInt8 mUseClearTypeForDownloadableFonts;
     PRInt8 mUseClearTypeAlways;
     HDC mScreenDC;
 
 private:
     void Init();
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1484,17 +1484,17 @@ random-if(!haveTestPlugin) == 546071-1.h
 == 550325-3.html 550325-1-ref.html
 == 550716-1.html 550716-1-ref.html
 == 551463-1.html 551463-1-ref.html
 == 551699-1.html 551699-1-ref.html
 == 552334-1.html 552334-1-ref.html
 # 553571 depends on MS Indic shaping behavior and Win7 font support;
 # not expected to be reliable on XP or non-Windows platforms
 random-if(!winWidget) random-if(/^Windows\x20NT\x205/.test(http.oscpu)) != 553571-1.html 553571-1-notref.html # expect dotted circle in test, not in ref
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,91) random-if(d2d) == 555388-1.html 555388-1-ref.html
+fuzzy-if(azureSkia,6,90) random-if(d2d) == 555388-1.html 555388-1-ref.html
 == 556661-1.html 556661-1-ref.html
 fails-if(Android) == 557087-1.html 557087-ref.html
 fails-if(Android) == 557087-2.html 557087-ref.html
 == 557736-1.html 557736-1-ref.html
 != 558011-1.xul 558011-1-ref.xul
 == 559284-1.html 559284-1-ref.html
 fails-if(Android) == 560455-1.xul 560455-1-ref.xul
 == 561981-1.html 561981-1-ref.html
--- a/layout/reftests/css-gradients/reftest.list
+++ b/layout/reftests/css-gradients/reftest.list
@@ -1,14 +1,14 @@
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,88500) fails-if(Android) == linear-1a.html linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,88500) == linear-1b.html linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,88500) fails-if(Android) == linear-keywords-1a.html linear-keywords-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,88500) fails-if(Android) == linear-keywords-1b.html linear-keywords-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,88500) fails-if(Android) == linear-percent.html linear-percent-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,92400) fails-if(Android) == linear-mix.html linear-mix-ref.html
+fuzzy-if(azureSkia,2,85500) fuzzy-if(azureQuartz,1,34919) fails-if(Android) == linear-1a.html linear-1-ref.html
+fuzzy-if(azureSkia,2,85500) fuzzy-if(azureQuartz,1,34919) fails-if(Android) == linear-1b.html linear-1-ref.html
+fuzzy-if(azureSkia,1,11332) fuzzy-if(azureQuartz,1,11483) fails-if(Android) == linear-keywords-1a.html linear-keywords-1-ref.html
+fuzzy-if(azureSkia,1,11332) fuzzy-if(azureQuartz,1,11483) fails-if(Android) == linear-keywords-1b.html linear-keywords-1-ref.html
+fuzzy-if(azureSkia,1,37500) fuzzy-if(azureQuartz,1,10230) fails-if(Android) == linear-percent.html linear-percent-ref.html
+fuzzy-if(azureSkia,1,4500) fuzzy-if(azureQuartz,1,17068) fails-if(Android) == linear-mix.html linear-mix-ref.html
 == linear-diagonal-1a.html linear-diagonal-1-ref.html
 == linear-diagonal-1b.html linear-diagonal-1-ref.html
 == linear-diagonal-1c.html linear-diagonal-1-ref.html
 == linear-diagonal-2a.html linear-diagonal-2-ref.html
 == linear-diagonal-2b.html linear-diagonal-2-ref.html
 == linear-diagonal-2c.html linear-diagonal-2-ref.html
 == linear-diagonal-3a.html linear-diagonal-3-ref.html
 == linear-diagonal-3b.html linear-diagonal-3-ref.html
@@ -31,36 +31,36 @@ fails-if(d2d) == linear-repeat-1f.html l
 fails-if(d2d) == linear-repeat-1g.html linear-repeat-1-ref.html # bug 582236
 == linear-size-1a.html linear-size-1-ref.html
 == linear-stops-1a.html linear-stops-1-ref.html
 == linear-stops-1b.html linear-stops-1-ref.html
 == linear-stops-1c.html linear-stops-1-ref.html
 == linear-stops-1d.html linear-stops-1-ref.html
 == linear-stops-1e.html linear-stops-1-ref.html
 == linear-stops-1f.html linear-stops-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1a.html linear-vertical-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1b.html linear-vertical-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1c.html linear-vertical-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1d.html linear-vertical-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1e.html linear-vertical-1-ref.html
+fuzzy-if(azureQuartz,1,9674) fails-if(Android) == linear-vertical-1a.html linear-vertical-1-ref.html
+fuzzy-if(azureQuartz,1,9674) fails-if(Android) == linear-vertical-1b.html linear-vertical-1-ref.html
+fuzzy-if(azureQuartz,1,9674) fails-if(Android) == linear-vertical-1c.html linear-vertical-1-ref.html
+fuzzy-if(azureQuartz,1,9674) fails-if(Android) == linear-vertical-1d.html linear-vertical-1-ref.html
+fuzzy-if(azureQuartz,1,9674) fails-if(Android) == linear-vertical-1e.html linear-vertical-1-ref.html
 == linear-viewport.html linear-viewport-ref.html
 == linear-zero-length-1a.html linear-zero-length-1-ref.html
 == linear-zero-length-1b.html linear-zero-length-1-ref.html
 == linear-zero-length-1c.html linear-zero-length-1-ref.html
 == nostops.html about:blank
 == onestop.html about:blank
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fails-if(Android) random-if(d2d) == radial-1a.html radial-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fails-if(Android) random-if(d2d) == radial-1b.html radial-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fails-if(Android) random-if(d2d) == radial-1c.html radial-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,3,7860) fails-if(Android) == radial-2a.html radial-2-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,3,7860) fails-if(Android) == radial-2b.html radial-2-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,3,7860) fails-if(Android) == radial-2c.html radial-2-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,3,7860) fails-if(Android) == radial-2d.html radial-2-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,3,7860) fails-if(Android) == radial-2e.html radial-2-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,3,7860) fails-if(Android) == radial-2f.html radial-2-ref.html
+fuzzy-if(azureSkia,1,5884) fuzzy-if(azureQuartz,1,1997) fails-if(Android) random-if(d2d) == radial-1a.html radial-1-ref.html
+fuzzy-if(azureSkia,1,5884) fuzzy-if(azureQuartz,1,1997) fails-if(Android) random-if(d2d) == radial-1b.html radial-1-ref.html
+fuzzy-if(azureSkia,1,5884) fuzzy-if(azureQuartz,1,1997) fails-if(Android) random-if(d2d) == radial-1c.html radial-1-ref.html
+fuzzy-if(azureSkia,1,7860) fuzzy-if(azureQuartz,1,1926) fails-if(Android) == radial-2a.html radial-2-ref.html
+fuzzy-if(azureSkia,1,7860) fuzzy-if(azureQuartz,1,1926) fails-if(Android) == radial-2b.html radial-2-ref.html
+fuzzy-if(azureSkia,1,7860) fuzzy-if(azureQuartz,1,1926) fails-if(Android) == radial-2c.html radial-2-ref.html
+fuzzy-if(azureSkia,1,7860) fuzzy-if(azureQuartz,1,1926) fails-if(Android) == radial-2d.html radial-2-ref.html
+fuzzy-if(azureSkia,1,7860) fuzzy-if(azureQuartz,1,1926) fails-if(Android) == radial-2e.html radial-2-ref.html
+fuzzy-if(azureSkia,1,7860) fuzzy-if(azureQuartz,1,1926) fails-if(Android) == radial-2f.html radial-2-ref.html
 == radial-position-1a.html radial-position-1-ref.html
 == radial-position-1b.html radial-position-1-ref.html
 == radial-shape-closest-corner-1a.html radial-shape-closest-corner-1-ref.html
 == radial-shape-closest-corner-1b.html radial-shape-closest-corner-1-ref.html
 == radial-shape-closest-corner-1c.html radial-shape-closest-corner-1-ref.html
 fuzzy-if(Android,17,3880) == radial-shape-closest-side-1a.html radial-shape-closest-side-1-ref.html
 fuzzy-if(Android,17,3880) == radial-shape-closest-side-1b.html radial-shape-closest-side-1-ref.html
 fuzzy-if(Android,17,3880) == radial-shape-closest-side-1c.html radial-shape-closest-side-1-ref.html
@@ -97,33 +97,33 @@ fails-if(d2d) == repeating-linear-1b.htm
 == twostops-1b.html twostops-1-ref.html
 fails-if(/Mac\x20OS\x20X\x2010\.[56]/.test(http.oscpu)) == twostops-1c.html twostops-1-ref.html # bug 524173
 == twostops-1d.html twostops-1-ref.html
 == twostops-1e.html twostops-1-ref.html
 == twostops-1f.html twostops-1-ref.html
 == twostops-1g.html twostops-1-ref.html
 
 # from http://www.xanthir.com/:4bhipd by way of http://a-ja.net/newgrad.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-1a.html aja-linear-1-ref.html
+fuzzy-if(azureSkia,1,19900) fuzzy-if(azureQuartz,1,4646) fails-if(Android) == aja-linear-1a.html aja-linear-1-ref.html
 fails-if(!d2d) == aja-linear-1b.html aja-linear-1-ref.html # bug 526694
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-1c.html aja-linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-1d.html aja-linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-1e.html aja-linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-1f.html aja-linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-1g.html aja-linear-1-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-2a.html aja-linear-2-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,20000) fails-if(Android) == aja-linear-2b.html aja-linear-2-ref.html
+fuzzy-if(azureSkia,1,19900) fuzzy-if(azureQuartz,1,4646) fails-if(Android) == aja-linear-1c.html aja-linear-1-ref.html
+fuzzy-if(azureSkia,1,19900) fuzzy-if(azureQuartz,1,4646) fails-if(Android) == aja-linear-1d.html aja-linear-1-ref.html
+fuzzy-if(azureSkia,1,19900) fuzzy-if(azureQuartz,1,4646) fails-if(Android) == aja-linear-1e.html aja-linear-1-ref.html
+fuzzy-if(azureSkia,1,19900) fuzzy-if(azureQuartz,1,4646) fails-if(Android) == aja-linear-1f.html aja-linear-1-ref.html
+fuzzy-if(azureSkia,1,19900) fuzzy-if(azureQuartz,1,4646) fails-if(Android) == aja-linear-1g.html aja-linear-1-ref.html
+fuzzy-if(azureSkia,1,19999) fuzzy-if(azureQuartz,1,4675) fails-if(Android) == aja-linear-2a.html aja-linear-2-ref.html
+fuzzy-if(azureSkia,1,19999) fuzzy-if(azureQuartz,1,4675) fails-if(Android) == aja-linear-2b.html aja-linear-2-ref.html
 fails == aja-linear-2c.html aja-linear-2-ref.html # bug 522607
 fails-if(!d2d) == aja-linear-2d.html aja-linear-2-ref.html # bug 526694
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,19999) fails-if(Android) == aja-linear-3a.html aja-linear-3-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,1,19999) fails-if(Android) == aja-linear-3b.html aja-linear-3-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,20000) fails-if(Android) == aja-linear-4a.html aja-linear-4-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,20000) fails-if(Android) == aja-linear-4b.html aja-linear-4-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,20000) fails-if(Android) == aja-linear-5a.html aja-linear-5-ref.html
-fuzzy-if(!contentSameGfxBackendAsCanvas,2,16477) fails-if(Android) fails-if(/Mac\x20OS\x20X\x2010\.5/.test(http.oscpu)) == aja-linear-6a.html aja-linear-6-ref.html # bug 526708
+fuzzy-if(azureSkia,1,19999) fuzzy-if(azureQuartz,1,4900) fails-if(Android) == aja-linear-3a.html aja-linear-3-ref.html
+fuzzy-if(azureSkia,1,19999) fuzzy-if(azureQuartz,1,4900) fails-if(Android) == aja-linear-3b.html aja-linear-3-ref.html
+fuzzy-if(azureSkia,2,20000) fuzzy-if(azureQuartz,1,8655) fails-if(Android) == aja-linear-4a.html aja-linear-4-ref.html
+fuzzy-if(azureSkia,2,20000) fuzzy-if(azureQuartz,1,8655) fails-if(Android) == aja-linear-4b.html aja-linear-4-ref.html
+fuzzy-if(azureSkia,4,19900) fuzzy-if(azureQuartz,2,7878) fails-if(Android) == aja-linear-5a.html aja-linear-5-ref.html
+fuzzy-if(azureSkia,2,16477) fuzzy-if(azureQuartz,1,3910) fails-if(Android) fails-if(/Mac\x20OS\x20X\x2010\.5/.test(http.oscpu)) == aja-linear-6a.html aja-linear-6-ref.html # bug 526708
 fails == aja-linear-6b.html aja-linear-6-ref.html # bug 522607
 == height-dependence-1.html height-dependence-1-ref.html
 fails-if(cocoaWidget) == height-dependence-2.html height-dependence-2-ref.html # bug 535007
 == height-dependence-3.html height-dependence-3-ref.html
 
 fails-if(d2d) == linear-onestopposition-1.html linear-onestopposition-1-ref.html # bug 638664
 == linear-onestopposition-1.html linear-onestopposition-1-ref2.html
 fails-if(d2d) fails-if(cocoaWidget) == radial-onestopposition-1a.html radial-onestopposition-1-ref.html # bug 638664
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -174,17 +174,17 @@ fails == inline-in-xul-basic-01.xul pass
 == mask-basic-01.svg pass.svg
 == mask-basic-02.svg mask-basic-02-ref.svg
 == mask-extref-dataURI-01.svg pass.svg
 == mask-containing-masked-content-01.svg pass.svg
 == mask-transformed-01.svg mask-transformed-01-ref.svg
 == nested-viewBox-01.svg pass.svg
 == nesting-invalid-01.svg nesting-invalid-01-ref.svg
 == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg 
-fuzzy-if(Android,9,61) fuzzy-if(!contentSameGfxBackendAsCanvas,1,99) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg 
+fuzzy-if(Android,9,61) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg 
 == objectBoundingBox-and-clipPath.svg pass.svg
 # Bug 588684
 random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-01.svg objectBoundingBox-and-fePointLight-01-ref.svg
 random-if(gtk2Widget) == objectBoundingBox-and-fePointLight-02.svg objectBoundingBox-and-fePointLight-02-ref.svg
 == objectBoundingBox-and-mask.svg pass.svg
 == objectBoundingBox-and-mask-02.svg pass.svg
 == objectBoundingBox-and-pattern-01a.svg objectBoundingBox-and-pattern-01-ref.svg
 == objectBoundingBox-and-pattern-01b.svg objectBoundingBox-and-pattern-01-ref.svg
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -481,23 +481,18 @@ function BuildConditionSandbox(aURL) {
  
     
     var gfxInfo = (NS_GFXINFO_CONTRACTID in CC) && CC[NS_GFXINFO_CONTRACTID].getService(CI.nsIGfxInfo);
     try {
       sandbox.d2d = gfxInfo.D2DEnabled;
     } catch (e) {
       sandbox.d2d = false;
     }
-
-    var info = gfxInfo.getInfo();
-    sandbox.azureQuartz = info.AzureCanvasBackend == "quartz";
-    sandbox.azureSkia = info.AzureCanvasBackend == "skia";
-    // true if we are using the same Azure backend for rendering canvas and content
-    sandbox.contentSameGfxBackendAsCanvas = info.AzureContentBackend == info.AzureCanvasBackend
-                                            || (info.AzureContentBackend == "none" && info.AzureCanvasBackend == "cairo");
+    sandbox.azureQuartz = gfxInfo.getInfo().AzureBackend == "quartz";
+    sandbox.azureSkia = gfxInfo.getInfo().AzureBackend == "skia";
 
     sandbox.layersGPUAccelerated =
       gWindowUtils.layerManagerType != "Basic";
     sandbox.layersOpenGL =
       gWindowUtils.layerManagerType == "OpenGL";
 
     // Shortcuts for widget toolkits.
     sandbox.Android = xr.OS == "Android";