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
sk_memset32_dither(uint32_t dst[],uint32_t v0,uint32_t v1,int count)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
clamp_tileproc(SkFixed x)43 static inline SkFixed clamp_tileproc(SkFixed x) {
44 return SkClampMax(x, 0xFFFF);
45 }
46
47 // Repeat
48
repeat_tileproc(SkFixed x)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
mirror_tileproc(SkFixed x)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 {
DescriptorDescriptor87 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:
DescriptorScope()104 DescriptorScope() {}
105
106 bool unflatten(SkReadBuffer&);
107
108 // fColors and fPos always point into local memory, so they can be safely mutated
109 //
mutableColors()110 SkColor* mutableColors() { return const_cast<SkColor*>(fColors); }
mutablePos()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
123 public:
124 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
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
getCache32PixelRef()136 SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
137
getAlpha()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
getFlags()169 uint32_t getFlags() const 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 bool isOpaque() const 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
getGradFlags()219 uint32_t getGradFlags() const { return fGradFlags; }
220
221 protected:
222 SkGradientShaderBase(SkReadBuffer& );
223 void flatten(SkWriteBuffer&) const override;
224 SK_TO_STRING_OVERRIDE()
225
226 const SkMatrix fPtsToUnit;
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 bool onAsLuminanceColor(SkColor*) const 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 private:
254 enum {
255 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
256
257 kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec))
258 };
259 SkColor fStorage[(kStorageSize + 3) >> 2];
260 SkColor* fOrigColors; // original colors, before modulation by paint in context.
261 SkScalar* fOrigPos; // original positions
262 bool fColorsAreOpaque;
263
264 GradientShaderCache* refCache(U8CPU alpha) const;
265 mutable SkMutex fCacheMutex;
266 mutable SkAutoTUnref<GradientShaderCache> fCache;
267
268 void initCommon();
269
270 typedef SkShader INHERITED;
271 };
272
init_dither_toggle(int x,int y)273 static inline int init_dither_toggle(int x, int y) {
274 x &= 1;
275 y = (y & 1) << 1;
276 return (x | y) * SkGradientShaderBase::kDitherStride32;
277 }
278
next_dither_toggle(int toggle)279 static inline int next_dither_toggle(int toggle) {
280 return toggle ^ SkGradientShaderBase::kDitherStride32;
281 }
282
init_dither_toggle16(int x,int y)283 static inline int init_dither_toggle16(int x, int y) {
284 return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
285 }
286
next_dither_toggle16(int toggle)287 static inline int next_dither_toggle16(int toggle) {
288 return toggle ^ SkGradientShaderBase::kDitherStride16;
289 }
290
291 ///////////////////////////////////////////////////////////////////////////////
292
293 #if SK_SUPPORT_GPU
294
295 #include "GrCoordTransform.h"
296 #include "GrFragmentProcessor.h"
297 #include "gl/GrGLProcessor.h"
298
299 class GrFragmentStage;
300 class GrInvariantOutput;
301
302 /*
303 * The interpretation of the texture matrix depends on the sample mode. The
304 * texture matrix is applied both when the texture coordinates are explicit
305 * and when vertex positions are used as texture coordinates. In the latter
306 * case the texture matrix is applied to the pre-view-matrix position
307 * values.
308 *
309 * Normal SampleMode
310 * The post-matrix texture coordinates are in normalize space with (0,0) at
311 * the top-left and (1,1) at the bottom right.
312 * RadialGradient
313 * The matrix specifies the radial gradient parameters.
314 * (0,0) in the post-matrix space is center of the radial gradient.
315 * Radial2Gradient
316 * Matrix transforms to space where first circle is centered at the
317 * origin. The second circle will be centered (x, 0) where x may be
318 * 0 and is provided by setRadial2Params. The post-matrix space is
319 * normalized such that 1 is the second radius - first radius.
320 * SweepGradient
321 * The angle from the origin of texture coordinates in post-matrix space
322 * determines the gradient value.
323 */
324
325 class GrTextureStripAtlas;
326
327 // Base class for Gr gradient effects
328 class GrGradientEffect : public GrFragmentProcessor {
329 public:
330
331 GrGradientEffect(GrContext* ctx,
332 const SkGradientShaderBase& shader,
333 const SkMatrix& matrix,
334 SkShader::TileMode tileMode);
335
336 virtual ~GrGradientEffect();
337
useAtlas()338 bool useAtlas() const { return SkToBool(-1 != fRow); }
getYCoord()339 SkScalar getYCoord() const { return fYCoord; };
340
getColorType()341 SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
342
343 enum PremulType {
344 kBeforeInterp_PremulType,
345 kAfterInterp_PremulType,
346 };
347
getPremulType()348 PremulType getPremulType() const { return fPremulType; }
349
getColors(int pos)350 const SkColor* getColors(int pos) const {
351 SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
352 SkASSERT((pos-1) <= fColorType);
353 return &fColors[pos];
354 }
355
356 protected:
357
358 /** Populates a pair of arrays with colors and stop info to construct a random gradient.
359 The function decides whether stop values should be used or not. The return value indicates
360 the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
361 sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
362 size kMaxRandomGradientColors. It may be updated to NULL, indicating that NULL should be
363 passed to the gradient factory rather than the array.
364 */
365 static const int kMaxRandomGradientColors = 4;
366 static int RandomGradientParams(SkRandom* r,
367 SkColor colors[kMaxRandomGradientColors],
368 SkScalar** stops,
369 SkShader::TileMode* tm);
370
371 bool onIsEqual(const GrFragmentProcessor&) const override;
372
373 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
374
getCoordTransform()375 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
376
377 private:
378 static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
379
380 GrCoordTransform fCoordTransform;
381 GrTextureAccess fTextureAccess;
382 SkScalar fYCoord;
383 GrTextureStripAtlas* fAtlas;
384 int fRow;
385 bool fIsOpaque;
386 SkGradientShaderBase::GpuColorType fColorType;
387 SkColor fColors[3]; // More than 3 colors we use texture
388 PremulType fPremulType; // This only changes behavior for two and three color special cases.
389 // It is already baked into to the table for texture gradients.
390 typedef GrFragmentProcessor INHERITED;
391
392 };
393
394 ///////////////////////////////////////////////////////////////////////////////
395
396 // Base class for GL gradient effects
397 class GrGLGradientEffect : public GrGLFragmentProcessor {
398 public:
399 GrGLGradientEffect();
400 virtual ~GrGLGradientEffect();
401
402 void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
403
404 protected:
405 /**
406 * Subclasses must call this. It will return a key for the part of the shader code controlled
407 * by the base class. The subclasses must stick it in their key and then pass it to the below
408 * emit* functions from their emitCode function.
409 */
410 static uint32_t GenBaseGradientKey(const GrProcessor&);
411
412 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
413 // should call this method from their emitCode().
414 void emitUniforms(GrGLFPBuilder* builder, const GrGradientEffect&);
415
416
417 // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
418 // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
419 // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
420 void emitColor(GrGLFPBuilder* builder,
421 const GrGradientEffect&,
422 const char* gradientTValue,
423 const char* outputColor,
424 const char* inputColor,
425 const TextureSamplerArray& samplers);
426
427 private:
428 enum {
429 kPremulTypeKeyBitCnt = 1,
430 kPremulTypeMask = 1,
431 kPremulBeforeInterpKey = kPremulTypeMask,
432
433 kTwoColorKey = 2 << kPremulTypeKeyBitCnt,
434 kThreeColorKey = 3 << kPremulTypeKeyBitCnt,
435 kColorKeyMask = kTwoColorKey | kThreeColorKey,
436 kColorKeyBitCnt = 2,
437
438 // Subclasses must shift any key bits they produce up by this amount
439 // and combine with the result of GenBaseGradientKey.
440 kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
441 };
442 GR_STATIC_ASSERT(kBaseKeyBitCnt <= 32);
443
444 SkScalar fCachedYCoord;
445 GrGLProgramDataManager::UniformHandle fFSYUni;
446 GrGLProgramDataManager::UniformHandle fColorStartUni;
447 GrGLProgramDataManager::UniformHandle fColorMidUni;
448 GrGLProgramDataManager::UniformHandle fColorEndUni;
449
450 typedef GrGLFragmentProcessor INHERITED;
451 };
452
453 #endif
454
455 #endif
456