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