blob: 4b7bbb0a0a13e16224f9a232169b6374025f43d5 [file] [log] [blame]
rileya@google.com1c6d64b2012-07-27 15:49:05 +00001/*
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
reeda6cac4c2014-08-21 10:50:25 -070011#include "SkGradientBitmapCache.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000012#include "SkGradientShader.h"
13#include "SkClampRange.h"
14#include "SkColorPriv.h"
brianosmanb9c51372016-09-15 11:09:45 -070015#include "SkColorSpace.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000016#include "SkReadBuffer.h"
17#include "SkWriteBuffer.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000018#include "SkMallocPixelRef.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000019#include "SkUtils.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000020#include "SkShader.h"
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000021#include "SkOnce.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000022
fmenozzicd9a1d02016-08-15 07:03:47 -070023#if SK_SUPPORT_GPU
24 #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
25#endif
26
humper@google.com05af1af2013-01-07 16:47:43 +000027static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
rileya@google.com1c6d64b2012-07-27 15:49:05 +000028 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
humper@google.com05af1af2013-01-07 16:47:43 +000047static inline SkFixed clamp_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000048 return SkClampMax(x, 0xFFFF);
49}
50
51// Repeat
52
humper@google.com05af1af2013-01-07 16:47:43 +000053static inline SkFixed repeat_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000054 return x & 0xFFFF;
55}
56
57// Mirror
58
rileya@google.com1c6d64b2012-07-27 15:49:05 +000059static inline SkFixed mirror_tileproc(SkFixed x) {
caryclark3127c992015-12-09 12:02:30 -080060 int s = SkLeftShift(x, 15) >> 31;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000061 return (x ^ s) & 0xFFFF;
62}
63
rileya@google.com1c6d64b2012-07-27 15:49:05 +000064///////////////////////////////////////////////////////////////////////////////
65
66typedef SkFixed (*TileProc)(SkFixed);
67
68///////////////////////////////////////////////////////////////////////////////
69
70static const TileProc gTileProcs[] = {
71 clamp_tileproc,
72 repeat_tileproc,
73 mirror_tileproc
74};
75
76///////////////////////////////////////////////////////////////////////////////
77
78class SkGradientShaderBase : public SkShader {
79public:
reed@google.com437d6eb2013-05-23 19:03:05 +000080 struct Descriptor {
81 Descriptor() {
82 sk_bzero(this, sizeof(*this));
83 fTileMode = SkShader::kClamp_TileMode;
84 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000085
reedaddf2ed2014-08-11 08:28:24 -070086 const SkMatrix* fLocalMatrix;
brianosmane25d71c2016-09-28 11:27:28 -070087 const SkColor4f* fColors;
brianosmanb9c51372016-09-15 11:09:45 -070088 sk_sp<SkColorSpace> fColorSpace;
reed@google.com437d6eb2013-05-23 19:03:05 +000089 const SkScalar* fPos;
90 int fCount;
91 SkShader::TileMode fTileMode;
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000092 uint32_t fGradFlags;
reed9fa60da2014-08-21 07:59:51 -070093
94 void flatten(SkWriteBuffer&) const;
95 };
96
97 class DescriptorScope : public Descriptor {
98 public:
99 DescriptorScope() {}
mtklein88fd0fb2014-12-01 06:56:38 -0800100
reed9fa60da2014-08-21 07:59:51 -0700101 bool unflatten(SkReadBuffer&);
102
103 // fColors and fPos always point into local memory, so they can be safely mutated
104 //
brianosmane25d71c2016-09-28 11:27:28 -0700105 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
reed9fa60da2014-08-21 07:59:51 -0700106 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
107
108 private:
109 enum {
110 kStorageCount = 16
111 };
brianosmane25d71c2016-09-28 11:27:28 -0700112 SkColor4f fColorStorage[kStorageCount];
reed9fa60da2014-08-21 07:59:51 -0700113 SkScalar fPosStorage[kStorageCount];
114 SkMatrix fLocalMatrixStorage;
115 SkAutoMalloc fDynamicStorage;
reed@google.com437d6eb2013-05-23 19:03:05 +0000116 };
117
mtkleincc695fe2014-12-10 10:29:19 -0800118 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000119 virtual ~SkGradientShaderBase();
120
brianosman93110a82016-09-15 08:40:21 -0700121 // The cache is initialized on-demand when getCache32 is called.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000122 class GradientShaderCache : public SkRefCnt {
123 public:
fmalita37d86882015-10-09 10:22:46 -0700124 GradientShaderCache(U8CPU alpha, bool dither, const SkGradientShaderBase& shader);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000125 ~GradientShaderCache();
126
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000127 const SkPMColor* getCache32();
128
129 SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
130
131 unsigned getAlpha() const { return fCacheAlpha; }
fmalita37d86882015-10-09 10:22:46 -0700132 bool getDither() const { return fCacheDither; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000133
134 private:
brianosman93110a82016-09-15 08:40:21 -0700135 // Working pointer. If it's nullptr, we need to recompute the cache values.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000136 SkPMColor* fCache32;
137
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000138 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.
fmalita37d86882015-10-09 10:22:46 -0700142 const bool fCacheDither; // The dither flag used when we computed the cache.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000143
144 const SkGradientShaderBase& fShader;
145
brianosman93110a82016-09-15 08:40:21 -0700146 // Make sure we only initialize the cache once.
147 SkOnce fCache32InitOnce;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000148
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000149 static void initCache32(GradientShaderCache* cache);
150
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000151 static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
fmalita37d86882015-10-09 10:22:46 -0700152 U8CPU alpha, uint32_t gradFlags, bool dither);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000153 };
154
155 class GradientShaderBaseContext : public SkShader::Context {
156 public:
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000157 GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000158
mtklein36352bf2015-03-25 18:17:31 -0700159 uint32_t getFlags() const override { return fFlags; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000160
fmalita088e21b2016-10-05 09:28:42 -0700161 bool isValid() const;
162
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000163 protected:
164 SkMatrix fDstToIndex;
165 SkMatrix::MapXYProc fDstToIndexProc;
166 uint8_t fDstToIndexClass;
167 uint8_t fFlags;
fmalita37d86882015-10-09 10:22:46 -0700168 bool fDither;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000169
Hal Canary67b39de2016-11-07 11:47:44 -0500170 sk_sp<GradientShaderCache> fCache;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000171
172 private:
173 typedef SkShader::Context INHERITED;
174 };
175
mtklein36352bf2015-03-25 18:17:31 -0700176 bool isOpaque() const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000177
brianosmand4546092016-09-22 12:31:58 -0700178 enum class GradientBitmapType : uint8_t {
179 kLegacy,
180 kSRGB,
181 kHalfFloat,
182 };
183
184 void getGradientTableBitmap(SkBitmap*, GradientBitmapType bitmapType) const;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000185
186 enum {
187 /// Seems like enough for visual accuracy. TODO: if pos[] deserves
188 /// it, use a larger cache.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000189 kCache32Bits = 8,
reed@google.com60040292013-02-04 18:21:23 +0000190 kCache32Count = (1 << kCache32Bits),
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000191 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.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000196 kDitherStride32 = kCache32Count,
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000197 };
198
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +0000199 uint32_t getGradFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000200
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000201protected:
fmalitabc590c02016-02-22 09:12:33 -0800202 class GradientShaderBase4fContext;
203
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000204 SkGradientShaderBase(SkReadBuffer& );
mtklein36352bf2015-03-25 18:17:31 -0700205 void flatten(SkWriteBuffer&) const override;
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000206 SK_TO_STRING_OVERRIDE()
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000207
mtkleincc695fe2014-12-10 10:29:19 -0800208 const SkMatrix fPtsToUnit;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000209 TileMode fTileMode;
210 TileProc fTileProc;
reed@google.com3d3a8602013-05-24 14:58:44 +0000211 uint8_t fGradFlags;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000212
213 struct Rec {
214 SkFixed fPos; // 0...1
215 uint32_t fScale; // (1 << 24) / range
216 };
217 Rec* fRecs;
218
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000219 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
skia.committer@gmail.comd3b28e82014-04-22 03:05:17 +0000220
mtklein36352bf2015-03-25 18:17:31 -0700221 bool onAsLuminanceColor(SkColor*) const override;
reed8367b8c2014-08-22 08:30:20 -0700222
brianosmand4546092016-09-22 12:31:58 -0700223
224 void initLinearBitmap(SkBitmap* bitmap) const;
225
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000226 /*
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
fmalita088e21b2016-10-05 09:28:42 -0700237 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
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000247private:
248 enum {
249 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
250
brianosmanb9c51372016-09-15 11:09:45 -0700251 kStorageSize = kColorStorageCount *
252 (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec) + sizeof(SkColor4f))
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000253 };
brianosmanb9c51372016-09-15 11:09:45 -0700254 SkColor fStorage[(kStorageSize + 3) >> 2];
reedf3182eb2015-11-17 08:12:19 -0800255public:
brianosmanb9c51372016-09-15 11:09:45 -0700256 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
reedf3182eb2015-11-17 08:12:19 -0800261
262 bool colorsAreOpaque() const { return fColorsAreOpaque; }
263
fmenozzicd9a1d02016-08-15 07:03:47 -0700264 TileMode getTileMode() const { return fTileMode; }
265 Rec* getRecs() const { return fRecs; }
266
reedf3182eb2015-11-17 08:12:19 -0800267private:
brianosmanb9c51372016-09-15 11:09:45 -0700268 bool fColorsAreOpaque;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000269
Hal Canary67b39de2016-11-07 11:47:44 -0500270 sk_sp<GradientShaderCache> refCache(U8CPU alpha, bool dither) const;
271 mutable SkMutex fCacheMutex;
272 mutable sk_sp<GradientShaderCache> fCache;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000273
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000274 void initCommon();
275
276 typedef SkShader INHERITED;
277};
278
reed@google.com55853db2013-02-01 19:34:59 +0000279static inline int init_dither_toggle(int x, int y) {
reed@google.com60040292013-02-04 18:21:23 +0000280 x &= 1;
281 y = (y & 1) << 1;
282 return (x | y) * SkGradientShaderBase::kDitherStride32;
reed@google.com55853db2013-02-01 19:34:59 +0000283}
284
285static inline int next_dither_toggle(int toggle) {
286 return toggle ^ SkGradientShaderBase::kDitherStride32;
287}
288
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000289///////////////////////////////////////////////////////////////////////////////
290
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000291#if SK_SUPPORT_GPU
292
brianosmanb9c51372016-09-15 11:09:45 -0700293#include "GrColorSpaceXform.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +0000294#include "GrCoordTransform.h"
bsalomon6251d172014-10-15 10:50:36 -0700295#include "GrFragmentProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -0800296#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -0700297#include "glsl/GrGLSLProgramDataManager.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000298
egdaniel605dd0f2014-11-12 08:35:25 -0800299class GrInvariantOutput;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000300
301/*
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000302 * The interpretation of the texture matrix depends on the sample mode. The
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000303 * texture matrix is applied both when the texture coordinates are explicit
304 * and when vertex positions are used as texture coordinates. In the latter
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000305 * case the texture matrix is applied to the pre-view-matrix position
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000306 * 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
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000316 * 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
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000318 * 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
rileya@google.comb3e50f22012-08-20 17:43:08 +0000324 class GrTextureStripAtlas;
325
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000326// Base class for Gr gradient effects
joshualittb0a8a372014-09-23 09:50:21 -0700327class GrGradientEffect : public GrFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000328public:
brianosman9557c272016-09-15 06:59:15 -0700329 struct CreateArgs {
330 CreateArgs(GrContext* context,
331 const SkGradientShaderBase* shader,
332 const SkMatrix* matrix,
brianosmanb9c51372016-09-15 11:09:45 -0700333 SkShader::TileMode tileMode,
334 sk_sp<GrColorSpaceXform> colorSpaceXform,
335 bool gammaCorrect)
brianosman9557c272016-09-15 06:59:15 -0700336 : fContext(context)
337 , fShader(shader)
338 , fMatrix(matrix)
brianosmanb9c51372016-09-15 11:09:45 -0700339 , fTileMode(tileMode)
340 , fColorSpaceXform(std::move(colorSpaceXform))
341 , fGammaCorrect(gammaCorrect) {}
brianosman9557c272016-09-15 06:59:15 -0700342
343 GrContext* fContext;
344 const SkGradientShaderBase* fShader;
345 const SkMatrix* fMatrix;
346 SkShader::TileMode fTileMode;
brianosmanb9c51372016-09-15 11:09:45 -0700347 sk_sp<GrColorSpaceXform> fColorSpaceXform;
348 bool fGammaCorrect;
brianosman9557c272016-09-15 06:59:15 -0700349 };
350
fmenozzi55d318d2016-08-09 08:05:57 -0700351 class GLSLProcessor;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000352
brianosman9557c272016-09-15 06:59:15 -0700353 GrGradientEffect(const CreateArgs&);
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000354
355 virtual ~GrGradientEffect();
356
rileya@google.comb3e50f22012-08-20 17:43:08 +0000357 bool useAtlas() const { return SkToBool(-1 != fRow); }
fmenozzicd9a1d02016-08-15 07:03:47 -0700358 SkScalar getYCoord() const { return fYCoord; }
rileya@google.comb3e50f22012-08-20 17:43:08 +0000359
fmenozzicd9a1d02016-08-15 07:03:47 -0700360 enum ColorType {
361 kTwo_ColorType,
362 kThree_ColorType, // Symmetric three color
363 kTexture_ColorType,
364
365#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
Brian Salomon466ad992016-10-13 16:08:36 -0400366 kSingleHardStop_ColorType, // 0, t, t, 1
fmenozzicd9a1d02016-08-15 07:03:47 -0700367 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);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000382
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 {
fmenozzicd9a1d02016-08-15 07:03:47 -0700391 SkASSERT(fColorType != kTexture_ColorType);
392 SkASSERT(pos < fColors.count());
bsalomon@google.com82d12232013-09-09 15:36:26 +0000393 return &fColors[pos];
394 }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000395
brianosmanb9c51372016-09-15 11:09:45 -0700396 const SkColor4f* getColors4f(int pos) const {
397 SkASSERT(fColorType != kTexture_ColorType);
398 SkASSERT(pos < fColors4f.count());
399 return &fColors4f[pos];
400 }
401
bsalomon@google.comd4726202012-08-03 14:34:46 +0000402protected:
Brian Osmane75c19f2016-10-10 11:26:43 -0400403 /** Helper struct that stores (and populates) parameters to construct a random gradient.
Brian Osmana2196532016-10-17 12:48:13 -0400404 If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and
405 fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount
406 will be the number of color stops in either case, and fColors and fStops can be passed to
407 the gradient factory. (The constructor may decide not to use stops, in which case fStops
408 will be nullptr). */
Brian Osman3f748602016-10-03 18:29:03 -0400409 struct RandomGradientParams {
Brian Osmane75c19f2016-10-10 11:26:43 -0400410 static const int kMaxRandomGradientColors = 4;
411
Brian Osman3f748602016-10-03 18:29:03 -0400412 RandomGradientParams(SkRandom* r);
413
Brian Osmana2196532016-10-17 12:48:13 -0400414 bool fUseColors4f;
Brian Osman3f748602016-10-03 18:29:03 -0400415 SkColor fColors[kMaxRandomGradientColors];
Brian Osmana2196532016-10-17 12:48:13 -0400416 SkColor4f fColors4f[kMaxRandomGradientColors];
417 sk_sp<SkColorSpace> fColorSpace;
Brian Osman3f748602016-10-03 18:29:03 -0400418 SkScalar fStopStorage[kMaxRandomGradientColors];
419 SkShader::TileMode fTileMode;
420 int fColorCount;
421 SkScalar* fStops;
422 };
bsalomon@google.comd4726202012-08-03 14:34:46 +0000423
mtklein36352bf2015-03-25 18:17:31 -0700424 bool onIsEqual(const GrFragmentProcessor&) const override;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000425
mtklein36352bf2015-03-25 18:17:31 -0700426 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700427
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +0000428 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
429
bsalomon@google.comd4726202012-08-03 14:34:46 +0000430private:
brianosmanb9c51372016-09-15 11:09:45 -0700431 // If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then
432 // fColors4f and fColorSpaceXform will be populated.
433 SkTDArray<SkColor> fColors;
434
435 SkTDArray<SkColor4f> fColors4f;
436 sk_sp<GrColorSpaceXform> fColorSpaceXform;
437
438 SkTDArray<SkScalar> fPositions;
439 SkShader::TileMode fTileMode;
fmenozzicd9a1d02016-08-15 07:03:47 -0700440
bsalomon@google.com77af6802013-10-02 13:04:56 +0000441 GrCoordTransform fCoordTransform;
Brian Salomon0bbecb22016-11-17 11:38:22 -0500442 TextureSampler fTextureSampler;
bsalomon@google.com81712882012-11-01 17:12:34 +0000443 SkScalar fYCoord;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000444 GrTextureStripAtlas* fAtlas;
445 int fRow;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000446 bool fIsOpaque;
fmenozzicd9a1d02016-08-15 07:03:47 -0700447 ColorType fColorType;
448 PremulType fPremulType; // This is already baked into the table for texture gradients, and
449 // only changes behavior for gradients that don't use a texture.
joshualittb0a8a372014-09-23 09:50:21 -0700450 typedef GrFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000451
452};
453
454///////////////////////////////////////////////////////////////////////////////
455
fmenozzicd9a1d02016-08-15 07:03:47 -0700456// Base class for GL gradient effects
fmenozzi55d318d2016-08-09 08:05:57 -0700457class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000458public:
fmenozzicd9a1d02016-08-15 07:03:47 -0700459 GLSLProcessor() {
460 fCachedYCoord = SK_ScalarMax;
461 }
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000462
wangyixb1daa862015-08-18 11:29:31 -0700463protected:
egdaniel018fb622015-10-28 07:26:40 -0700464 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000465
bsalomon@google.comf78df332012-10-29 12:43:38 +0000466protected:
bsalomon63e99f72014-07-21 08:03:14 -0700467 /**
468 * Subclasses must call this. It will return a key for the part of the shader code controlled
469 * by the base class. The subclasses must stick it in their key and then pass it to the below
470 * emit* functions from their emitCode function.
471 */
joshualittb0a8a372014-09-23 09:50:21 -0700472 static uint32_t GenBaseGradientKey(const GrProcessor&);
bsalomon63e99f72014-07-21 08:03:14 -0700473
474 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
475 // should call this method from their emitCode().
egdaniel7ea439b2015-12-03 09:20:44 -0800476 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
bsalomon63e99f72014-07-21 08:03:14 -0700477
fmenozzicd9a1d02016-08-15 07:03:47 -0700478 // Emit code that gets a fragment's color from an expression for t; has branches for
479 // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
480 // color gradients that use the traditional texture lookup, as well as several varieties
481 // of hard stop gradients
cdalton85285412016-02-18 12:37:07 -0800482 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800483 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500484 const GrShaderCaps* shaderCaps,
joshualitt60030bc2014-11-25 14:21:55 -0800485 const GrGradientEffect&,
bsalomon63e99f72014-07-21 08:03:14 -0700486 const char* gradientTValue,
bsalomon63e99f72014-07-21 08:03:14 -0700487 const char* outputColor,
488 const char* inputColor,
bsalomonb58a2b42016-09-26 06:55:02 -0700489 const TextureSamplers&);
bsalomon63e99f72014-07-21 08:03:14 -0700490
491private:
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000492 enum {
fmenozzi64e8e5d2016-07-19 10:45:57 -0700493 // First bit for premul before/after interp
fmenozzicd9a1d02016-08-15 07:03:47 -0700494 kPremulBeforeInterpKey = 1,
bsalomon@google.com82d12232013-09-09 15:36:26 +0000495
fmenozzicd9a1d02016-08-15 07:03:47 -0700496 // Next three bits for 2/3 color type or different special
497 // hard stop cases (neither means using texture atlas)
498 kTwoColorKey = 2,
499 kThreeColorKey = 4,
500#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
501 kHardStopCenteredKey = 6,
502 kHardStopZeroZeroOneKey = 8,
503 kHardStopZeroOneOneKey = 10,
504
505 // Next two bits for tile mode
506 kClampTileMode = 16,
507 kRepeatTileMode = 32,
508 kMirrorTileMode = 48,
509
510 // Lower six bits for premul, 2/3 color type, and tile mode
511 kReservedBits = 6,
512#endif
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000513 };
514
bsalomon@google.com81712882012-11-01 17:12:34 +0000515 SkScalar fCachedYCoord;
fmenozzicd9a1d02016-08-15 07:03:47 -0700516 GrGLSLProgramDataManager::UniformHandle fColorsUni;
Brian Salomon466ad992016-10-13 16:08:36 -0400517 GrGLSLProgramDataManager::UniformHandle fHardStopT;
egdaniel018fb622015-10-28 07:26:40 -0700518 GrGLSLProgramDataManager::UniformHandle fFSYUni;
brianosmand4546092016-09-22 12:31:58 -0700519 GrGLSLProgramDataManager::UniformHandle fColorSpaceXformUni;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000520
egdaniel64c47282015-11-13 06:54:19 -0800521 typedef GrGLSLFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000522};
523
524#endif
525
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000526#endif