blob: 05da3df0e0cdcd4a2268276583a4494e526f8166 [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.com8f9cbd62011-12-09 15:55:34 +000013#include "GrNoncopyable.h"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000014#include "GrRefCnt.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000015#include "GrSamplerState.h"
16#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
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 /**
29 * Number of texture stages. Each stage takes as input a color and
30 * 2D texture coordinates. The color input to the first enabled stage is the
31 * per-vertex color or the constant color (setColor/setAlpha) if there are
32 * no per-vertex colors. For subsequent stages the input color is the output
33 * color from the previous enabled stage. The output color of each stage is
34 * the input color modulated with the result of a texture lookup. Texture
35 * lookups are specified by a texture a sampler (setSamplerState). Texture
36 * coordinates for each stage come from the vertices based on a
37 * GrVertexLayout bitfield. The output fragment color is the output color of
38 * the last enabled stage. The presence or absence of texture coordinates
39 * for each stage in the vertex layout indicates whether a stage is enabled
40 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000041 *
42 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
rmistry@google.comd6176b02012-08-23 18:14:13 +000043 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
44 * through kNumStages-1 are earmarked for use by GrTextContext and
robertphillips@google.combf5cad42012-05-10 12:40:40 +000045 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000046 */
47 enum {
twiz@google.com58071162012-07-18 21:41:50 +000048 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000049 kMaxTexCoords = kNumStages
50 };
51
rmistry@google.comd6176b02012-08-23 18:14:13 +000052 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000053 : fRenderTarget(NULL) {
54
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000055 this->reset();
56 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000057
rmistry@google.comd6176b02012-08-23 18:14:13 +000058 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000059 : fRenderTarget(NULL) {
60
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000061 *this = state;
62 }
63
robertphillips@google.com9ec07532012-06-22 12:01:30 +000064 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000065 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000066 GrSafeSetNull(fRenderTarget);
67 }
68
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000069 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000070 * Resets to the default state.
71 * Sampler states *will* be modified: textures or CustomStage objects
72 * will be released.
rmistry@google.comd6176b02012-08-23 18:14:13 +000073 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000074 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000075
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000076 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000077
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000078 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000079 fViewMatrix.reset();
80 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000081 fSrcBlend = kOne_GrBlendCoeff;
82 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000083 fBlendConstant = 0x0;
84 fFlagBits = 0x0;
85 fVertexEdgeType = kHairLine_EdgeType;
86 fStencilSettings.setDisabled();
87 fFirstCoverageStage = kNumStages;
88 fCoverage = 0xffffffff;
89 fColorFilterMode = SkXfermode::kDst_Mode;
90 fColorFilterColor = 0x0;
91 fDrawFace = kBoth_DrawFace;
92 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000093
94 ///////////////////////////////////////////////////////////////////////////
95 /// @name Color
96 ////
97
98 /**
99 * Sets color for next draw to a premultiplied-alpha color.
100 *
101 * @param color the color to set.
102 */
103 void setColor(GrColor color) { fColor = color; }
104
105 GrColor getColor() const { return fColor; }
106
107 /**
108 * Sets the color to be used for the next draw to be
109 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
110 *
111 * @param alpha The alpha value to set as the color.
112 */
113 void setAlpha(uint8_t a) {
114 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
115 }
116
117 /**
118 * Add a color filter that can be represented by a color and a mode. Applied
119 * after color-computing texture stages.
120 */
121 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
122 fColorFilterColor = c;
123 fColorFilterMode = mode;
124 }
125
126 GrColor getColorFilterColor() const { return fColorFilterColor; }
127 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
128
129 /// @}
130
131 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000132 /// @name Coverage
133 ////
134
135 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000136 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000137 * initial value (after construction or reset()) is 0xff. The constant
138 * coverage is ignored when per-vertex coverage is provided.
139 */
140 void setCoverage(uint8_t coverage) {
141 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
142 }
143
144 /**
145 * Version of above that specifies 4 channel per-vertex color. The value
146 * should be premultiplied.
147 */
148 void setCoverage4(GrColor coverage) {
149 fCoverage = coverage;
150 }
151
152 GrColor getCoverage() const {
153 return fCoverage;
154 }
155
156 /// @}
157
158 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000159 /// @name Textures
160 ////
161
162 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000163 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000164 */
165 void createTextureEffect(int stage, GrTexture* texture) {
166 GrAssert(!this->getSampler(stage).getCustomStage());
167 this->sampler(stage)->setCustomStage(
168 SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
169 }
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000170 void createTextureEffect(int stage, GrTexture* texture, const GrTextureParams& params) {
171 GrAssert(!this->getSampler(stage).getCustomStage());
172 this->sampler(stage)->setCustomStage(
173 SkNEW_ARGS(GrSingleTextureEffect, (texture, params)))->unref();
174 }
175
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000176
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000177 bool stagesDisabled() {
178 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000179 if (NULL != fSamplerStates[i].getCustomStage()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000180 return false;
181 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000182 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000183 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000184 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000185
186 void disableStage(int index) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000187 fSamplerStates[index].setCustomStage(NULL);
188 }
189
robertphillips@google.com972265d2012-06-13 18:49:30 +0000190 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000191 * Release all the textures and custom stages referred to by this
192 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000193 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000194 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000195 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000196 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000197 }
198 }
199
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000200 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000201 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000202 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
203 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000204 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000205 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000206 }
207 }
208 private:
209 GrDrawState* fDrawState;
210 };
211
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000212 /// @}
213
214 ///////////////////////////////////////////////////////////////////////////
215 /// @name Samplers
216 ////
217
218 /**
219 * Returns the current sampler for a stage.
220 */
221 const GrSamplerState& getSampler(int stage) const {
222 GrAssert((unsigned)stage < kNumStages);
223 return fSamplerStates[stage];
224 }
225
226 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000227 * Writable pointer to a stage's sampler.
228 */
229 GrSamplerState* sampler(int stage) {
230 GrAssert((unsigned)stage < kNumStages);
231 return fSamplerStates + stage;
232 }
233
234 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000235 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000236 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000237 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000238 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000239 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000240 fSamplerStates[i].preConcatMatrix(matrix);
241 }
242 }
243 }
244
bsalomon@google.come3d32162012-07-20 13:37:06 +0000245 /**
246 * Preconcats the matrix of all samplers in the mask with the inverse of a
247 * matrix. If the matrix inverse cannot be computed (and there is at least
248 * one enabled stage) then false is returned.
249 */
250 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
251 GrMatrix inv;
252 bool computed = false;
253 for (int i = 0; i < kNumStages; ++i) {
254 if (this->isStageEnabled(i)) {
255 if (!computed && !matrix.invert(&inv)) {
256 return false;
257 } else {
258 computed = true;
259 }
260 fSamplerStates[i].preConcatMatrix(inv);
261 }
262 }
263 return true;
264 }
265
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000266 /// @}
267
268 ///////////////////////////////////////////////////////////////////////////
269 /// @name Coverage / Color Stages
270 ////
271
272 /**
273 * A common pattern is to compute a color with the initial stages and then
274 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000275 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
276 * computed based on the pre-coverage-modulated color. The division of
277 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000278 * this method. Initially this is kNumStages (all stages
279 * are color-computing).
280 */
281 void setFirstCoverageStage(int firstCoverageStage) {
282 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000283 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000284 }
285
286 /**
287 * Gets the index of the first coverage-computing stage.
288 */
289 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000290 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000291 }
292
293 ///@}
294
295 ///////////////////////////////////////////////////////////////////////////
296 /// @name Blending
297 ////
298
299 /**
300 * Sets the blending function coeffecients.
301 *
302 * The blend function will be:
303 * D' = sat(S*srcCoef + D*dstCoef)
304 *
305 * where D is the existing destination color, S is the incoming source
306 * color, and D' is the new destination color that will be written. sat()
307 * is the saturation function.
308 *
309 * @param srcCoef coeffecient applied to the src color.
310 * @param dstCoef coeffecient applied to the dst color.
311 */
312 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
313 fSrcBlend = srcCoeff;
314 fDstBlend = dstCoeff;
315 #if GR_DEBUG
316 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000317 case kDC_GrBlendCoeff:
318 case kIDC_GrBlendCoeff:
319 case kDA_GrBlendCoeff:
320 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000321 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
322 "coverage stages.\n");
323 break;
324 default:
325 break;
326 }
327 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000328 case kSC_GrBlendCoeff:
329 case kISC_GrBlendCoeff:
330 case kSA_GrBlendCoeff:
331 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000332 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
333 "coverage stages.\n");
334 break;
335 default:
336 break;
337 }
338 #endif
339 }
340
341 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
342 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
343
344 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
345 GrBlendCoeff* dstBlendCoeff) const {
346 *srcBlendCoeff = fSrcBlend;
347 *dstBlendCoeff = fDstBlend;
348 }
349
350 /**
351 * Sets the blending function constant referenced by the following blending
352 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000353 * kConstC_GrBlendCoeff
354 * kIConstC_GrBlendCoeff
355 * kConstA_GrBlendCoeff
356 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000357 *
358 * @param constant the constant to set
359 */
360 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
361
362 /**
363 * Retrieves the last value set by setBlendConstant()
364 * @return the blending constant value
365 */
366 GrColor getBlendConstant() const { return fBlendConstant; }
367
368 /// @}
369
370 ///////////////////////////////////////////////////////////////////////////
371 /// @name View Matrix
372 ////
373
374 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000375 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000376 *
377 * In the post-view-matrix space the rectangle [0,w]x[0,h]
378 * fully covers the render target. (w and h are the width and height of the
379 * the rendertarget.)
380 */
381 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
382
383 /**
384 * Gets a writable pointer to the view matrix.
385 */
386 GrMatrix* viewMatrix() { return &fViewMatrix; }
387
388 /**
389 * Multiplies the current view matrix by a matrix
390 *
391 * After this call V' = V*m where V is the old view matrix,
392 * m is the parameter to this function, and V' is the new view matrix.
393 * (We consider positions to be column vectors so position vector p is
394 * transformed by matrix X as p' = X*p.)
395 *
396 * @param m the matrix used to modify the view matrix.
397 */
398 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
399
400 /**
401 * Multiplies the current view matrix by a matrix
402 *
403 * After this call V' = m*V where V is the old view matrix,
404 * m is the parameter to this function, and V' is the new view matrix.
405 * (We consider positions to be column vectors so position vector p is
406 * transformed by matrix X as p' = X*p.)
407 *
408 * @param m the matrix used to modify the view matrix.
409 */
410 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
411
412 /**
413 * Retrieves the current view matrix
414 * @return the current view matrix.
415 */
416 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
417
418 /**
419 * Retrieves the inverse of the current view matrix.
420 *
421 * If the current view matrix is invertible, return true, and if matrix
422 * is non-null, copy the inverse into it. If the current view matrix is
423 * non-invertible, return false and ignore the matrix parameter.
424 *
425 * @param matrix if not null, will receive a copy of the current inverse.
426 */
427 bool getViewInverse(GrMatrix* matrix) const {
428 // TODO: determine whether we really need to leave matrix unmodified
429 // at call sites when inversion fails.
430 GrMatrix inverse;
431 if (fViewMatrix.invert(&inverse)) {
432 if (matrix) {
433 *matrix = inverse;
434 }
435 return true;
436 }
437 return false;
438 }
439
440 class AutoViewMatrixRestore : public ::GrNoncopyable {
441 public:
442 AutoViewMatrixRestore() : fDrawState(NULL) {}
443 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
444 fDrawState = NULL;
445 this->set(ds, newMatrix);
446 }
447 AutoViewMatrixRestore(GrDrawState* ds) {
448 fDrawState = NULL;
449 this->set(ds);
450 }
451 ~AutoViewMatrixRestore() {
452 this->set(NULL, GrMatrix::I());
453 }
454 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
455 if (NULL != fDrawState) {
456 fDrawState->setViewMatrix(fSavedMatrix);
457 }
458 if (NULL != ds) {
459 fSavedMatrix = ds->getViewMatrix();
460 ds->setViewMatrix(newMatrix);
461 }
462 fDrawState = ds;
463 }
464 void set(GrDrawState* ds) {
465 if (NULL != fDrawState) {
466 fDrawState->setViewMatrix(fSavedMatrix);
467 }
468 if (NULL != ds) {
469 fSavedMatrix = ds->getViewMatrix();
470 }
471 fDrawState = ds;
472 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000473 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000474 private:
475 GrDrawState* fDrawState;
476 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000477 };
478
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000479 /// @}
480
481 ///////////////////////////////////////////////////////////////////////////
482 /// @name Render Target
483 ////
484
485 /**
486 * Sets the rendertarget used at the next drawing call
487 *
488 * @param target The render target to set.
489 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000490 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000491 GrSafeAssign(fRenderTarget, target);
492 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000493
494 /**
495 * Retrieves the currently set rendertarget.
496 *
497 * @return The currently set render target.
498 */
499 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
500 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
501
502 class AutoRenderTargetRestore : public ::GrNoncopyable {
503 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000504 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000505 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
506 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000507 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000508 this->set(ds, newTarget);
509 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000510 ~AutoRenderTargetRestore() { this->restore(); }
511
512 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000513 if (NULL != fDrawState) {
514 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000515 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000516 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000517 GrSafeSetNull(fSavedTarget);
518 }
519
520 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
521 this->restore();
522
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000523 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000524 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000525 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000526 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000527 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000528 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000530 }
531 private:
532 GrDrawState* fDrawState;
533 GrRenderTarget* fSavedTarget;
534 };
535
536 /// @}
537
538 ///////////////////////////////////////////////////////////////////////////
539 /// @name Stencil
540 ////
541
542 /**
543 * Sets the stencil settings to use for the next draw.
544 * Changing the clip has the side-effect of possibly zeroing
545 * out the client settable stencil bits. So multipass algorithms
546 * using stencil should not change the clip between passes.
547 * @param settings the stencil settings to use.
548 */
549 void setStencil(const GrStencilSettings& settings) {
550 fStencilSettings = settings;
551 }
552
553 /**
554 * Shortcut to disable stencil testing and ops.
555 */
556 void disableStencil() {
557 fStencilSettings.setDisabled();
558 }
559
560 const GrStencilSettings& getStencil() const { return fStencilSettings; }
561
562 GrStencilSettings* stencil() { return &fStencilSettings; }
563
564 /// @}
565
566 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000567 /// @name Color Matrix
568 ////
569
570 /**
571 * Sets the color matrix to use for the next draw.
572 * @param matrix the 5x4 matrix to apply to the incoming color
573 */
574 void setColorMatrix(const float matrix[20]) {
575 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
576 }
577
578 const float* getColorMatrix() const { return fColorMatrix; }
579
580 /// @}
581
582 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000583 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000584 // Edge equations can be specified to perform antialiasing. Because the
585 // edges are specified as per-vertex data, vertices that are shared by
586 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000587 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000588 ////
589
590 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000591 * When specifying edges as vertex data this enum specifies what type of
592 * edges are in use. The edges are always 4 GrScalars in memory, even when
593 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000594 *
595 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
596 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000597 */
598 enum VertexEdgeType {
599 /* 1-pixel wide line
600 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
601 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000602 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000603 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000604 being inside, positive outside. Edge specified in window space
605 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000606 kQuad_EdgeType,
607 /* Same as above but for hairline quadratics. Uses unsigned distance.
608 Coverage is min(0, 1-distance). */
609 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000610 /* Circle specified as center_x, center_y, outer_radius, inner_radius
611 all in window space (y-down). */
612 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000613
614 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000615 };
616
617 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000618 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
620 * are not specified the value of this setting has no effect.
621 */
622 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000623 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000624 fVertexEdgeType = type;
625 }
626
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000627 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000629 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000630
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000631 ///////////////////////////////////////////////////////////////////////////
632 /// @name State Flags
633 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000634
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000635 /**
636 * Flags that affect rendering. Controlled using enable/disableState(). All
637 * default to disabled.
638 */
639 enum StateBits {
640 /**
641 * Perform dithering. TODO: Re-evaluate whether we need this bit
642 */
643 kDither_StateBit = 0x01,
644 /**
645 * Perform HW anti-aliasing. This means either HW FSAA, if supported
646 * by the render target, or smooth-line rendering if a line primitive
647 * is drawn and line smoothing is supported by the 3D API.
648 */
649 kHWAntialias_StateBit = 0x02,
650 /**
651 * Draws will respect the clip, otherwise the clip is ignored.
652 */
653 kClip_StateBit = 0x04,
654 /**
655 * Disables writing to the color buffer. Useful when performing stencil
656 * operations.
657 */
658 kNoColorWrites_StateBit = 0x08,
659 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000660 * Draws will apply the color matrix, otherwise the color matrix is
661 * ignored.
662 */
bsalomon@google.com0342a852012-08-20 19:22:38 +0000663 kColorMatrix_StateBit = 0x10,
664
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000665 // Users of the class may add additional bits to the vector
666 kDummyStateBit,
667 kLastPublicStateBit = kDummyStateBit-1,
668 };
669
670 void resetStateFlags() {
671 fFlagBits = 0;
672 }
673
674 /**
675 * Enable render state settings.
676 *
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000677 * @param stateBits bitfield of StateBits specifing the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000678 */
679 void enableState(uint32_t stateBits) {
680 fFlagBits |= stateBits;
681 }
682
683 /**
684 * Disable render state settings.
685 *
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000686 * @param stateBits bitfield of StateBits specifing the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000687 */
688 void disableState(uint32_t stateBits) {
689 fFlagBits &= ~(stateBits);
690 }
691
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000692 /**
693 * Enable or disable stateBits based on a boolean.
694 *
695 * @param stateBits bitfield of StateBits to enable or disablt
696 * @param enable if true enable stateBits, otherwise disable
697 */
698 void setState(uint32_t stateBits, bool enable) {
699 if (enable) {
700 this->enableState(stateBits);
701 } else {
702 this->disableState(stateBits);
703 }
704 }
705
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000706 bool isDitherState() const {
707 return 0 != (fFlagBits & kDither_StateBit);
708 }
709
710 bool isHWAntialiasState() const {
711 return 0 != (fFlagBits & kHWAntialias_StateBit);
712 }
713
714 bool isClipState() const {
715 return 0 != (fFlagBits & kClip_StateBit);
716 }
717
718 bool isColorWriteDisabled() const {
719 return 0 != (fFlagBits & kNoColorWrites_StateBit);
720 }
721
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000722 bool isStateFlagEnabled(uint32_t stateBit) const {
723 return 0 != (stateBit & fFlagBits);
724 }
725
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000726 /// @}
727
728 ///////////////////////////////////////////////////////////////////////////
729 /// @name Face Culling
730 ////
731
732 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000733 kInvalid_DrawFace = -1,
734
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735 kBoth_DrawFace,
736 kCCW_DrawFace,
737 kCW_DrawFace,
738 };
739
740 /**
741 * Controls whether clockwise, counterclockwise, or both faces are drawn.
742 * @param face the face(s) to draw.
743 */
744 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000745 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 fDrawFace = face;
747 }
748
749 /**
750 * Gets whether the target is drawing clockwise, counterclockwise,
751 * or both faces.
752 * @return the current draw face(s).
753 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000754 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000755
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000756 /// @}
757
758 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000759
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000760 bool isStageEnabled(int s) const {
761 GrAssert((unsigned)s < kNumStages);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000762 return (NULL != fSamplerStates[s].getCustomStage());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000763 }
764
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000765 // Most stages are usually not used, so conditionals here
766 // reduce the expected number of bytes touched by 50%.
767 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000768 if (fColor != s.fColor ||
769 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
770 fRenderTarget != s.fRenderTarget ||
771 fSrcBlend != s.fSrcBlend ||
772 fDstBlend != s.fDstBlend ||
773 fBlendConstant != s.fBlendConstant ||
774 fFlagBits != s.fFlagBits ||
775 fVertexEdgeType != s.fVertexEdgeType ||
776 fStencilSettings != s.fStencilSettings ||
777 fFirstCoverageStage != s.fFirstCoverageStage ||
778 fCoverage != s.fCoverage ||
779 fColorFilterMode != s.fColorFilterMode ||
780 fColorFilterColor != s.fColorFilterColor ||
781 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000782 return false;
783 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000784
785 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000786 bool enabled = this->isStageEnabled(i);
787 if (enabled != s.isStageEnabled(i)) {
788 return false;
789 }
790 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000791 return false;
792 }
793 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000794 if (kColorMatrix_StateBit & s.fFlagBits) {
795 if (memcmp(fColorMatrix,
796 s.fColorMatrix,
797 sizeof(fColorMatrix))) {
798 return false;
799 }
800 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000801
802 return true;
803 }
804 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
805
rmistry@google.comd6176b02012-08-23 18:14:13 +0000806 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000807 // reduce the expected number of bytes touched by 50%.
808 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000809 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000810 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000811 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
812 fSrcBlend = s.fSrcBlend;
813 fDstBlend = s.fDstBlend;
814 fBlendConstant = s.fBlendConstant;
815 fFlagBits = s.fFlagBits;
816 fVertexEdgeType = s.fVertexEdgeType;
817 fStencilSettings = s.fStencilSettings;
818 fFirstCoverageStage = s.fFirstCoverageStage;
819 fCoverage = s.fCoverage;
820 fColorFilterMode = s.fColorFilterMode;
821 fColorFilterColor = s.fColorFilterColor;
822 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000823
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000824 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000825 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000826 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000827 }
828 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000829
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000830 if (kColorMatrix_StateBit & s.fFlagBits) {
831 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
832 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000833
834 return *this;
835 }
836
837private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000838
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000839 // These fields are roughly sorted by decreasing liklihood of being different in op==
840 GrColor fColor;
841 GrMatrix fViewMatrix;
842 GrRenderTarget* fRenderTarget;
843 GrBlendCoeff fSrcBlend;
844 GrBlendCoeff fDstBlend;
845 GrColor fBlendConstant;
846 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000847 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000848 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000849 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000850 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000851 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000852 GrColor fColorFilterColor;
853 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000854
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000855 // This field must be last; it will not be copied or compared
856 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000857 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000858 // only compared if the color matrix enable flag is set
859 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000860
reed@google.comfa35e3d2012-06-26 20:16:17 +0000861 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000862};
863
864#endif