Added asNewCustomStage to SkShader and implemented it for all the gradient shaders.

Not actually hooked up yet, but it should be ready to replace asABitmap for a future CL.
Review URL: https://codereview.appspot.com/6351113

git-svn-id: http://skia.googlecode.com/svn/trunk@4702 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrGradientEffects.cpp b/src/gpu/effects/GrGradientEffects.cpp
index ec465b8..2faeec0 100644
--- a/src/gpu/effects/GrGradientEffects.cpp
+++ b/src/gpu/effects/GrGradientEffects.cpp
@@ -8,6 +8,7 @@
 #include "GrGradientEffects.h"
 #include "gl/GrGLProgramStage.h"
 #include "GrProgramStageFactory.h"
+#include "SkGr.h"
 
 // Base class for GL gradient custom stages
 class GrGLGradientStage : public GrGLProgramStage {
@@ -50,10 +51,37 @@
     SkSafeRef(fTexture);
 }
 
+GrGradientEffect::GrGradientEffect(GrContext* ctx, const SkShader& shader)
+                                   : fTexture (NULL)
+                                   , fUseTexture (false) {
+    // TODO: check for simple cases where we don't need a texture:
+    //GradientInfo info;
+    //shader.asAGradient(&info);
+    //if (info.fColorCount == 2) { ...
+
+    SkBitmap bitmap;
+    shader.asABitmap(&bitmap, NULL, NULL, NULL);
+
+    // Note: we just construct a default sampler state here, which isn't great,
+    // however, as long as the bitmap has power-of-two dimensions, which should
+    // be the case for gradient bitmaps, it should be fine
+    GrAssert(SkIsPow2(bitmap.width()) && SkIsPow2(bitmap.height()));
+    GrSamplerState sampler;
+
+    GrContext::TextureCacheEntry entry = GrLockCachedBitmapTexture(ctx, bitmap,
+                                                                   &sampler);
+    fTexture = entry.texture();
+    SkSafeRef(fTexture);
+    fUseTexture = true;
+
+    // Unlock immediately, this is not great, but we don't have a way of
+    // knowing when else to unlock it currently, so it may get purged from
+    // the cache, but it'll still be ref'd until it's no longer being used.
+    GrUnlockCachedBitmapTexture(ctx, entry);
+}
+
 GrGradientEffect::~GrGradientEffect() {
-    if (fTexture) {
-        SkSafeUnref(fTexture);
-    }
+    SkSafeUnref(fTexture);
 }
 
 unsigned int GrGradientEffect::numTextures() const {
@@ -105,6 +133,10 @@
                   : INHERITED(texture) { 
 }
 
+GrLinearGradient::GrLinearGradient(GrContext* ctx, const SkShader& shader)
+                  : INHERITED(ctx, shader) {
+}
+
 GrLinearGradient::~GrLinearGradient() {
 
 }
@@ -113,10 +145,6 @@
     return GrTProgramStageFactory<GrLinearGradient>::getInstance();
 }
 
-bool GrLinearGradient::isEqual(const GrCustomStage& sBase) const {
-    return INHERITED::isEqual(sBase);
-}
-
 /////////////////////////////////////////////////////////////////////
 
 class GrGLRadialGradient : public GrGLGradientStage {
@@ -160,19 +188,18 @@
 
 }
 
+GrRadialGradient::GrRadialGradient(GrContext* ctx, const SkShader& shader)
+    : INHERITED(ctx, shader) {
+}
+
 GrRadialGradient::~GrRadialGradient() {
 
 }
 
-
 const GrProgramStageFactory& GrRadialGradient::getFactory() const {
     return GrTProgramStageFactory<GrRadialGradient>::getInstance();
 }
 
-bool GrRadialGradient::isEqual(const GrCustomStage& sBase) const {
-    return INHERITED::isEqual(sBase);
-}
-
 /////////////////////////////////////////////////////////////////////
 
 // For brevity, and these definitions are likely to move to a different class soon.
@@ -418,6 +445,19 @@
 
 }
 
+GrRadial2Gradient::GrRadial2Gradient(GrContext* ctx, const SkShader& shader)
+    : INHERITED(ctx, shader) {
+    SkShader::GradientInfo info;
+    info.fColorCount = 0;
+    shader.asAGradient(&info);
+    fCenterX1 = SkPoint::Distance(info.fPoint[0], info.fPoint[1]);
+    SkScalar diffRadius = info.fRadius[1] - info.fRadius[0];
+    fPosRoot = diffRadius < 0;
+    SkScalar inv = 0 == diffRadius ? 0 : SkScalarInvert(diffRadius);
+    fRadius0 = SkScalarMul(info.fRadius[0], inv);
+    fCenterX1 = SkScalarMul(fCenterX1, inv);
+}
+
 GrRadial2Gradient::~GrRadial2Gradient() {
 
 }
@@ -736,6 +776,16 @@
 
 }
 
+GrConical2Gradient::GrConical2Gradient(GrContext* ctx, const SkShader& shader)
+    : INHERITED(ctx, shader) {
+    SkShader::GradientInfo info;
+    info.fColorCount = 0;
+    shader.asAGradient(&info);
+    fCenterX1 = SkPoint::Distance(info.fPoint[0], info.fPoint[1]);
+    fRadius0 = info.fRadius[0];
+    fDiffRadius = info.fRadius[1] - info.fRadius[0];
+}
+
 GrConical2Gradient::~GrConical2Gradient() {
 
 }
@@ -796,6 +846,10 @@
 
 }
 
+GrSweepGradient::GrSweepGradient(GrContext* ctx, const SkShader& shader) 
+    : INHERITED(ctx, shader) {
+}
+
 GrSweepGradient::~GrSweepGradient() {
 
 }
@@ -804,7 +858,3 @@
     return GrTProgramStageFactory<GrSweepGradient>::getInstance();
 }
 
-bool GrSweepGradient::isEqual(const GrCustomStage& sBase) const {
-    return INHERITED::isEqual(sBase);
-}
-