Home | History | Annotate | Download | only in gradients
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkGradientShaderPriv_DEFINED
      9 #define SkGradientShaderPriv_DEFINED
     10 
     11 #include "SkGradientBitmapCache.h"
     12 #include "SkGradientShader.h"
     13 #include "SkClampRange.h"
     14 #include "SkColorPriv.h"
     15 #include "SkReadBuffer.h"
     16 #include "SkWriteBuffer.h"
     17 #include "SkMallocPixelRef.h"
     18 #include "SkUtils.h"
     19 #include "SkTemplates.h"
     20 #include "SkShader.h"
     21 #include "SkOnce.h"
     22 
     23 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
     24                                int count) {
     25     if (count > 0) {
     26         if (v0 == v1) {
     27             sk_memset32(dst, v0, count);
     28         } else {
     29             int pairs = count >> 1;
     30             for (int i = 0; i < pairs; i++) {
     31                 *dst++ = v0;
     32                 *dst++ = v1;
     33             }
     34             if (count & 1) {
     35                 *dst = v0;
     36             }
     37         }
     38     }
     39 }
     40 
     41 //  Clamp
     42 
     43 static inline SkFixed clamp_tileproc(SkFixed x) {
     44     return SkClampMax(x, 0xFFFF);
     45 }
     46 
     47 // Repeat
     48 
     49 static inline SkFixed repeat_tileproc(SkFixed x) {
     50     return x & 0xFFFF;
     51 }
     52 
     53 // Mirror
     54 
     55 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
     56 // See http://code.google.com/p/skia/issues/detail?id=472
     57 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
     58 #pragma optimize("", off)
     59 #endif
     60 
     61 static inline SkFixed mirror_tileproc(SkFixed x) {
     62     int s = x << 15 >> 31;
     63     return (x ^ s) & 0xFFFF;
     64 }
     65 
     66 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
     67 #pragma optimize("", on)
     68 #endif
     69 
     70 ///////////////////////////////////////////////////////////////////////////////
     71 
     72 typedef SkFixed (*TileProc)(SkFixed);
     73 
     74 ///////////////////////////////////////////////////////////////////////////////
     75 
     76 static const TileProc gTileProcs[] = {
     77     clamp_tileproc,
     78     repeat_tileproc,
     79     mirror_tileproc
     80 };
     81 
     82 ///////////////////////////////////////////////////////////////////////////////
     83 
     84 class SkGradientShaderBase : public SkShader {
     85 public:
     86     struct Descriptor {
     87         Descriptor() {
     88             sk_bzero(this, sizeof(*this));
     89             fTileMode = SkShader::kClamp_TileMode;
     90         }
     91 
     92         const SkMatrix*     fLocalMatrix;
     93         const SkColor*      fColors;
     94         const SkScalar*     fPos;
     95         int                 fCount;
     96         SkShader::TileMode  fTileMode;
     97         uint32_t            fGradFlags;
     98 
     99         void flatten(SkWriteBuffer&) const;
    100     };
    101 
    102     class DescriptorScope : public Descriptor {
    103     public:
    104         DescriptorScope() {}
    105 
    106         bool unflatten(SkReadBuffer&);
    107 
    108         // fColors and fPos always point into local memory, so they can be safely mutated
    109         //
    110         SkColor* mutableColors() { return const_cast<SkColor*>(fColors); }
    111         SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
    112 
    113     private:
    114         enum {
    115             kStorageCount = 16
    116         };
    117         SkColor fColorStorage[kStorageCount];
    118         SkScalar fPosStorage[kStorageCount];
    119         SkMatrix fLocalMatrixStorage;
    120         SkAutoMalloc fDynamicStorage;
    121     };
    122 
    123 public:
    124     SkGradientShaderBase(const Descriptor& desc);
    125     virtual ~SkGradientShaderBase();
    126 
    127     // The cache is initialized on-demand when getCache16/32 is called.
    128     class GradientShaderCache : public SkRefCnt {
    129     public:
    130         GradientShaderCache(U8CPU alpha, const SkGradientShaderBase& shader);
    131         ~GradientShaderCache();
    132 
    133         const uint16_t*     getCache16();
    134         const SkPMColor*    getCache32();
    135 
    136         SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
    137 
    138         unsigned getAlpha() const { return fCacheAlpha; }
    139 
    140     private:
    141         // Working pointers. If either is NULL, we need to recompute the corresponding cache values.
    142         uint16_t*   fCache16;
    143         SkPMColor*  fCache32;
    144 
    145         uint16_t*         fCache16Storage;    // Storage for fCache16, allocated on demand.
    146         SkMallocPixelRef* fCache32PixelRef;
    147         const unsigned    fCacheAlpha;        // The alpha value we used when we computed the cache.
    148                                               // Larger than 8bits so we can store uninitialized
    149                                               // value.
    150 
    151         const SkGradientShaderBase& fShader;
    152 
    153         // Make sure we only initialize the caches once.
    154         bool    fCache16Inited, fCache32Inited;
    155         SkMutex fCache16Mutex, fCache32Mutex;
    156 
    157         static void initCache16(GradientShaderCache* cache);
    158         static void initCache32(GradientShaderCache* cache);
    159 
    160         static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
    161         static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
    162                                     U8CPU alpha, uint32_t gradFlags);
    163     };
    164 
    165     class GradientShaderBaseContext : public SkShader::Context {
    166     public:
    167         GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
    168 
    169         virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; }
    170 
    171     protected:
    172         SkMatrix    fDstToIndex;
    173         SkMatrix::MapXYProc fDstToIndexProc;
    174         uint8_t     fDstToIndexClass;
    175         uint8_t     fFlags;
    176 
    177         SkAutoTUnref<GradientShaderCache> fCache;
    178 
    179     private:
    180         typedef SkShader::Context INHERITED;
    181     };
    182 
    183     virtual bool isOpaque() const SK_OVERRIDE;
    184 
    185     void getGradientTableBitmap(SkBitmap*) const;
    186 
    187     enum {
    188         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
    189         /// it, use a larger cache.
    190         kCache16Bits    = 8,
    191         kCache16Count = (1 << kCache16Bits),
    192         kCache16Shift   = 16 - kCache16Bits,
    193         kSqrt16Shift    = 8 - kCache16Bits,
    194 
    195         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
    196         /// it, use a larger cache.
    197         kCache32Bits    = 8,
    198         kCache32Count   = (1 << kCache32Bits),
    199         kCache32Shift   = 16 - kCache32Bits,
    200         kSqrt32Shift    = 8 - kCache32Bits,
    201 
    202         /// This value is used to *read* the dither cache; it may be 0
    203         /// if dithering is disabled.
    204         kDitherStride32 = kCache32Count,
    205         kDitherStride16 = kCache16Count,
    206     };
    207 
    208     enum GpuColorType {
    209         kTwo_GpuColorType,
    210         kThree_GpuColorType, // Symmetric three color
    211         kTexture_GpuColorType
    212     };
    213 
    214     // Determines and returns the gradient is a two color gradient, symmetric three color gradient
    215     // or other (texture gradient). If it is two or symmetric three color, the colors array will
    216     // also be filled with the gradient colors
    217     GpuColorType getGpuColorType(SkColor colors[3]) const;
    218 
    219     uint32_t getGradFlags() const { return fGradFlags; }
    220 
    221 protected:
    222     SkGradientShaderBase(SkReadBuffer& );
    223     virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
    224     SK_TO_STRING_OVERRIDE()
    225 
    226     SkMatrix    fPtsToUnit;     // set by subclass
    227     TileMode    fTileMode;
    228     TileProc    fTileProc;
    229     int         fColorCount;
    230     uint8_t     fGradFlags;
    231 
    232     struct Rec {
    233         SkFixed     fPos;   // 0...1
    234         uint32_t    fScale; // (1 << 24) / range
    235     };
    236     Rec*        fRecs;
    237 
    238     void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
    239 
    240     virtual bool onAsLuminanceColor(SkColor*) const SK_OVERRIDE;
    241 
    242     /*
    243      * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
    244      * Count is the number of colors in the gradient
    245      * It will then flip all the color and rec information and return in their respective Dst
    246      * pointers. It is assumed that space has already been allocated for the Dst pointers.
    247      * The rec src and dst are only assumed to be valid if count > 2
    248      */
    249     static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
    250                                    SkColor* colorSrc, Rec* recSrc,
    251                                    int count);
    252 
    253     // V23_COMPATIBILITY_CODE
    254     // Used for 2-pt conical gradients since we sort start/end cirlces by radius
    255     // Assumes space has already been allocated for fOrigColors
    256     void flipGradientColors();
    257 
    258 private:
    259     enum {
    260         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
    261 
    262         kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec))
    263     };
    264     SkColor     fStorage[(kStorageSize + 3) >> 2];
    265     SkColor*    fOrigColors; // original colors, before modulation by paint in context.
    266     SkScalar*   fOrigPos;   // original positions
    267     bool        fColorsAreOpaque;
    268 
    269     GradientShaderCache* refCache(U8CPU alpha) const;
    270     mutable SkMutex                           fCacheMutex;
    271     mutable SkAutoTUnref<GradientShaderCache> fCache;
    272 
    273     void initCommon();
    274 
    275     typedef SkShader INHERITED;
    276 };
    277 
    278 static inline int init_dither_toggle(int x, int y) {
    279     x &= 1;
    280     y = (y & 1) << 1;
    281     return (x | y) * SkGradientShaderBase::kDitherStride32;
    282 }
    283 
    284 static inline int next_dither_toggle(int toggle) {
    285     return toggle ^ SkGradientShaderBase::kDitherStride32;
    286 }
    287 
    288 static inline int init_dither_toggle16(int x, int y) {
    289     return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
    290 }
    291 
    292 static inline int next_dither_toggle16(int toggle) {
    293     return toggle ^ SkGradientShaderBase::kDitherStride16;
    294 }
    295 
    296 ///////////////////////////////////////////////////////////////////////////////
    297 
    298 #if SK_SUPPORT_GPU
    299 
    300 #include "GrCoordTransform.h"
    301 #include "gl/GrGLProcessor.h"
    302 
    303 class GrProcessorStage;
    304 class GrBackendProcessorFactory;
    305 
    306 /*
    307  * The interpretation of the texture matrix depends on the sample mode. The
    308  * texture matrix is applied both when the texture coordinates are explicit
    309  * and  when vertex positions are used as texture  coordinates. In the latter
    310  * case the texture matrix is applied to the pre-view-matrix position
    311  * values.
    312  *
    313  * Normal SampleMode
    314  *  The post-matrix texture coordinates are in normalize space with (0,0) at
    315  *  the top-left and (1,1) at the bottom right.
    316  * RadialGradient
    317  *  The matrix specifies the radial gradient parameters.
    318  *  (0,0) in the post-matrix space is center of the radial gradient.
    319  * Radial2Gradient
    320  *   Matrix transforms to space where first circle is centered at the
    321  *   origin. The second circle will be centered (x, 0) where x may be
    322  *   0 and is provided by setRadial2Params. The post-matrix space is
    323  *   normalized such that 1 is the second radius - first radius.
    324  * SweepGradient
    325  *  The angle from the origin of texture coordinates in post-matrix space
    326  *  determines the gradient value.
    327  */
    328 
    329  class GrTextureStripAtlas;
    330 
    331 // Base class for Gr gradient effects
    332 class GrGradientEffect : public GrFragmentProcessor {
    333 public:
    334 
    335     GrGradientEffect(GrContext* ctx,
    336                      const SkGradientShaderBase& shader,
    337                      const SkMatrix& matrix,
    338                      SkShader::TileMode tileMode);
    339 
    340     virtual ~GrGradientEffect();
    341 
    342     bool useAtlas() const { return SkToBool(-1 != fRow); }
    343     SkScalar getYCoord() const { return fYCoord; };
    344 
    345     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
    346 
    347     SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
    348 
    349     enum PremulType {
    350         kBeforeInterp_PremulType,
    351         kAfterInterp_PremulType,
    352     };
    353 
    354     PremulType getPremulType() const { return fPremulType; }
    355 
    356     const SkColor* getColors(int pos) const {
    357         SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
    358         SkASSERT((pos-1) <= fColorType);
    359         return &fColors[pos];
    360     }
    361 
    362 protected:
    363 
    364     /** Populates a pair of arrays with colors and stop info to construct a random gradient.
    365         The function decides whether stop values should be used or not. The return value indicates
    366         the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
    367         sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
    368         size kMaxRandomGradientColors. It may be updated to NULL, indicating that NULL should be
    369         passed to the gradient factory rather than the array.
    370     */
    371     static const int kMaxRandomGradientColors = 4;
    372     static int RandomGradientParams(SkRandom* r,
    373                                     SkColor colors[kMaxRandomGradientColors],
    374                                     SkScalar** stops,
    375                                     SkShader::TileMode* tm);
    376 
    377     virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
    378 
    379     const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
    380 
    381 private:
    382     static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
    383 
    384     GrCoordTransform fCoordTransform;
    385     GrTextureAccess fTextureAccess;
    386     SkScalar fYCoord;
    387     GrTextureStripAtlas* fAtlas;
    388     int fRow;
    389     bool fIsOpaque;
    390     SkGradientShaderBase::GpuColorType fColorType;
    391     SkColor fColors[3]; // More than 3 colors we use texture
    392     PremulType fPremulType; // This only changes behavior for two and three color special cases.
    393                             // It is already baked into to the table for texture gradients.
    394     typedef GrFragmentProcessor INHERITED;
    395 
    396 };
    397 
    398 ///////////////////////////////////////////////////////////////////////////////
    399 
    400 // Base class for GL gradient effects
    401 class GrGLGradientEffect : public GrGLFragmentProcessor {
    402 public:
    403     GrGLGradientEffect(const GrBackendProcessorFactory& factory);
    404     virtual ~GrGLGradientEffect();
    405 
    406     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
    407 
    408 protected:
    409     /**
    410      * Subclasses must call this. It will return a key for the part of the shader code controlled
    411      * by the base class. The subclasses must stick it in their key and then pass it to the below
    412      * emit* functions from their emitCode function.
    413      */
    414     static uint32_t GenBaseGradientKey(const GrProcessor&);
    415 
    416     // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
    417     // should call this method from their emitCode().
    418     void emitUniforms(GrGLProgramBuilder* builder, uint32_t baseKey);
    419 
    420 
    421     // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
    422     // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
    423     // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
    424     void emitColor(GrGLProgramBuilder* builder,
    425                    const char* gradientTValue,
    426                    uint32_t baseKey,
    427                    const char* outputColor,
    428                    const char* inputColor,
    429                    const TextureSamplerArray& samplers);
    430 
    431 private:
    432     enum {
    433         kPremulTypeKeyBitCnt = 1,
    434         kPremulTypeMask = 1,
    435         kPremulBeforeInterpKey = kPremulTypeMask,
    436 
    437         kTwoColorKey = 2 << kPremulTypeKeyBitCnt,
    438         kThreeColorKey = 3 << kPremulTypeKeyBitCnt,
    439         kColorKeyMask = kTwoColorKey | kThreeColorKey,
    440         kColorKeyBitCnt = 2,
    441 
    442         // Subclasses must shift any key bits they produce up by this amount
    443         // and combine with the result of GenBaseGradientKey.
    444         kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
    445     };
    446     GR_STATIC_ASSERT(kBaseKeyBitCnt <= 32);
    447 
    448     static SkGradientShaderBase::GpuColorType ColorTypeFromKey(uint32_t baseKey){
    449         if (kTwoColorKey == (baseKey & kColorKeyMask)) {
    450             return SkGradientShaderBase::kTwo_GpuColorType;
    451         } else if (kThreeColorKey == (baseKey & kColorKeyMask)) {
    452             return SkGradientShaderBase::kThree_GpuColorType;
    453         } else {return SkGradientShaderBase::kTexture_GpuColorType;}
    454     }
    455 
    456     static GrGradientEffect::PremulType PremulTypeFromKey(uint32_t baseKey){
    457         if (kPremulBeforeInterpKey == (baseKey & kPremulTypeMask)) {
    458             return GrGradientEffect::kBeforeInterp_PremulType;
    459         } else {
    460             return GrGradientEffect::kAfterInterp_PremulType;
    461         }
    462     }
    463 
    464     SkScalar fCachedYCoord;
    465     GrGLProgramDataManager::UniformHandle fFSYUni;
    466     GrGLProgramDataManager::UniformHandle fColorStartUni;
    467     GrGLProgramDataManager::UniformHandle fColorMidUni;
    468     GrGLProgramDataManager::UniformHandle fColorEndUni;
    469 
    470     typedef GrGLFragmentProcessor INHERITED;
    471 };
    472 
    473 #endif
    474 
    475 #endif
    476