blob: 54372ce836e5fab39357340320d518da48481749 [file] [log] [blame]
tomhudson@google.com93813632011-10-27 20:21:16 +00001/*
2 * Copyright 2011 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 GrDrawState_DEFINED
9#define GrDrawState_DEFINED
10
11#include "GrColor.h"
12#include "GrMatrix.h"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000013#include "GrRefCnt.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000014#include "GrEffectStage.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000015#include "GrStencil.h"
bsalomon@google.com64aef2b2012-06-11 15:36:13 +000016#include "GrTexture.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000017#include "GrRenderTarget.h"
tomhudson@google.com1e8f0162012-07-20 16:25:18 +000018#include "effects/GrSingleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000019
20#include "SkXfermode.h"
21
bsalomon@google.comaf84e742012-10-05 13:23:24 +000022class GrPaint;
tomhudson@google.com93813632011-10-27 20:21:16 +000023
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000024class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000026 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000027
tomhudson@google.com93813632011-10-27 20:21:16 +000028 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000029 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
30 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
31 * output from the previous enabled stage and a position. The position is either derived from
32 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
33 * GrVertexLayout used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000034 *
bsalomon@google.com13221342012-10-26 13:41:59 +000035 * The stages are divided into two sets, color-computing and coverage-computing. The final color
36 * stage produces the final pixel color. The coverage-computing stages function exactly as the
37 * color-computing but the output of the final coverage stage is treated as a fractional pixel
38 * coverage rather than as input to the src/dst color blend step.
39 *
40 * The input color to the first enabled color-stage is either the constant color or interpolated
41 * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is
42 * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
43 * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
44 * GrEffect).
45 *
46 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
47 * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
48 * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000049 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000050 */
51 enum {
twiz@google.com58071162012-07-18 21:41:50 +000052 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000053 kMaxTexCoords = kNumStages
54 };
55
rmistry@google.comd6176b02012-08-23 18:14:13 +000056 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000057 : fRenderTarget(NULL) {
58
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000059 this->reset();
60 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000061
rmistry@google.comd6176b02012-08-23 18:14:13 +000062 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000063 : fRenderTarget(NULL) {
64
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000065 *this = state;
66 }
67
robertphillips@google.com9ec07532012-06-22 12:01:30 +000068 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000069 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000070 GrSafeSetNull(fRenderTarget);
71 }
72
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000073 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000074 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000075 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000076 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000077 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000078
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000079 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000080
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000081 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000082 fViewMatrix.reset();
83 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000084 fSrcBlend = kOne_GrBlendCoeff;
85 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000086 fBlendConstant = 0x0;
87 fFlagBits = 0x0;
88 fVertexEdgeType = kHairLine_EdgeType;
89 fStencilSettings.setDisabled();
90 fFirstCoverageStage = kNumStages;
91 fCoverage = 0xffffffff;
92 fColorFilterMode = SkXfermode::kDst_Mode;
93 fColorFilterColor = 0x0;
94 fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000095 }
96
97 /**
98 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +000099 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000100 * GrPaint equivalents are not modified. GrPaint has fewer stages than
101 * GrDrawState. The extra GrDrawState stages are disabled.
102 */
103 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000104
105 ///////////////////////////////////////////////////////////////////////////
106 /// @name Color
107 ////
108
109 /**
110 * Sets color for next draw to a premultiplied-alpha color.
111 *
112 * @param color the color to set.
113 */
114 void setColor(GrColor color) { fColor = color; }
115
116 GrColor getColor() const { return fColor; }
117
118 /**
119 * Sets the color to be used for the next draw to be
120 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
121 *
122 * @param alpha The alpha value to set as the color.
123 */
124 void setAlpha(uint8_t a) {
125 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
126 }
127
128 /**
129 * Add a color filter that can be represented by a color and a mode. Applied
130 * after color-computing texture stages.
131 */
132 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
133 fColorFilterColor = c;
134 fColorFilterMode = mode;
135 }
136
137 GrColor getColorFilterColor() const { return fColorFilterColor; }
138 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
139
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000140 /**
141 * Constructor sets the color to be 'color' which is undone by the destructor.
142 */
143 class AutoColorRestore : public ::GrNoncopyable {
144 public:
145 AutoColorRestore(GrDrawState* drawState, GrColor color) {
146 fDrawState = drawState;
147 fOldColor = fDrawState->getColor();
148 fDrawState->setColor(color);
149 }
150 ~AutoColorRestore() {
151 fDrawState->setColor(fOldColor);
152 }
153 private:
154 GrDrawState* fDrawState;
155 GrColor fOldColor;
156 };
157
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000158 /// @}
159
160 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000161 /// @name Coverage
162 ////
163
164 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000165 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000166 * initial value (after construction or reset()) is 0xff. The constant
167 * coverage is ignored when per-vertex coverage is provided.
168 */
169 void setCoverage(uint8_t coverage) {
170 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
171 }
172
173 /**
174 * Version of above that specifies 4 channel per-vertex color. The value
175 * should be premultiplied.
176 */
177 void setCoverage4(GrColor coverage) {
178 fCoverage = coverage;
179 }
180
181 GrColor getCoverage() const {
182 return fCoverage;
183 }
184
185 /// @}
186
187 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000188 /// @name Textures
189 ////
190
191 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000192 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000193 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000194 void createTextureEffect(int stageIdx, GrTexture* texture) {
195 GrAssert(!this->getStage(stageIdx).getEffect());
196 this->stage(stageIdx)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000197 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000198 void createTextureEffect(int stageIdx, GrTexture* texture, const GrMatrix& matrix) {
199 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000200 GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture));
bsalomon@google.com08283af2012-10-26 13:01:20 +0000201 this->stage(stageIdx)->setEffect(effect, matrix)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000202 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000203 void createTextureEffect(int stageIdx,
204 GrTexture* texture,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000205 const GrMatrix& matrix,
206 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000207 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000208 GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, params));
bsalomon@google.com08283af2012-10-26 13:01:20 +0000209 this->stage(stageIdx)->setEffect(effect, matrix)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000210 }
211
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000212
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000213 bool stagesDisabled() {
214 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000215 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000216 return false;
217 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000218 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000219 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000220 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000221
bsalomon@google.com08283af2012-10-26 13:01:20 +0000222 void disableStage(int stageIdx) {
223 fStages[stageIdx].setEffect(NULL);
tomhudson@google.com676e6602012-07-10 17:21:48 +0000224 }
225
robertphillips@google.com972265d2012-06-13 18:49:30 +0000226 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000227 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000228 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000229 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000230 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000231 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000232 }
233 }
234
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000235 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000236 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000237 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
238 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000239 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000240 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000241 }
242 }
243 private:
244 GrDrawState* fDrawState;
245 };
246
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000247 /// @}
248
249 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com08283af2012-10-26 13:01:20 +0000250 /// @name Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000251 ////
252
253 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000254 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000255 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000256 const GrEffectStage& getStage(int stageIdx) const {
257 GrAssert((unsigned)stageIdx < kNumStages);
258 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000259 }
260
261 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000262 * Writable pointer to a stage.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000263 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000264 GrEffectStage* stage(int stageIdx) {
265 GrAssert((unsigned)stageIdx < kNumStages);
266 return fStages + stageIdx;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000267 }
268
269 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000270 * Called when the source coord system is changing. preConcat gives the transformation from the
271 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000272 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000273 void preConcatStageMatrices(const GrMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000274 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000275 if (this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000276 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000277 }
278 }
279 }
280
bsalomon@google.come3d32162012-07-20 13:37:06 +0000281 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000282 * Called when the source coord system is changing. preConcatInverse is the inverse of the
283 * transformation from the old coord system to the new coord system. Returns false if the matrix
284 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000285 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000286 bool preConcatStageMatricesWithInverse(const GrMatrix& preConcatInverse) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000287 GrMatrix inv;
288 bool computed = false;
289 for (int i = 0; i < kNumStages; ++i) {
290 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000291 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000292 return false;
293 } else {
294 computed = true;
295 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000296 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000297 }
298 }
299 return true;
300 }
301
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000302 /// @}
303
304 ///////////////////////////////////////////////////////////////////////////
305 /// @name Coverage / Color Stages
306 ////
307
308 /**
309 * A common pattern is to compute a color with the initial stages and then
310 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000311 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
312 * computed based on the pre-coverage-modulated color. The division of
313 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000314 * this method. Initially this is kNumStages (all stages
315 * are color-computing).
316 */
317 void setFirstCoverageStage(int firstCoverageStage) {
318 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000319 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000320 }
321
322 /**
323 * Gets the index of the first coverage-computing stage.
324 */
325 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000326 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000327 }
328
329 ///@}
330
331 ///////////////////////////////////////////////////////////////////////////
332 /// @name Blending
333 ////
334
335 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000336 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000337 *
338 * The blend function will be:
339 * D' = sat(S*srcCoef + D*dstCoef)
340 *
341 * where D is the existing destination color, S is the incoming source
342 * color, and D' is the new destination color that will be written. sat()
343 * is the saturation function.
344 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000345 * @param srcCoef coefficient applied to the src color.
346 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000347 */
348 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
349 fSrcBlend = srcCoeff;
350 fDstBlend = dstCoeff;
351 #if GR_DEBUG
352 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000353 case kDC_GrBlendCoeff:
354 case kIDC_GrBlendCoeff:
355 case kDA_GrBlendCoeff:
356 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000357 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
358 "coverage stages.\n");
359 break;
360 default:
361 break;
362 }
363 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000364 case kSC_GrBlendCoeff:
365 case kISC_GrBlendCoeff:
366 case kSA_GrBlendCoeff:
367 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000368 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
369 "coverage stages.\n");
370 break;
371 default:
372 break;
373 }
374 #endif
375 }
376
377 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
378 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
379
380 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
381 GrBlendCoeff* dstBlendCoeff) const {
382 *srcBlendCoeff = fSrcBlend;
383 *dstBlendCoeff = fDstBlend;
384 }
385
386 /**
387 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000388 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000389 * kConstC_GrBlendCoeff
390 * kIConstC_GrBlendCoeff
391 * kConstA_GrBlendCoeff
392 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000393 *
394 * @param constant the constant to set
395 */
396 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
397
398 /**
399 * Retrieves the last value set by setBlendConstant()
400 * @return the blending constant value
401 */
402 GrColor getBlendConstant() const { return fBlendConstant; }
403
404 /// @}
405
406 ///////////////////////////////////////////////////////////////////////////
407 /// @name View Matrix
408 ////
409
410 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000411 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000412 *
413 * In the post-view-matrix space the rectangle [0,w]x[0,h]
414 * fully covers the render target. (w and h are the width and height of the
415 * the rendertarget.)
416 */
417 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
418
419 /**
420 * Gets a writable pointer to the view matrix.
421 */
422 GrMatrix* viewMatrix() { return &fViewMatrix; }
423
424 /**
425 * Multiplies the current view matrix by a matrix
426 *
427 * After this call V' = V*m where V is the old view matrix,
428 * m is the parameter to this function, and V' is the new view matrix.
429 * (We consider positions to be column vectors so position vector p is
430 * transformed by matrix X as p' = X*p.)
431 *
432 * @param m the matrix used to modify the view matrix.
433 */
434 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
435
436 /**
437 * Multiplies the current view matrix by a matrix
438 *
439 * After this call V' = m*V where V is the old view matrix,
440 * m is the parameter to this function, and V' is the new view matrix.
441 * (We consider positions to be column vectors so position vector p is
442 * transformed by matrix X as p' = X*p.)
443 *
444 * @param m the matrix used to modify the view matrix.
445 */
446 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
447
448 /**
449 * Retrieves the current view matrix
450 * @return the current view matrix.
451 */
452 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
453
454 /**
455 * Retrieves the inverse of the current view matrix.
456 *
457 * If the current view matrix is invertible, return true, and if matrix
458 * is non-null, copy the inverse into it. If the current view matrix is
459 * non-invertible, return false and ignore the matrix parameter.
460 *
461 * @param matrix if not null, will receive a copy of the current inverse.
462 */
463 bool getViewInverse(GrMatrix* matrix) const {
464 // TODO: determine whether we really need to leave matrix unmodified
465 // at call sites when inversion fails.
466 GrMatrix inverse;
467 if (fViewMatrix.invert(&inverse)) {
468 if (matrix) {
469 *matrix = inverse;
470 }
471 return true;
472 }
473 return false;
474 }
475
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000476 ////////////////////////////////////////////////////////////////////////////
477
478 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000479 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000480 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000481 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000482 class AutoViewMatrixRestore : public ::GrNoncopyable {
483 public:
484 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000485
486 AutoViewMatrixRestore(GrDrawState* ds,
487 const GrMatrix& preconcatMatrix,
488 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000489 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000490 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000491 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000492
493 ~AutoViewMatrixRestore() { this->restore(); }
494
bsalomon@google.coma8347462012-10-08 18:59:39 +0000495 /**
496 * Can be called prior to destructor to restore the original matrix.
497 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000498 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000499
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000500 void set(GrDrawState* drawState,
501 const GrMatrix& preconcatMatrix,
502 uint32_t explicitCoordStageMask = 0);
503
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000504 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000505
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000506 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000507 GrDrawState* fDrawState;
508 GrMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000509 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000510 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000511 };
512
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000513 ////////////////////////////////////////////////////////////////////////////
514
515 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000516 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
517 * destructor undoes the changes, restoring the view matrix that was set before the
518 * constructor. It is similar to passing the inverse of the current view matrix to
519 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000520 */
521 class AutoDeviceCoordDraw : ::GrNoncopyable {
522 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000523 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000524 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000525 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
526 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
527 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000528 */
529 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000530 uint32_t explicitCoordStageMask = 0) {
531 fDrawState = NULL;
532 this->set(drawState, explicitCoordStageMask);
533 }
534
bsalomon@google.coma8347462012-10-08 18:59:39 +0000535 ~AutoDeviceCoordDraw() { this->restore(); }
536
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000537 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
538
bsalomon@google.coma8347462012-10-08 18:59:39 +0000539 /**
540 * Returns true if this object was successfully initialized on to a GrDrawState. It may
541 * return false because a non-default constructor or set() were never called or because
542 * the view matrix was not invertible.
543 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000544 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000545
bsalomon@google.coma8347462012-10-08 18:59:39 +0000546 /**
547 * Returns the matrix that was set previously set on the drawState. This is only valid
548 * if succeeded returns true.
549 */
550 const GrMatrix& getOriginalMatrix() const {
551 GrAssert(this->succeeded());
552 return fViewMatrix;
553 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000554
bsalomon@google.coma8347462012-10-08 18:59:39 +0000555 /**
556 * Can be called prior to destructor to restore the original matrix.
557 */
558 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000559
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000560 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000561 GrDrawState* fDrawState;
562 GrMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000563 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000564 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000565 };
566
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000567 /// @}
568
569 ///////////////////////////////////////////////////////////////////////////
570 /// @name Render Target
571 ////
572
573 /**
574 * Sets the rendertarget used at the next drawing call
575 *
576 * @param target The render target to set.
577 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000578 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000579 GrSafeAssign(fRenderTarget, target);
580 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000581
582 /**
583 * Retrieves the currently set rendertarget.
584 *
585 * @return The currently set render target.
586 */
587 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
588 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
589
590 class AutoRenderTargetRestore : public ::GrNoncopyable {
591 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000592 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000593 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
594 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000595 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 this->set(ds, newTarget);
597 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000598 ~AutoRenderTargetRestore() { this->restore(); }
599
600 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000601 if (NULL != fDrawState) {
602 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000603 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000604 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000605 GrSafeSetNull(fSavedTarget);
606 }
607
608 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
609 this->restore();
610
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000611 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000612 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000613 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000614 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000615 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000616 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000617 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000618 }
619 private:
620 GrDrawState* fDrawState;
621 GrRenderTarget* fSavedTarget;
622 };
623
624 /// @}
625
626 ///////////////////////////////////////////////////////////////////////////
627 /// @name Stencil
628 ////
629
630 /**
631 * Sets the stencil settings to use for the next draw.
632 * Changing the clip has the side-effect of possibly zeroing
633 * out the client settable stencil bits. So multipass algorithms
634 * using stencil should not change the clip between passes.
635 * @param settings the stencil settings to use.
636 */
637 void setStencil(const GrStencilSettings& settings) {
638 fStencilSettings = settings;
639 }
640
641 /**
642 * Shortcut to disable stencil testing and ops.
643 */
644 void disableStencil() {
645 fStencilSettings.setDisabled();
646 }
647
648 const GrStencilSettings& getStencil() const { return fStencilSettings; }
649
650 GrStencilSettings* stencil() { return &fStencilSettings; }
651
652 /// @}
653
654 ///////////////////////////////////////////////////////////////////////////
655 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000656 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000657 // edges are specified as per-vertex data, vertices that are shared by
658 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000659 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000660 ////
661
662 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000663 * When specifying edges as vertex data this enum specifies what type of
664 * edges are in use. The edges are always 4 GrScalars in memory, even when
665 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000666 *
667 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
668 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000669 */
670 enum VertexEdgeType {
671 /* 1-pixel wide line
672 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
673 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000674 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000675 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000676 being inside, positive outside. Edge specified in window space
677 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000678 kQuad_EdgeType,
679 /* Same as above but for hairline quadratics. Uses unsigned distance.
680 Coverage is min(0, 1-distance). */
681 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000682 /* Circle specified as center_x, center_y, outer_radius, inner_radius
683 all in window space (y-down). */
684 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000685
686 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000687 };
688
689 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000690 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000691 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
692 * are not specified the value of this setting has no effect.
693 */
694 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000695 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000696 fVertexEdgeType = type;
697 }
698
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000699 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000700
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000701 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000702
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000703 ///////////////////////////////////////////////////////////////////////////
704 /// @name State Flags
705 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000706
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000707 /**
708 * Flags that affect rendering. Controlled using enable/disableState(). All
709 * default to disabled.
710 */
711 enum StateBits {
712 /**
713 * Perform dithering. TODO: Re-evaluate whether we need this bit
714 */
715 kDither_StateBit = 0x01,
716 /**
717 * Perform HW anti-aliasing. This means either HW FSAA, if supported
718 * by the render target, or smooth-line rendering if a line primitive
719 * is drawn and line smoothing is supported by the 3D API.
720 */
721 kHWAntialias_StateBit = 0x02,
722 /**
723 * Draws will respect the clip, otherwise the clip is ignored.
724 */
725 kClip_StateBit = 0x04,
726 /**
727 * Disables writing to the color buffer. Useful when performing stencil
728 * operations.
729 */
730 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000731
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000732 // Users of the class may add additional bits to the vector
733 kDummyStateBit,
734 kLastPublicStateBit = kDummyStateBit-1,
735 };
736
737 void resetStateFlags() {
738 fFlagBits = 0;
739 }
740
741 /**
742 * Enable render state settings.
743 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000744 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000745 */
746 void enableState(uint32_t stateBits) {
747 fFlagBits |= stateBits;
748 }
749
750 /**
751 * Disable render state settings.
752 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000753 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000754 */
755 void disableState(uint32_t stateBits) {
756 fFlagBits &= ~(stateBits);
757 }
758
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000759 /**
760 * Enable or disable stateBits based on a boolean.
761 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000762 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000763 * @param enable if true enable stateBits, otherwise disable
764 */
765 void setState(uint32_t stateBits, bool enable) {
766 if (enable) {
767 this->enableState(stateBits);
768 } else {
769 this->disableState(stateBits);
770 }
771 }
772
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000773 bool isDitherState() const {
774 return 0 != (fFlagBits & kDither_StateBit);
775 }
776
777 bool isHWAntialiasState() const {
778 return 0 != (fFlagBits & kHWAntialias_StateBit);
779 }
780
781 bool isClipState() const {
782 return 0 != (fFlagBits & kClip_StateBit);
783 }
784
785 bool isColorWriteDisabled() const {
786 return 0 != (fFlagBits & kNoColorWrites_StateBit);
787 }
788
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000789 bool isStateFlagEnabled(uint32_t stateBit) const {
790 return 0 != (stateBit & fFlagBits);
791 }
792
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000793 /// @}
794
795 ///////////////////////////////////////////////////////////////////////////
796 /// @name Face Culling
797 ////
798
799 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000800 kInvalid_DrawFace = -1,
801
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000802 kBoth_DrawFace,
803 kCCW_DrawFace,
804 kCW_DrawFace,
805 };
806
807 /**
808 * Controls whether clockwise, counterclockwise, or both faces are drawn.
809 * @param face the face(s) to draw.
810 */
811 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000812 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000813 fDrawFace = face;
814 }
815
816 /**
817 * Gets whether the target is drawing clockwise, counterclockwise,
818 * or both faces.
819 * @return the current draw face(s).
820 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000821 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000822
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000823 /// @}
824
825 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000826
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000827 bool isStageEnabled(int s) const {
828 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +0000829 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000830 }
831
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000832 // Most stages are usually not used, so conditionals here
833 // reduce the expected number of bytes touched by 50%.
834 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000835 if (fColor != s.fColor ||
836 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
837 fRenderTarget != s.fRenderTarget ||
838 fSrcBlend != s.fSrcBlend ||
839 fDstBlend != s.fDstBlend ||
840 fBlendConstant != s.fBlendConstant ||
841 fFlagBits != s.fFlagBits ||
842 fVertexEdgeType != s.fVertexEdgeType ||
843 fStencilSettings != s.fStencilSettings ||
844 fFirstCoverageStage != s.fFirstCoverageStage ||
845 fCoverage != s.fCoverage ||
846 fColorFilterMode != s.fColorFilterMode ||
847 fColorFilterColor != s.fColorFilterColor ||
848 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000849 return false;
850 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000851
852 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000853 bool enabled = this->isStageEnabled(i);
854 if (enabled != s.isStageEnabled(i)) {
855 return false;
856 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000857 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000858 return false;
859 }
860 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000861 return true;
862 }
863 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
864
rmistry@google.comd6176b02012-08-23 18:14:13 +0000865 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000866 // reduce the expected number of bytes touched by 50%.
867 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000868 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000869 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000870 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
871 fSrcBlend = s.fSrcBlend;
872 fDstBlend = s.fDstBlend;
873 fBlendConstant = s.fBlendConstant;
874 fFlagBits = s.fFlagBits;
875 fVertexEdgeType = s.fVertexEdgeType;
876 fStencilSettings = s.fStencilSettings;
877 fFirstCoverageStage = s.fFirstCoverageStage;
878 fCoverage = s.fCoverage;
879 fColorFilterMode = s.fColorFilterMode;
880 fColorFilterColor = s.fColorFilterColor;
881 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000882
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000883 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000884 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000885 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000886 }
887 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000888
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000889 return *this;
890 }
891
892private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000893
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000894 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000895 GrColor fColor;
896 GrMatrix fViewMatrix;
897 GrRenderTarget* fRenderTarget;
898 GrBlendCoeff fSrcBlend;
899 GrBlendCoeff fDstBlend;
900 GrColor fBlendConstant;
901 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000902 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000903 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000904 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000905 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000906 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000907 GrColor fColorFilterColor;
908 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000909
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000910 // This field must be last; it will not be copied or compared
911 // if the corresponding fTexture[] is NULL.
bsalomon@google.com08283af2012-10-26 13:01:20 +0000912 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000913
reed@google.comfa35e3d2012-06-26 20:16:17 +0000914 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000915};
916
917#endif