diff options
-rw-r--r-- | include/core/SkShader.h | 13 | ||||
-rw-r--r-- | src/core/SkShader.cpp | 5 | ||||
-rw-r--r-- | src/effects/SkGradientShader.cpp | 72 | ||||
-rw-r--r-- | src/gpu/effects/GrGradientEffects.cpp | 82 | ||||
-rw-r--r-- | src/gpu/effects/GrGradientEffects.h | 13 |
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; |