Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / gradients / SkTwoPointConicalGradient.cpp
index 434339c..574df08 100644 (file)
@@ -7,6 +7,20 @@
 
 #include "SkTwoPointConicalGradient.h"
 
+#include "SkTwoPointConicalGradient_gpu.h"
+
+struct TwoPtRadialContext {
+    const TwoPtRadial&  fRec;
+    float               fRelX, fRelY;
+    const float         fIncX, fIncY;
+    float               fB;
+    const float         fDB;
+
+    TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
+                       SkScalar dfx, SkScalar dfy);
+    SkFixed nextT();
+};
+
 static int valid_divide(float numer, float denom, float* ratio) {
     SkASSERT(ratio);
     if (0 == denom) {
@@ -18,7 +32,7 @@ static int valid_divide(float numer, float denom, float* ratio) {
 
 // Return the number of distinct real roots, and write them into roots[] in
 // ascending order
-static int find_quad_roots(float A, float B, float C, float roots[2]) {
+static int find_quad_roots(float A, float B, float C, float roots[2], bool descendingOrder = false) {
     SkASSERT(roots);
 
     if (A == 0) {
@@ -52,6 +66,9 @@ static int find_quad_roots(float A, float B, float C, float roots[2]) {
     float r1 = C / Q;
     roots[0] = r0 < r1 ? r0 : r1;
     roots[1] = r0 > r1 ? r0 : r1;
+    if (descendingOrder) {
+        SkTSwap(roots[0], roots[1]);
+    }
     return 2;
 }
 
@@ -62,7 +79,8 @@ static float lerp(float x, float dx, float t) {
 static float sqr(float x) { return x * x; }
 
 void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
-                       const SkPoint& center1, SkScalar rad1) {
+                       const SkPoint& center1, SkScalar rad1,
+                       bool flipped) {
     fCenterX = SkScalarToFloat(center0.fX);
     fCenterY = SkScalarToFloat(center0.fY);
     fDCenterX = SkScalarToFloat(center1.fX) - fCenterX;
@@ -73,49 +91,52 @@ void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
     fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
     fRadius2 = sqr(fRadius);
     fRDR = fRadius * fDRadius;
-}
 
-void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) {
-    fRelX = SkScalarToFloat(fx) - fCenterX;
-    fRelY = SkScalarToFloat(fy) - fCenterY;
-    fIncX = SkScalarToFloat(dfx);
-    fIncY = SkScalarToFloat(dfy);
-    fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR);
-    fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY);
+    fFlipped = flipped;
 }
 
-SkFixed TwoPtRadial::nextT() {
+TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
+                                       SkScalar dfx, SkScalar dfy)
+    : fRec(rec)
+    , fRelX(SkScalarToFloat(fx) - rec.fCenterX)
+    , fRelY(SkScalarToFloat(fy) - rec.fCenterY)
+    , fIncX(SkScalarToFloat(dfx))
+    , fIncY(SkScalarToFloat(dfy))
+    , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR))
+    , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {}
+
+SkFixed TwoPtRadialContext::nextT() {
     float roots[2];
 
-    float C = sqr(fRelX) + sqr(fRelY) - fRadius2;
-    int countRoots = find_quad_roots(fA, fB, C, roots);
+    float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2;
+    int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped);
 
     fRelX += fIncX;
     fRelY += fIncY;
     fB += fDB;
 
     if (0 == countRoots) {
-        return kDontDrawT;
+        return TwoPtRadial::kDontDrawT;
     }
 
     // Prefer the bigger t value if both give a radius(t) > 0
     // find_quad_roots returns the values sorted, so we start with the last
     float t = roots[countRoots - 1];
-    float r = lerp(fRadius, fDRadius, t);
+    float r = lerp(fRec.fRadius, fRec.fDRadius, t);
     if (r <= 0) {
         t = roots[0];   // might be the same as roots[countRoots-1]
-        r = lerp(fRadius, fDRadius, t);
+        r = lerp(fRec.fRadius, fRec.fDRadius, t);
         if (r <= 0) {
-            return kDontDrawT;
+            return TwoPtRadial::kDontDrawT;
         }
     }
     return SkFloatToFixed(t);
 }
 
-typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC,
+typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,
                                     const SkPMColor* cache, int toggle, int count);
 
-static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
                            const SkPMColor* SK_RESTRICT cache, int toggle,
                            int count) {
     for (; count > 0; --count) {
@@ -132,7 +153,7 @@ static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
     }
 }
 
-static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
                             const SkPMColor* SK_RESTRICT cache, int toggle,
                             int count) {
     for (; count > 0; --count) {
@@ -149,7 +170,7 @@ static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
     }
 }
 
-static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
                             const SkPMColor* SK_RESTRICT cache, int toggle,
                             int count) {
     for (; count > 0; --count) {
@@ -167,7 +188,7 @@ static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
 }
 
 void SkTwoPointConicalGradient::init() {
-    fRec.init(fCenter1, fRadius1, fCenter2, fRadius2);
+    fRec.init(fCenter1, fRadius1, fCenter2, fRadius2, fFlippedGrad);
     fPtsToUnit.reset();
 }
 
@@ -176,12 +197,14 @@ void SkTwoPointConicalGradient::init() {
 SkTwoPointConicalGradient::SkTwoPointConicalGradient(
         const SkPoint& start, SkScalar startRadius,
         const SkPoint& end, SkScalar endRadius,
-        const Descriptor& desc)
-    : SkGradientShaderBase(desc),
+        bool flippedGrad, const Descriptor& desc,
+        const SkMatrix* localMatrix)
+    : SkGradientShaderBase(desc, localMatrix),
     fCenter1(start),
     fCenter2(end),
     fRadius1(startRadius),
-    fRadius2(endRadius) {
+    fRadius2(endRadius),
+    fFlippedGrad(flippedGrad) {
     // this is degenerate, and should be caught by our caller
     SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2);
     this->init();
@@ -194,8 +217,32 @@ bool SkTwoPointConicalGradient::isOpaque() const {
     return false;
 }
 
-void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
-                                          int count) {
+size_t SkTwoPointConicalGradient::contextSize() const {
+    return sizeof(TwoPointConicalGradientContext);
+}
+
+SkShader::Context* SkTwoPointConicalGradient::onCreateContext(const ContextRec& rec,
+                                                              void* storage) const {
+    return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, (*this, rec));
+}
+
+SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext(
+        const SkTwoPointConicalGradient& shader, const ContextRec& rec)
+    : INHERITED(shader, rec)
+{
+    // we don't have a span16 proc
+    fFlags &= ~kHasSpan16_Flag;
+
+    // in general, we might discard based on computed-radius, so clear
+    // this flag (todo: sometimes we can detect that we never discard...)
+    fFlags &= ~kOpaqueAlpha_Flag;
+}
+
+void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan(
+        int x, int y, SkPMColor* dstCParam, int count) {
+    const SkTwoPointConicalGradient& twoPointConicalGradient =
+            static_cast<const SkTwoPointConicalGradient&>(fShader);
+
     int toggle = init_dither_toggle(x, y);
 
     SkASSERT(count > 0);
@@ -204,15 +251,15 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
 
     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
 
-    const SkPMColor* SK_RESTRICT cache = this->getCache32();
+    const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
 
     TwoPointConicalProc shadeProc = twopoint_repeat;
-    if (SkShader::kClamp_TileMode == fTileMode) {
+    if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) {
         shadeProc = twopoint_clamp;
-    } else if (SkShader::kMirror_TileMode == fTileMode) {
+    } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) {
         shadeProc = twopoint_mirror;
     } else {
-        SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+        SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode);
     }
 
     if (fDstToIndexClass != kPerspective_MatrixClass) {
@@ -233,16 +280,16 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
             dy = fDstToIndex.getSkewY();
         }
 
