aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkShader.h13
-rw-r--r--src/core/SkShader.cpp5
-rw-r--r--src/effects/SkGradientShader.cpp72
-rw-r--r--src/gpu/effects/GrGradientEffects.cpp82
-rw-r--r--src/gpu/effects/GrGradientEffects.h13
5 files changed, 163 insertions, 22 deletions
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index 7108c34e45..1ba1d671f3 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -17,6 +17,9 @@
#include "SkPaint.h"
class SkPath;
+class GrContext;
+class GrCustomStage;
+class GrSamplerState;
/** \class SkShader
*
@@ -299,6 +302,16 @@ public:
virtual GradientType asAGradient(GradientInfo* info) const;
+ /**
+ * If the shader subclass has a GrCustomStage implementation, this returns
+ * a new custom stage (the caller assumes ownership, and will need to
+ * unref it). A GrContext pointer is required since custom stages may
+ * need to create textures. The sampler parameter is necessary to set
+ * up matrix/tile modes/etc, and will eventually be removed.
+ */
+ virtual GrCustomStage* asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const;
+
//////////////////////////////////////////////////////////////////////////
// Factory methods for stock shaders
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index cd40b7f2c8..a0ae49d73e 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -200,6 +200,11 @@ SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
return kNone_GradientType;
}
+GrCustomStage* SkShader::asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const {
+ return NULL;
+}
+
SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
TileMode tmx, TileMode tmy) {
return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp
index b86c4e2e8a..8838e77eb0 100644
--- a/src/effects/SkGradientShader.cpp
+++ b/src/effects/SkGradientShader.cpp
@@ -15,6 +15,9 @@
#include "SkUtils.h"
#include "SkTemplates.h"
#include "SkBitmapCache.h"
+#include "../gpu/effects/GrGradientEffects.h"
+#include "../gpu/GrSamplerState.h"
+#include "../gpu/SkGr.h"
#ifndef SK_DISABLE_DITHER_32BIT_GRADIENT
#define USE_DITHER_32BIT_GRADIENT
@@ -796,6 +799,8 @@ public:
virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*,
SkScalar* twoPointRadialParams) const SK_OVERRIDE;
virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
+ virtual GrCustomStage* asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Linear_Gradient)
@@ -1044,6 +1049,16 @@ SkShader::GradientType Linear_Gradient::asAGradient(GradientInfo* info) const {
return kLinear_GradientType;
}
+GrCustomStage* Linear_Gradient::asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const {
+ SkASSERT(NULL != context && NULL != sampler);
+ sampler->matrix()->preConcat(fPtsToUnit);
+ sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+ sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
+ return SkNEW_ARGS(GrLinearGradient, (context, *this));
+}
+
static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
int count) {
if (reinterpret_cast<uintptr_t>(dst) & 2) {
@@ -1444,6 +1459,7 @@ public:
}
return kRadial_BitmapType;
}
+
virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE {
if (info) {
commonAsAGradient(info);
@@ -1453,6 +1469,16 @@ public:
return kRadial_GradientType;
}
+ virtual GrCustomStage* asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const SK_OVERRIDE {
+ SkASSERT(NULL != context && NULL != sampler);
+ sampler->matrix()->preConcat(fPtsToUnit);
+ sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+ sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
+ return SkNEW_ARGS(GrRadialGradient, (context, *this));
+ }
+
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Radial_Gradient)
protected:
@@ -1903,6 +1929,24 @@ public:
return kRadial2_GradientType;
}
+ virtual GrCustomStage* asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const SK_OVERRIDE {
+ SkASSERT(NULL != context && NULL != sampler);
+ SkScalar diffLen = fDiff.length();
+ if (0 != diffLen) {
+ SkScalar invDiffLen = SkScalarInvert(diffLen);
+ sampler->matrix()->setSinCos(-SkScalarMul(invDiffLen, fDiff.fY),
+ SkScalarMul(invDiffLen, fDiff.fX));
+ } else {
+ sampler->matrix()->reset();
+ }
+ sampler->matrix()->preConcat(fPtsToUnit);
+ sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+ sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
+ return SkNEW_ARGS(GrRadial2Gradient, (context, *this));
+ }
+
virtual void shadeSpan(int x, int y, SkPMColor* dstCParam,
int count) SK_OVERRIDE {
SkASSERT(count > 0);
@@ -2355,6 +2399,25 @@ public:
return kConical_GradientType;
}
+ virtual GrCustomStage* asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const SK_OVERRIDE {
+ SkASSERT(NULL != context && NULL != sampler);
+ SkPoint diff = fCenter2 - fCenter1;
+ SkScalar diffLen = diff.length();
+ if (0 != diffLen) {
+ SkScalar invDiffLen = SkScalarInvert(diffLen);
+ sampler->matrix()->setSinCos(-SkScalarMul(invDiffLen, diff.fY),
+ SkScalarMul(invDiffLen, diff.fX));
+ } else {
+ sampler->matrix()->reset();
+ }
+ sampler->matrix()->preTranslate(-fCenter1.fX, -fCenter1.fY);
+ sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+ sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
+ return SkNEW_ARGS(GrConical2Gradient, (context, *this));
+ }
+
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Two_Point_Conical_Gradient)
protected:
@@ -2422,6 +2485,15 @@ public:
return kSweep_GradientType;
}
+ virtual GrCustomStage* asNewCustomStage(GrContext* context,
+ GrSamplerState* sampler) const SK_OVERRIDE {
+ sampler->matrix()->preConcat(fPtsToUnit);
+ sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+ sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+ sampler->setFilter(GrSamplerState::kBilinear_Filter);
+ return SkNEW_ARGS(GrSweepGradient, (context, *this));
+ }
+
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sweep_Gradient)
protected:
diff --git a/src/gpu/effects/GrGradientEffects.cpp b/src/gpu/effects/GrGradientEffects.cpp
index ec465b815b..2faeec02a1 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 @@ GrGradientEffect::GrGradientEffect(GrTexture* texture)
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 @@ GrLinearGradient::GrLinearGradient(GrTexture* texture)
: INHERITED(texture) {
}
+GrLinearGradient::GrLinearGradient(GrContext* ctx, const SkShader& shader)
+ : INHERITED(ctx, shader) {
+}
+
GrLinearGradient::~GrLinearGradient() {
}
@@ -113,10 +145,6 @@ const GrProgramStageFactory& GrLinearGradient::getFactory() const {
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(GrTexture* texture)
}
+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(GrTexture* texture,
}
+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(GrTexture* texture,
}
+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(GrTexture* texture)
}
+GrSweepGradient::GrSweepGradient(GrContext* ctx, const SkShader& shader)
+ : INHERITED(ctx, shader) {
+}
+
GrSweepGradient::~GrSweepGradient() {
}
@@ -804,7 +858,3 @@ const GrProgramStageFactory& GrSweepGradient::getFactory() const {
return GrTProgramStageFactory<GrSweepGradient>::getInstance();
}
-bool GrSweepGradient::isEqual(const GrCustomStage& sBase) const {
- return INHERITED::isEqual(sBase);
-}
-
diff --git a/src/gpu/effects/GrGradientEffects.h b/src/gpu/effects/GrGradientEffects.h
index eb1a8f2739..fdd5d52353 100644
--- a/src/gpu/effects/GrGradientEffects.h
+++ b/src/gpu/effects/GrGradientEffects.h
@@ -11,6 +11,7 @@
#include "GrSingleTextureEffect.h"
#include "GrTypes.h"
#include "GrScalar.h"
+#include "SkShader.h"
/*
* The intepretation of the texture matrix depends on the sample mode. The
@@ -40,9 +41,7 @@ class GrGradientEffect : public GrCustomStage {
public:
GrGradientEffect(GrTexture* texture);
-
- // TODO: Look at a GradientInfo and make the texture only if necessary
- // GrGradientEffect(GrContext* ctx, GradientInfo* info);
+ GrGradientEffect(GrContext* ctx, const SkShader& shader);
virtual ~GrGradientEffect();
@@ -67,11 +66,11 @@ class GrLinearGradient : public GrGradientEffect {
public:
GrLinearGradient(GrTexture* texture);
+ GrLinearGradient(GrContext* ctx, const SkShader& shader);
virtual ~GrLinearGradient();
static const char* Name() { return "Linear Gradient"; }
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
- virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
typedef GrGLLinearGradient GLProgramStage;
@@ -87,11 +86,11 @@ class GrRadialGradient : public GrGradientEffect {
public:
GrRadialGradient(GrTexture* texture);
+ GrRadialGradient(GrContext* ctx, const SkShader& shader);
virtual ~GrRadialGradient();
static const char* Name() { return "Radial Gradient"; }
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
- virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
typedef GrGLRadialGradient GLProgramStage;
@@ -107,6 +106,7 @@ class GrRadial2Gradient : public GrGradientEffect {
public:
GrRadial2Gradient(GrTexture* texture, GrScalar center, GrScalar radius, bool posRoot);
+ GrRadial2Gradient(GrContext* ctx, const SkShader& shader);
virtual ~GrRadial2Gradient();
static const char* Name() { return "Two-Point Radial Gradient"; }
@@ -143,6 +143,7 @@ class GrConical2Gradient : public GrGradientEffect {
public:
GrConical2Gradient(GrTexture* texture, GrScalar center, GrScalar radius, GrScalar diffRadius);
+ GrConical2Gradient(GrContext* ctx, const SkShader& shader);
virtual ~GrConical2Gradient();
static const char* Name() { return "Two-Point Conical Gradient"; }
@@ -179,11 +180,11 @@ class GrSweepGradient : public GrGradientEffect {
public:
GrSweepGradient(GrTexture* texture);
+ GrSweepGradient(GrContext* ctx, const SkShader& shader);
virtual ~GrSweepGradient();
static const char* Name() { return "Sweep Gradient"; }
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
- virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
typedef GrGLSweepGradient GLProgramStage;