#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkMallocPixelRef.h"
-#include "SkUnitMapper.h"
#include "SkUtils.h"
#include "SkTemplates.h"
#include "SkBitmapCache.h"
#include "SkShader.h"
+#include "SkOnce.h"
static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
int count) {
fTileMode = SkShader::kClamp_TileMode;
}
+ const SkMatrix* fLocalMatrix;
const SkColor* fColors;
const SkScalar* fPos;
int fCount;
SkShader::TileMode fTileMode;
- SkUnitMapper* fMapper;
- uint32_t fFlags;
+ uint32_t fGradFlags;
};
public:
SkGradientShaderBase(const Descriptor& desc);
virtual ~SkGradientShaderBase();
- virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
- virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
+ // The cache is initialized on-demand when getCache16/32 is called.
+ class GradientShaderCache : public SkRefCnt {
+ public:
+ GradientShaderCache(U8CPU alpha, const SkGradientShaderBase& shader);
+ ~GradientShaderCache();
+
+ const uint16_t* getCache16();
+ const SkPMColor* getCache32();
+
+ SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
+
+ unsigned getAlpha() const { return fCacheAlpha; }
+
+ private:
+ // Working pointers. If either is NULL, we need to recompute the corresponding cache values.
+ uint16_t* fCache16;
+ SkPMColor* fCache32;
+
+ uint16_t* fCache16Storage; // Storage for fCache16, allocated on demand.
+ SkMallocPixelRef* fCache32PixelRef;
+ const unsigned fCacheAlpha; // The alpha value we used when we computed the cache.
+ // Larger than 8bits so we can store uninitialized
+ // value.
+
+ const SkGradientShaderBase& fShader;
+
+ // Make sure we only initialize the caches once.
+ bool fCache16Inited, fCache32Inited;
+ SkMutex fCache16Mutex, fCache32Mutex;
+
+ static void initCache16(GradientShaderCache* cache);
+ static void initCache32(GradientShaderCache* cache);
+
+ static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
+ static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
+ U8CPU alpha, uint32_t gradFlags);
+ };
+
+ class GradientShaderBaseContext : public SkShader::Context {
+ public:
+ GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
+
+ virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; }
+
+ protected:
+ SkMatrix fDstToIndex;
+ SkMatrix::MapXYProc fDstToIndexProc;
+ uint8_t fDstToIndexClass;
+ uint8_t fFlags;
+
+ SkAutoTUnref<GradientShaderCache> fCache;
+
+ private:
+ typedef SkShader::Context INHERITED;
+ };
+
virtual bool isOpaque() const SK_OVERRIDE;
void getGradientTableBitmap(SkBitmap*) const;
kDitherStride16 = kCache16Count,
};
+ enum GpuColorType {
+ kTwo_GpuColorType,
+ kThree_GpuColorType, // Symmetric three color
+ kTexture_GpuColorType
+ };
+
+ // Determines and returns the gradient is a two color gradient, symmetric three color gradient
+ // or other (texture gradient). If it is two or symmetric three color, the colors array will
+ // also be filled with the gradient colors
+ GpuColorType getGpuColorType(SkColor colors[3]) const;
+
+ uint32_t getGradFlags() const { return fGradFlags; }
protected:
SkGradientShaderBase(SkReadBuffer& );
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
- SkUnitMapper* fMapper;
SkMatrix fPtsToUnit; // set by subclass
- SkMatrix fDstToIndex;
- SkMatrix::MapXYProc fDstToIndexProc;
TileMode fTileMode;
TileProc fTileProc;
int fColorCount;
- uint8_t fDstToIndexClass;
- uint8_t fFlags;
uint8_t fGradFlags;
struct Rec {
};
Rec* fRecs;
- const uint16_t* getCache16() const;
- const SkPMColor* getCache32() const;
+ void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
- void commonAsAGradient(GradientInfo*) const;
+ /*
+ * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
+ * Count is the number of colors in the gradient
+ * It will then flip all the color and rec information and return in their respective Dst
+ * pointers. It is assumed that space has already been allocated for the Dst pointers.
+ * The rec src and dst are only assumed to be valid if count > 2
+ */
+ static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
+ SkColor* colorSrc, Rec* recSrc,
+ int count);
+
+ // V23_COMPATIBILITY_CODE
+ // Used for 2-pt conical gradients since we sort start/end cirlces by radius
+ // Assumes space has already been allocated for fOrigColors
+ void flipGradientColors();
private:
enum {
kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
};
SkColor fStorage[(kStorageSize + 3) >> 2];
- SkColor* fOrigColors; // original colors, before modulation by paint in setContext
+ SkColor* fOrigColors; // original colors, before modulation by paint in context.
bool fColorsAreOpaque;
- mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values
- mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values
+ GradientShaderCache* refCache(U8CPU alpha) const;
+ mutable SkMutex fCacheMutex;
+ mutable SkAutoTUnref<GradientShaderCache> fCache;
- mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand
- mutable SkMallocPixelRef* fCache32PixelRef;
- mutable unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
-
- static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
- static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
- U8CPU alpha, uint32_t gradFlags);
- void setCacheAlpha(U8CPU alpha) const;
void initCommon();
typedef SkShader INHERITED;
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
- enum ColorType {
- kTwo_ColorType,
- kThree_ColorType,
- kTexture_ColorType
- };
-
- ColorType getColorType() const { return fColorType; }
+ SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
enum PremulType {
kBeforeInterp_PremulType,
PremulType getPremulType() const { return fPremulType; }
const SkColor* getColors(int pos) const {
- SkASSERT(fColorType != kTexture_ColorType);
+ SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
SkASSERT((pos-1) <= fColorType);
return &fColors[pos];
}
private:
static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
- enum {
- kMaxAnalyticColors = 3 // if more colors use texture
- };
-
GrCoordTransform fCoordTransform;
GrTextureAccess fTextureAccess;
SkScalar fYCoord;
GrTextureStripAtlas* fAtlas;
int fRow;
bool fIsOpaque;
- ColorType fColorType;
- SkColor fColors[kMaxAnalyticColors];
+ SkGradientShaderBase::GpuColorType fColorType;
+ SkColor fColors[3]; // More than 3 colors we use texture
PremulType fPremulType; // This only changes behavior for two and three color special cases.
// It is already baked into to the table for texture gradients.
typedef GrEffect INHERITED;
GrGLGradientEffect(const GrBackendEffectFactory& factory);
virtual ~GrGLGradientEffect();
- virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+ virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE;
protected:
+ /**
+ * Subclasses must call this. It will return a key for the part of the shader code controlled
+ * by the base class. The subclasses must stick it in their key and then pass it to the below
+ * emit* functions from their emitCode function.
+ */
+ static uint32_t GenBaseGradientKey(const GrDrawEffect&);
+
+ // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
+ // should call this method from their emitCode().
+ void emitUniforms(GrGLShaderBuilder* builder, uint32_t baseKey);
+
+
+ // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
+ // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
+ // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
+ void emitColor(GrGLShaderBuilder* builder,
+ const char* gradientTValue,
+ uint32_t baseKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray& samplers);
+
+private:
enum {
kPremulTypeKeyBitCnt = 1,
kPremulTypeMask = 1,
// and combine with the result of GenBaseGradientKey.
kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
};
-
- static GrGradientEffect::ColorType ColorTypeFromKey(EffectKey key){
- if (kTwoColorKey == (key & kColorKeyMask)) {
- return GrGradientEffect::kTwo_ColorType;
- } else if (kThreeColorKey == (key & kColorKeyMask)) {
- return GrGradientEffect::kThree_ColorType;
- } else {return GrGradientEffect::kTexture_ColorType;}
+ GR_STATIC_ASSERT(kBaseKeyBitCnt <= 32);
+
+ static SkGradientShaderBase::GpuColorType ColorTypeFromKey(uint32_t baseKey){
+ if (kTwoColorKey == (baseKey & kColorKeyMask)) {
+ return SkGradientShaderBase::kTwo_GpuColorType;
+ } else if (kThreeColorKey == (baseKey & kColorKeyMask)) {
+ return SkGradientShaderBase::kThree_GpuColorType;
+ } else {return SkGradientShaderBase::kTexture_GpuColorType;}
}
- static GrGradientEffect::PremulType PremulTypeFromKey(EffectKey key){
- if (kPremulBeforeInterpKey == (key & kPremulTypeMask)) {
+ static GrGradientEffect::PremulType PremulTypeFromKey(uint32_t baseKey){
+ if (kPremulBeforeInterpKey == (baseKey & kPremulTypeMask)) {
return GrGradientEffect::kBeforeInterp_PremulType;
} else {
return GrGradientEffect::kAfterInterp_PremulType;
}
}
- /**
- * Subclasses must call this. It will return a value restricted to the lower kBaseKeyBitCnt
- * bits.
- */
- static EffectKey GenBaseGradientKey(const GrDrawEffect&);
-
- // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
- // should call this method from their emitCode().
- void emitUniforms(GrGLShaderBuilder* builder, EffectKey key);
-
-
- // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
- // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
- // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
- void emitColor(GrGLShaderBuilder* builder,
- const char* gradientTValue,
- EffectKey key,
- const char* outputColor,
- const char* inputColor,
- const TextureSamplerArray& samplers);
-
-private:
SkScalar fCachedYCoord;
- GrGLUniformManager::UniformHandle fFSYUni;
- GrGLUniformManager::UniformHandle fColorStartUni;
- GrGLUniformManager::UniformHandle fColorMidUni;
- GrGLUniformManager::UniformHandle fColorEndUni;
+ GrGLProgramDataManager::UniformHandle fFSYUni;
+ GrGLProgramDataManager::UniformHandle fColorStartUni;
+ GrGLProgramDataManager::UniformHandle fColorMidUni;
+ GrGLProgramDataManager::UniformHandle fColorEndUni;
typedef GrGLEffect INHERITED;
};