blob: ec75bdc05a3ff688dbed327087a92d083ebb93a8 [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"
Hal Canary95e3c052017-01-11 12:44:43 -050013
Herb Derby83e939b2017-02-07 14:25:11 -050014#include "SkArenaAlloc.h"
Hal Canary95e3c052017-01-11 12:44:43 -050015#include "SkAutoMalloc.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000016#include "SkClampRange.h"
17#include "SkColorPriv.h"
brianosmanb9c51372016-09-15 11:09:45 -070018#include "SkColorSpace.h"
Kevin Lubickc456b732017-01-11 17:21:57 +000019#include "SkOnce.h"
Hal Canary95e3c052017-01-11 12:44:43 -050020#include "SkReadBuffer.h"
21#include "SkShader.h"
22#include "SkUtils.h"
23#include "SkWriteBuffer.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000024
fmenozzicd9a1d02016-08-15 07:03:47 -070025#if SK_SUPPORT_GPU
26 #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
27#endif
28
humper@google.com05af1af2013-01-07 16:47:43 +000029static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
rileya@google.com1c6d64b2012-07-27 15:49:05 +000030 int count) {
31 if (count > 0) {
32 if (v0 == v1) {
33 sk_memset32(dst, v0, count);
34 } else {
35 int pairs = count >> 1;
36 for (int i = 0; i < pairs; i++) {
37 *dst++ = v0;
38 *dst++ = v1;
39 }
40 if (count & 1) {
41 *dst = v0;
42 }
43 }
44 }
45}
46
47// Clamp
48
humper@google.com05af1af2013-01-07 16:47:43 +000049static inline SkFixed clamp_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000050 return SkClampMax(x, 0xFFFF);
51}
52
53// Repeat
54
humper@google.com05af1af2013-01-07 16:47:43 +000055static inline SkFixed repeat_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000056 return x & 0xFFFF;
57}
58
59// Mirror
60
rileya@google.com1c6d64b2012-07-27 15:49:05 +000061static inline SkFixed mirror_tileproc(SkFixed x) {
caryclark3127c992015-12-09 12:02:30 -080062 int s = SkLeftShift(x, 15) >> 31;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000063 return (x ^ s) & 0xFFFF;
64}
65
rileya@google.com1c6d64b2012-07-27 15:49:05 +000066///////////////////////////////////////////////////////////////////////////////
67
68typedef SkFixed (*TileProc)(SkFixed);
69
70///////////////////////////////////////////////////////////////////////////////
71
72static const TileProc gTileProcs[] = {
73 clamp_tileproc,
74 repeat_tileproc,
75 mirror_tileproc
76};
77
78///////////////////////////////////////////////////////////////////////////////
79
80class SkGradientShaderBase : public SkShader {
81public:
reed@google.com437d6eb2013-05-23 19:03:05 +000082 struct Descriptor {
83 Descriptor() {
84 sk_bzero(this, sizeof(*this));
85 fTileMode = SkShader::kClamp_TileMode;
86 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000087
reedaddf2ed2014-08-11 08:28:24 -070088 const SkMatrix* fLocalMatrix;
brianosmane25d71c2016-09-28 11:27:28 -070089 const SkColor4f* fColors;
brianosmanb9c51372016-09-15 11:09:45 -070090 sk_sp<SkColorSpace> fColorSpace;
reed@google.com437d6eb2013-05-23 19:03:05 +000091 const SkScalar* fPos;
92 int fCount;
93 SkShader::TileMode fTileMode;
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000094 uint32_t fGradFlags;
reed9fa60da2014-08-21 07:59:51 -070095
96 void flatten(SkWriteBuffer&) const;
97 };
98
99 class DescriptorScope : public Descriptor {
100 public:
101 DescriptorScope() {}
mtklein88fd0fb2014-12-01 06:56:38 -0800102
reed9fa60da2014-08-21 07:59:51 -0700103 bool unflatten(SkReadBuffer&);
104
105 // fColors and fPos always point into local memory, so they can be safely mutated
106 //
brianosmane25d71c2016-09-28 11:27:28 -0700107 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
reed9fa60da2014-08-21 07:59:51 -0700108 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
109
110 private:
111 enum {
112 kStorageCount = 16
113 };
brianosmane25d71c2016-09-28 11:27:28 -0700114 SkColor4f fColorStorage[kStorageCount];
reed9fa60da2014-08-21 07:59:51 -0700115 SkScalar fPosStorage[kStorageCount];
116 SkMatrix fLocalMatrixStorage;
117 SkAutoMalloc fDynamicStorage;
reed@google.com437d6eb2013-05-23 19:03:05 +0000118 };
119
mtkleincc695fe2014-12-10 10:29:19 -0800120 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
Brian Salomond3b65972017-03-22 12:05:03 -0400121 ~SkGradientShaderBase() override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000122
brianosman93110a82016-09-15 08:40:21 -0700123 // The cache is initialized on-demand when getCache32 is called.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000124 class GradientShaderCache : public SkRefCnt {
125 public:
fmalita37d86882015-10-09 10:22:46 -0700126 GradientShaderCache(U8CPU alpha, bool dither, const SkGradientShaderBase& shader);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000127 ~GradientShaderCache();
128
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000129 const SkPMColor* getCache32();
130
Mike Reed6b3155c2017-04-03 14:41:44 -0400131 SkPixelRef* getCache32PixelRef() const { return fCache32PixelRef.get(); }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000132
133 unsigned getAlpha() const { return fCacheAlpha; }
fmalita37d86882015-10-09 10:22:46 -0700134 bool getDither() const { return fCacheDither; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000135
136 private:
brianosman93110a82016-09-15 08:40:21 -0700137 // Working pointer. If it's nullptr, we need to recompute the cache values.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000138 SkPMColor* fCache32;
139
Mike Reed6b3155c2017-04-03 14:41:44 -0400140 sk_sp<SkPixelRef> fCache32PixelRef;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000141 const unsigned fCacheAlpha; // The alpha value we used when we computed the cache.
142 // Larger than 8bits so we can store uninitialized
143 // value.
fmalita37d86882015-10-09 10:22:46 -0700144 const bool fCacheDither; // The dither flag used when we computed the cache.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000145
146 const SkGradientShaderBase& fShader;
147
brianosman93110a82016-09-15 08:40:21 -0700148 // Make sure we only initialize the cache once.
149 SkOnce fCache32InitOnce;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000150
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000151 static void initCache32(GradientShaderCache* cache);
152
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000153 static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
fmalita37d86882015-10-09 10:22:46 -0700154 U8CPU alpha, uint32_t gradFlags, bool dither);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000155 };
156
157 class GradientShaderBaseContext : public SkShader::Context {
158 public:
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000159 GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000160
mtklein36352bf2015-03-25 18:17:31 -0700161 uint32_t getFlags() const override { return fFlags; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000162
fmalita088e21b2016-10-05 09:28:42 -0700163 bool isValid() const;
164
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000165 protected:
166 SkMatrix fDstToIndex;
167 SkMatrix::MapXYProc fDstToIndexProc;
168 uint8_t fDstToIndexClass;
169 uint8_t fFlags;
fmalita37d86882015-10-09 10:22:46 -0700170 bool fDither;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000171
Hal Canary67b39de2016-11-07 11:47:44 -0500172 sk_sp<GradientShaderCache> fCache;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000173
174 private:
175 typedef SkShader::Context INHERITED;
176 };
177
mtklein36352bf2015-03-25 18:17:31 -0700178 bool isOpaque() const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000179
brianosmand4546092016-09-22 12:31:58 -0700180 enum class GradientBitmapType : uint8_t {
181 kLegacy,
182 kSRGB,
183 kHalfFloat,
184 };
185
186 void getGradientTableBitmap(SkBitmap*, GradientBitmapType bitmapType) const;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000187
188 enum {
189 /// Seems like enough for visual accuracy. TODO: if pos[] deserves
190 /// it, use a larger cache.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000191 kCache32Bits = 8,
reed@google.com60040292013-02-04 18:21:23 +0000192 kCache32Count = (1 << kCache32Bits),
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000193 kCache32Shift = 16 - kCache32Bits,
194 kSqrt32Shift = 8 - kCache32Bits,
195
196 /// This value is used to *read* the dither cache; it may be 0
197 /// if dithering is disabled.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000198 kDitherStride32 = kCache32Count,
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000199 };
200
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +0000201 uint32_t getGradFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000202
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000203protected:
fmalitabc590c02016-02-22 09:12:33 -0800204 class GradientShaderBase4fContext;
205
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000206 SkGradientShaderBase(SkReadBuffer& );
mtklein36352bf2015-03-25 18:17:31 -0700207 void flatten(SkWriteBuffer&) const override;
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000208 SK_TO_STRING_OVERRIDE()
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000209
mtkleincc695fe2014-12-10 10:29:19 -0800210 const SkMatrix fPtsToUnit;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000211 TileMode fTileMode;
212 TileProc fTileProc;
reed@google.com3d3a8602013-05-24 14:58:44 +0000213 uint8_t fGradFlags;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000214
215 struct Rec {
216 SkFixed fPos; // 0...1
217 uint32_t fScale; // (1 << 24) / range
218 };
219 Rec* fRecs;
220
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000221 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
skia.committer@gmail.comd3b28e82014-04-22 03:05:17 +0000222
mtklein36352bf2015-03-25 18:17:31 -0700223 bool onAsLuminanceColor(SkColor*) const override;
reed8367b8c2014-08-22 08:30:20 -0700224
brianosmand4546092016-09-22 12:31:58 -0700225
226 void initLinearBitmap(SkBitmap* bitmap) const;
227
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000228 /*
229 * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
230 * Count is the number of colors in the gradient
231 * It will then flip all the color and rec information and return in their respective Dst
232 * pointers. It is assumed that space has already been allocated for the Dst pointers.
233 * The rec src and dst are only assumed to be valid if count > 2
234 */
235 static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
236 SkColor* colorSrc, Rec* recSrc,
237 int count);
238
fmalita088e21b2016-10-05 09:28:42 -0700239 template <typename T, typename... Args>
Herb Derby83e939b2017-02-07 14:25:11 -0500240 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
241 auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
fmalita088e21b2016-10-05 09:28:42 -0700242 if (!ctx->isValid()) {
fmalita088e21b2016-10-05 09:28:42 -0700243 return nullptr;
244 }
245 return ctx;
246 }
247
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000248private:
249 enum {
250 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
251
brianosmanb9c51372016-09-15 11:09:45 -0700252 kStorageSize = kColorStorageCount *
253 (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec) + sizeof(SkColor4f))
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000254 };
brianosmanb9c51372016-09-15 11:09:45 -0700255 SkColor fStorage[(kStorageSize + 3) >> 2];
reedf3182eb2015-11-17 08:12:19 -0800256public:
brianosmanb9c51372016-09-15 11:09:45 -0700257 SkColor* fOrigColors; // original colors, before modulation by paint in context.
258 SkColor4f* fOrigColors4f; // original colors, as linear floats
259 SkScalar* fOrigPos; // original positions
260 int fColorCount;
261 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
reedf3182eb2015-11-17 08:12:19 -0800262
263 bool colorsAreOpaque() const { return fColorsAreOpaque; }
264
fmenozzicd9a1d02016-08-15 07:03:47 -0700265 TileMode getTileMode() const { return fTileMode; }
266 Rec* getRecs() const { return fRecs; }
267
reedf3182eb2015-11-17 08:12:19 -0800268private:
brianosmanb9c51372016-09-15 11:09:45 -0700269 bool fColorsAreOpaque;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000270
Hal Canary67b39de2016-11-07 11:47:44 -0500271 sk_sp<GradientShaderCache> refCache(U8CPU alpha, bool dither) const;
272 mutable SkMutex fCacheMutex;
273 mutable sk_sp<GradientShaderCache> fCache;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000274
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000275 void initCommon();
276
277 typedef SkShader INHERITED;
278};
279
reed@google.com55853db2013-02-01 19:34:59 +0000280static inline int init_dither_toggle(int x, int y) {
reed@google.com60040292013-02-04 18:21:23 +0000281 x &= 1;
282 y = (y & 1) << 1;
283 return (x | y) * SkGradientShaderBase::kDitherStride32;
reed@google.com55853db2013-02-01 19:34:59 +0000284}
285
286static inline int next_dither_toggle(int toggle) {
287 return toggle ^ SkGradientShaderBase::kDitherStride32;
288}
289
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000290///////////////////////////////////////////////////////////////////////////////
291
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000292#if SK_SUPPORT_GPU
293
brianosmanb9c51372016-09-15 11:09:45 -0700294#include "GrColorSpaceXform.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +0000295#include "GrCoordTransform.h"
bsalomon6251d172014-10-15 10:50:36 -0700296#include "GrFragmentProcessor.h"
Brian Osmanc624d9d2017-03-08 11:42:02 -0500297#include "glsl/GrGLSLColorSpaceXformHelper.h"
egdaniel64c47282015-11-13 06:54:19 -0800298#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -0700299#include "glsl/GrGLSLProgramDataManager.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000300
egdaniel605dd0f2014-11-12 08:35:25 -0800301class GrInvariantOutput;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000302
303/*
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000304 * The interpretation of the texture matrix depends on the sample mode. The
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000305 * texture matrix is applied both when the texture coordinates are explicit
306 * and when vertex positions are used as texture coordinates. In the latter
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000307 * case the texture matrix is applied to the pre-view-matrix position
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000308 * values.
309 *
310 * Normal SampleMode
311 * The post-matrix texture coordinates are in normalize space with (0,0) at
312 * the top-left and (1,1) at the bottom right.
313 * RadialGradient
314 * The matrix specifies the radial gradient parameters.
315 * (0,0) in the post-matrix space is center of the radial gradient.
316 * Radial2Gradient
317 * Matrix transforms to space where first circle is centered at the
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000318 * origin. The second circle will be centered (x, 0) where x may be
319 * 0 and is provided by setRadial2Params. The post-matrix space is
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000320 * normalized such that 1 is the second radius - first radius.
321 * SweepGradient
322 * The angle from the origin of texture coordinates in post-matrix space
323 * determines the gradient value.
324 */
325
rileya@google.comb3e50f22012-08-20 17:43:08 +0000326 class GrTextureStripAtlas;
327
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000328// Base class for Gr gradient effects
joshualittb0a8a372014-09-23 09:50:21 -0700329class GrGradientEffect : public GrFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000330public:
brianosman9557c272016-09-15 06:59:15 -0700331 struct CreateArgs {
332 CreateArgs(GrContext* context,
333 const SkGradientShaderBase* shader,
334 const SkMatrix* matrix,
brianosmanb9c51372016-09-15 11:09:45 -0700335 SkShader::TileMode tileMode,
336 sk_sp<GrColorSpaceXform> colorSpaceXform,
337 bool gammaCorrect)
brianosman9557c272016-09-15 06:59:15 -0700338 : fContext(context)
339 , fShader(shader)
340 , fMatrix(matrix)
brianosmanb9c51372016-09-15 11:09:45 -0700341 , fTileMode(tileMode)
342 , fColorSpaceXform(std::move(colorSpaceXform))
343 , fGammaCorrect(gammaCorrect) {}
brianosman9557c272016-09-15 06:59:15 -0700344
345 GrContext* fContext;
346 const SkGradientShaderBase* fShader;
347 const SkMatrix* fMatrix;
348 SkShader::TileMode fTileMode;
brianosmanb9c51372016-09-15 11:09:45 -0700349 sk_sp<GrColorSpaceXform> fColorSpaceXform;
350 bool fGammaCorrect;
brianosman9557c272016-09-15 06:59:15 -0700351 };
352
fmenozzi55d318d2016-08-09 08:05:57 -0700353 class GLSLProcessor;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000354
Brian Salomond3b65972017-03-22 12:05:03 -0400355 ~GrGradientEffect() override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000356
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 Salomon587e08f2017-01-27 10:59:27 -0500403 GrGradientEffect(const CreateArgs&, bool isOpaque);
404
Hal Canary6f6961e2017-01-31 13:50:44 -0500405 #if GR_TEST_UTILS
Brian Osmane75c19f2016-10-10 11:26:43 -0400406 /** Helper struct that stores (and populates) parameters to construct a random gradient.
Brian Osmana2196532016-10-17 12:48:13 -0400407 If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and
408 fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount
409 will be the number of color stops in either case, and fColors and fStops can be passed to
410 the gradient factory. (The constructor may decide not to use stops, in which case fStops
411 will be nullptr). */
Brian Osman3f748602016-10-03 18:29:03 -0400412 struct RandomGradientParams {
Brian Salomon5d4cd9e2017-02-09 11:16:46 -0500413 static const int kMaxRandomGradientColors = 5;
Brian Osmane75c19f2016-10-10 11:26:43 -0400414
Brian Osman3f748602016-10-03 18:29:03 -0400415 RandomGradientParams(SkRandom* r);
416
Brian Osmana2196532016-10-17 12:48:13 -0400417 bool fUseColors4f;
Brian Osman3f748602016-10-03 18:29:03 -0400418 SkColor fColors[kMaxRandomGradientColors];
Brian Osmana2196532016-10-17 12:48:13 -0400419 SkColor4f fColors4f[kMaxRandomGradientColors];
420 sk_sp<SkColorSpace> fColorSpace;
Brian Osman3f748602016-10-03 18:29:03 -0400421 SkScalar fStopStorage[kMaxRandomGradientColors];
422 SkShader::TileMode fTileMode;
423 int fColorCount;
424 SkScalar* fStops;
425 };
Hal Canary6f6961e2017-01-31 13:50:44 -0500426 #endif
bsalomon@google.comd4726202012-08-03 14:34:46 +0000427
mtklein36352bf2015-03-25 18:17:31 -0700428 bool onIsEqual(const GrFragmentProcessor&) const override;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000429
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +0000430 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
431
bsalomon@google.comd4726202012-08-03 14:34:46 +0000432private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500433 static OptimizationFlags OptFlags(bool isOpaque);
434
brianosmanb9c51372016-09-15 11:09:45 -0700435 // If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then
436 // fColors4f and fColorSpaceXform will be populated.
437 SkTDArray<SkColor> fColors;
438
439 SkTDArray<SkColor4f> fColors4f;
440 sk_sp<GrColorSpaceXform> fColorSpaceXform;
441
442 SkTDArray<SkScalar> fPositions;
443 SkShader::TileMode fTileMode;
fmenozzicd9a1d02016-08-15 07:03:47 -0700444
bsalomon@google.com77af6802013-10-02 13:04:56 +0000445 GrCoordTransform fCoordTransform;
Brian Salomon0bbecb22016-11-17 11:38:22 -0500446 TextureSampler fTextureSampler;
bsalomon@google.com81712882012-11-01 17:12:34 +0000447 SkScalar fYCoord;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000448 GrTextureStripAtlas* fAtlas;
449 int fRow;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000450 bool fIsOpaque;
fmenozzicd9a1d02016-08-15 07:03:47 -0700451 ColorType fColorType;
452 PremulType fPremulType; // This is already baked into the table for texture gradients, and
453 // only changes behavior for gradients that don't use a texture.
joshualittb0a8a372014-09-23 09:50:21 -0700454 typedef GrFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000455
456};
457
458///////////////////////////////////////////////////////////////////////////////
459
fmenozzicd9a1d02016-08-15 07:03:47 -0700460// Base class for GL gradient effects
fmenozzi55d318d2016-08-09 08:05:57 -0700461class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000462public:
fmenozzicd9a1d02016-08-15 07:03:47 -0700463 GLSLProcessor() {
464 fCachedYCoord = SK_ScalarMax;
465 }
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000466
wangyixb1daa862015-08-18 11:29:31 -0700467protected:
egdaniel018fb622015-10-28 07:26:40 -0700468 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000469
bsalomon@google.comf78df332012-10-29 12:43:38 +0000470protected:
bsalomon63e99f72014-07-21 08:03:14 -0700471 /**
472 * Subclasses must call this. It will return a key for the part of the shader code controlled
473 * by the base class. The subclasses must stick it in their key and then pass it to the below
474 * emit* functions from their emitCode function.
475 */
joshualittb0a8a372014-09-23 09:50:21 -0700476 static uint32_t GenBaseGradientKey(const GrProcessor&);
bsalomon63e99f72014-07-21 08:03:14 -0700477
478 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
479 // should call this method from their emitCode().
egdaniel7ea439b2015-12-03 09:20:44 -0800480 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
bsalomon63e99f72014-07-21 08:03:14 -0700481
fmenozzicd9a1d02016-08-15 07:03:47 -0700482 // Emit code that gets a fragment's color from an expression for t; has branches for
483 // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
484 // color gradients that use the traditional texture lookup, as well as several varieties
485 // of hard stop gradients
cdalton85285412016-02-18 12:37:07 -0800486 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800487 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500488 const GrShaderCaps* shaderCaps,
joshualitt60030bc2014-11-25 14:21:55 -0800489 const GrGradientEffect&,
bsalomon63e99f72014-07-21 08:03:14 -0700490 const char* gradientTValue,
bsalomon63e99f72014-07-21 08:03:14 -0700491 const char* outputColor,
492 const char* inputColor,
bsalomonb58a2b42016-09-26 06:55:02 -0700493 const TextureSamplers&);
bsalomon63e99f72014-07-21 08:03:14 -0700494
495private:
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000496 enum {
fmenozzi64e8e5d2016-07-19 10:45:57 -0700497 // First bit for premul before/after interp
fmenozzicd9a1d02016-08-15 07:03:47 -0700498 kPremulBeforeInterpKey = 1,
bsalomon@google.com82d12232013-09-09 15:36:26 +0000499
fmenozzicd9a1d02016-08-15 07:03:47 -0700500 // Next three bits for 2/3 color type or different special
501 // hard stop cases (neither means using texture atlas)
502 kTwoColorKey = 2,
503 kThreeColorKey = 4,
504#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
505 kHardStopCenteredKey = 6,
506 kHardStopZeroZeroOneKey = 8,
507 kHardStopZeroOneOneKey = 10,
508
509 // Next two bits for tile mode
510 kClampTileMode = 16,
511 kRepeatTileMode = 32,
512 kMirrorTileMode = 48,
513
514 // Lower six bits for premul, 2/3 color type, and tile mode
515 kReservedBits = 6,
516#endif
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000517 };
518
bsalomon@google.com81712882012-11-01 17:12:34 +0000519 SkScalar fCachedYCoord;
fmenozzicd9a1d02016-08-15 07:03:47 -0700520 GrGLSLProgramDataManager::UniformHandle fColorsUni;
Brian Salomon466ad992016-10-13 16:08:36 -0400521 GrGLSLProgramDataManager::UniformHandle fHardStopT;
egdaniel018fb622015-10-28 07:26:40 -0700522 GrGLSLProgramDataManager::UniformHandle fFSYUni;
Brian Osmanc624d9d2017-03-08 11:42:02 -0500523 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000524
egdaniel64c47282015-11-13 06:54:19 -0800525 typedef GrGLSLFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000526};
527
528#endif
529
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000530#endif