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 
sk_memset32_dither(uint32_t dst[],uint32_t v0,uint32_t v1,int count)22 static 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 
clamp_tileproc(SkFixed x)42 static inline SkFixed clamp_tileproc(SkFixed x) {
43     return SkClampMax(x, 0xFFFF);
44 }
45 
46 // Repeat
47 
repeat_tileproc(SkFixed x)48 static 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 
mirror_tileproc(SkFixed x)60 static 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 
71 typedef SkFixed (*TileProc)(SkFixed);
72 
73 ///////////////////////////////////////////////////////////////////////////////
74 
75 static const TileProc gTileProcs[] = {
76     clamp_tileproc,
77     repeat_tileproc,
78     mirror_tileproc
79 };
80 
81 ///////////////////////////////////////////////////////////////////////////////
82 
83 class SkGradientShaderBase : public SkShader {
84 public:
85     struct Descriptor {
DescriptorDescriptor86         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:
DescriptorScope()103         DescriptorScope() {}
104 
105         bool unflatten(SkReadBuffer&);
106 
107         // fColors and fPos always point into local memory, so they can be safely mutated
108         //
mutableColors()109         SkColor* mutableColors() { return const_cast<SkColor*>(fColors); }
mutablePos()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 
122 public:
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 
getCache32PixelRef()135         SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
136 
getAlpha()137         unsigned getAlpha() const { return fCacheAlpha; }
getDither()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 
getFlags()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 
getGradFlags()221     uint32_t getGradFlags() const { return fGradFlags; }
222 
223 protected:
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 
257 private:
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];
264 public:
265     SkColor*    fOrigColors; // original colors, before modulation by paint in context.
266     SkScalar*   fOrigPos;   // original positions
267 
colorsAreOpaque()268     bool colorsAreOpaque() const { return fColorsAreOpaque; }
269 
270 private:
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 
init_dither_toggle(int x,int y)282 static 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 
next_dither_toggle(int toggle)288 static inline int next_dither_toggle(int toggle) {
289     return toggle ^ SkGradientShaderBase::kDitherStride32;
290 }
291 
init_dither_toggle16(int x,int y)292 static inline int init_dither_toggle16(int x, int y) {
293     return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
294 }
295 
next_dither_toggle16(int toggle)296 static 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 
309 class 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
337 class GrGradientEffect : public GrFragmentProcessor {
338 public:
339 
340     GrGradientEffect(GrContext* ctx,
341                      const SkGradientShaderBase& shader,
342                      const SkMatrix& matrix,
343                      SkShader::TileMode tileMode);
344 
345     virtual ~GrGradientEffect();
346 
useAtlas()347     bool useAtlas() const { return SkToBool(-1 != fRow); }
getYCoord()348     SkScalar getYCoord() const { return fYCoord; };
349 
getColorType()350     SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
351 
352     enum PremulType {
353         kBeforeInterp_PremulType,
354         kAfterInterp_PremulType,
355     };
356 
getPremulType()357     PremulType getPremulType() const { return fPremulType; }
358 
getColors(int pos)359     const SkColor* getColors(int pos) const {
360         SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
361         SkASSERT((pos-1) <= fColorType);
362         return &fColors[pos];
363     }
364 
365 protected:
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 
getCoordTransform()384     const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
385 
386 private:
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
406 class GrGLGradientEffect : public GrGLSLFragmentProcessor {
407 public:
408     GrGLGradientEffect();
409 
410 protected:
411     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
412 
413 protected:
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 
438 private:
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