blob: 84fe49880ac60e5ef876e9f421db5e519055eabf [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
11#include "SkGradientShader.h"
12#include "SkClampRange.h"
13#include "SkColorPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000014#include "SkReadBuffer.h"
15#include "SkWriteBuffer.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000016#include "SkMallocPixelRef.h"
17#include "SkUnitMapper.h"
18#include "SkUtils.h"
19#include "SkTemplates.h"
20#include "SkBitmapCache.h"
21#include "SkShader.h"
rileya@google.com1c6d64b2012-07-27 15:49:05 +000022
humper@google.com05af1af2013-01-07 16:47:43 +000023static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
rileya@google.com1c6d64b2012-07-27 15:49:05 +000024 int count) {
25 if (count > 0) {
26 if (v0 == v1) {
27 sk_memset32(dst, v0, count);
28 } else {
29 int pairs = count >> 1;
30 for (int i = 0; i < pairs; i++) {
31 *dst++ = v0;
32 *dst++ = v1;
33 }
34 if (count & 1) {
35 *dst = v0;
36 }
37 }
38 }
39}
40
41// Clamp
42
humper@google.com05af1af2013-01-07 16:47:43 +000043static inline SkFixed clamp_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000044 return SkClampMax(x, 0xFFFF);
45}
46
47// Repeat
48
humper@google.com05af1af2013-01-07 16:47:43 +000049static inline SkFixed repeat_tileproc(SkFixed x) {
rileya@google.com1c6d64b2012-07-27 15:49:05 +000050 return x & 0xFFFF;
51}
52
53// Mirror
54
55// Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
56// See http://code.google.com/p/skia/issues/detail?id=472
57#if defined(_MSC_VER) && (_MSC_VER >= 1600)
58#pragma optimize("", off)
59#endif
60
61static inline SkFixed mirror_tileproc(SkFixed x) {
62 int s = x << 15 >> 31;
63 return (x ^ s) & 0xFFFF;
64}
65
66#if defined(_MSC_VER) && (_MSC_VER >= 1600)
67#pragma optimize("", on)
68#endif
69
70///////////////////////////////////////////////////////////////////////////////
71
72typedef SkFixed (*TileProc)(SkFixed);
73
74///////////////////////////////////////////////////////////////////////////////
75
76static const TileProc gTileProcs[] = {
77 clamp_tileproc,
78 repeat_tileproc,
79 mirror_tileproc
80};
81
82///////////////////////////////////////////////////////////////////////////////
83
84class SkGradientShaderBase : public SkShader {
85public:
reed@google.com437d6eb2013-05-23 19:03:05 +000086 struct Descriptor {
87 Descriptor() {
88 sk_bzero(this, sizeof(*this));
89 fTileMode = SkShader::kClamp_TileMode;
90 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000091
reed@google.com437d6eb2013-05-23 19:03:05 +000092 const SkColor* fColors;
93 const SkScalar* fPos;
94 int fCount;
95 SkShader::TileMode fTileMode;
96 SkUnitMapper* fMapper;
reed@google.com3d3a8602013-05-24 14:58:44 +000097 uint32_t fFlags;
reed@google.com437d6eb2013-05-23 19:03:05 +000098 };
99
100public:
101 SkGradientShaderBase(const Descriptor& desc);
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000102 virtual ~SkGradientShaderBase();
103
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000104 virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
105 virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000106 virtual bool isOpaque() const SK_OVERRIDE;
107
108 void getGradientTableBitmap(SkBitmap*) const;
109
110 enum {
111 /// Seems like enough for visual accuracy. TODO: if pos[] deserves
112 /// it, use a larger cache.
113 kCache16Bits = 8,
reed@google.com3c2102c2013-02-01 12:59:40 +0000114 kCache16Count = (1 << kCache16Bits),
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000115 kCache16Shift = 16 - kCache16Bits,
116 kSqrt16Shift = 8 - kCache16Bits,
117
118 /// Seems like enough for visual accuracy. TODO: if pos[] deserves
119 /// it, use a larger cache.
120 kCache32Bits = 8,
reed@google.com60040292013-02-04 18:21:23 +0000121 kCache32Count = (1 << kCache32Bits),
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000122 kCache32Shift = 16 - kCache32Bits,
123 kSqrt32Shift = 8 - kCache32Bits,
124
125 /// This value is used to *read* the dither cache; it may be 0
126 /// if dithering is disabled.
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000127 kDitherStride32 = kCache32Count,
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000128 kDitherStride16 = kCache16Count,
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000129 };
130
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000131 enum GpuColorType {
132 kTwo_GpuColorType,
133 kThree_GpuColorType, // Symmetric three color
134 kTexture_GpuColorType
135 };
136
137 // Determines and returns the gradient is a two color gradient, symmetric three color gradient
138 // or other (texture gradient). If it is two or symmetric three color, the colors array will
139 // also be filled with the gradient colors
140 GpuColorType getGpuColorType(SkColor colors[3]) const;
141
skia.committer@gmail.com8a777a52014-04-19 03:04:56 +0000142 uint32_t getFlags() const { return fGradFlags; }
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000143
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000144protected:
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000145 SkGradientShaderBase(SkReadBuffer& );
146 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000147 SK_TO_STRING_OVERRIDE()
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000148
149 SkUnitMapper* fMapper;
150 SkMatrix fPtsToUnit; // set by subclass
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000151 SkMatrix fDstToIndex;
152 SkMatrix::MapXYProc fDstToIndexProc;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000153 TileMode fTileMode;
154 TileProc fTileProc;
155 int fColorCount;
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000156 uint8_t fDstToIndexClass;
157 uint8_t fFlags;
reed@google.com3d3a8602013-05-24 14:58:44 +0000158 uint8_t fGradFlags;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000159
160 struct Rec {
161 SkFixed fPos; // 0...1
162 uint32_t fScale; // (1 << 24) / range
163 };
164 Rec* fRecs;
165
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000166 const uint16_t* getCache16() const;
167 const SkPMColor* getCache32() const;
168
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +0000169 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
170
171 /*
172 * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
173 * Count is the number of colors in the gradient
174 * It will then flip all the color and rec information and return in their respective Dst
175 * pointers. It is assumed that space has already been allocated for the Dst pointers.
176 * The rec src and dst are only assumed to be valid if count > 2
177 */
178 static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
179 SkColor* colorSrc, Rec* recSrc,
180 int count);
181
182 // V23_COMPATIBILITY_CODE
183 // Used for 2-pt conical gradients since we sort start/end cirlces by radius
184 // Assumes space has already been allocated for fOrigColors
185 void flipGradientColors();
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000186
187private:
188 enum {
189 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
190
191 kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
192 };
193 SkColor fStorage[(kStorageSize + 3) >> 2];
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000194 SkColor* fOrigColors; // original colors, before modulation by paint in setContext
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000195 bool fColorsAreOpaque;
196
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000197 mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values
198 mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000199
commit-bot@chromium.org53783b02014-04-17 21:09:49 +0000200 mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand
201 mutable SkMallocPixelRef* fCache32PixelRef;
202 mutable unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
203
204 static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
205 static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
206 U8CPU alpha, uint32_t gradFlags);
207 void setCacheAlpha(U8CPU alpha) const;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000208 void initCommon();
209
210 typedef SkShader INHERITED;
211};
212
reed@google.com55853db2013-02-01 19:34:59 +0000213static inline int init_dither_toggle(int x, int y) {
reed@google.com60040292013-02-04 18:21:23 +0000214 x &= 1;
215 y = (y & 1) << 1;
216 return (x | y) * SkGradientShaderBase::kDitherStride32;
reed@google.com55853db2013-02-01 19:34:59 +0000217}
218
219static inline int next_dither_toggle(int toggle) {
220 return toggle ^ SkGradientShaderBase::kDitherStride32;
221}
222
223static inline int init_dither_toggle16(int x, int y) {
224 return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
225}
226
227static inline int next_dither_toggle16(int toggle) {
228 return toggle ^ SkGradientShaderBase::kDitherStride16;
229}
230
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000231///////////////////////////////////////////////////////////////////////////////
232
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000233#if SK_SUPPORT_GPU
234
bsalomon@google.com77af6802013-10-02 13:04:56 +0000235#include "GrCoordTransform.h"
bsalomon@google.comd698f772012-10-25 13:22:00 +0000236#include "gl/GrGLEffect.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000237
bsalomon@google.com08283af2012-10-26 13:01:20 +0000238class GrEffectStage;
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000239class GrBackendEffectFactory;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000240
241/*
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000242 * The interpretation of the texture matrix depends on the sample mode. The
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000243 * texture matrix is applied both when the texture coordinates are explicit
244 * and when vertex positions are used as texture coordinates. In the latter
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000245 * case the texture matrix is applied to the pre-view-matrix position
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000246 * values.
247 *
248 * Normal SampleMode
249 * The post-matrix texture coordinates are in normalize space with (0,0) at
250 * the top-left and (1,1) at the bottom right.
251 * RadialGradient
252 * The matrix specifies the radial gradient parameters.
253 * (0,0) in the post-matrix space is center of the radial gradient.
254 * Radial2Gradient
255 * Matrix transforms to space where first circle is centered at the
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000256 * origin. The second circle will be centered (x, 0) where x may be
257 * 0 and is provided by setRadial2Params. The post-matrix space is
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000258 * normalized such that 1 is the second radius - first radius.
259 * SweepGradient
260 * The angle from the origin of texture coordinates in post-matrix space
261 * determines the gradient value.
262 */
263
rileya@google.comb3e50f22012-08-20 17:43:08 +0000264 class GrTextureStripAtlas;
265
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000266// Base class for Gr gradient effects
bsalomon@google.coma469c282012-10-24 18:28:34 +0000267class GrGradientEffect : public GrEffect {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000268public:
269
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000270 GrGradientEffect(GrContext* ctx,
271 const SkGradientShaderBase& shader,
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000272 const SkMatrix& matrix,
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000273 SkShader::TileMode tileMode);
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000274
275 virtual ~GrGradientEffect();
276
rileya@google.comb3e50f22012-08-20 17:43:08 +0000277 bool useAtlas() const { return SkToBool(-1 != fRow); }
bsalomon@google.com81712882012-11-01 17:12:34 +0000278 SkScalar getYCoord() const { return fYCoord; };
rileya@google.comb3e50f22012-08-20 17:43:08 +0000279
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000280 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
skia.committer@gmail.com9a070f22013-09-10 07:01:44 +0000281
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000282 SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
bsalomon@google.com82d12232013-09-09 15:36:26 +0000283
284 enum PremulType {
285 kBeforeInterp_PremulType,
286 kAfterInterp_PremulType,
287 };
288
289 PremulType getPremulType() const { return fPremulType; }
290
291 const SkColor* getColors(int pos) const {
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000292 SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
bsalomon@google.com82d12232013-09-09 15:36:26 +0000293 SkASSERT((pos-1) <= fColorType);
294 return &fColors[pos];
295 }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000296
bsalomon@google.comd4726202012-08-03 14:34:46 +0000297protected:
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000298
bsalomon@google.comd4726202012-08-03 14:34:46 +0000299 /** Populates a pair of arrays with colors and stop info to construct a random gradient.
300 The function decides whether stop values should be used or not. The return value indicates
301 the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
302 sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
303 size kMaxRandomGradientColors. It may be updated to NULL, indicating that NULL should be
304 passed to the gradient factory rather than the array.
305 */
306 static const int kMaxRandomGradientColors = 4;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000307 static int RandomGradientParams(SkRandom* r,
bsalomon@google.comd4726202012-08-03 14:34:46 +0000308 SkColor colors[kMaxRandomGradientColors],
309 SkScalar** stops,
310 SkShader::TileMode* tm);
311
bsalomon@google.com8a252f72013-01-22 20:35:13 +0000312 virtual bool onIsEqual(const GrEffect& effect) const SK_OVERRIDE;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000313
commit-bot@chromium.org5fd7d5c2013-10-04 01:20:09 +0000314 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
315
bsalomon@google.comd4726202012-08-03 14:34:46 +0000316private:
bsalomon@google.com77af6802013-10-02 13:04:56 +0000317 static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000318
bsalomon@google.com77af6802013-10-02 13:04:56 +0000319 GrCoordTransform fCoordTransform;
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000320 GrTextureAccess fTextureAccess;
bsalomon@google.com81712882012-11-01 17:12:34 +0000321 SkScalar fYCoord;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000322 GrTextureStripAtlas* fAtlas;
323 int fRow;
bsalomon@google.com371e1052013-01-11 21:08:55 +0000324 bool fIsOpaque;
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000325 SkGradientShaderBase::GpuColorType fColorType;
326 SkColor fColors[3]; // More than 3 colors we use texture
bsalomon@google.com82d12232013-09-09 15:36:26 +0000327 PremulType fPremulType; // This only changes behavior for two and three color special cases.
328 // It is already baked into to the table for texture gradients.
bsalomon@google.coma469c282012-10-24 18:28:34 +0000329 typedef GrEffect INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000330
331};
332
333///////////////////////////////////////////////////////////////////////////////
334
bsalomon@google.com8ea78d82012-10-24 20:11:30 +0000335// Base class for GL gradient effects
bsalomon@google.comf78df332012-10-29 12:43:38 +0000336class GrGLGradientEffect : public GrGLEffect {
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000337public:
bsalomon@google.com0707c292012-10-25 21:45:42 +0000338 GrGLGradientEffect(const GrBackendEffectFactory& factory);
339 virtual ~GrGLGradientEffect();
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000340
bsalomon@google.comc7818882013-03-20 19:19:53 +0000341 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000342
bsalomon@google.comf78df332012-10-29 12:43:38 +0000343protected:
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000344 enum {
bsalomon@google.com82d12232013-09-09 15:36:26 +0000345 kPremulTypeKeyBitCnt = 1,
bsalomon@google.com77af6802013-10-02 13:04:56 +0000346 kPremulTypeMask = 1,
bsalomon@google.com82d12232013-09-09 15:36:26 +0000347 kPremulBeforeInterpKey = kPremulTypeMask,
348
bsalomon@google.com77af6802013-10-02 13:04:56 +0000349 kTwoColorKey = 2 << kPremulTypeKeyBitCnt,
350 kThreeColorKey = 3 << kPremulTypeKeyBitCnt,
bsalomon@google.com82d12232013-09-09 15:36:26 +0000351 kColorKeyMask = kTwoColorKey | kThreeColorKey,
352 kColorKeyBitCnt = 2,
353
354 // Subclasses must shift any key bits they produce up by this amount
355 // and combine with the result of GenBaseGradientKey.
bsalomon@google.com77af6802013-10-02 13:04:56 +0000356 kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000357 };
358
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000359 static SkGradientShaderBase::GpuColorType ColorTypeFromKey(EffectKey key){
bsalomon@google.com82d12232013-09-09 15:36:26 +0000360 if (kTwoColorKey == (key & kColorKeyMask)) {
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000361 return SkGradientShaderBase::kTwo_GpuColorType;
bsalomon@google.com82d12232013-09-09 15:36:26 +0000362 } else if (kThreeColorKey == (key & kColorKeyMask)) {
commit-bot@chromium.org996402b2014-04-18 14:42:11 +0000363 return SkGradientShaderBase::kThree_GpuColorType;
364 } else {return SkGradientShaderBase::kTexture_GpuColorType;}
bsalomon@google.com82d12232013-09-09 15:36:26 +0000365 }
366
367 static GrGradientEffect::PremulType PremulTypeFromKey(EffectKey key){
368 if (kPremulBeforeInterpKey == (key & kPremulTypeMask)) {
369 return GrGradientEffect::kBeforeInterp_PremulType;
370 } else {
371 return GrGradientEffect::kAfterInterp_PremulType;
372 }
373 }
374
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000375 /**
bsalomon@google.com82d12232013-09-09 15:36:26 +0000376 * Subclasses must call this. It will return a value restricted to the lower kBaseKeyBitCnt
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000377 * bits.
378 */
bsalomon@google.com82d12232013-09-09 15:36:26 +0000379 static EffectKey GenBaseGradientKey(const GrDrawEffect&);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000380
bsalomon@google.comf78df332012-10-29 12:43:38 +0000381 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
382 // should call this method from their emitCode().
bsalomon@google.com82d12232013-09-09 15:36:26 +0000383 void emitUniforms(GrGLShaderBuilder* builder, EffectKey key);
bsalomon@google.comf78df332012-10-29 12:43:38 +0000384
bsalomon@google.com82d12232013-09-09 15:36:26 +0000385
386 // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
387 // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
388 // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
389 void emitColor(GrGLShaderBuilder* builder,
390 const char* gradientTValue,
391 EffectKey key,
392 const char* outputColor,
393 const char* inputColor,
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000394 const TextureSamplerArray& samplers);
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000395
396private:
bsalomon@google.com81712882012-11-01 17:12:34 +0000397 SkScalar fCachedYCoord;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000398 GrGLUniformManager::UniformHandle fFSYUni;
bsalomon@google.com82d12232013-09-09 15:36:26 +0000399 GrGLUniformManager::UniformHandle fColorStartUni;
400 GrGLUniformManager::UniformHandle fColorMidUni;
401 GrGLUniformManager::UniformHandle fColorEndUni;
rileya@google.comb3e50f22012-08-20 17:43:08 +0000402
bsalomon@google.comf78df332012-10-29 12:43:38 +0000403 typedef GrGLEffect INHERITED;
rileya@google.com1c6d64b2012-07-27 15:49:05 +0000404};
405
406#endif
407
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000408#endif