Upstream version 5.34.104.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
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 SkColor*      fColors;
93         const SkScalar*     fPos;
94         int                 fCount;
95         SkShader::TileMode  fTileMode;
96         SkUnitMapper*       fMapper;
97         uint32_t            fFlags;
98     };
99
100 public:
101     SkGradientShaderBase(const Descriptor& desc);
102     virtual ~SkGradientShaderBase();
103
104     virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
105     virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
106     virtual bool isOpaque() const SK_OVERRIDE;
107
108     void getGradientTableBitmap(SkBitmap*) const;
109
110     enum {
111         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
112         /// it, use a larger cache.
113         kCache16Bits    = 8,
114         kCache16Count = (1 << kCache16Bits),
115         kCache16Shift   = 16 - kCache16Bits,
116         kSqrt16Shift    = 8 - kCache16Bits,
117
118         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
119         /// it, use a larger cache.
120         kCache32Bits    = 8,
121         kCache32Count   = (1 << kCache32Bits),
122         kCache32Shift   = 16 - kCache32Bits,
123         kSqrt32Shift    = 8 - kCache32Bits,
124
125         /// This value is used to *read* the dither cache; it may be 0
126         /// if dithering is disabled.
127         kDitherStride32 = kCache32Count,
128         kDitherStride16 = kCache16Count,
129     };
130
131
132 protected:
133     SkGradientShaderBase(SkReadBuffer& );
134     virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
135     SK_DEVELOPER_TO_STRING()
136
137     SkUnitMapper* fMapper;
138     SkMatrix    fPtsToUnit;     // set by subclass
139     SkMatrix    fDstToIndex;
140     SkMatrix::MapXYProc fDstToIndexProc;
141     TileMode    fTileMode;
142     TileProc    fTileProc;
143     int         fColorCount;
144     uint8_t     fDstToIndexClass;
145     uint8_t     fFlags;
146     uint8_t     fGradFlags;
147
148     struct Rec {
149         SkFixed     fPos;   // 0...1
150         uint32_t    fScale; // (1 << 24) / range
151     };
152     Rec*        fRecs;
153
154     const uint16_t*     getCache16() const;
155     const SkPMColor*    getCache32() const;
156
157     void commonAsAGradient(GradientInfo*) const;
158
159 private:
160     enum {
161         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
162
163         kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
164     };
165     SkColor     fStorage[(kStorageSize + 3) >> 2];
166     SkColor*    fOrigColors; // original colors, before modulation by paint in setContext
167     bool        fColorsAreOpaque;
168
169     mutable uint16_t*   fCache16;   // working ptr. If this is NULL, we need to recompute the cache values
170     mutable SkPMColor*  fCache32;   // working ptr. If this is NULL, we need to recompute the cache values
171
172     mutable uint16_t*   fCache16Storage;    // storage for fCache16, allocated on demand
173     mutable SkMallocPixelRef* fCache32PixelRef;
174     mutable unsigned    fCacheAlpha;        // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
175
176     static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
177     static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
178                                 U8CPU alpha, uint32_t gradFlags);
179     void setCacheAlpha(U8CPU alpha) const;
180     void initCommon();
181
182     typedef SkShader INHERITED;
183 };
184
185 static inline int init_dither_toggle(int x, int y) {
186     x &= 1;
187     y = (y & 1) << 1;
188     return (x | y) * SkGradientShaderBase::kDitherStride32;
189 }
190
191 static inline int next_dither_toggle(int toggle) {
192     return toggle ^ SkGradientShaderBase::kDitherStride32;
193 }
194
195 static inline int init_dither_toggle16(int x, int y) {
196     return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
197 }
198
199 static inline int next_dither_toggle16(int toggle) {
200     return toggle ^ SkGradientShaderBase::kDitherStride16;
201 }
202
203 ///////////////////////////////////////////////////////////////////////////////
204
205 #if SK_SUPPORT_GPU
206
207 #include "GrCoordTransform.h"
208 #include "gl/GrGLEffect.h"
209
210 class GrEffectStage;
211 class GrBackendEffectFactory;
212
213 /*
214  * The interpretation of the texture matrix depends on the sample mode. The
215  * texture matrix is applied both when the texture coordinates are explicit
216  * and  when vertex positions are used as texture  coordinates. In the latter
217  * case the texture matrix is applied to the pre-view-matrix position
218  * values.
219  *
220  * Normal SampleMode
221  *  The post-matrix texture coordinates are in normalize space with (0,0) at
222  *  the top-left and (1,1) at the bottom right.
223  * RadialGradient
224  *  The matrix specifies the radial gradient parameters.
225  *  (0,0) in the post-matrix space is center of the radial gradient.
226  * Radial2Gradient
227  *   Matrix transforms to space where first circle is centered at the
228  *   origin. The second circle will be centered (x, 0) where x may be
229  *   0 and is provided by setRadial2Params. The post-matrix space is
230  *   normalized such that 1 is the second radius - first radius.
231  * SweepGradient
232  *  The angle from the origin of texture coordinates in post-matrix space
233  *  determines the gradient value.
234  */
235
236  class GrTextureStripAtlas;
237
238 // Base class for Gr gradient effects
239 class GrGradientEffect : public GrEffect {
240 public:
241
242     GrGradientEffect(GrContext* ctx,
243                      const SkGradientShaderBase& shader,
244                      const SkMatrix& matrix,
245                      SkShader::TileMode tileMode);
246
247     virtual ~GrGradientEffect();
248
249     bool useAtlas() const { return SkToBool(-1 != fRow); }
250     SkScalar getYCoord() const { return fYCoord; };
251
252     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
253
254     enum ColorType {
255         kTwo_ColorType,
256         kThree_ColorType,
257         kTexture_ColorType
258     };
259
260     ColorType getColorType() const { return fColorType; }
261
262     enum PremulType {
263         kBeforeInterp_PremulType,
264         kAfterInterp_PremulType,
265     };
266
267     PremulType getPremulType() const { return fPremulType; }
268
269     const SkColor* getColors(int pos) const {
270         SkASSERT(fColorType != kTexture_ColorType);
271         SkASSERT((pos-1) <= fColorType);
272         return &fColors[pos];
273     }
274
275 protected:
276
277     /** Populates a pair of arrays with colors and stop info to construct a random gradient.
278         The function decides whether stop values should be used or not. The return value indicates
279         the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
280         sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
281         size kMaxRandomGradientColors. It may be updated to NULL, indicating that NULL should be
282         passed to the gradient factory rather than the array.
283     */
284     static const int kMaxRandomGradientColors = 4;
285     static int RandomGradientParams(SkRandom* r,
286                                     SkColor colors[kMaxRandomGradientColors],
287                                     SkScalar** stops,
288                                     SkShader::TileMode* tm);
289
290     virtual bool onIsEqual(const GrEffect& effect) const SK_OVERRIDE;
291
292     const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
293
294 private:
295     static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
296
297     enum {
298         kMaxAnalyticColors = 3 // if more colors use texture
299     };
300
301     GrCoordTransform fCoordTransform;
302     GrTextureAccess fTextureAccess;
303     SkScalar fYCoord;
304     GrTextureStripAtlas* fAtlas;
305     int fRow;
306     bool fIsOpaque;
307     ColorType fColorType;
308     SkColor fColors[kMaxAnalyticColors];
309     PremulType fPremulType; // This only changes behavior for two and three color special cases.
310                             // It is already baked into to the table for texture gradients.
311     typedef GrEffect INHERITED;
312
313 };
314
315 ///////////////////////////////////////////////////////////////////////////////
316
317 // Base class for GL gradient effects
318 class GrGLGradientEffect : public GrGLEffect {
319 public:
320     GrGLGradientEffect(const GrBackendEffectFactory& factory);
321     virtual ~GrGLGradientEffect();
322
323     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
324
325 protected:
326     enum {
327         kPremulTypeKeyBitCnt = 1,
328         kPremulTypeMask = 1,
329         kPremulBeforeInterpKey = kPremulTypeMask,
330
331         kTwoColorKey = 2 << kPremulTypeKeyBitCnt,
332         kThreeColorKey = 3 << kPremulTypeKeyBitCnt,
333         kColorKeyMask = kTwoColorKey | kThreeColorKey,
334         kColorKeyBitCnt = 2,
335
336         // Subclasses must shift any key bits they produce up by this amount
337         // and combine with the result of GenBaseGradientKey.
338         kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
339     };
340
341     static GrGradientEffect::ColorType ColorTypeFromKey(EffectKey key){
342         if (kTwoColorKey == (key & kColorKeyMask)) {
343             return GrGradientEffect::kTwo_ColorType;
344         } else if (kThreeColorKey == (key & kColorKeyMask)) {
345             return GrGradientEffect::kThree_ColorType;
346         } else {return GrGradientEffect::kTexture_ColorType;}
347     }
348
349     static GrGradientEffect::PremulType PremulTypeFromKey(EffectKey key){
350         if (kPremulBeforeInterpKey == (key & kPremulTypeMask)) {
351             return GrGradientEffect::kBeforeInterp_PremulType;
352         } else {
353             return GrGradientEffect::kAfterInterp_PremulType;
354         }
355     }
356
357     /**
358      * Subclasses must call this. It will return a value restricted to the lower kBaseKeyBitCnt
359      * bits.
360      */
361     static EffectKey GenBaseGradientKey(const GrDrawEffect&);
362
363     // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
364     // should call this method from their emitCode().
365     void emitUniforms(GrGLShaderBuilder* builder, EffectKey key);
366
367
368     // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
369     // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
370     // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
371     void emitColor(GrGLShaderBuilder* builder,
372                    const char* gradientTValue,
373                    EffectKey key,
374                    const char* outputColor,
375                    const char* inputColor,
376                    const TextureSamplerArray& samplers);
377
378 private:
379     SkScalar fCachedYCoord;
380     GrGLUniformManager::UniformHandle fFSYUni;
381     GrGLUniformManager::UniformHandle fColorStartUni;
382     GrGLUniformManager::UniformHandle fColorMidUni;
383     GrGLUniformManager::UniformHandle fColorEndUni;
384
385     typedef GrGLEffect INHERITED;
386 };
387
388 #endif
389
390 #endif