blob: 13ed2878034f7164ad5c6dbd31ee61bbce0ff279 [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"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000019#include "effects/GrSimpleTextureEffect.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 /**
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000196 * Creates a GrSimpleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000197 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000198 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000199 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000200 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000201 this->stage(stageIdx)->setEffect(effect)->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.comb9086a02012-11-01 18:02:54 +0000205 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000206 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000207 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000208 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000209 this->stage(stageIdx)->setEffect(effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000210 }
211
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000212 bool stagesDisabled() {
213 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000214 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000215 return false;
216 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000217 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000218 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000219 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000220
bsalomon@google.com08283af2012-10-26 13:01:20 +0000221 void disableStage(int stageIdx) {
222 fStages[stageIdx].setEffect(NULL);
tomhudson@google.com676e6602012-07-10 17:21:48 +0000223 }
224
robertphillips@google.com972265d2012-06-13 18:49:30 +0000225 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000226 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000227 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000228 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000229 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000230 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000231 }
232 }
233
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000234 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000235 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000236 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
237 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000238 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000239 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000240 }
241 }
242 private:
243 GrDrawState* fDrawState;
244 };
245
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000246 /// @}
247
248 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com08283af2012-10-26 13:01:20 +0000249 /// @name Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000250 ////
251
252 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000253 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000254 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000255 const GrEffectStage& getStage(int stageIdx) const {
256 GrAssert((unsigned)stageIdx < kNumStages);
257 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000258 }
259
260 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000261 * Writable pointer to a stage.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000262 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000263 GrEffectStage* stage(int stageIdx) {
264 GrAssert((unsigned)stageIdx < kNumStages);
265 return fStages + stageIdx;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000266 }
267
268 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000269 * Called when the source coord system is changing. preConcat gives the transformation from the
270 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000271 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000272 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000273 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000274 if (this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000275 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000276 }
277 }
278 }
279
bsalomon@google.come3d32162012-07-20 13:37:06 +0000280 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000281 * Called when the source coord system is changing. preConcatInverse is the inverse of the
282 * transformation from the old coord system to the new coord system. Returns false if the matrix
283 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000284 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000285 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
286 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000287 bool computed = false;
288 for (int i = 0; i < kNumStages; ++i) {
289 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000290 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000291 return false;
292 } else {
293 computed = true;
294 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000295 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000296 }
297 }
298 return true;
299 }
300
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000301 /// @}
302
303 ///////////////////////////////////////////////////////////////////////////
304 /// @name Coverage / Color Stages
305 ////
306
307 /**
308 * A common pattern is to compute a color with the initial stages and then
309 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000310 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
311 * computed based on the pre-coverage-modulated color. The division of
312 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000313 * this method. Initially this is kNumStages (all stages
314 * are color-computing).
315 */
316 void setFirstCoverageStage(int firstCoverageStage) {
317 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000318 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000319 }
320
321 /**
322 * Gets the index of the first coverage-computing stage.
323 */
324 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000325 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000326 }
327
328 ///@}
329
330 ///////////////////////////////////////////////////////////////////////////
331 /// @name Blending
332 ////
333
334 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000335 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000336 *
337 * The blend function will be:
338 * D' = sat(S*srcCoef + D*dstCoef)
339 *
340 * where D is the existing destination color, S is the incoming source
341 * color, and D' is the new destination color that will be written. sat()
342 * is the saturation function.
343 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000344 * @param srcCoef coefficient applied to the src color.
345 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000346 */
347 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
348 fSrcBlend = srcCoeff;
349 fDstBlend = dstCoeff;
350 #if GR_DEBUG
351 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000352 case kDC_GrBlendCoeff:
353 case kIDC_GrBlendCoeff:
354 case kDA_GrBlendCoeff:
355 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000356 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
357 "coverage stages.\n");
358 break;
359 default:
360 break;
361 }
362 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000363 case kSC_GrBlendCoeff:
364 case kISC_GrBlendCoeff:
365 case kSA_GrBlendCoeff:
366 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000367 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
368 "coverage stages.\n");
369 break;
370 default:
371 break;
372 }
373 #endif
374 }
375
376 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
377 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
378
379 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
380 GrBlendCoeff* dstBlendCoeff) const {
381 *srcBlendCoeff = fSrcBlend;
382 *dstBlendCoeff = fDstBlend;
383 }
384
385 /**
386 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000387 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000388 * kConstC_GrBlendCoeff
389 * kIConstC_GrBlendCoeff
390 * kConstA_GrBlendCoeff
391 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000392 *
393 * @param constant the constant to set
394 */
395 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
396
397 /**
398 * Retrieves the last value set by setBlendConstant()
399 * @return the blending constant value
400 */
401 GrColor getBlendConstant() const { return fBlendConstant; }
402
403 /// @}
404
405 ///////////////////////////////////////////////////////////////////////////
406 /// @name View Matrix
407 ////
408
409 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000410 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000411 *
412 * In the post-view-matrix space the rectangle [0,w]x[0,h]
413 * fully covers the render target. (w and h are the width and height of the
414 * the rendertarget.)
415 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000416 void setViewMatrix(const SkMatrix& m) { fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000417
418 /**
419 * Gets a writable pointer to the view matrix.
420 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000421 SkMatrix* viewMatrix() { return &fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000422
423 /**
424 * Multiplies the current view matrix by a matrix
425 *
426 * After this call V' = V*m where V is the old view matrix,
427 * m is the parameter to this function, and V' is the new view matrix.
428 * (We consider positions to be column vectors so position vector p is
429 * transformed by matrix X as p' = X*p.)
430 *
431 * @param m the matrix used to modify the view matrix.
432 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000433 void preConcatViewMatrix(const SkMatrix& m) { fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000434
435 /**
436 * Multiplies the current view matrix by a matrix
437 *
438 * After this call V' = m*V where V is the old view matrix,
439 * m is the parameter to this function, and V' is the new view matrix.
440 * (We consider positions to be column vectors so position vector p is
441 * transformed by matrix X as p' = X*p.)
442 *
443 * @param m the matrix used to modify the view matrix.
444 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000445 void postConcatViewMatrix(const SkMatrix& m) { fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000446
447 /**
448 * Retrieves the current view matrix
449 * @return the current view matrix.
450 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000451 const SkMatrix& getViewMatrix() const { return fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000452
453 /**
454 * Retrieves the inverse of the current view matrix.
455 *
456 * If the current view matrix is invertible, return true, and if matrix
457 * is non-null, copy the inverse into it. If the current view matrix is
458 * non-invertible, return false and ignore the matrix parameter.
459 *
460 * @param matrix if not null, will receive a copy of the current inverse.
461 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000462 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000463 // TODO: determine whether we really need to leave matrix unmodified
464 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000465 SkMatrix inverse;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000466 if (fViewMatrix.invert(&inverse)) {
467 if (matrix) {
468 *matrix = inverse;
469 }
470 return true;
471 }
472 return false;
473 }
474
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000475 ////////////////////////////////////////////////////////////////////////////
476
477 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000478 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000479 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000480 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000481 class AutoViewMatrixRestore : public ::GrNoncopyable {
482 public:
483 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000484
485 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000486 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000487 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000488 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000489 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000490 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000491
492 ~AutoViewMatrixRestore() { this->restore(); }
493
bsalomon@google.coma8347462012-10-08 18:59:39 +0000494 /**
495 * Can be called prior to destructor to restore the original matrix.
496 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000497 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000498
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000499 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000500 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000501 uint32_t explicitCoordStageMask = 0);
502
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000503 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000504
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000505 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000506 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000507 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000508 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000509 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000510 };
511
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000512 ////////////////////////////////////////////////////////////////////////////
513
514 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000515 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
516 * destructor undoes the changes, restoring the view matrix that was set before the
517 * constructor. It is similar to passing the inverse of the current view matrix to
518 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000519 */
520 class AutoDeviceCoordDraw : ::GrNoncopyable {
521 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000522 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000523 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000524 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
525 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
526 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000527 */
528 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000529 uint32_t explicitCoordStageMask = 0) {
530 fDrawState = NULL;
531 this->set(drawState, explicitCoordStageMask);
532 }
533
bsalomon@google.coma8347462012-10-08 18:59:39 +0000534 ~AutoDeviceCoordDraw() { this->restore(); }
535
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000536 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
537
bsalomon@google.coma8347462012-10-08 18:59:39 +0000538 /**
539 * Returns true if this object was successfully initialized on to a GrDrawState. It may
540 * return false because a non-default constructor or set() were never called or because
541 * the view matrix was not invertible.
542 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000543 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000544
bsalomon@google.coma8347462012-10-08 18:59:39 +0000545 /**
546 * Returns the matrix that was set previously set on the drawState. This is only valid
547 * if succeeded returns true.
548 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000549 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000550 GrAssert(this->succeeded());
551 return fViewMatrix;
552 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000553
bsalomon@google.coma8347462012-10-08 18:59:39 +0000554 /**
555 * Can be called prior to destructor to restore the original matrix.
556 */
557 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000558
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000559 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000560 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000561 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000562 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000563 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000564 };
565
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000566 /// @}
567
568 ///////////////////////////////////////////////////////////////////////////
569 /// @name Render Target
570 ////
571
572 /**
573 * Sets the rendertarget used at the next drawing call
574 *
575 * @param target The render target to set.
576 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000577 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000578 GrSafeAssign(fRenderTarget, target);
579 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580
581 /**
582 * Retrieves the currently set rendertarget.
583 *
584 * @return The currently set render target.
585 */
586 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
587 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
588
589 class AutoRenderTargetRestore : public ::GrNoncopyable {
590 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000591 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
593 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000594 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000595 this->set(ds, newTarget);
596 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000597 ~AutoRenderTargetRestore() { this->restore(); }
598
599 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 if (NULL != fDrawState) {
601 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000602 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000603 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000604 GrSafeSetNull(fSavedTarget);
605 }
606
607 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
608 this->restore();
609
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000610 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000611 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000613 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000614 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000615 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000616 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000617 }
618 private:
619 GrDrawState* fDrawState;
620 GrRenderTarget* fSavedTarget;
621 };
622
623 /// @}
624
625 ///////////////////////////////////////////////////////////////////////////
626 /// @name Stencil
627 ////
628
629 /**
630 * Sets the stencil settings to use for the next draw.
631 * Changing the clip has the side-effect of possibly zeroing
632 * out the client settable stencil bits. So multipass algorithms
633 * using stencil should not change the clip between passes.
634 * @param settings the stencil settings to use.
635 */
636 void setStencil(const GrStencilSettings& settings) {
637 fStencilSettings = settings;
638 }
639
640 /**
641 * Shortcut to disable stencil testing and ops.
642 */
643 void disableStencil() {
644 fStencilSettings.setDisabled();
645 }
646
647 const GrStencilSettings& getStencil() const { return fStencilSettings; }
648
649 GrStencilSettings* stencil() { return &fStencilSettings; }
650
651 /// @}
652
653 ///////////////////////////////////////////////////////////////////////////
654 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000655 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000656 // edges are specified as per-vertex data, vertices that are shared by
657 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000658 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000659 ////
660
661 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000662 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +0000663 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +0000664 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000665 *
666 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
667 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000668 */
669 enum VertexEdgeType {
670 /* 1-pixel wide line
671 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
672 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000673 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000674 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000675 being inside, positive outside. Edge specified in window space
676 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000677 kQuad_EdgeType,
678 /* Same as above but for hairline quadratics. Uses unsigned distance.
679 Coverage is min(0, 1-distance). */
680 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000681 /* Circle specified as center_x, center_y, outer_radius, inner_radius
682 all in window space (y-down). */
683 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000684
685 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000686 };
687
688 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000689 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000690 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
691 * are not specified the value of this setting has no effect.
692 */
693 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000694 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000695 fVertexEdgeType = type;
696 }
697
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000698 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000699
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000700 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000701
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000702 ///////////////////////////////////////////////////////////////////////////
703 /// @name State Flags
704 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000705
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000706 /**
707 * Flags that affect rendering. Controlled using enable/disableState(). All
708 * default to disabled.
709 */
710 enum StateBits {
711 /**
712 * Perform dithering. TODO: Re-evaluate whether we need this bit
713 */
714 kDither_StateBit = 0x01,
715 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000716 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
717 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
718 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000719 */
720 kHWAntialias_StateBit = 0x02,
721 /**
722 * Draws will respect the clip, otherwise the clip is ignored.
723 */
724 kClip_StateBit = 0x04,
725 /**
726 * Disables writing to the color buffer. Useful when performing stencil
727 * operations.
728 */
729 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000730
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000731 /**
732 * Usually coverage is applied after color blending. The color is blended using the coeffs
733 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
734 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
735 * this case there is no distinction between coverage and color and the caller needs direct
736 * control over the blend coeffs. When set, there will be a single blend step controlled by
737 * setBlendFunc() which will use coverage*color as the src color.
738 */
739 kCoverageDrawing_StateBit = 0x10,
740
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000741 // Users of the class may add additional bits to the vector
742 kDummyStateBit,
743 kLastPublicStateBit = kDummyStateBit-1,
744 };
745
746 void resetStateFlags() {
747 fFlagBits = 0;
748 }
749
750 /**
751 * Enable render state settings.
752 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000753 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000754 */
755 void enableState(uint32_t stateBits) {
756 fFlagBits |= stateBits;
757 }
758
759 /**
760 * Disable render state settings.
761 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000762 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000763 */
764 void disableState(uint32_t stateBits) {
765 fFlagBits &= ~(stateBits);
766 }
767
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000768 /**
769 * Enable or disable stateBits based on a boolean.
770 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000771 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000772 * @param enable if true enable stateBits, otherwise disable
773 */
774 void setState(uint32_t stateBits, bool enable) {
775 if (enable) {
776 this->enableState(stateBits);
777 } else {
778 this->disableState(stateBits);
779 }
780 }
781
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000782 bool isDitherState() const {
783 return 0 != (fFlagBits & kDither_StateBit);
784 }
785
786 bool isHWAntialiasState() const {
787 return 0 != (fFlagBits & kHWAntialias_StateBit);
788 }
789
790 bool isClipState() const {
791 return 0 != (fFlagBits & kClip_StateBit);
792 }
793
794 bool isColorWriteDisabled() const {
795 return 0 != (fFlagBits & kNoColorWrites_StateBit);
796 }
797
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000798 bool isCoverageDrawing() const {
799 return 0 != (fFlagBits & kCoverageDrawing_StateBit);
800 }
801
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000802 bool isStateFlagEnabled(uint32_t stateBit) const {
803 return 0 != (stateBit & fFlagBits);
804 }
805
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000806 /// @}
807
808 ///////////////////////////////////////////////////////////////////////////
809 /// @name Face Culling
810 ////
811
812 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000813 kInvalid_DrawFace = -1,
814
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000815 kBoth_DrawFace,
816 kCCW_DrawFace,
817 kCW_DrawFace,
818 };
819
820 /**
821 * Controls whether clockwise, counterclockwise, or both faces are drawn.
822 * @param face the face(s) to draw.
823 */
824 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000825 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000826 fDrawFace = face;
827 }
828
829 /**
830 * Gets whether the target is drawing clockwise, counterclockwise,
831 * or both faces.
832 * @return the current draw face(s).
833 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000834 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000835
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000836 /// @}
837
838 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000839
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000840 bool isStageEnabled(int s) const {
841 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +0000842 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000843 }
844
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000845 // Most stages are usually not used, so conditionals here
846 // reduce the expected number of bytes touched by 50%.
847 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000848 if (fColor != s.fColor ||
849 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
850 fRenderTarget != s.fRenderTarget ||
851 fSrcBlend != s.fSrcBlend ||
852 fDstBlend != s.fDstBlend ||
853 fBlendConstant != s.fBlendConstant ||
854 fFlagBits != s.fFlagBits ||
855 fVertexEdgeType != s.fVertexEdgeType ||
856 fStencilSettings != s.fStencilSettings ||
857 fFirstCoverageStage != s.fFirstCoverageStage ||
858 fCoverage != s.fCoverage ||
859 fColorFilterMode != s.fColorFilterMode ||
860 fColorFilterColor != s.fColorFilterColor ||
861 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000862 return false;
863 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000864
865 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000866 bool enabled = this->isStageEnabled(i);
867 if (enabled != s.isStageEnabled(i)) {
868 return false;
869 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000870 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000871 return false;
872 }
873 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000874 return true;
875 }
876 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
877
rmistry@google.comd6176b02012-08-23 18:14:13 +0000878 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000879 // reduce the expected number of bytes touched by 50%.
880 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000881 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000882 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000883 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
884 fSrcBlend = s.fSrcBlend;
885 fDstBlend = s.fDstBlend;
886 fBlendConstant = s.fBlendConstant;
887 fFlagBits = s.fFlagBits;
888 fVertexEdgeType = s.fVertexEdgeType;
889 fStencilSettings = s.fStencilSettings;
890 fFirstCoverageStage = s.fFirstCoverageStage;
891 fCoverage = s.fCoverage;
892 fColorFilterMode = s.fColorFilterMode;
893 fColorFilterColor = s.fColorFilterColor;
894 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000895
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000896 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000897 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000898 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000899 }
900 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000901
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000902 return *this;
903 }
904
905private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000906
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000907 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000908 GrColor fColor;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000909 SkMatrix fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000910 GrRenderTarget* fRenderTarget;
911 GrBlendCoeff fSrcBlend;
912 GrBlendCoeff fDstBlend;
913 GrColor fBlendConstant;
914 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000915 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000916 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000917 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000918 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000919 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000920 GrColor fColorFilterColor;
921 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000922
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000923 // This field must be last; it will not be copied or compared
924 // if the corresponding fTexture[] is NULL.
bsalomon@google.com08283af2012-10-26 13:01:20 +0000925 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000926
reed@google.comfa35e3d2012-06-26 20:16:17 +0000927 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000928};
929
930#endif