-\r
-/*\r
- * Copyright 2012 Google Inc.\r
- *\r
- * Use of this source code is governed by a BSD-style license that can be\r
- * found in the LICENSE file.\r
- */\r
-\r
-#ifndef SkGradientShaderPriv_DEFINED\r
-#define SkGradientShaderPriv_DEFINED\r
-\r
-#include "SkGradientShader.h"\r
-#include "SkClampRange.h"\r
-#include "SkColorPriv.h"\r
-#include "SkMallocPixelRef.h"\r
-#include "SkUnitMapper.h"\r
-#include "SkUtils.h"\r
-#include "SkTemplates.h"\r
-#include "SkBitmapCache.h"\r
-#include "SkShader.h"\r
-#include "GrSamplerState.h"\r
-#include "SkGr.h"\r
-#include "gl/GrGLProgramStage.h"\r
-\r
-#ifndef SK_DISABLE_DITHER_32BIT_GRADIENT\r
- #define USE_DITHER_32BIT_GRADIENT\r
-#endif\r
-\r
-static void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,\r
- int count) {\r
- if (count > 0) {\r
- if (v0 == v1) {\r
- sk_memset32(dst, v0, count);\r
- } else {\r
- int pairs = count >> 1;\r
- for (int i = 0; i < pairs; i++) {\r
- *dst++ = v0;\r
- *dst++ = v1;\r
- }\r
- if (count & 1) {\r
- *dst = v0;\r
- }\r
- }\r
- }\r
-}\r
-\r
-// Clamp\r
-\r
-static SkFixed clamp_tileproc(SkFixed x) {\r
- return SkClampMax(x, 0xFFFF);\r
-}\r
-\r
-// Repeat\r
-\r
-static SkFixed repeat_tileproc(SkFixed x) {\r
- return x & 0xFFFF;\r
-}\r
-\r
-// Mirror\r
-\r
-// Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.\r
-// See http://code.google.com/p/skia/issues/detail?id=472\r
-#if defined(_MSC_VER) && (_MSC_VER >= 1600)\r
-#pragma optimize("", off)\r
-#endif\r
-\r
-static inline SkFixed mirror_tileproc(SkFixed x) {\r
- int s = x << 15 >> 31;\r
- return (x ^ s) & 0xFFFF;\r
-}\r
-\r
-#if defined(_MSC_VER) && (_MSC_VER >= 1600)\r
-#pragma optimize("", on)\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-typedef SkFixed (*TileProc)(SkFixed);\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-static const TileProc gTileProcs[] = {\r
- clamp_tileproc,\r
- repeat_tileproc,\r
- mirror_tileproc\r
-};\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-class SkGradientShaderBase : public SkShader {\r
-public:\r
- SkGradientShaderBase(const SkColor colors[], const SkScalar pos[],\r
- int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper);\r
- virtual ~SkGradientShaderBase();\r
-\r
- // overrides\r
- virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;\r
- virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }\r
- virtual bool isOpaque() const SK_OVERRIDE;\r
-\r
- enum {\r
- /// Seems like enough for visual accuracy. TODO: if pos[] deserves\r
- /// it, use a larger cache.\r
- kCache16Bits = 8,\r
- kGradient16Length = (1 << kCache16Bits),\r
- /// Each cache gets 1 extra entry at the end so we don't have to\r
- /// test for end-of-cache in lerps. This is also the value used\r
- /// to stride *writes* into the dither cache; it must not be zero.\r
- /// Total space for a cache is 2x kCache16Count entries: one\r
- /// regular cache, one for dithering.\r
- kCache16Count = kGradient16Length + 1,\r
- kCache16Shift = 16 - kCache16Bits,\r
- kSqrt16Shift = 8 - kCache16Bits,\r
-\r
- /// Seems like enough for visual accuracy. TODO: if pos[] deserves\r
- /// it, use a larger cache.\r
- kCache32Bits = 8,\r
- kGradient32Length = (1 << kCache32Bits),\r
- /// Each cache gets 1 extra entry at the end so we don't have to\r
- /// test for end-of-cache in lerps. This is also the value used\r
- /// to stride *writes* into the dither cache; it must not be zero.\r
- /// Total space for a cache is 2x kCache32Count entries: one\r
- /// regular cache, one for dithering.\r
- kCache32Count = kGradient32Length + 1,\r
- kCache32Shift = 16 - kCache32Bits,\r
- kSqrt32Shift = 8 - kCache32Bits,\r
-\r
- /// This value is used to *read* the dither cache; it may be 0\r
- /// if dithering is disabled.\r
-#ifdef USE_DITHER_32BIT_GRADIENT\r
- kDitherStride32 = kCache32Count,\r
-#else\r
- kDitherStride32 = 0,\r
-#endif\r
- kDitherStride16 = kCache16Count,\r
- kLerpRemainderMask32 = (1 << (16 - kCache32Bits)) - 1\r
- };\r
-\r
-\r
-protected:\r
- SkGradientShaderBase(SkFlattenableReadBuffer& );\r
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;\r
-\r
- SkUnitMapper* fMapper;\r
- SkMatrix fPtsToUnit; // set by subclass\r
- SkMatrix fDstToIndex;\r
- SkMatrix::MapXYProc fDstToIndexProc;\r
- TileMode fTileMode;\r
- TileProc fTileProc;\r
- int fColorCount;\r
- uint8_t fDstToIndexClass;\r
- uint8_t fFlags;\r
-\r
- struct Rec {\r
- SkFixed fPos; // 0...1\r
- uint32_t fScale; // (1 << 24) / range\r
- };\r
- Rec* fRecs;\r
-\r
- const uint16_t* getCache16() const;\r
- const SkPMColor* getCache32() const;\r
-\r
- void commonAsABitmap(SkBitmap*) const;\r
- void commonAsAGradient(GradientInfo*) const;\r
-\r
-private:\r
- enum {\r
- kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space\r
-\r
- kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))\r
- };\r
- SkColor fStorage[(kStorageSize + 3) >> 2];\r
- SkColor* fOrigColors; // original colors, before modulation by paint in setContext\r
- bool fColorsAreOpaque;\r
-\r
- mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values\r
- mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values\r
-\r
- mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand\r
- mutable SkMallocPixelRef* fCache32PixelRef;\r
- mutable unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value\r
-\r
- static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);\r
- static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,\r
- U8CPU alpha);\r
- void setCacheAlpha(U8CPU alpha) const;\r
- void initCommon();\r
-\r
- typedef SkShader INHERITED;\r
-};\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-class GrSamplerState;\r
-class GrProgramStageFactory;\r
-\r
-/*\r
- * The intepretation of the texture matrix depends on the sample mode. The\r
- * texture matrix is applied both when the texture coordinates are explicit\r
- * and when vertex positions are used as texture coordinates. In the latter\r
- * case the texture matrix is applied to the pre-view-matrix position \r
- * values.\r
- *\r
- * Normal SampleMode\r
- * The post-matrix texture coordinates are in normalize space with (0,0) at\r
- * the top-left and (1,1) at the bottom right.\r
- * RadialGradient\r
- * The matrix specifies the radial gradient parameters.\r
- * (0,0) in the post-matrix space is center of the radial gradient.\r
- * Radial2Gradient\r
- * Matrix transforms to space where first circle is centered at the\r
- * origin. The second circle will be centered (x, 0) where x may be \r
- * 0 and is provided by setRadial2Params. The post-matrix space is \r
- * normalized such that 1 is the second radius - first radius.\r
- * SweepGradient\r
- * The angle from the origin of texture coordinates in post-matrix space\r
- * determines the gradient value.\r
- */\r
-\r
-// Base class for Gr gradient effects\r
-class GrGradientEffect : public GrCustomStage {\r
-public:\r
-\r
- GrGradientEffect(GrTexture* texture);\r
- GrGradientEffect(GrContext* ctx, const SkShader& shader, \r
- GrSamplerState* sampler);\r
-\r
- virtual ~GrGradientEffect();\r
-\r
- unsigned int numTextures() const;\r
- GrTexture* texture(unsigned int index) const;\r
-\r
- bool useTexture() const { return fUseTexture; }\r
-\r
-private:\r
-\r
- GrTexture* fTexture;\r
- bool fUseTexture;\r
-\r
- typedef GrCustomStage INHERITED;\r
-\r
-};\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-// Base class for GL gradient custom stages\r
-class GrGLGradientStage : public GrGLProgramStage {\r
-public:\r
-\r
- GrGLGradientStage(const GrProgramStageFactory& factory);\r
- virtual ~GrGLGradientStage();\r
-\r
- // emit code that gets a fragment's color from an expression for t; for now\r
- // this always uses the texture, but for simpler cases we'll be able to lerp\r
- void emitColorLookup(GrGLShaderBuilder* builder, const char* t, \r
- const char* outputColor, const char* samplerName);\r
-\r
-private:\r
-\r
- typedef GrGLProgramStage INHERITED;\r
-};\r
-\r
-#endif\r
-\r
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGradientShaderPriv_DEFINED
+#define SkGradientShaderPriv_DEFINED
+
+#include "SkGradientShader.h"
+#include "SkClampRange.h"
+#include "SkColorPriv.h"
+#include "SkMallocPixelRef.h"
+#include "SkUnitMapper.h"
+#include "SkUtils.h"
+#include "SkTemplates.h"
+#include "SkBitmapCache.h"
+#include "SkShader.h"
+#include "GrSamplerState.h"
+#include "SkGr.h"
+#include "gl/GrGLProgramStage.h"
+
+#ifndef SK_DISABLE_DITHER_32BIT_GRADIENT
+ #define USE_DITHER_32BIT_GRADIENT
+#endif
+
+static void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
+ int count) {
+ if (count > 0) {
+ if (v0 == v1) {
+ sk_memset32(dst, v0, count);
+ } else {
+ int pairs = count >> 1;
+ for (int i = 0; i < pairs; i++) {
+ *dst++ = v0;
+ *dst++ = v1;
+ }
+ if (count & 1) {
+ *dst = v0;
+ }
+ }
+ }
+}
+
+// Clamp
+
+static SkFixed clamp_tileproc(SkFixed x) {
+ return SkClampMax(x, 0xFFFF);
+}
+
+// Repeat
+
+static SkFixed repeat_tileproc(SkFixed x) {
+ return x & 0xFFFF;
+}
+
+// Mirror
+
+// Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
+// See http://code.google.com/p/skia/issues/detail?id=472
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+#pragma optimize("", off)
+#endif
+
+static inline SkFixed mirror_tileproc(SkFixed x) {
+ int s = x << 15 >> 31;
+ return (x ^ s) & 0xFFFF;
+}
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+#pragma optimize("", on)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef SkFixed (*TileProc)(SkFixed);
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const TileProc gTileProcs[] = {
+ clamp_tileproc,
+ repeat_tileproc,
+ mirror_tileproc
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkGradientShaderBase : public SkShader {
+public:
+ SkGradientShaderBase(const SkColor colors[], const SkScalar pos[],
+ int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper);
+ virtual ~SkGradientShaderBase();
+
+ // overrides
+ virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
+ virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
+ virtual bool isOpaque() const SK_OVERRIDE;
+
+ void getGradientTableBitmap(SkBitmap*) const;
+
+ enum {
+ /// Seems like enough for visual accuracy. TODO: if pos[] deserves
+ /// it, use a larger cache.
+ kCache16Bits = 8,
+ kGradient16Length = (1 << kCache16Bits),
+ /// Each cache gets 1 extra entry at the end so we don't have to
+ /// test for end-of-cache in lerps. This is also the value used
+ /// to stride *writes* into the dither cache; it must not be zero.
+ /// Total space for a cache is 2x kCache16Count entries: one
+ /// regular cache, one for dithering.
+ kCache16Count = kGradient16Length + 1,
+ kCache16Shift = 16 - kCache16Bits,
+ kSqrt16Shift = 8 - kCache16Bits,
+
+ /// Seems like enough for visual accuracy. TODO: if pos[] deserves
+ /// it, use a larger cache.
+ kCache32Bits = 8,
+ kGradient32Length = (1 << kCache32Bits),
+ /// Each cache gets 1 extra entry at the end so we don't have to
+ /// test for end-of-cache in lerps. This is also the value used
+ /// to stride *writes* into the dither cache; it must not be zero.
+ /// Total space for a cache is 2x kCache32Count entries: one
+ /// regular cache, one for dithering.
+ kCache32Count = kGradient32Length + 1,
+ kCache32Shift = 16 - kCache32Bits,
+ kSqrt32Shift = 8 - kCache32Bits,
+
+ /// This value is used to *read* the dither cache; it may be 0
+ /// if dithering is disabled.
+#ifdef USE_DITHER_32BIT_GRADIENT
+ kDitherStride32 = kCache32Count,
+#else
+ kDitherStride32 = 0,
+#endif
+ kDitherStride16 = kCache16Count,
+ kLerpRemainderMask32 = (1 << (16 - kCache32Bits)) - 1
+ };
+
+
+protected:
+ SkGradientShaderBase(SkFlattenableReadBuffer& );
+ virtual void flatten(SkFlattenableWriteBuffer&) const SK_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;
+
+ struct Rec {
+ SkFixed fPos; // 0...1
+ uint32_t fScale; // (1 << 24) / range
+ };
+ Rec* fRecs;
+
+ const uint16_t* getCache16() const;
+ const SkPMColor* getCache32() const;
+
+ void commonAsAGradient(GradientInfo*) const;
+
+private:
+ enum {
+ kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
+
+ kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
+ };
+ SkColor fStorage[(kStorageSize + 3) >> 2];
+ SkColor* fOrigColors; // original colors, before modulation by paint in setContext
+ 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
+
+ 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);
+ void setCacheAlpha(U8CPU alpha) const;
+ void initCommon();
+
+ typedef SkShader INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GrSamplerState;
+class GrProgramStageFactory;
+
+/*
+ * The intepretation of the texture matrix depends on the sample mode. The
+ * texture matrix is applied both when the texture coordinates are explicit
+ * and when vertex positions are used as texture coordinates. In the latter
+ * case the texture matrix is applied to the pre-view-matrix position
+ * values.
+ *
+ * Normal SampleMode
+ * The post-matrix texture coordinates are in normalize space with (0,0) at
+ * the top-left and (1,1) at the bottom right.
+ * RadialGradient
+ * The matrix specifies the radial gradient parameters.
+ * (0,0) in the post-matrix space is center of the radial gradient.
+ * Radial2Gradient
+ * Matrix transforms to space where first circle is centered at the
+ * origin. The second circle will be centered (x, 0) where x may be
+ * 0 and is provided by setRadial2Params. The post-matrix space is
+ * normalized such that 1 is the second radius - first radius.
+ * SweepGradient
+ * The angle from the origin of texture coordinates in post-matrix space
+ * determines the gradient value.
+ */
+
+// Base class for Gr gradient effects
+class GrGradientEffect : public GrCustomStage {
+public:
+
+ // FIXME: This constructor is only used in GrGpuGL_unittest.cpp, and should
+ // be removed once an alternative testing setup has been devised.
+ GrGradientEffect(GrTexture* texture);
+ GrGradientEffect(GrContext* ctx, const SkGradientShaderBase& shader,
+ GrSamplerState* sampler);
+
+ virtual ~GrGradientEffect();
+
+ unsigned int numTextures() const;
+ GrTexture* texture(unsigned int index) const;
+
+ bool useTexture() const { return fUseTexture; }
+
+private:
+
+ GrTexture* fTexture;
+ bool fUseTexture;
+
+ typedef GrCustomStage INHERITED;
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Base class for GL gradient custom stages
+class GrGLGradientStage : public GrGLProgramStage {
+public:
+
+ GrGLGradientStage(const GrProgramStageFactory& factory);
+ virtual ~GrGLGradientStage();
+
+ // emit code that gets a fragment's color from an expression for t; for now
+ // this always uses the texture, but for simpler cases we'll be able to lerp
+ void emitColorLookup(GrGLShaderBuilder* builder, const char* t,
+ const char* outputColor, const char* samplerName);
+
+private:
+
+ typedef GrGLProgramStage INHERITED;
+};
+
+#endif
+