blob: 1208b776ed735f2ef5718475c994eaab7a196807 [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
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000011#include "GrBackendEffectFactory.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000012#include "GrColor.h"
bsalomon@google.comb9086a02012-11-01 18:02:54 +000013#include "SkMatrix.h"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000014#include "GrRefCnt.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000015#include "GrEffectStage.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000016#include "GrStencil.h"
bsalomon@google.com64aef2b2012-06-11 15:36:13 +000017#include "GrTexture.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000018#include "GrRenderTarget.h"
tomhudson@google.com1e8f0162012-07-20 16:25:18 +000019#include "effects/GrSingleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000020
21#include "SkXfermode.h"
22
bsalomon@google.comaf84e742012-10-05 13:23:24 +000023class GrPaint;
tomhudson@google.com93813632011-10-27 20:21:16 +000024
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000026public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000027 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000028
tomhudson@google.com93813632011-10-27 20:21:16 +000029 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000030 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
31 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
32 * output from the previous enabled stage and a position. The position is either derived from
33 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
34 * GrVertexLayout used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000035 *
bsalomon@google.com13221342012-10-26 13:41:59 +000036 * The stages are divided into two sets, color-computing and coverage-computing. The final color
37 * stage produces the final pixel color. The coverage-computing stages function exactly as the
38 * color-computing but the output of the final coverage stage is treated as a fractional pixel
39 * coverage rather than as input to the src/dst color blend step.
40 *
41 * The input color to the first enabled color-stage is either the constant color or interpolated
42 * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is
43 * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
44 * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
45 * GrEffect).
46 *
bsalomon@google.comcf939ae2012-12-13 19:59:23 +000047 * See the documentation of kCoverageDrawing_StateBit for information about disabling the
48 * the color / coverage distinction.
49 *
bsalomon@google.com13221342012-10-26 13:41:59 +000050 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
51 * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
52 * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000053 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000054 */
55 enum {
twiz@google.com58071162012-07-18 21:41:50 +000056 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000057 kMaxTexCoords = kNumStages
58 };
59
rmistry@google.comd6176b02012-08-23 18:14:13 +000060 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000061 : fRenderTarget(NULL) {
62
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000063 this->reset();
64 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000065
rmistry@google.comd6176b02012-08-23 18:14:13 +000066 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000067 : fRenderTarget(NULL) {
68
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000069 *this = state;
70 }
71
robertphillips@google.com9ec07532012-06-22 12:01:30 +000072 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000073 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000074 GrSafeSetNull(fRenderTarget);
75 }
76
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000077 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000078 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000079 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000080 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000081 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000082
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000083 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000084
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000085 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000086 fViewMatrix.reset();
87 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000088 fSrcBlend = kOne_GrBlendCoeff;
89 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000090 fBlendConstant = 0x0;
91 fFlagBits = 0x0;
92 fVertexEdgeType = kHairLine_EdgeType;
93 fStencilSettings.setDisabled();
94 fFirstCoverageStage = kNumStages;
95 fCoverage = 0xffffffff;
96 fColorFilterMode = SkXfermode::kDst_Mode;
97 fColorFilterColor = 0x0;
98 fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000099 }
100
101 /**
102 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000103 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000104 * GrPaint equivalents are not modified. GrPaint has fewer stages than
105 * GrDrawState. The extra GrDrawState stages are disabled.
106 */
107 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000108
109 ///////////////////////////////////////////////////////////////////////////
110 /// @name Color
111 ////
112
113 /**
114 * Sets color for next draw to a premultiplied-alpha color.
115 *
116 * @param color the color to set.
117 */
118 void setColor(GrColor color) { fColor = color; }
119
120 GrColor getColor() const { return fColor; }
121
122 /**
123 * Sets the color to be used for the next draw to be
124 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
125 *
126 * @param alpha The alpha value to set as the color.
127 */
128 void setAlpha(uint8_t a) {
129 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
130 }
131
132 /**
133 * Add a color filter that can be represented by a color and a mode. Applied
134 * after color-computing texture stages.
135 */
136 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
137 fColorFilterColor = c;
138 fColorFilterMode = mode;
139 }
140
141 GrColor getColorFilterColor() const { return fColorFilterColor; }
142 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
143
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000144 /**
145 * Constructor sets the color to be 'color' which is undone by the destructor.
146 */
147 class AutoColorRestore : public ::GrNoncopyable {
148 public:
149 AutoColorRestore(GrDrawState* drawState, GrColor color) {
150 fDrawState = drawState;
151 fOldColor = fDrawState->getColor();
152 fDrawState->setColor(color);
153 }
154 ~AutoColorRestore() {
155 fDrawState->setColor(fOldColor);
156 }
157 private:
158 GrDrawState* fDrawState;
159 GrColor fOldColor;
160 };
161
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000162 /// @}
163
164 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000165 /// @name Coverage
166 ////
167
168 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000169 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000170 * initial value (after construction or reset()) is 0xff. The constant
171 * coverage is ignored when per-vertex coverage is provided.
172 */
173 void setCoverage(uint8_t coverage) {
174 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
175 }
176
177 /**
178 * Version of above that specifies 4 channel per-vertex color. The value
179 * should be premultiplied.
180 */
181 void setCoverage4(GrColor coverage) {
182 fCoverage = coverage;
183 }
184
185 GrColor getCoverage() const {
186 return fCoverage;
187 }
188
189 /// @}
190
191 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000192 /// @name Textures
193 ////
194
195 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000196 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000197 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000198 void createTextureEffect(int stageIdx, GrTexture* texture) {
199 GrAssert(!this->getStage(stageIdx).getEffect());
200 this->stage(stageIdx)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000201 }
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000202 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000203 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000204 GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix));
205 this->stage(stageIdx)->setEffect(effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000206 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000207 void createTextureEffect(int stageIdx,
208 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000209 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000210 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000211 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000212 GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params));
213 this->stage(stageIdx)->setEffect(effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000214 }
215
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000216
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000217 bool stagesDisabled() {
218 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000219 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000220 return false;
221 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000222 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000223 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000224 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000225
bsalomon@google.com08283af2012-10-26 13:01:20 +0000226 void disableStage(int stageIdx) {
227 fStages[stageIdx].setEffect(NULL);
tomhudson@google.com676e6602012-07-10 17:21:48 +0000228 }
229
robertphillips@google.com972265d2012-06-13 18:49:30 +0000230 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000231 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000232 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000233 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000234 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000235 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000236 }
237 }
238
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000239 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000240 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000241 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
242 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000243 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000244 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000245 }
246 }
247 private:
248 GrDrawState* fDrawState;
249 };
250
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000251 /// @}
252
253 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com08283af2012-10-26 13:01:20 +0000254 /// @name Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000255 ////
256
257 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000258 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000259 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000260 const GrEffectStage& getStage(int stageIdx) const {
261 GrAssert((unsigned)stageIdx < kNumStages);
262 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000263 }
264
265 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000266 * Writable pointer to a stage.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000267 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000268 GrEffectStage* stage(int stageIdx) {
269 GrAssert((unsigned)stageIdx < kNumStages);
270 return fStages + stageIdx;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000271 }
272
273 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000274 * Called when the source coord system is changing. preConcat gives the transformation from the
275 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000276 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000277 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000278 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000279 if (this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000280 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000281 }
282 }
283 }
284
bsalomon@google.come3d32162012-07-20 13:37:06 +0000285 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000286 * Called when the source coord system is changing. preConcatInverse is the inverse of the
287 * transformation from the old coord system to the new coord system. Returns false if the matrix
288 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000289 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000290 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
291 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000292 bool computed = false;
293 for (int i = 0; i < kNumStages; ++i) {
294 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000295 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000296 return false;
297 } else {
298 computed = true;
299 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000300 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000301 }
302 }
303 return true;
304 }
305
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000306 /// @}
307
308 ///////////////////////////////////////////////////////////////////////////
309 /// @name Coverage / Color Stages
310 ////
311
312 /**
313 * A common pattern is to compute a color with the initial stages and then
314 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000315 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
316 * computed based on the pre-coverage-modulated color. The division of
317 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000318 * this method. Initially this is kNumStages (all stages
319 * are color-computing).
320 */
321 void setFirstCoverageStage(int firstCoverageStage) {
322 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000323 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000324 }
325
326 /**
327 * Gets the index of the first coverage-computing stage.
328 */
329 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000330 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000331 }
332
333 ///@}
334
335 ///////////////////////////////////////////////////////////////////////////
336 /// @name Blending
337 ////
338
339 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000340 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000341 *
342 * The blend function will be:
343 * D' = sat(S*srcCoef + D*dstCoef)
344 *
345 * where D is the existing destination color, S is the incoming source
346 * color, and D' is the new destination color that will be written. sat()
347 * is the saturation function.
348 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000349 * @param srcCoef coefficient applied to the src color.
350 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000351 */
352 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
353 fSrcBlend = srcCoeff;
354 fDstBlend = dstCoeff;
355 #if GR_DEBUG
356 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000357 case kDC_GrBlendCoeff:
358 case kIDC_GrBlendCoeff:
359 case kDA_GrBlendCoeff:
360 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000361 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
362 "coverage stages.\n");
363 break;
364 default:
365 break;
366 }
367 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000368 case kSC_GrBlendCoeff:
369 case kISC_GrBlendCoeff:
370 case kSA_GrBlendCoeff:
371 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000372 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
373 "coverage stages.\n");
374 break;
375 default:
376 break;
377 }
378 #endif
379 }
380
381 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
382 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
383
384 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
385 GrBlendCoeff* dstBlendCoeff) const {
386 *srcBlendCoeff = fSrcBlend;
387 *dstBlendCoeff = fDstBlend;
388 }
389
390 /**
391 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000392 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000393 * kConstC_GrBlendCoeff
394 * kIConstC_GrBlendCoeff
395 * kConstA_GrBlendCoeff
396 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000397 *
398 * @param constant the constant to set
399 */
400 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
401
402 /**
403 * Retrieves the last value set by setBlendConstant()
404 * @return the blending constant value
405 */
406 GrColor getBlendConstant() const { return fBlendConstant; }
407
408 /// @}
409
410 ///////////////////////////////////////////////////////////////////////////
411 /// @name View Matrix
412 ////
413
414 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000415 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000416 *
417 * In the post-view-matrix space the rectangle [0,w]x[0,h]
418 * fully covers the render target. (w and h are the width and height of the
419 * the rendertarget.)
420 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000421 void setViewMatrix(const SkMatrix& m) { fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000422
423 /**
424 * Gets a writable pointer to the view matrix.
425 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000426 SkMatrix* viewMatrix() { return &fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000427
428 /**
429 * Multiplies the current view matrix by a matrix
430 *
431 * After this call V' = V*m where V is the old view matrix,
432 * m is the parameter to this function, and V' is the new view matrix.
433 * (We consider positions to be column vectors so position vector p is
434 * transformed by matrix X as p' = X*p.)
435 *
436 * @param m the matrix used to modify the view matrix.
437 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000438 void preConcatViewMatrix(const SkMatrix& m) { fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000439
440 /**
441 * Multiplies the current view matrix by a matrix
442 *
443 * After this call V' = m*V where V is the old view matrix,
444 * m is the parameter to this function, and V' is the new view matrix.
445 * (We consider positions to be column vectors so position vector p is
446 * transformed by matrix X as p' = X*p.)
447 *
448 * @param m the matrix used to modify the view matrix.
449 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000450 void postConcatViewMatrix(const SkMatrix& m) { fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000451
452 /**
453 * Retrieves the current view matrix
454 * @return the current view matrix.
455 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000456 const SkMatrix& getViewMatrix() const { return fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000457
458 /**
459 * Retrieves the inverse of the current view matrix.
460 *
461 * If the current view matrix is invertible, return true, and if matrix
462 * is non-null, copy the inverse into it. If the current view matrix is
463 * non-invertible, return false and ignore the matrix parameter.
464 *
465 * @param matrix if not null, will receive a copy of the current inverse.
466 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000467 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000468 // TODO: determine whether we really need to leave matrix unmodified
469 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000470 SkMatrix inverse;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000471 if (fViewMatrix.invert(&inverse)) {
472 if (matrix) {
473 *matrix = inverse;
474 }
475 return true;
476 }
477 return false;
478 }
479
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000480 ////////////////////////////////////////////////////////////////////////////
481
482 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000483 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000484 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000485 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000486 class AutoViewMatrixRestore : public ::GrNoncopyable {
487 public:
488 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000489
490 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000491 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000492 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000493 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000494 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000495 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000496
497 ~AutoViewMatrixRestore() { this->restore(); }
498
bsalomon@google.coma8347462012-10-08 18:59:39 +0000499 /**
500 * Can be called prior to destructor to restore the original matrix.
501 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000502 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000503
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000504 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000505 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000506 uint32_t explicitCoordStageMask = 0);
507
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000508 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000509
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000510 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000511 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000512 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000513 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000514 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000515 };
516
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000517 ////////////////////////////////////////////////////////////////////////////
518
519 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000520 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
521 * destructor undoes the changes, restoring the view matrix that was set before the
522 * constructor. It is similar to passing the inverse of the current view matrix to
523 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000524 */
525 class AutoDeviceCoordDraw : ::GrNoncopyable {
526 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000527 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000528 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000529 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
530 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
531 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000532 */
533 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000534 uint32_t explicitCoordStageMask = 0) {
535 fDrawState = NULL;
536 this->set(drawState, explicitCoordStageMask);
537 }
538
bsalomon@google.coma8347462012-10-08 18:59:39 +0000539 ~AutoDeviceCoordDraw() { this->restore(); }
540
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000541 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
542
bsalomon@google.coma8347462012-10-08 18:59:39 +0000543 /**
544 * Returns true if this object was successfully initialized on to a GrDrawState. It may
545 * return false because a non-default constructor or set() were never called or because
546 * the view matrix was not invertible.
547 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000548 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000549
bsalomon@google.coma8347462012-10-08 18:59:39 +0000550 /**
551 * Returns the matrix that was set previously set on the drawState. This is only valid
552 * if succeeded returns true.
553 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000554 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000555 GrAssert(this->succeeded());
556 return fViewMatrix;
557 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000558
bsalomon@google.coma8347462012-10-08 18:59:39 +0000559 /**
560 * Can be called prior to destructor to restore the original matrix.
561 */
562 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000563
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000564 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000565 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000566 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000567 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000568 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000569 };
570
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000571 /// @}
572
573 ///////////////////////////////////////////////////////////////////////////
574 /// @name Render Target
575 ////
576
577 /**
578 * Sets the rendertarget used at the next drawing call
579 *
580 * @param target The render target to set.
581 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000582 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000583 GrSafeAssign(fRenderTarget, target);
584 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000585
586 /**
587 * Retrieves the currently set rendertarget.
588 *
589 * @return The currently set render target.
590 */
591 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
592 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
593
594 class AutoRenderTargetRestore : public ::GrNoncopyable {
595 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000596 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000597 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
598 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000599 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 this->set(ds, newTarget);
601 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000602 ~AutoRenderTargetRestore() { this->restore(); }
603
604 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000605 if (NULL != fDrawState) {
606 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000607 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000609 GrSafeSetNull(fSavedTarget);
610 }
611
612 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
613 this->restore();
614
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000615 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000616 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000617 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000618 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000620 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000621 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000622 }
623 private:
624 GrDrawState* fDrawState;
625 GrRenderTarget* fSavedTarget;
626 };
627
628 /// @}
629
630 ///////////////////////////////////////////////////////////////////////////
631 /// @name Stencil
632 ////
633
634 /**
635 * Sets the stencil settings to use for the next draw.
636 * Changing the clip has the side-effect of possibly zeroing
637 * out the client settable stencil bits. So multipass algorithms
638 * using stencil should not change the clip between passes.
639 * @param settings the stencil settings to use.
640 */
641 void setStencil(const GrStencilSettings& settings) {
642 fStencilSettings = settings;
643 }
644
645 /**
646 * Shortcut to disable stencil testing and ops.
647 */
648 void disableStencil() {
649 fStencilSettings.setDisabled();
650 }
651
652 const GrStencilSettings& getStencil() const { return fStencilSettings; }
653
654 GrStencilSettings* stencil() { return &fStencilSettings; }
655
656 /// @}
657
658 ///////////////////////////////////////////////////////////////////////////
659 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000660 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000661 // edges are specified as per-vertex data, vertices that are shared by
662 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000663 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000664 ////
665
666 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000667 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +0000668 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +0000669 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000670 *
671 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
672 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000673 */
674 enum VertexEdgeType {
675 /* 1-pixel wide line
676 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
677 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000678 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000679 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000680 being inside, positive outside. Edge specified in window space
681 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000682 kQuad_EdgeType,
683 /* Same as above but for hairline quadratics. Uses unsigned distance.
684 Coverage is min(0, 1-distance). */
685 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000686 /* Circle specified as center_x, center_y, outer_radius, inner_radius
687 all in window space (y-down). */
688 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000689
690 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000691 };
692
693 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000694 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000695 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
696 * are not specified the value of this setting has no effect.
697 */
698 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000699 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000700 fVertexEdgeType = type;
701 }
702
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000703 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000704
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000705 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000706
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000707 ///////////////////////////////////////////////////////////////////////////
708 /// @name State Flags
709 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000710
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000711 /**
712 * Flags that affect rendering. Controlled using enable/disableState(). All
713 * default to disabled.
714 */
715 enum StateBits {
716 /**
717 * Perform dithering. TODO: Re-evaluate whether we need this bit
718 */
719 kDither_StateBit = 0x01,
720 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000721 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
722 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
723 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000724 */
725 kHWAntialias_StateBit = 0x02,
726 /**
727 * Draws will respect the clip, otherwise the clip is ignored.
728 */
729 kClip_StateBit = 0x04,
730 /**
731 * Disables writing to the color buffer. Useful when performing stencil
732 * operations.
733 */
734 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000735
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000736 /**
737 * Usually coverage is applied after color blending. The color is blended using the coeffs
738 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
739 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
740 * this case there is no distinction between coverage and color and the caller needs direct
741 * control over the blend coeffs. When set, there will be a single blend step controlled by
742 * setBlendFunc() which will use coverage*color as the src color.
743 */
744 kCoverageDrawing_StateBit = 0x10,
745
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 // Users of the class may add additional bits to the vector
747 kDummyStateBit,
748 kLastPublicStateBit = kDummyStateBit-1,
749 };
750
751 void resetStateFlags() {
752 fFlagBits = 0;
753 }
754
755 /**
756 * Enable render state settings.
757 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000758 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000759 */
760 void enableState(uint32_t stateBits) {
761 fFlagBits |= stateBits;
762 }
763
764 /**
765 * Disable render state settings.
766 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000767 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000768 */
769 void disableState(uint32_t stateBits) {
770 fFlagBits &= ~(stateBits);
771 }
772
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000773 /**
774 * Enable or disable stateBits based on a boolean.
775 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000776 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000777 * @param enable if true enable stateBits, otherwise disable
778 */
779 void setState(uint32_t stateBits, bool enable) {
780 if (enable) {
781 this->enableState(stateBits);
782 } else {
783 this->disableState(stateBits);
784 }
785 }
786
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000787 bool isDitherState() const {
788 return 0 != (fFlagBits & kDither_StateBit);
789 }
790
791 bool isHWAntialiasState() const {
792 return 0 != (fFlagBits & kHWAntialias_StateBit);
793 }
794
795 bool isClipState() const {
796 return 0 != (fFlagBits & kClip_StateBit);
797 }
798
799 bool isColorWriteDisabled() const {
800 return 0 != (fFlagBits & kNoColorWrites_StateBit);
801 }
802
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000803 bool isCoverageDrawing() const {
804 return 0 != (fFlagBits & kCoverageDrawing_StateBit);
805 }
806
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000807 bool isStateFlagEnabled(uint32_t stateBit) const {
808 return 0 != (stateBit & fFlagBits);
809 }
810
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000811 /// @}
812
813 ///////////////////////////////////////////////////////////////////////////
814 /// @name Face Culling
815 ////
816
817 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000818 kInvalid_DrawFace = -1,
819
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000820 kBoth_DrawFace,
821 kCCW_DrawFace,
822 kCW_DrawFace,
823 };
824
825 /**
826 * Controls whether clockwise, counterclockwise, or both faces are drawn.
827 * @param face the face(s) to draw.
828 */
829 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000830 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000831 fDrawFace = face;
832 }
833
834 /**
835 * Gets whether the target is drawing clockwise, counterclockwise,
836 * or both faces.
837 * @return the current draw face(s).
838 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000839 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000840
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 /// @}
842
843 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000844
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000845 bool isStageEnabled(int s) const {
846 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +0000847 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000848 }
849
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000850 // Most stages are usually not used, so conditionals here
851 // reduce the expected number of bytes touched by 50%.
852 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000853 if (fColor != s.fColor ||
854 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
855 fRenderTarget != s.fRenderTarget ||
856 fSrcBlend != s.fSrcBlend ||
857 fDstBlend != s.fDstBlend ||
858 fBlendConstant != s.fBlendConstant ||
859 fFlagBits != s.fFlagBits ||
860 fVertexEdgeType != s.fVertexEdgeType ||
861 fStencilSettings != s.fStencilSettings ||
862 fFirstCoverageStage != s.fFirstCoverageStage ||
863 fCoverage != s.fCoverage ||
864 fColorFilterMode != s.fColorFilterMode ||
865 fColorFilterColor != s.fColorFilterColor ||
866 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000867 return false;
868 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000869
870 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000871 bool enabled = this->isStageEnabled(i);
872 if (enabled != s.isStageEnabled(i)) {
873 return false;
874 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000875 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000876 return false;
877 }
878 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000879 return true;
880 }
881 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
882
rmistry@google.comd6176b02012-08-23 18:14:13 +0000883 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000884 // reduce the expected number of bytes touched by 50%.
885 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000886 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000887 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000888 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
889 fSrcBlend = s.fSrcBlend;
890 fDstBlend = s.fDstBlend;
891 fBlendConstant = s.fBlendConstant;
892 fFlagBits = s.fFlagBits;
893 fVertexEdgeType = s.fVertexEdgeType;
894 fStencilSettings = s.fStencilSettings;
895 fFirstCoverageStage = s.fFirstCoverageStage;
896 fCoverage = s.fCoverage;
897 fColorFilterMode = s.fColorFilterMode;
898 fColorFilterColor = s.fColorFilterColor;
899 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000900
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000901 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000902 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000903 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000904 }
905 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000906
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000907 return *this;
908 }
909
910private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000911
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000912 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000913 GrColor fColor;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000914 SkMatrix fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000915 GrRenderTarget* fRenderTarget;
916 GrBlendCoeff fSrcBlend;
917 GrBlendCoeff fDstBlend;
918 GrColor fBlendConstant;
919 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000920 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000921 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000922 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000923 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000924 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000925 GrColor fColorFilterColor;
926 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000927
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000928 // This field must be last; it will not be copied or compared
929 // if the corresponding fTexture[] is NULL.
bsalomon@google.com08283af2012-10-26 13:01:20 +0000930 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000931
reed@google.comfa35e3d2012-06-26 20:16:17 +0000932 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000933};
934
935#endif