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 "SkColorSpace.h"
16 #include "SkReadBuffer.h"
17 #include "SkWriteBuffer.h"
18 #include "SkMallocPixelRef.h"
19 #include "SkUtils.h"
20 #include "SkShader.h"
21 #include "SkOnce.h"
22 
23 #if SK_SUPPORT_GPU
24     #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
25 #endif
26 
27 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
28                                int count) {
29     if (count > 0) {
30         if (v0 == v1) {
31             sk_memset32(dst, v0, count);
32         } else {
33             int pairs = count >> 1;
34             for (int i = 0; i < pairs; i++) {
35                 *dst++ = v0;
36                 *dst++ = v1;
37             }
38             if (count & 1) {
39                 *dst = v0;
40             }
41         }
42     }
43 }
44 
45 //  Clamp
46 
47 static inline SkFixed clamp_tileproc(SkFixed x) {
48     return SkClampMax(x, 0xFFFF);
49 }
50 
51 // Repeat
52 
53 static inline SkFixed repeat_tileproc(SkFixed x) {
54     return x & 0xFFFF;
55 }
56 
57 // Mirror
58 
59 static inline SkFixed mirror_tileproc(SkFixed x) {
60     int s = SkLeftShift(x, 15) >> 31;
61     return (x ^ s) & 0xFFFF;
62 }
63 
64 ///////////////////////////////////////////////////////////////////////////////
65 
66 typedef SkFixed (*TileProc)(SkFixed);
67 
68 ///////////////////////////////////////////////////////////////////////////////
69 
70 static const TileProc gTileProcs[] = {
71     clamp_tileproc,
72     repeat_tileproc,
73     mirror_tileproc
74 };
75 
76 ///////////////////////////////////////////////////////////////////////////////
77 
78 class SkGradientShaderBase : public SkShader {
79 public:
80     struct Descriptor {
81         Descriptor() {
82             sk_bzero(this, sizeof(*this));
83             fTileMode = SkShader::kClamp_TileMode;
84         }
85 
86         const SkMatrix*     fLocalMatrix;
87         const SkColor4f*    fColors;
88         sk_sp<SkColorSpace> fColorSpace;
89         const SkScalar*     fPos;
90         int                 fCount;
91         SkShader::TileMode  fTileMode;
92         uint32_t            fGradFlags;
93 
94         void flatten(SkWriteBuffer&) const;
95     };
96 
97     class DescriptorScope : public Descriptor {
98     public:
99         DescriptorScope() {}
100 
101         bool unflatten(SkReadBuffer&);
102 
103         // fColors and fPos always point into local memory, so they can be safely mutated
104         //
105         SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
106         SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
107 
108     private:
109         enum {
110             kStorageCount = 16
111         };
112         SkColor4f fColorStorage[kStorageCount];
113         SkScalar fPosStorage[kStorageCount];
114         SkMatrix fLocalMatrixStorage;
115         SkAutoMalloc fDynamicStorage;
116     };
117 
118     SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
119     virtual ~SkGradientShaderBase();
120 
121     // The cache is initialized on-demand when getCache32 is called.
122     class GradientShaderCache : public SkRefCnt {
123     public:
124         GradientShaderCache(U8CPU alpha, bool dither, const SkGradientShaderBase& shader);
125         ~GradientShaderCache();
126 
127         const SkPMColor*    getCache32();
128 
129         SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
130 
131         unsigned getAlpha() const { return fCacheAlpha; }
132         bool getDither() const { return fCacheDither; }
133 
134     private:
135         // Working pointer. If it's nullptr, we need to recompute the cache values.
136         SkPMColor*  fCache32;
137 
138         SkMallocPixelRef* fCache32PixelRef;
139         const unsigned    fCacheAlpha;        // The alpha value we used when we computed the cache.
140                                               // Larger than 8bits so we can store uninitialized
141                                               // value.
142         const bool        fCacheDither;       // The dither flag used when we computed the cache.
143 
144         const SkGradientShaderBase& fShader;
145 
146         // Make sure we only initialize the cache once.
147         SkOnce fCache32InitOnce;
148 
149         static void initCache32(GradientShaderCache* cache);
150 
151         static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
152                                     U8CPU alpha, uint32_t gradFlags, bool dither);
153     };
154 
155     class GradientShaderBaseContext : public SkShader::Context {
156     public:
157         GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
158 
159         uint32_t getFlags() const override { return fFlags; }
160 
161         bool isValid() const;
162 
163     protected:
164         SkMatrix    fDstToIndex;
165         SkMatrix::MapXYProc fDstToIndexProc;
166         uint8_t     fDstToIndexClass;
167         uint8_t     fFlags;
168         bool        fDither;
169 
170         SkAutoTUnref<GradientShaderCache> fCache;
171 
172     private:
173         typedef SkShader::Context INHERITED;
174     };
175 
176     bool isOpaque() const override;
177 
178     enum class GradientBitmapType : uint8_t {
179         kLegacy,
180         kSRGB,
181         kHalfFloat,
182     };
183 
184     void getGradientTableBitmap(SkBitmap*, GradientBitmapType bitmapType) const;
185 
186     enum {
187         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
188         /// it, use a larger cache.
189         kCache32Bits    = 8,
190         kCache32Count   = (1 << kCache32Bits),
191         kCache32Shift   = 16 - kCache32Bits,
192         kSqrt32Shift    = 8 - kCache32Bits,
193 
194         /// This value is used to *read* the dither cache; it may be 0
195         /// if dithering is disabled.
196         kDitherStride32 = kCache32Count,
197     };
198 
199     uint32_t getGradFlags() const { return fGradFlags; }
200 
201 protected:
202     class GradientShaderBase4fContext;
203 
204     SkGradientShaderBase(SkReadBuffer& );
205     void flatten(SkWriteBuffer&) const override;
206     SK_TO_STRING_OVERRIDE()
207 
208     const SkMatrix fPtsToUnit;
209     TileMode    fTileMode;
210     TileProc    fTileProc;
211     uint8_t     fGradFlags;
212 
213     struct Rec {
214         SkFixed     fPos;   // 0...1
215         uint32_t    fScale; // (1 << 24) / range
216     };
217     Rec*        fRecs;
218 
219     void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
220 
221     bool onAsLuminanceColor(SkColor*) const override;
222 
223 
224     void initLinearBitmap(SkBitmap* bitmap) const;
225 
226     /*
227      * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
228      * Count is the number of colors in the gradient
229      * It will then flip all the color and rec information and return in their respective Dst
230      * pointers. It is assumed that space has already been allocated for the Dst pointers.
231      * The rec src and dst are only assumed to be valid if count > 2
232      */
233     static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
234                                    SkColor* colorSrc, Rec* recSrc,
235                                    int count);
236 
237     template <typename T, typename... Args>
238     static Context* CheckedCreateContext(void* storage, Args&&... args) {
239         auto* ctx = new (storage) T(std::forward<Args>(args)...);
240         if (!ctx->isValid()) {
241             ctx->~T();
242             return nullptr;
243         }
244         return ctx;
245     }
246 
247 private:
248     enum {
249         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
250 
251         kStorageSize = kColorStorageCount *
252                        (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec) + sizeof(SkColor4f))
253     };
254     SkColor             fStorage[(kStorageSize + 3) >> 2];
255 public:
256     SkColor*            fOrigColors;   // original colors, before modulation by paint in context.
257     SkColor4f*          fOrigColors4f; // original colors, as linear floats
258     SkScalar*           fOrigPos;      // original positions
259     int                 fColorCount;
260     sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
261 
262     bool colorsAreOpaque() const { return fColorsAreOpaque; }
263 
264     TileMode getTileMode() const { return fTileMode; }
265     Rec* getRecs() const { return fRecs; }
266 
267 private:
268     bool                fColorsAreOpaque;
269 
270     GradientShaderCache* refCache(U8CPU alpha, bool dither) const;
271     mutable SkMutex                           fCacheMutex;
272     mutable SkAutoTUnref<GradientShaderCache> fCache;
273 
274     void initCommon();
275 
276     typedef SkShader INHERITED;
277 };
278 
279 static inline int init_dither_toggle(int x, int y) {
280     x &= 1;
281     y = (y & 1) << 1;
282     return (x | y) * SkGradientShaderBase::kDitherStride32;
283 }
284 
285 static inline int next_dither_toggle(int toggle) {
286     return toggle ^ SkGradientShaderBase::kDitherStride32;
287 }
288 
289 ///////////////////////////////////////////////////////////////////////////////
290 
291 #if SK_SUPPORT_GPU
292 
293 #include "GrColorSpaceXform.h"
294 #include "GrCoordTransform.h"
295 #include "GrFragmentProcessor.h"
296 #include "glsl/GrGLSLFragmentProcessor.h"
297 #include "glsl/GrGLSLProgramDataManager.h"
298 
299 class GrInvariantOutput;
300 
301 /*
302  * The interpretation of the texture matrix depends on the sample mode. The
303  * texture matrix is applied both when the texture coordinates are explicit
304  * and  when vertex positions are used as texture  coordinates. In the latter
305  * case the texture matrix is applied to the pre-view-matrix position
306  * values.
307  *
308  * Normal SampleMode
309  *  The post-matrix texture coordinates are in normalize space with (0,0) at
310  *  the top-left and (1,1) at the bottom right.
311  * RadialGradient
312  *  The matrix specifies the radial gradient parameters.
313  *  (0,0) in the post-matrix space is center of the radial gradient.
314  * Radial2Gradient
315  *   Matrix transforms to space where first circle is centered at the
316  *   origin. The second circle will be centered (x, 0) where x may be
317  *   0 and is provided by setRadial2Params. The post-matrix space is
318  *   normalized such that 1 is the second radius - first radius.
319  * SweepGradient
320  *  The angle from the origin of texture coordinates in post-matrix space
321  *  determines the gradient value.
322  */
323 
324  class GrTextureStripAtlas;
325 
326 // Base class for Gr gradient effects
327 class GrGradientEffect : public GrFragmentProcessor {
328 public:
329     struct CreateArgs {
330         CreateArgs(GrContext* context,
331                    const SkGradientShaderBase* shader,
332                    const SkMatrix* matrix,
333                    SkShader::TileMode tileMode,
334                    sk_sp<GrColorSpaceXform> colorSpaceXform,
335                    bool gammaCorrect)
336             : fContext(context)
337             , fShader(shader)
338             , fMatrix(matrix)
339             , fTileMode(tileMode)
340             , fColorSpaceXform(std::move(colorSpaceXform))
341             , fGammaCorrect(gammaCorrect) {}
342 
343         GrContext*                  fContext;
344         const SkGradientShaderBase* fShader;
345         const SkMatrix*             fMatrix;
346         SkShader::TileMode          fTileMode;
347         sk_sp<GrColorSpaceXform>    fColorSpaceXform;
348         bool                        fGammaCorrect;
349     };
350 
351     class GLSLProcessor;
352 
353     GrGradientEffect(const CreateArgs&);
354 
355     virtual ~GrGradientEffect();
356 
357     bool useAtlas() const { return SkToBool(-1 != fRow); }
358     SkScalar getYCoord() const { return fYCoord; }
359 
360     enum ColorType {
361         kTwo_ColorType,
362         kThree_ColorType, // Symmetric three color
363         kTexture_ColorType,
364 
365 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
366         kHardStopCentered_ColorType,   // 0, 0.5, 0.5, 1
367         kHardStopLeftEdged_ColorType,  // 0, 0, 1
368         kHardStopRightEdged_ColorType, // 0, 1, 1
369 #endif
370     };
371 
372     ColorType getColorType() const { return fColorType; }
373 
374     // Determines the type of gradient, one of:
375     //    - Two-color
376     //    - Symmetric three-color
377     //    - Texture
378     //    - Centered hard stop
379     //    - Left-edged hard stop
380     //    - Right-edged hard stop
381     ColorType determineColorType(const SkGradientShaderBase& shader);
382 
383     enum PremulType {
384         kBeforeInterp_PremulType,
385         kAfterInterp_PremulType,
386     };
387 
388     PremulType getPremulType() const { return fPremulType; }
389 
390     const SkColor* getColors(int pos) const {
391         SkASSERT(fColorType != kTexture_ColorType);
392         SkASSERT(pos < fColors.count());
393         return &fColors[pos];
394     }
395 
396     const SkColor4f* getColors4f(int pos) const {
397         SkASSERT(fColorType != kTexture_ColorType);
398         SkASSERT(pos < fColors4f.count());
399         return &fColors4f[pos];
400     }
401 
402 protected:
403     /** Populates a pair of arrays with colors and stop info to construct a random gradient.
404         The function decides whether stop values should be used or not. The return value indicates
405         the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
406         sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
407         size kMaxRandomGradientColors. It may be updated to nullptr, indicating that nullptr should
408         be passed to the gradient factory rather than the array.
409     */
410     static const int kMaxRandomGradientColors = 4;
411     static int RandomGradientParams(SkRandom* r,
412                                     SkColor colors[kMaxRandomGradientColors],
413                                     SkScalar** stops,
414                                     SkShader::TileMode* tm);
415 
416     bool onIsEqual(const GrFragmentProcessor&) const override;
417 
418     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
419 
420     const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
421 
422 private:
423     // If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then
424     // fColors4f and fColorSpaceXform will be populated.
425     SkTDArray<SkColor>       fColors;
426 
427     SkTDArray<SkColor4f>     fColors4f;
428     sk_sp<GrColorSpaceXform> fColorSpaceXform;
429 
430     SkTDArray<SkScalar>      fPositions;
431     SkShader::TileMode       fTileMode;
432 
433     GrCoordTransform fCoordTransform;
434     GrTextureAccess fTextureAccess;
435     SkScalar fYCoord;
436     GrTextureStripAtlas* fAtlas;
437     int fRow;
438     bool fIsOpaque;
439     ColorType fColorType;
440     PremulType fPremulType; // This is already baked into the table for texture gradients, and
441                             // only changes behavior for gradients that don't use a texture.
442     typedef GrFragmentProcessor INHERITED;
443 
444 };
445 
446 ///////////////////////////////////////////////////////////////////////////////
447 
448 // Base class for GL gradient effects
449 class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
450 public:
451     GLSLProcessor() {
452         fCachedYCoord = SK_ScalarMax;
453     }
454 
455 protected:
456     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
457 
458 protected:
459     /**
460      * Subclasses must call this. It will return a key for the part of the shader code controlled
461      * by the base class. The subclasses must stick it in their key and then pass it to the below
462      * emit* functions from their emitCode function.
463      */
464     static uint32_t GenBaseGradientKey(const GrProcessor&);
465 
466     // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
467     // should call this method from their emitCode().
468     void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
469 
470     // Emit code that gets a fragment's color from an expression for t; has branches for
471     // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
472     // color gradients that use the traditional texture lookup, as well as several varieties
473     // of hard stop gradients
474     void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
475                    GrGLSLUniformHandler* uniformHandler,
476                    const GrGLSLCaps* caps,
477                    const GrGradientEffect&,
478                    const char* gradientTValue,
479                    const char* outputColor,
480                    const char* inputColor,
481                    const TextureSamplers&);
482 
483 private:
484     enum {
485         // First bit for premul before/after interp
486         kPremulBeforeInterpKey  =  1,
487 
488         // Next three bits for 2/3 color type or different special
489         // hard stop cases (neither means using texture atlas)
490         kTwoColorKey            =  2,
491         kThreeColorKey          =  4,
492 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
493         kHardStopCenteredKey    =  6,
494         kHardStopZeroZeroOneKey =  8,
495         kHardStopZeroOneOneKey  = 10,
496 
497         // Next two bits for tile mode
498         kClampTileMode          = 16,
499         kRepeatTileMode         = 32,
500         kMirrorTileMode         = 48,
501 
502         // Lower six bits for premul, 2/3 color type, and tile mode
503         kReservedBits           = 6,
504 #endif
505     };
506 
507     SkScalar fCachedYCoord;
508     GrGLSLProgramDataManager::UniformHandle fColorsUni;
509     GrGLSLProgramDataManager::UniformHandle fFSYUni;
510     GrGLSLProgramDataManager::UniformHandle fColorSpaceXformUni;
511 
512     typedef GrGLSLFragmentProcessor INHERITED;
513 };
514 
515 #endif
516 
517 #endif
518