blob: 7f1f5f8c88ed7e3b96edd3ff076e13ff46c3d0cf [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 "SkMallocPixelRef.h"
Kevin Lubickc456b732017-01-11 17:21:57 +000020#include "SkOnce.h"
Hal Canary95e3c052017-01-11 12:44:43 -050021#include "SkReadBuffer.h"
22#include "SkShader.h"
23#include "SkUtils.h"
24#include "SkWriteBuffer.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000025
fmenozzicd9a1d02016-08-15 07:03:47 -070026#if SK_SUPPORT_GPU
27 #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
28#endif
29
humper@google.com05af1af2013-01-07 16:47:43 +000030static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
rileya@google.com1c6d64b2012-07-27 15:49:05 +000031 int count) {
32 if (count > 0) {
33 if (v0 == v1) {
34 sk_memset32(dst, v0, count);
35 } else {
36 int pairs = count >> 1;
37 for (int i = 0; i < pairs; i++) {
38 *dst++ = v0;
39 *dst++ = v1;
40 }
41 if (count & 1) {
42 *dst = v0;
43 }
44 }
45 }
46}
47
48// Clamp
49
humper@google.com05af1af2013-01-07 16:47:43 +000050static inline SkFixed clamp_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000051 return SkClampMax(x, 0xFFFF);
52}
53
54// Repeat
55
humper@google.com05af1af2013-01-07 16:47:43 +000056static inline SkFixed repeat_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000057 return x & 0xFFFF;
58}
59
60// Mirror
61
rileya@google.com1c6d64b2012-07-27 15:49:05 +000062static inline SkFixed mirror_tileproc(SkFixed x) {
caryclark3127c992015-12-09 12:02:30 -080063 int s = SkLeftShift(x, 15) >> 31;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000064 return (x ^ s) & 0xFFFF;
65}
66
rileya@google.com1c6d64b2012-07-27 15:49:05 +000067///////////////////////////////////////////////////////////////////////////////
68
69typedef SkFixed (*TileProc)(SkFixed);
70
71///////////////////////////////////////////////////////////////////////////////
72
73static const TileProc gTileProcs[] = {
74 clamp_tileproc,
75 repeat_tileproc,
76 mirror_tileproc
77};
78
79///////////////////////////////////////////////////////////////////////////////
80
81class SkGradientShaderBase : public SkShader {
82public:
reed@google.com437d6eb2013-05-23 19:03:05 +000083 struct Descriptor {
84 Descriptor() {
85 sk_bzero(this, sizeof(*this));
86 fTileMode = SkShader::kClamp_TileMode;
87 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000088
reedaddf2ed2014-08-11 08:28:24 -070089 const SkMatrix* fLocalMatrix;
brianosmane25d71c2016-09-28 11:27:28 -070090 const SkColor4f* fColors;
brianosmanb9c51372016-09-15 11:09:45 -070091 sk_sp<SkColorSpace> fColorSpace;
reed@google.com437d6eb2013-05-23 19:03:05 +000092 const SkScalar* fPos;
93 int fCount;
94 SkShader::TileMode fTileMode;
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000095 uint32_t fGradFlags;
reed9fa60da2014-08-21 07:59:51 -070096
97 void flatten(SkWriteBuffer&) const;
98 };
99
100 class DescriptorScope : public Descriptor {
101 public:
102 DescriptorScope() {}
mtklein88fd0fb2014-12-01 06:56:38 -0800103
reed9fa60da2014-08-21 07:59:51 -0700104 bool unflatten(SkReadBuffer&);
105
106 // fColors and fPos always point into local memory, so they can be safely mutated
107 //
brianosmane25d71c2016-09-28 11:27:28 -0700108 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
reed9fa60da2014-08-21 07:59:51 -0700109 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
110
111 private:
112 enum {
113 kStorageCount = 16
114 };
brianosmane25d71c2016-09-28 11:27:28 -0700115 SkColor4f fColorStorage[kStorageCount];
reed9fa60da2014-08-21 07:59:51 -0700116 SkScalar fPosStorage[kStorageCount];
117 SkMatrix fLocalMatrixStorage;
118 SkAutoMalloc fDynamicStorage;
reed@google.com437d6eb2013-05-23 19:03:05 +0000119 };
120
mtkleincc695fe2014-12-10 10:29:19 -0800121 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000122 virtual ~SkGradientShaderBase();
123
brianosman93110a82016-09-15 08:40:21 -0700124 // The cache is initialized on-demand when getCache32 is called.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000125 class GradientShaderCache : public SkRefCnt {
126 public:
fmalita37d86882015-10-09 10:22:46 -0700127 GradientShaderCache(U8CPU alpha, bool dither, const SkGradientShaderBase& shader);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000128 ~GradientShaderCache();
129
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000130 const SkPMColor* getCache32();
131
132 SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
133
134 unsigned getAlpha() const { return fCacheAlpha; }
fmalita37d86882015-10-09 10:22:46 -0700135 bool getDither() const { return fCacheDither; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000136
137 private:
brianosman93110a82016-09-15 08:40:21 -0700138 // Working pointer. If it's nullptr, we need to recompute the cache values.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000139 SkPMColor* fCache32;
140
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000141 SkMallocPixelRef* fCache32PixelRef;
142 const unsigned fCacheAlpha; // The alpha value we used when we computed the cache.
143 // Larger than 8bits so we can store uninitialized
144 // value.
fmalita37d86882015-10-09 10:22:46 -0700145 const bool fCacheDither; // The dither flag used when we computed the cache.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000146
147 const SkGradientShaderBase& fShader;
148
brianosman93110a82016-09-15 08:40:21 -0700149 // Make sure we only initialize the cache once.
150 SkOnce fCache32InitOnce;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000151
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000152 static void initCache32(GradientShaderCache* cache);
153
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000154 static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
fmalita37d86882015-10-09 10:22:46 -0700155 U8CPU alpha, uint32_t gradFlags, bool dither);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000156 };
157
158 class GradientShaderBaseContext : public SkShader::Context {
159 public:
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000160 GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000161
mtklein36352bf2015-03-25 18:17:31 -0700162 uint32_t getFlags() const override { return fFlags; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000163
fmalita088e21b2016-10-05 09:28:42 -0700164 bool isValid() const;
165
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000166 protected:
167 SkMatrix fDstToIndex;
168 SkMatrix::MapXYProc fDstToIndexProc;
169 uint8_t fDstToIndexClass;
170 uint8_t fFlags;
fmalita37d86882015-10-09 10:22:46 -0700171 bool fDither;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000172
Hal Canary67b39de2016-11-07 11:47:44 -0500173 sk_sp<GradientShaderCache> fCache;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000174
175 private:
176 typedef SkShader::Context INHERITED;
177 };
178
mtklein36352bf2015-03-25 18:17:31 -0700179 bool isOpaque() const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000180
brianosmand4546092016-09-22 12:31:58 -0700181 enum class GradientBitmapType : uint8_t {
182 kLegacy,
183 kSRGB,
184 kHalfFloat,
185 };
186
187 void getGradientTableBitmap(SkBitmap*, GradientBitmapType bitmapType) const;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000188
189 enum {
190 /// Seems like enough for visual accuracy. TODO: if pos[] deserves
191 /// it, use a larger cache.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000192 kCache32Bits = 8,
reed@google.com60040292013-02-04 18:21:23 +0000193 kCache32Count = (1 << kCache32Bits),
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000194 kCache32Shift = 16 - kCache32Bits,
195 kSqrt32Shift = 8 - kCache32Bits,
196
197 /// This value is used to *read* the dither cache; it may be 0
198 /// if dithering is disabled.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000199 kDitherStride32 = kCache32Count,
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000200 };
201
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +0000202 uint32_t getGradFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000203
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000204protected:
fmalitabc590c02016-02-22 09:12:33 -0800205 class GradientShaderBase4fContext;
206
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000207 SkGradientShaderBase(SkReadBuffer& );
mtklein36352bf2015-03-25 18:17:31 -0700208 void flatten(SkWriteBuffer&) const override;
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000209 SK_TO_STRING_OVERRIDE()
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000210
mtkleincc695fe2014-12-10 10:29:19 -0800211 const SkMatrix fPtsToUnit;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000212 TileMode fTileMode;
213 TileProc fTileProc;
reed@google.com3d3a8602013-05-24 14:58:44 +0000214 uint8_t fGradFlags;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000215
216 struct Rec {
217 SkFixed fPos; // 0...1
218 uint32_t fScale; // (1 << 24) / range
219 };
220 Rec* fRecs;
221
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000222 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
skia.committer@gmail.comd3b28e82014-04-22 03:05:17 +0000223
mtklein36352bf2015-03-25 18:17:31 -0700224 bool onAsLuminanceColor(SkColor*) const override;
reed8367b8c2014-08-22 08:30:20 -0700225
brianosmand4546092016-09-22 12:31:58 -0700226
227 void initLinearBitmap(SkBitmap* bitmap) const;
228
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000229 /*
230 * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
231 * Count is the number of colors in the gradient
232 * It will then flip all the color and rec information and return in their respective Dst
233 * pointers. It is assumed that space has already been allocated for the Dst pointers.
234 * The rec src and dst are only assumed to be valid if count > 2
235 */
236 static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
237 SkColor* colorSrc, Rec* recSrc,
238 int count);
239
fmalita088e21b2016-10-05 09:28:42 -0700240 template <typename T, typename... Args>
Herb Derby83e939b2017-02-07 14:25:11 -0500241 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
242 auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
fmalita088e21b2016-10-05 09:28:42 -0700243 if (!ctx->isValid()) {
fmalita088e21b2016-10-05 09:28:42 -0700244 return nullptr;
245 }
246 return ctx;
247 }
248
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000249private:
250 enum {
251 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
252
brianosmanb9c51372016-09-15 11:09:45 -0700253 kStorageSize = kColorStorageCount *
254 (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec) + sizeof(SkColor4f))
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000255 };
brianosmanb9c51372016-09-15 11:09:45 -0700256 SkColor fStorage[(kStorageSize + 3) >> 2];
reedf3182eb2015-11-17 08:12:19 -0800257public:
brianosmanb9c51372016-09-15 11:09:45 -0700258 SkColor* fOrigColors; // original colors, before modulation by paint in context.
259 SkColor4f* fOrigColors4f; // original colors, as linear floats
260 SkScalar* fOrigPos; // original positions
261 int fColorCount;
262 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
reedf3182eb2015-11-17 08:12:19 -0800263
264 bool colorsAreOpaque() const { return fColorsAreOpaque; }
265
fmenozzicd9a1d02016-08-15 07:03:47 -0700266 TileMode getTileMode() const { return fTileMode; }
267 Rec* getRecs() const { return fRecs; }
268
reedf3182eb2015-11-17 08:12:19 -0800269private:
brianosmanb9c51372016-09-15 11:09:45 -0700270 bool fColorsAreOpaque;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000271
Hal Canary67b39de2016-11-07 11:47:44 -0500272 sk_sp<GradientShaderCache> refCache(U8CPU alpha, bool dither) const;
273 mutable SkMutex fCacheMutex;
274 mutable sk_sp<GradientShaderCache> fCache;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000275
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000276 void initCommon();
277
278 typedef SkShader INHERITED;
279};
280
reed@google.com55853db2013-02-01 19:34:59 +0000281static inline int init_dither_toggle(int x, int y) {
reed@google.com60040292013-02-04 18:21:23 +0000282 x &= 1;
283 y = (y & 1) << 1;
284 return (x | y) * SkGradientShaderBase::kDitherStride32;
reed@google.com55853db2013-02-01 19:34:59 +0000285}
286
287static inline int next_dither_toggle(int toggle) {
288 return toggle ^ SkGradientShaderBase::kDitherStride32;
289}
290
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000291///////////////////////////////////////////////////////////////////////////////
292
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000293#if SK_SUPPORT_GPU
294
brianosmanb9c51372016-09-15 11:09:45 -0700295#include "GrColorSpaceXform.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +0000296#include "GrCoordTransform.h"
bsalomon6251d172014-10-15 10:50:36 -0700297#include "GrFragmentProcessor.h"
Brian Osmanc624d9d2017-03-08 11:42:02 -0500298#include "glsl/GrGLSLColorSpaceXformHelper.h"
egdaniel64c47282015-11-13 06:54:19 -0800299#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -0700300#include "glsl/GrGLSLProgramDataManager.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000301
egdaniel605dd0f2014-11-12 08:35:25 -0800302class GrInvariantOutput;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000303
304/*
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000305 * The interpretation of the texture matrix depends on the sample mode. The
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000306 * texture matrix is applied both when the texture coordinates are explicit
307 * and when vertex positions are used as texture coordinates. In the latter
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000308 * case the texture matrix is applied to the pre-view-matrix position
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000309 * values.
310 *
311 * Normal SampleMode
312 * The post-matrix texture coordinates are in normalize space with (0,0) at
313 * the top-left and (1,1) at the bottom right.
314 * RadialGradient
315 * The matrix specifies the radial gradient parameters.
316 * (0,0) in the post-matrix space is center of the radial gradient.
317 * Radial2Gradient
318 * Matrix transforms to space where first circle is centered at the
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000319 * origin. The second circle will be centered (x, 0) where x may be
320 * 0 and is provided by setRadial2Params. The post-matrix space is
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000321 * normalized such that 1 is the second radius - first radius.
322 * SweepGradient
323 * The angle from the origin of texture coordinates in post-matrix space
324 * determines the gradient value.
325 */
326
rileya@google.comb3e50f22012-08-20 17:43:08 +0000327 class GrTextureStripAtlas;
328
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000329// Base class for Gr gradient effects
joshualittb0a8a372014-09-23 09:50:21 -0700330class GrGradientEffect : public GrFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000331public:
brianosman9557c272016-09-15 06:59:15 -0700332 struct CreateArgs {
333 CreateArgs(GrContext* context,
334 const SkGradientShaderBase* shader,
335 const SkMatrix* matrix,
brianosmanb9c51372016-09-15 11:09:45 -0700336 SkShader::TileMode tileMode,
337 sk_sp<GrColorSpaceXform> colorSpaceXform,
338 bool gammaCorrect)
brianosman9557c272016-09-15 06:59:15 -0700339 : fContext(context)
340 , fShader(shader)
341 , fMatrix(matrix)
brianosmanb9c51372016-09-15 11:09:45 -0700342 , fTileMode(tileMode)
343 , fColorSpaceXform(std::move(colorSpaceXform))
344 , fGammaCorrect(gammaCorrect) {}
brianosman9557c272016-09-15 06:59:15 -0700345
346 GrContext* fContext;
347 const SkGradientShaderBase* fShader;
348 const SkMatrix* fMatrix;
349 SkShader::TileMode fTileMode;
brianosmanb9c51372016-09-15 11:09:45 -0700350 sk_sp<GrColorSpaceXform> fColorSpaceXform;
351 bool fGammaCorrect;
brianosman9557c272016-09-15 06:59:15 -0700352 };
353
fmenozzi55d318d2016-08-09 08:05:57 -0700354 class GLSLProcessor;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000355
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000356 virtual ~GrGradientEffect();
357
rileya@google.comb3e50f22012-08-20 17:43:08 +0000358 bool useAtlas() const { return SkToBool(-1 != fRow); }
fmenozzicd9a1d02016-08-15 07:03:47 -0700359 SkScalar getYCoord() const { return fYCoord; }
rileya@google.comb3e50f22012-08-20 17:43:08 +0000360
fmenozzicd9a1d02016-08-15 07:03:47 -0700361 enum ColorType {
362 kTwo_ColorType,
363 kThree_ColorType, // Symmetric three color
364 kTexture_ColorType,
365
366#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
Brian Salomon466ad992016-10-13 16:08:36 -0400367 kSingleHardStop_ColorType, // 0, t, t, 1
fmenozzicd9a1d02016-08-15 07:03:47 -0700368 kHardStopLeftEdged_ColorType, // 0, 0, 1
369 kHardStopRightEdged_ColorType, // 0, 1, 1
370#endif
371 };
372
373 ColorType getColorType() const { return fColorType; }
374
375 // Determines the type of gradient, one of:
376 // - Two-color
377 // - Symmetric three-color
378 // - Texture
379 // - Centered hard stop
380 // - Left-edged hard stop
381 // - Right-edged hard stop
382 ColorType determineColorType(const SkGradientShaderBase& shader);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000383
384 enum PremulType {
385 kBeforeInterp_PremulType,
386 kAfterInterp_PremulType,
387 };
388
389 PremulType getPremulType() const { return fPremulType; }
390
391 const SkColor* getColors(int pos) const {
fmenozzicd9a1d02016-08-15 07:03:47 -0700392 SkASSERT(fColorType != kTexture_ColorType);
393 SkASSERT(pos < fColors.count());
bsalomon@google.com82d12232013-09-09 15:36:26 +0000394 return &fColors[pos];
395 }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000396
brianosmanb9c51372016-09-15 11:09:45 -0700397 const SkColor4f* getColors4f(int pos) const {
398 SkASSERT(fColorType != kTexture_ColorType);
399 SkASSERT(pos < fColors4f.count());
400 return &fColors4f[pos];
401 }
402
bsalomon@google.comd4726202012-08-03 14:34:46 +0000403protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500404 GrGradientEffect(const CreateArgs&, bool isOpaque);
405
Hal Canary6f6961e2017-01-31 13:50:44 -0500406 #if GR_TEST_UTILS
Brian Osmane75c19f2016-10-10 11:26:43 -0400407 /** Helper struct that stores (and populates) parameters to construct a random gradient.
Brian Osmana2196532016-10-17 12:48:13 -0400408 If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and
409 fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount
410 will be the number of color stops in either case, and fColors and fStops can be passed to
411 the gradient factory. (The constructor may decide not to use stops, in which case fStops
412 will be nullptr). */
Brian Osman3f748602016-10-03 18:29:03 -0400413 struct RandomGradientParams {
Brian Salomon5d4cd9e2017-02-09 11:16:46 -0500414 static const int kMaxRandomGradientColors = 5;
Brian Osmane75c19f2016-10-10 11:26:43 -0400415
Brian Osman3f748602016-10-03 18:29:03 -0400416 RandomGradientParams(SkRandom* r);
417
Brian Osmana2196532016-10-17 12:48:13 -0400418 bool fUseColors4f;
Brian Osman3f748602016-10-03 18:29:03 -0400419 SkColor fColors[kMaxRandomGradientColors];
Brian Osmana2196532016-10-17 12:48:13 -0400420 SkColor4f fColors4f[kMaxRandomGradientColors];
421 sk_sp<SkColorSpace> fColorSpace;
Brian Osman3f748602016-10-03 18:29:03 -0400422 SkScalar fStopStorage[kMaxRandomGradientColors];
423 SkShader::TileMode fTileMode;
424 int fColorCount;
425 SkScalar* fStops;
426 };
Hal Canary6f6961e2017-01-31 13:50:44 -0500427 #endif
bsalomon@google.comd4726202012-08-03 14:34:46 +0000428
mtklein36352bf2015-03-25 18:17:31 -0700429 bool onIsEqual(const GrFragmentProcessor&) const override;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000430
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +0000431 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
432
bsalomon@google.comd4726202012-08-03 14:34:46 +0000433private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500434 static OptimizationFlags OptFlags(bool isOpaque);
435
brianosmanb9c51372016-09-15 11:09:45 -0700436 // If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then
437 // fColors4f and fColorSpaceXform will be populated.
438 SkTDArray<SkColor> fColors;
439
440 SkTDArray<SkColor4f> fColors4f;
441 sk_sp<GrColorSpaceXform> fColorSpaceXform;
442
443 SkTDArray<SkScalar> fPositions;
444 SkShader::TileMode fTileMode;
fmenozzicd9a1d02016-08-15 07:03:47 -0700445
bsalomon@google.com77af6802013-10-02 13:04:56 +0000446 GrCoordTransform fCoordTransform;
Brian Salomon0bbecb22016-11-17 11:38:22 -0500447 TextureSampler fTextureSampler;
bsalomon@google.com81712882012-11-01 17:12:34 +0000448 SkScalar fYCoord;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000449 GrTextureStripAtlas* fAtlas;
450 int fRow;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000451 bool fIsOpaque;
fmenozzicd9a1d02016-08-15 07:03:47 -0700452 ColorType fColorType;
453 PremulType fPremulType; // This is already baked into the table for texture gradients, and
454 // only changes behavior for gradients that don't use a texture.
joshualittb0a8a372014-09-23 09:50:21 -0700455 typedef GrFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000456
457};
458
459///////////////////////////////////////////////////////////////////////////////
460
fmenozzicd9a1d02016-08-15 07:03:47 -0700461// Base class for GL gradient effects
fmenozzi55d318d2016-08-09 08:05:57 -0700462class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000463public:
fmenozzicd9a1d02016-08-15 07:03:47 -0700464 GLSLProcessor() {
465 fCachedYCoord = SK_ScalarMax;
466 }
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000467
wangyixb1daa862015-08-18 11:29:31 -0700468protected:
egdaniel018fb622015-10-28 07:26:40 -0700469 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000470
bsalomon@google.comf78df332012-10-29 12:43:38 +0000471protected:
bsalomon63e99f72014-07-21 08:03:14 -0700472 /**
473 * Subclasses must call this. It will return a key for the part of the shader code controlled
474 * by the base class. The subclasses must stick it in their key and then pass it to the below
475 * emit* functions from their emitCode function.
476 */
joshualittb0a8a372014-09-23 09:50:21 -0700477 static uint32_t GenBaseGradientKey(const GrProcessor&);
bsalomon63e99f72014-07-21 08:03:14 -0700478
479 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
480 // should call this method from their emitCode().
egdaniel7ea439b2015-12-03 09:20:44 -0800481 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
bsalomon63e99f72014-07-21 08:03:14 -0700482
fmenozzicd9a1d02016-08-15 07:03:47 -0700483 // Emit code that gets a fragment's color from an expression for t; has branches for
484 // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
485 // color gradients that use the traditional texture lookup, as well as several varieties
486 // of hard stop gradients
cdalton85285412016-02-18 12:37:07 -0800487 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800488 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500489 const GrShaderCaps* shaderCaps,
joshualitt60030bc2014-11-25 14:21:55 -0800490 const GrGradientEffect&,
bsalomon63e99f72014-07-21 08:03:14 -0700491 const char* gradientTValue,
bsalomon63e99f72014-07-21 08:03:14 -0700492 const char* outputColor,
493 const char* inputColor,
bsalomonb58a2b42016-09-26 06:55:02 -0700494 const TextureSamplers&);
bsalomon63e99f72014-07-21 08:03:14 -0700495
496private:
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000497 enum {
fmenozzi64e8e5d2016-07-19 10:45:57 -0700498 // First bit for premul before/after interp
fmenozzicd9a1d02016-08-15 07:03:47 -0700499 kPremulBeforeInterpKey = 1,
bsalomon@google.com82d12232013-09-09 15:36:26 +0000500
fmenozzicd9a1d02016-08-15 07:03:47 -0700501 // Next three bits for 2/3 color type or different special
502 // hard stop cases (neither means using texture atlas)
503 kTwoColorKey = 2,
504 kThreeColorKey = 4,
505#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
506 kHardStopCenteredKey = 6,
507 kHardStopZeroZeroOneKey = 8,
508 kHardStopZeroOneOneKey = 10,
509
510 // Next two bits for tile mode
511 kClampTileMode = 16,
512 kRepeatTileMode = 32,
513 kMirrorTileMode = 48,
514
515 // Lower six bits for premul, 2/3 color type, and tile mode
516 kReservedBits = 6,
517#endif
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000518 };
519
bsalomon@google.com81712882012-11-01 17:12:34 +0000520 SkScalar fCachedYCoord;
fmenozzicd9a1d02016-08-15 07:03:47 -0700521 GrGLSLProgramDataManager::UniformHandle fColorsUni;
Brian Salomon466ad992016-10-13 16:08:36 -0400522 GrGLSLProgramDataManager::UniformHandle fHardStopT;
egdaniel018fb622015-10-28 07:26:40 -0700523 GrGLSLProgramDataManager::UniformHandle fFSYUni;
Brian Osmanc624d9d2017-03-08 11:42:02 -0500524 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000525
egdaniel64c47282015-11-13 06:54:19 -0800526 typedef GrGLSLFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000527};
528
529#endif
530
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000531#endif