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
23static 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
43static inline SkFixed clamp_tileproc(SkFixed x) {
44    return SkClampMax(x, 0xFFFF);
45}
46
47// Repeat
48
49static 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
61static 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
72typedef SkFixed (*TileProc)(SkFixed);
73
74///////////////////////////////////////////////////////////////////////////////
75
76static const TileProc gTileProcs[] = {
77    clamp_tileproc,
78    repeat_tileproc,
79    mirror_tileproc
80};
81
82///////////////////////////////////////////////////////////////////////////////
83
84class SkGradientShaderBase : public SkShader {
85public:
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
123public:
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
221protected:
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
258private:
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
278static 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
284static inline int next_dither_toggle(int toggle) {
285    return toggle ^ SkGradientShaderBase::kDitherStride32;
286}
287
288static inline int init_dither_toggle16(int x, int y) {
289    return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
290}
291
292static 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
303class GrProcessorStage;
304class 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
332class GrGradientEffect : public GrFragmentProcessor {
333public:
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
362protected:
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
381private:
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
401class GrGLGradientEffect : public GrGLFragmentProcessor {
402public:
403    GrGLGradientEffect(const GrBackendProcessorFactory& factory);
404    virtual ~GrGLGradientEffect();
405
406    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
407
408protected:
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
431private:
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