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