-        fRec.setup(fx, fy, dx, dy);
-        (*shadeProc)(&fRec, dstC, cache, toggle, count);
+        TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy);
+        (*shadeProc)(&rec, dstC, cache, toggle, count);
     } else {    // perspective case
         SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf;
         SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf;
         for (; count > 0; --count) {
             SkPoint srcPt;
             dstProc(fDstToIndex, dstX, dstY, &srcPt);
-            fRec.setup(srcPt.fX, srcPt.fY, 0, 0);
-            (*shadeProc)(&fRec, dstC, cache, toggle, 1);
+            TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt.fY, 0, 0);
+            (*shadeProc)(&rec, dstC, cache, toggle, 1);
 
             dstX += SK_Scalar1;
             toggle = next_dither_toggle(toggle);
@@ -251,23 +298,6 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
     }
 }
 
-bool SkTwoPointConicalGradient::setContext(const SkBitmap& device,
-                                           const SkPaint& paint,
-                                           const SkMatrix& matrix) {
-    if (!this->INHERITED::setContext(device, paint, matrix)) {
-        return false;
-    }
-
-    // we don't have a span16 proc
-    fFlags &= ~kHasSpan16_Flag;
-
-    // in general, we might discard based on computed-radius, so clear
-    // this flag (todo: sometimes we can detect that we never discard...)
-    fFlags &= ~kOpaqueAlpha_Flag;
-
-    return true;
-}
-
 SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
     SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const {
     SkPoint diff = fCenter2 - fCenter1;
@@ -297,14 +327,19 @@ SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
     return kTwoPointConical_BitmapType;
 }
 
+// Returns the original non-sorted version of the gradient
 SkShader::GradientType SkTwoPointConicalGradient::asAGradient(
     GradientInfo* info) const {
     if (info) {
-        commonAsAGradient(info);
+        commonAsAGradient(info, fFlippedGrad);
         info->fPoint[0] = fCenter1;
         info->fPoint[1] = fCenter2;
         info->fRadius[0] = fRadius1;
         info->fRadius[1] = fRadius2;
+        if (fFlippedGrad) {
+            SkTSwap(info->fPoint[0], info->fPoint[1]);
+            SkTSwap(info->fRadius[0], info->fRadius[1]);
+        }
     }
     return kConical_GradientType;
 }
