blob: 8c188de39b88ce5079974f0f171f0ad880a4954f [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"
Mike Kleina3771842017-05-04 19:38:48 -040020#include "SkPM4fPriv.h"
21#include "SkRasterPipeline.h"
Hal Canary95e3c052017-01-11 12:44:43 -050022#include "SkReadBuffer.h"
23#include "SkShader.h"
24#include "SkUtils.h"
25#include "SkWriteBuffer.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000026
fmenozzicd9a1d02016-08-15 07:03:47 -070027#if SK_SUPPORT_GPU
28 #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1
29#endif
30
humper@google.com05af1af2013-01-07 16:47:43 +000031static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
rileya@google.com1c6d64b2012-07-27 15:49:05 +000032 int count) {
33 if (count > 0) {
34 if (v0 == v1) {
35 sk_memset32(dst, v0, count);
36 } else {
37 int pairs = count >> 1;
38 for (int i = 0; i < pairs; i++) {
39 *dst++ = v0;
40 *dst++ = v1;
41 }
42 if (count & 1) {
43 *dst = v0;
44 }
45 }
46 }
47}
48
49// Clamp
50
humper@google.com05af1af2013-01-07 16:47:43 +000051static inline SkFixed clamp_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000052 return SkClampMax(x, 0xFFFF);
53}
54
55// Repeat
56
humper@google.com05af1af2013-01-07 16:47:43 +000057static inline SkFixed repeat_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000058 return x & 0xFFFF;
59}
60
61// Mirror
62
rileya@google.com1c6d64b2012-07-27 15:49:05 +000063static inline SkFixed mirror_tileproc(SkFixed x) {
caryclark3127c992015-12-09 12:02:30 -080064 int s = SkLeftShift(x, 15) >> 31;
rileya@google.com1c6d64b2012-07-27 15:49:05 +000065 return (x ^ s) & 0xFFFF;
66}
67
rileya@google.com1c6d64b2012-07-27 15:49:05 +000068///////////////////////////////////////////////////////////////////////////////
69
70typedef SkFixed (*TileProc)(SkFixed);
71
72///////////////////////////////////////////////////////////////////////////////
73
74static const TileProc gTileProcs[] = {
75 clamp_tileproc,
76 repeat_tileproc,
77 mirror_tileproc
78};
79
80///////////////////////////////////////////////////////////////////////////////
81
82class SkGradientShaderBase : public SkShader {
83public:
reed@google.com437d6eb2013-05-23 19:03:05 +000084 struct Descriptor {
85 Descriptor() {
86 sk_bzero(this, sizeof(*this));
87 fTileMode = SkShader::kClamp_TileMode;
88 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000089
reedaddf2ed2014-08-11 08:28:24 -070090 const SkMatrix* fLocalMatrix;
brianosmane25d71c2016-09-28 11:27:28 -070091 const SkColor4f* fColors;
brianosmanb9c51372016-09-15 11:09:45 -070092 sk_sp<SkColorSpace> fColorSpace;
reed@google.com437d6eb2013-05-23 19:03:05 +000093 const SkScalar* fPos;
94 int fCount;
95 SkShader::TileMode fTileMode;
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +000096 uint32_t fGradFlags;
reed9fa60da2014-08-21 07:59:51 -070097
98 void flatten(SkWriteBuffer&) const;
99 };
100
101 class DescriptorScope : public Descriptor {
102 public:
103 DescriptorScope() {}
mtklein88fd0fb2014-12-01 06:56:38 -0800104
reed9fa60da2014-08-21 07:59:51 -0700105 bool unflatten(SkReadBuffer&);
106
107 // fColors and fPos always point into local memory, so they can be safely mutated
108 //
brianosmane25d71c2016-09-28 11:27:28 -0700109 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
reed9fa60da2014-08-21 07:59:51 -0700110 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
111
112 private:
113 enum {
114 kStorageCount = 16
115 };
brianosmane25d71c2016-09-28 11:27:28 -0700116 SkColor4f fColorStorage[kStorageCount];
reed9fa60da2014-08-21 07:59:51 -0700117 SkScalar fPosStorage[kStorageCount];
118 SkMatrix fLocalMatrixStorage;
119 SkAutoMalloc fDynamicStorage;
reed@google.com437d6eb2013-05-23 19:03:05 +0000120 };
121
mtkleincc695fe2014-12-10 10:29:19 -0800122 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
Brian Salomond3b65972017-03-22 12:05:03 -0400123 ~SkGradientShaderBase() override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000124
brianosman93110a82016-09-15 08:40:21 -0700125 // The cache is initialized on-demand when getCache32 is called.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000126 class GradientShaderCache : public SkRefCnt {
127 public:
fmalita37d86882015-10-09 10:22:46 -0700128 GradientShaderCache(U8CPU alpha, bool dither, const SkGradientShaderBase& shader);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000129 ~GradientShaderCache();
130
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000131 const SkPMColor* getCache32();
132
Mike Reed6b3155c2017-04-03 14:41:44 -0400133 SkPixelRef* getCache32PixelRef() const { return fCache32PixelRef.get(); }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000134
135 unsigned getAlpha() const { return fCacheAlpha; }
fmalita37d86882015-10-09 10:22:46 -0700136 bool getDither() const { return fCacheDither; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000137
138 private:
brianosman93110a82016-09-15 08:40:21 -0700139 // Working pointer. If it's nullptr, we need to recompute the cache values.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000140 SkPMColor* fCache32;
141
Mike Reed6b3155c2017-04-03 14:41:44 -0400142 sk_sp<SkPixelRef> fCache32PixelRef;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000143 const unsigned fCacheAlpha; // The alpha value we used when we computed the cache.
144 // Larger than 8bits so we can store uninitialized
145 // value.
fmalita37d86882015-10-09 10:22:46 -0700146 const bool fCacheDither; // The dither flag used when we computed the cache.
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000147
148 const SkGradientShaderBase& fShader;
149
brianosman93110a82016-09-15 08:40:21 -0700150 // Make sure we only initialize the cache once.
151 SkOnce fCache32InitOnce;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000152
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000153 static void initCache32(GradientShaderCache* cache);
154
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000155 static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
fmalita37d86882015-10-09 10:22:46 -0700156 U8CPU alpha, uint32_t gradFlags, bool dither);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000157 };
158
159 class GradientShaderBaseContext : public SkShader::Context {
160 public:
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000161 GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000162
mtklein36352bf2015-03-25 18:17:31 -0700163 uint32_t getFlags() const override { return fFlags; }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000164
fmalita088e21b2016-10-05 09:28:42 -0700165 bool isValid() const;
166
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000167 protected:
168 SkMatrix fDstToIndex;
169 SkMatrix::MapXYProc fDstToIndexProc;
170 uint8_t fDstToIndexClass;
171 uint8_t fFlags;
fmalita37d86882015-10-09 10:22:46 -0700172 bool fDither;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000173
Hal Canary67b39de2016-11-07 11:47:44 -0500174 sk_sp<GradientShaderCache> fCache;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000175
176 private:
177 typedef SkShader::Context INHERITED;
178 };
179
mtklein36352bf2015-03-25 18:17:31 -0700180 bool isOpaque() const override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000181
brianosmand4546092016-09-22 12:31:58 -0700182 enum class GradientBitmapType : uint8_t {
183 kLegacy,
184 kSRGB,
185 kHalfFloat,
186 };
187
188 void getGradientTableBitmap(SkBitmap*, GradientBitmapType bitmapType) const;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000189
190 enum {
191 /// Seems like enough for visual accuracy. TODO: if pos[] deserves
192 /// it, use a larger cache.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000193 kCache32Bits = 8,
reed@google.com60040292013-02-04 18:21:23 +0000194 kCache32Count = (1 << kCache32Bits),
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000195 kCache32Shift = 16 - kCache32Bits,
196 kSqrt32Shift = 8 - kCache32Bits,
197
198 /// This value is used to *read* the dither cache; it may be 0
199 /// if dithering is disabled.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000200 kDitherStride32 = kCache32Count,
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000201 };
202
commit-bot@chromium.org6c5aea22014-04-22 16:25:15 +0000203 uint32_t getGradFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000204
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000205protected:
Mike Kleina3771842017-05-04 19:38:48 -0400206 struct Rec {
207 SkFixed fPos; // 0...1
208 uint32_t fScale; // (1 << 24) / range
209 };
210
fmalitabc590c02016-02-22 09:12:33 -0800211 class GradientShaderBase4fContext;
212
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000213 SkGradientShaderBase(SkReadBuffer& );
mtklein36352bf2015-03-25 18:17:31 -0700214 void flatten(SkWriteBuffer&) const override;
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000215 SK_TO_STRING_OVERRIDE()
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000216
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000217 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
skia.committer@gmail.comd3b28e82014-04-22 03:05:17 +0000218
mtklein36352bf2015-03-25 18:17:31 -0700219 bool onAsLuminanceColor(SkColor*) const override;
reed8367b8c2014-08-22 08:30:20 -0700220
brianosmand4546092016-09-22 12:31:58 -0700221 void initLinearBitmap(SkBitmap* bitmap) const;
222
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000223 /*
224 * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
225 * Count is the number of colors in the gradient
226 * It will then flip all the color and rec information and return in their respective Dst
227 * pointers. It is assumed that space has already been allocated for the Dst pointers.
228 * The rec src and dst are only assumed to be valid if count > 2
229 */
230 static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
231 SkColor* colorSrc, Rec* recSrc,
232 int count);
233
Mike Kleina3771842017-05-04 19:38:48 -0400234 bool onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc,
235 const SkMatrix& ctm, const SkPaint& paint,
236 const SkMatrix* localM) const override;
237
238 virtual bool adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
239 SkMatrix* matrix,
240 SkRasterPipeline* p) const { return false; }
241
fmalita088e21b2016-10-05 09:28:42 -0700242 template <typename T, typename... Args>
Herb Derby83e939b2017-02-07 14:25:11 -0500243 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
244 auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
fmalita088e21b2016-10-05 09:28:42 -0700245 if (!ctx->isValid()) {
fmalita088e21b2016-10-05 09:28:42 -0700246 return nullptr;
247 }
248 return ctx;
249 }
250
Mike Kleina3771842017-05-04 19:38:48 -0400251 const SkMatrix fPtsToUnit;
252 TileMode fTileMode;
253 TileProc fTileProc;
254 uint8_t fGradFlags;
255 Rec* fRecs;
256
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000257private:
258 enum {
259 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
260
brianosmanb9c51372016-09-15 11:09:45 -0700261 kStorageSize = kColorStorageCount *
262 (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec) + sizeof(SkColor4f))
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000263 };
brianosmanb9c51372016-09-15 11:09:45 -0700264 SkColor fStorage[(kStorageSize + 3) >> 2];
reedf3182eb2015-11-17 08:12:19 -0800265public:
brianosmanb9c51372016-09-15 11:09:45 -0700266 SkColor* fOrigColors; // original colors, before modulation by paint in context.
267 SkColor4f* fOrigColors4f; // original colors, as linear floats
268 SkScalar* fOrigPos; // original positions
269 int fColorCount;
270 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
reedf3182eb2015-11-17 08:12:19 -0800271
272 bool colorsAreOpaque() const { return fColorsAreOpaque; }
273
fmenozzicd9a1d02016-08-15 07:03:47 -0700274 TileMode getTileMode() const { return fTileMode; }
275 Rec* getRecs() const { return fRecs; }
276
reedf3182eb2015-11-17 08:12:19 -0800277private:
brianosmanb9c51372016-09-15 11:09:45 -0700278 bool fColorsAreOpaque;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000279
Hal Canary67b39de2016-11-07 11:47:44 -0500280 sk_sp<GradientShaderCache> refCache(U8CPU alpha, bool dither) const;
281 mutable SkMutex fCacheMutex;
282 mutable sk_sp<GradientShaderCache> fCache;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000283
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000284 void initCommon();
285
286 typedef SkShader INHERITED;
287};
288
Mike Kleina3771842017-05-04 19:38:48 -0400289
reed@google.com55853db2013-02-01 19:34:59 +0000290static inline int init_dither_toggle(int x, int y) {
reed@google.com60040292013-02-04 18:21:23 +0000291 x &= 1;
292 y = (y & 1) << 1;
293 return (x | y) * SkGradientShaderBase::kDitherStride32;
reed@google.com55853db2013-02-01 19:34:59 +0000294}
295
296static inline int next_dither_toggle(int toggle) {
297 return toggle ^ SkGradientShaderBase::kDitherStride32;
298}
299
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000300///////////////////////////////////////////////////////////////////////////////
301
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000302#if SK_SUPPORT_GPU
303
brianosmanb9c51372016-09-15 11:09:45 -0700304#include "GrColorSpaceXform.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +0000305#include "GrCoordTransform.h"
bsalomon6251d172014-10-15 10:50:36 -0700306#include "GrFragmentProcessor.h"
Brian Osmanc624d9d2017-03-08 11:42:02 -0500307#include "glsl/GrGLSLColorSpaceXformHelper.h"
egdaniel64c47282015-11-13 06:54:19 -0800308#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -0700309#include "glsl/GrGLSLProgramDataManager.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000310
egdaniel605dd0f2014-11-12 08:35:25 -0800311class GrInvariantOutput;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000312
313/*
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000314 * The interpretation of the texture matrix depends on the sample mode. The
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000315 * texture matrix is applied both when the texture coordinates are explicit
316 * and when vertex positions are used as texture coordinates. In the latter
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000317 * case the texture matrix is applied to the pre-view-matrix position
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000318 * values.
319 *
320 * Normal SampleMode
321 * The post-matrix texture coordinates are in normalize space with (0,0) at
322 * the top-left and (1,1) at the bottom right.
323 * RadialGradient
324 * The matrix specifies the radial gradient parameters.
325 * (0,0) in the post-matrix space is center of the radial gradient.
326 * Radial2Gradient
327 * Matrix transforms to space where first circle is centered at the
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000328 * origin. The second circle will be centered (x, 0) where x may be
329 * 0 and is provided by setRadial2Params. The post-matrix space is
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000330 * normalized such that 1 is the second radius - first radius.
331 * SweepGradient
332 * The angle from the origin of texture coordinates in post-matrix space
333 * determines the gradient value.
334 */
335
rileya@google.comb3e50f22012-08-20 17:43:08 +0000336 class GrTextureStripAtlas;
337
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000338// Base class for Gr gradient effects
joshualittb0a8a372014-09-23 09:50:21 -0700339class GrGradientEffect : public GrFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000340public:
brianosman9557c272016-09-15 06:59:15 -0700341 struct CreateArgs {
342 CreateArgs(GrContext* context,
343 const SkGradientShaderBase* shader,
344 const SkMatrix* matrix,
brianosmanb9c51372016-09-15 11:09:45 -0700345 SkShader::TileMode tileMode,
346 sk_sp<GrColorSpaceXform> colorSpaceXform,
347 bool gammaCorrect)
brianosman9557c272016-09-15 06:59:15 -0700348 : fContext(context)
349 , fShader(shader)
350 , fMatrix(matrix)
brianosmanb9c51372016-09-15 11:09:45 -0700351 , fTileMode(tileMode)
352 , fColorSpaceXform(std::move(colorSpaceXform))
353 , fGammaCorrect(gammaCorrect) {}
brianosman9557c272016-09-15 06:59:15 -0700354
355 GrContext* fContext;
356 const SkGradientShaderBase* fShader;
357 const SkMatrix* fMatrix;
358 SkShader::TileMode fTileMode;
brianosmanb9c51372016-09-15 11:09:45 -0700359 sk_sp<GrColorSpaceXform> fColorSpaceXform;
360 bool fGammaCorrect;
brianosman9557c272016-09-15 06:59:15 -0700361 };
362
fmenozzi55d318d2016-08-09 08:05:57 -0700363 class GLSLProcessor;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000364
Brian Salomond3b65972017-03-22 12:05:03 -0400365 ~GrGradientEffect() override;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000366
rileya@google.comb3e50f22012-08-20 17:43:08 +0000367 bool useAtlas() const { return SkToBool(-1 != fRow); }
fmenozzicd9a1d02016-08-15 07:03:47 -0700368 SkScalar getYCoord() const { return fYCoord; }
rileya@google.comb3e50f22012-08-20 17:43:08 +0000369
fmenozzicd9a1d02016-08-15 07:03:47 -0700370 enum ColorType {
371 kTwo_ColorType,
372 kThree_ColorType, // Symmetric three color
373 kTexture_ColorType,
374
375#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
Brian Salomon466ad992016-10-13 16:08:36 -0400376 kSingleHardStop_ColorType, // 0, t, t, 1
fmenozzicd9a1d02016-08-15 07:03:47 -0700377 kHardStopLeftEdged_ColorType, // 0, 0, 1
378 kHardStopRightEdged_ColorType, // 0, 1, 1
379#endif
380 };
381
382 ColorType getColorType() const { return fColorType; }
383
384 // Determines the type of gradient, one of:
385 // - Two-color
386 // - Symmetric three-color
387 // - Texture
388 // - Centered hard stop
389 // - Left-edged hard stop
390 // - Right-edged hard stop
391 ColorType determineColorType(const SkGradientShaderBase& shader);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000392
393 enum PremulType {
394 kBeforeInterp_PremulType,
395 kAfterInterp_PremulType,
396 };
397
398 PremulType getPremulType() const { return fPremulType; }
399
400 const SkColor* getColors(int pos) const {
fmenozzicd9a1d02016-08-15 07:03:47 -0700401 SkASSERT(fColorType != kTexture_ColorType);
402 SkASSERT(pos < fColors.count());
bsalomon@google.com82d12232013-09-09 15:36:26 +0000403 return &fColors[pos];
404 }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000405
brianosmanb9c51372016-09-15 11:09:45 -0700406 const SkColor4f* getColors4f(int pos) const {
407 SkASSERT(fColorType != kTexture_ColorType);
408 SkASSERT(pos < fColors4f.count());
409 return &fColors4f[pos];
410 }
411
bsalomon@google.comd4726202012-08-03 14:34:46 +0000412protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500413 GrGradientEffect(const CreateArgs&, bool isOpaque);
414
Hal Canary6f6961e2017-01-31 13:50:44 -0500415 #if GR_TEST_UTILS
Brian Osmane75c19f2016-10-10 11:26:43 -0400416 /** Helper struct that stores (and populates) parameters to construct a random gradient.
Brian Osmana2196532016-10-17 12:48:13 -0400417 If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and
418 fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount
419 will be the number of color stops in either case, and fColors and fStops can be passed to
420 the gradient factory. (The constructor may decide not to use stops, in which case fStops
421 will be nullptr). */
Brian Osman3f748602016-10-03 18:29:03 -0400422 struct RandomGradientParams {
Brian Salomon5d4cd9e2017-02-09 11:16:46 -0500423 static const int kMaxRandomGradientColors = 5;
Brian Osmane75c19f2016-10-10 11:26:43 -0400424
Brian Osman3f748602016-10-03 18:29:03 -0400425 RandomGradientParams(SkRandom* r);
426
Brian Osmana2196532016-10-17 12:48:13 -0400427 bool fUseColors4f;
Brian Osman3f748602016-10-03 18:29:03 -0400428 SkColor fColors[kMaxRandomGradientColors];
Brian Osmana2196532016-10-17 12:48:13 -0400429 SkColor4f fColors4f[kMaxRandomGradientColors];
430 sk_sp<SkColorSpace> fColorSpace;
Brian Osman3f748602016-10-03 18:29:03 -0400431 SkScalar fStopStorage[kMaxRandomGradientColors];
432 SkShader::TileMode fTileMode;
433 int fColorCount;
434 SkScalar* fStops;
435 };
Hal Canary6f6961e2017-01-31 13:50:44 -0500436 #endif
bsalomon@google.comd4726202012-08-03 14:34:46 +0000437
mtklein36352bf2015-03-25 18:17:31 -0700438 bool onIsEqual(const GrFragmentProcessor&) const override;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000439
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +0000440 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
441
bsalomon@google.comd4726202012-08-03 14:34:46 +0000442private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500443 static OptimizationFlags OptFlags(bool isOpaque);
444
brianosmanb9c51372016-09-15 11:09:45 -0700445 // If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then
446 // fColors4f and fColorSpaceXform will be populated.
447 SkTDArray<SkColor> fColors;
448
449 SkTDArray<SkColor4f> fColors4f;
450 sk_sp<GrColorSpaceXform> fColorSpaceXform;
451
452 SkTDArray<SkScalar> fPositions;
453 SkShader::TileMode fTileMode;
fmenozzicd9a1d02016-08-15 07:03:47 -0700454
bsalomon@google.com77af6802013-10-02 13:04:56 +0000455 GrCoordTransform fCoordTransform;
Brian Salomon0bbecb22016-11-17 11:38:22 -0500456 TextureSampler fTextureSampler;
bsalomon@google.com81712882012-11-01 17:12:34 +0000457 SkScalar fYCoord;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000458 GrTextureStripAtlas* fAtlas;
459 int fRow;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000460 bool fIsOpaque;
fmenozzicd9a1d02016-08-15 07:03:47 -0700461 ColorType fColorType;
462 PremulType fPremulType; // This is already baked into the table for texture gradients, and
463 // only changes behavior for gradients that don't use a texture.
joshualittb0a8a372014-09-23 09:50:21 -0700464 typedef GrFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000465
466};
467
468///////////////////////////////////////////////////////////////////////////////
469
fmenozzicd9a1d02016-08-15 07:03:47 -0700470// Base class for GL gradient effects
fmenozzi55d318d2016-08-09 08:05:57 -0700471class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000472public:
fmenozzicd9a1d02016-08-15 07:03:47 -0700473 GLSLProcessor() {
474 fCachedYCoord = SK_ScalarMax;
475 }
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000476
wangyixb1daa862015-08-18 11:29:31 -0700477protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400478 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000479
bsalomon@google.comf78df332012-10-29 12:43:38 +0000480protected:
bsalomon63e99f72014-07-21 08:03:14 -0700481 /**
482 * Subclasses must call this. It will return a key for the part of the shader code controlled
483 * by the base class. The subclasses must stick it in their key and then pass it to the below
484 * emit* functions from their emitCode function.
485 */
joshualittb0a8a372014-09-23 09:50:21 -0700486 static uint32_t GenBaseGradientKey(const GrProcessor&);
bsalomon63e99f72014-07-21 08:03:14 -0700487
488 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
489 // should call this method from their emitCode().
egdaniel7ea439b2015-12-03 09:20:44 -0800490 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&);
bsalomon63e99f72014-07-21 08:03:14 -0700491
fmenozzicd9a1d02016-08-15 07:03:47 -0700492 // Emit code that gets a fragment's color from an expression for t; has branches for
493 // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+
494 // color gradients that use the traditional texture lookup, as well as several varieties
495 // of hard stop gradients
cdalton85285412016-02-18 12:37:07 -0800496 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800497 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500498 const GrShaderCaps* shaderCaps,
joshualitt60030bc2014-11-25 14:21:55 -0800499 const GrGradientEffect&,
bsalomon63e99f72014-07-21 08:03:14 -0700500 const char* gradientTValue,
bsalomon63e99f72014-07-21 08:03:14 -0700501 const char* outputColor,
502 const char* inputColor,
bsalomonb58a2b42016-09-26 06:55:02 -0700503 const TextureSamplers&);
bsalomon63e99f72014-07-21 08:03:14 -0700504
505private:
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000506 enum {
fmenozzi64e8e5d2016-07-19 10:45:57 -0700507 // First bit for premul before/after interp
fmenozzicd9a1d02016-08-15 07:03:47 -0700508 kPremulBeforeInterpKey = 1,
bsalomon@google.com82d12232013-09-09 15:36:26 +0000509
fmenozzicd9a1d02016-08-15 07:03:47 -0700510 // Next three bits for 2/3 color type or different special
511 // hard stop cases (neither means using texture atlas)
512 kTwoColorKey = 2,
513 kThreeColorKey = 4,
514#if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS
515 kHardStopCenteredKey = 6,
516 kHardStopZeroZeroOneKey = 8,
517 kHardStopZeroOneOneKey = 10,
518
519 // Next two bits for tile mode
520 kClampTileMode = 16,
521 kRepeatTileMode = 32,
522 kMirrorTileMode = 48,
523
524 // Lower six bits for premul, 2/3 color type, and tile mode
525 kReservedBits = 6,
526#endif
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000527 };
528
bsalomon@google.com81712882012-11-01 17:12:34 +0000529 SkScalar fCachedYCoord;
fmenozzicd9a1d02016-08-15 07:03:47 -0700530 GrGLSLProgramDataManager::UniformHandle fColorsUni;
Brian Salomon466ad992016-10-13 16:08:36 -0400531 GrGLSLProgramDataManager::UniformHandle fHardStopT;
egdaniel018fb622015-10-28 07:26:40 -0700532 GrGLSLProgramDataManager::UniformHandle fFSYUni;
Brian Osmanc624d9d2017-03-08 11:42:02 -0500533 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000534
egdaniel64c47282015-11-13 06:54:19 -0800535 typedef GrGLSLFragmentProcessor INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000536};
537
538#endif
539
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000540#endif