@@ -316,6 +351,20 @@ SkTwoPointConicalGradient::SkTwoPointConicalGradient(
     fCenter2(buffer.readPoint()),
     fRadius1(buffer.readScalar()),
     fRadius2(buffer.readScalar()) {
+    if (buffer.pictureVersion() >= 24 || 0 == buffer.pictureVersion()) {
+        fFlippedGrad = buffer.readBool();
+    } else {
+        // V23_COMPATIBILITY_CODE
+        // Sort gradient by radius size for old pictures
+        if (fRadius2 < fRadius1) {
+            SkTSwap(fCenter1, fCenter2);
+            SkTSwap(fRadius1, fRadius2);
+            this->flipGradientColors();
+            fFlippedGrad = true;
+        } else {
+            fFlippedGrad = false;
+        }
+    }
     this->init();
 };
 
@@ -326,379 +375,16 @@ void SkTwoPointConicalGradient::flatten(
     buffer.writePoint(fCenter2);
     buffer.writeScalar(fRadius1);
     buffer.writeScalar(fRadius2);
+    buffer.writeBool(fFlippedGrad);
 }
 
-/////////////////////////////////////////////////////////////////////
-
 #if SK_SUPPORT_GPU
 
-#include "GrTBackendEffectFactory.h"
-
-// For brevity
-typedef GrGLUniformManager::UniformHandle UniformHandle;
-
-class GrGLConical2Gradient : public GrGLGradientEffect {
-public:
-
-    GrGLConical2Gradient(const GrBackendEffectFactory& factory, const GrDrawEffect&);
-    virtual ~GrGLConical2Gradient() { }
-
-    virtual void emitCode(GrGLShaderBuilder*,
-                          const GrDrawEffect&,
-                          EffectKey,
-                          const char* outputColor,
-                          const char* inputColor,
-                          const TransformedCoordsArray&,
-                          const TextureSamplerArray&) SK_OVERRIDE;
-    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
-
-    static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
-
-protected:
-
-    UniformHandle fParamUni;
-
-    const char* fVSVaryingName;
-    const char* fFSVaryingName;
-
-    bool fIsDegenerate;
-
-    // @{
-    /// Values last uploaded as uniforms
-
-    SkScalar fCachedCenter;
-    SkScalar fCachedRadius;
-    SkScalar fCachedDiffRadius;
-
-    // @}
-
-private:
-
-    typedef GrGLGradientEffect INHERITED;
-
-};
-
-/////////////////////////////////////////////////////////////////////
-
-class GrConical2Gradient : public GrGradientEffect {
-public:
-
-    static GrEffectRef* Create(GrContext* ctx,
-                               const SkTwoPointConicalGradient& shader,
-                               const SkMatrix& matrix,
-                               SkShader::TileMode tm) {
-        AutoEffectUnref effect(SkNEW_ARGS(GrConical2Gradient, (ctx, shader, matrix, tm)));
-        return CreateEffectRef(effect);
-    }
-
-    virtual ~GrConical2Gradient() { }
-
-    static const char* Name() { return "Two-Point Conical Gradient"; }
-    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
-        return GrTBackendEffectFactory<GrConical2Gradient>::getInstance();
-    }
-
-    // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
-    bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(fCenterX1); }
-    SkScalar center() const { return fCenterX1; }
-    SkScalar diffRadius() const { return fDiffRadius; }
-    SkScalar radius() const { return fRadius0; }
-
-    typedef GrGLConical2Gradient GLEffect;
-
-private:
-    virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
-        const GrConical2Gradient& s = CastEffect<GrConical2Gradient>(sBase);
-        return (INHERITED::onIsEqual(sBase) &&
-                this->fCenterX1 == s.fCenterX1 &&
-                this->fRadius0 == s.fRadius0 &&
-                this->fDiffRadius == s.fDiffRadius);
-    }
-
-    GrConical2Gradient(GrContext* ctx,
-                       const SkTwoPointConicalGradient& shader,
-                       const SkMatrix& matrix,
-                       SkShader::TileMode tm)
-        : INHERITED(ctx, shader, matrix, tm)
-        , fCenterX1(shader.getCenterX1())
-        , fRadius0(shader.getStartRadius())
-        , fDiffRadius(shader.getDiffRadius()) {
-        // We pass the linear part of the quadratic as a varying.
-        //    float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
-        fBTransform = this->getCoordTransform();
-        SkMatrix& bMatrix = *fBTransform.accessMatrix();
-        SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius);
-        bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) +
-                                            SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0]));
-        bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) +
-                                           SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1]));
-        bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) +
-                                            SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2]));
-        this->addCoordTransform(&fBTransform);
-    }
-
-    GR_DECLARE_EFFECT_TEST;
-
-    // @{
-    // Cache of values - these can change arbitrarily, EXCEPT
-    // we shouldn't change between degenerate and non-degenerate?!
-
-    GrCoordTransform fBTransform;
-    SkScalar         fCenterX1;
-    SkScalar         fRadius0;
-    SkScalar         fDiffRadius;
-
-    // @}
-
-    typedef GrGradientEffect INHERITED;
-};
-
-GR_DEFINE_EFFECT_TEST(GrConical2Gradient);
-
-GrEffectRef* GrConical2Gradient::TestCreate(SkRandom* random,
-                                            GrContext* context,
-                                            const GrDrawTargetCaps&,
-                                            GrTexture**) {
-    SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
-    SkScalar radius1 = random->nextUScalar1();
-    SkPoint center2;
-    SkScalar radius2;
-    do {
-        center2.set(random->nextUScalar1(), random->nextUScalar1());
-        radius2 = random->nextUScalar1 ();
-        // If the circles are identical the factory will give us an empty shader.
-    } while (radius1 == radius2 && center1 == center2);
-
-    SkColor colors[kMaxRandomGradientColors];
-    SkScalar stopsArray[kMaxRandomGradientColors];
-    SkScalar* stops = stopsArray;
-    SkShader::TileMode tm;
-    int colorCount = RandomGradientParams(random, colors, &stops, &tm);
-    SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
-                                                                          center2, radius2,
-                                                                          colors, stops, colorCount,
-                                                                          tm));
-    SkPaint paint;
-    return shader->asNewEffect(context, paint);
-}
-
-
-/////////////////////////////////////////////////////////////////////
-
-GrGLConical2Gradient::GrGLConical2Gradient(const GrBackendEffectFactory& factory,
-                                           const GrDrawEffect& drawEffect)
-    : INHERITED(factory)
-    , fVSVaryingName(NULL)
-    , fFSVaryingName(NULL)
-    , fCachedCenter(SK_ScalarMax)
-    , fCachedRadius(-SK_ScalarMax)
-    , fCachedDiffRadius(-SK_ScalarMax) {
-
-    const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>();
-    fIsDegenerate = data.isDegenerate();
-}
-
-void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
-                                    const GrDrawEffect&,
-                                    EffectKey key,
-                                    const char* outputColor,
-                                    const char* inputColor,
-                                    const TransformedCoordsArray& coords,
-                                    const TextureSamplerArray& samplers) {
-    this->emitUniforms(builder, key);
-    fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
-                                         kFloat_GrSLType, "Conical2FSParams", 6);
-
-    SkString cName("c");
-    SkString ac4Name("ac4");
-    SkString dName("d");
-    SkString qName("q");
-    SkString r0Name("r0");
-    SkString r1Name("r1");
-    SkString tName("t");
-    SkString p0; // 4a
-    SkString p1; // 1/a
-    SkString p2; // distance between centers
-    SkString p3; // start radius
-    SkString p4; // start radius squared
-    SkString p5; // difference in radii (r1 - r0)
-
-    builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4);
-    builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5);
-
-    // We interpolate the linear component in coords[1].
-    SkASSERT(coords[0].type() == coords[1].type());
-    const char* coords2D;
-    SkString bVar;
-    if (kVec3f_GrSLType == coords[0].type()) {
-        builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n",
-                               coords[0].c_str(), coords[1].c_str(), coords[0].c_str());
-        coords2D = "interpolants.xy";
-        bVar = "interpolants.z";
-    } else {
-        coords2D = coords[0].c_str();
-        bVar.printf("%s.x", coords[1].c_str());
-    }
-
-    // output will default to transparent black (we simply won't write anything
-    // else to it if invalid, instead of discarding or returning prematurely)
-    builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
-
-    // c = (x^2)+(y^2) - params[4]
-    builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
-                           cName.c_str(), coords2D, coords2D, p4.c_str());
-
-    // Non-degenerate case (quadratic)
-    if (!fIsDegenerate) {
-
-        // ac4 = params[0] * c
-        builder->fsCodeAppendf("\tfloat %s = %s * %s;\n", ac4Name.c_str(), p0.c_str(),
-                               cName.c_str());
-
-        // d = b^2 - ac4
-        builder->fsCodeAppendf("\tfloat %s = %s * %s - %s;\n", dName.c_str(),
-                               bVar.c_str(), bVar.c_str(), ac4Name.c_str());
-
-        // only proceed if discriminant is >= 0
-        builder->fsCodeAppendf("\tif (%s >= 0.0) {\n", dName.c_str());
-
-        // intermediate value we'll use to compute the roots
-        // q = -0.5 * (b +/- sqrt(d))
-        builder->fsCodeAppendf("\t\tfloat %s = -0.5 * (%s + (%s < 0.0 ? -1.0 : 1.0)"
-                               " * sqrt(%s));\n", qName.c_str(), bVar.c_str(),
-                               bVar.c_str(), dName.c_str());
-
-        // compute both roots
-        // r0 = q * params[1]
-        builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(),
-                               qName.c_str(), p1.c_str());
-        // r1 = c / q
-        builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(),
-                               cName.c_str(), qName.c_str());
-
-        // Note: If there are two roots that both generate radius(t) > 0, the
-        // Canvas spec says to choose the larger t.
-
-        // so we'll look at the larger one first:
-        builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(),
-                               r0Name.c_str(), r1Name.c_str());
-
-        // if r(t) > 0, then we're done; t will be our x coordinate
-        builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
-                               p5.c_str(), p3.c_str());
-
-        builder->fsCodeAppend("\t\t");
-        this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
-
-        // otherwise, if r(t) for the larger root was <= 0, try the other root
-        builder->fsCodeAppend("\t\t} else {\n");
-        builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(),
-                               r0Name.c_str(), r1Name.c_str());
-
-        // if r(t) > 0 for the smaller root, then t will be our x coordinate
-        builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n",
-                               tName.c_str(), p5.c_str(), p3.c_str());
-
-        builder->fsCodeAppend("\t\t\t");
-        this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
-
-        // end if (r(t) > 0) for smaller root
-        builder->fsCodeAppend("\t\t\t}\n");
-        // end if (r(t) > 0), else, for larger root
-        builder->fsCodeAppend("\t\t}\n");
-        // end if (discriminant >= 0)
-        builder->fsCodeAppend("\t}\n");
-    } else {
-
-        // linear case: t = -c/b
-        builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
-                               cName.c_str(), bVar.c_str());
-
-        // if r(t) > 0, then t will be the x coordinate
-        builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
-                               p5.c_str(), p3.c_str());
-        builder->fsCodeAppend("\t");
-        this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
-        builder->fsCodeAppend("\t}\n");
-    }
-}
-
-void GrGLConical2Gradient::setData(const GrGLUniformManager& uman,
-                                   const GrDrawEffect& drawEffect) {
-    INHERITED::setData(uman, drawEffect);
-    const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>();
-    SkASSERT(data.isDegenerate() == fIsDegenerate);
-    SkScalar centerX1 = data.center();
-    SkScalar radius0 = data.radius();
-    SkScalar diffRadius = data.diffRadius();
-
-    if (fCachedCenter != centerX1 ||
-        fCachedRadius != radius0 ||
-        fCachedDiffRadius != diffRadius) {
-
-        SkScalar a = SkScalarMul(centerX1, centerX1) - diffRadius * diffRadius;
-
-        // When we're in the degenerate (linear) case, the second
-        // value will be INF but the program doesn't read it. (We
-        // use the same 6 uniforms even though we don't need them
-        // all in the linear case just to keep the code complexity
-        // down).
-        float values[6] = {
-            SkScalarToFloat(a * 4),
-            1.f / (SkScalarToFloat(a)),
-            SkScalarToFloat(centerX1),
-            SkScalarToFloat(radius0),
-            SkScalarToFloat(SkScalarMul(radius0, radius0)),
-            SkScalarToFloat(diffRadius)
-        };
-
-        uman.set1fv(fParamUni, 6, values);
-        fCachedCenter = centerX1;
-        fCachedRadius = radius0;
-        fCachedDiffRadius = diffRadius;
-    }
-}
-
-GrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrDrawEffect& drawEffect,
-                                                   const GrGLCaps&) {
-    enum {
-        kIsDegenerate = 1 << kBaseKeyBitCnt,
-    };
-
-    EffectKey key = GenBaseGradientKey(drawEffect);
-    if (drawEffect.castEffect<GrConical2Gradient>().isDegenerate()) {
-        key |= kIsDegenerate;
-    }
-    return key;
-}
-
-/////////////////////////////////////////////////////////////////////
-
 GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint&) const {
     SkASSERT(NULL != context);
     SkASSERT(fPtsToUnit.isIdentity());
-    // invert the localM, translate to center1, rotate so center2 is on x axis.
-    SkMatrix matrix;
-    if (!this->getLocalMatrix().invert(&matrix)) {
-        return NULL;
-    }
-    matrix.postTranslate(-fCenter1.fX, -fCenter1.fY);
-
-    SkPoint diff = fCenter2 - fCenter1;
-    SkScalar diffLen = diff.length();
-    if (0 != diffLen) {
-        SkScalar invDiffLen = SkScalarInvert(diffLen);
-        SkMatrix rot;
-        rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY),
-                       SkScalarMul(invDiffLen, diff.fX));
-        matrix.postConcat(rot);
-    }
 
-    return GrConical2Gradient::Create(context, *this, matrix, fTileMode);
+    return Gr2PtConicalGradientEffect::Create(context, *this, fTileMode);
 }
 
 #else