blob: ca3b2c18abdaf8d382c31fb2af033e02f374b1b6 [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
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 /**
30 * Number of texture stages. Each stage takes as input a color and
31 * 2D texture coordinates. The color input to the first enabled stage is the
32 * per-vertex color or the constant color (setColor/setAlpha) if there are
33 * no per-vertex colors. For subsequent stages the input color is the output
34 * color from the previous enabled stage. The output color of each stage is
35 * the input color modulated with the result of a texture lookup. Texture
36 * lookups are specified by a texture a sampler (setSamplerState). Texture
37 * coordinates for each stage come from the vertices based on a
38 * GrVertexLayout bitfield. The output fragment color is the output color of
39 * the last enabled stage. The presence or absence of texture coordinates
40 * for each stage in the vertex layout indicates whether a stage is enabled
41 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000042 *
43 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
rmistry@google.comd6176b02012-08-23 18:14:13 +000044 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
45 * through kNumStages-1 are earmarked for use by GrTextContext and
robertphillips@google.combf5cad42012-05-10 12:40:40 +000046 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000047 */
48 enum {
twiz@google.com58071162012-07-18 21:41:50 +000049 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000050 kMaxTexCoords = kNumStages
51 };
52
rmistry@google.comd6176b02012-08-23 18:14:13 +000053 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000054 : fRenderTarget(NULL) {
55
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000056 this->reset();
57 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000058
rmistry@google.comd6176b02012-08-23 18:14:13 +000059 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000060 : fRenderTarget(NULL) {
61
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000062 *this = state;
63 }
64
robertphillips@google.com9ec07532012-06-22 12:01:30 +000065 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000066 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000067 GrSafeSetNull(fRenderTarget);
68 }
69
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000070 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000071 * Resets to the default state.
72 * Sampler states *will* be modified: textures or CustomStage objects
73 * will be released.
rmistry@google.comd6176b02012-08-23 18:14:13 +000074 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000075 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000076
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000077 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000078
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000080 fViewMatrix.reset();
81 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000082 fSrcBlend = kOne_GrBlendCoeff;
83 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000084 fBlendConstant = 0x0;
85 fFlagBits = 0x0;
86 fVertexEdgeType = kHairLine_EdgeType;
87 fStencilSettings.setDisabled();
88 fFirstCoverageStage = kNumStages;
89 fCoverage = 0xffffffff;
90 fColorFilterMode = SkXfermode::kDst_Mode;
91 fColorFilterColor = 0x0;
92 fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000093 }
94
95 /**
96 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
97 * encompases more than GrPaint. Aspects of GrDrawState that have no
98 * GrPaint equivalents are not modified. GrPaint has fewer stages than
99 * GrDrawState. The extra GrDrawState stages are disabled.
100 */
101 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000102
103 ///////////////////////////////////////////////////////////////////////////
104 /// @name Color
105 ////
106
107 /**
108 * Sets color for next draw to a premultiplied-alpha color.
109 *
110 * @param color the color to set.
111 */
112 void setColor(GrColor color) { fColor = color; }
113
114 GrColor getColor() const { return fColor; }
115
116 /**
117 * Sets the color to be used for the next draw to be
118 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
119 *
120 * @param alpha The alpha value to set as the color.
121 */
122 void setAlpha(uint8_t a) {
123 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
124 }
125
126 /**
127 * Add a color filter that can be represented by a color and a mode. Applied
128 * after color-computing texture stages.
129 */
130 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
131 fColorFilterColor = c;
132 fColorFilterMode = mode;
133 }
134
135 GrColor getColorFilterColor() const { return fColorFilterColor; }
136 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
137
138 /// @}
139
140 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000141 /// @name Coverage
142 ////
143
144 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000145 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000146 * initial value (after construction or reset()) is 0xff. The constant
147 * coverage is ignored when per-vertex coverage is provided.
148 */
149 void setCoverage(uint8_t coverage) {
150 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
151 }
152
153 /**
154 * Version of above that specifies 4 channel per-vertex color. The value
155 * should be premultiplied.
156 */
157 void setCoverage4(GrColor coverage) {
158 fCoverage = coverage;
159 }
160
161 GrColor getCoverage() const {
162 return fCoverage;
163 }
164
165 /// @}
166
167 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000168 /// @name Textures
169 ////
170
171 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000172 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000173 */
174 void createTextureEffect(int stage, GrTexture* texture) {
175 GrAssert(!this->getSampler(stage).getCustomStage());
176 this->sampler(stage)->setCustomStage(
177 SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
178 }
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000179 void createTextureEffect(int stage, GrTexture* texture, const GrTextureParams& params) {
180 GrAssert(!this->getSampler(stage).getCustomStage());
181 this->sampler(stage)->setCustomStage(
182 SkNEW_ARGS(GrSingleTextureEffect, (texture, params)))->unref();
183 }
184
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000185
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000186 bool stagesDisabled() {
187 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000188 if (NULL != fSamplerStates[i].getCustomStage()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000189 return false;
190 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000191 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000192 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000193 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000194
195 void disableStage(int index) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000196 fSamplerStates[index].setCustomStage(NULL);
197 }
198
robertphillips@google.com972265d2012-06-13 18:49:30 +0000199 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000200 * Release all the textures and custom stages referred to by this
201 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000202 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000203 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000204 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000205 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000206 }
207 }
208
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000209 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000210 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000211 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
212 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000213 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000214 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000215 }
216 }
217 private:
218 GrDrawState* fDrawState;
219 };
220
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000221 /// @}
222
223 ///////////////////////////////////////////////////////////////////////////
224 /// @name Samplers
225 ////
226
227 /**
228 * Returns the current sampler for a stage.
229 */
230 const GrSamplerState& getSampler(int stage) const {
231 GrAssert((unsigned)stage < kNumStages);
232 return fSamplerStates[stage];
233 }
234
235 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000236 * Writable pointer to a stage's sampler.
237 */
238 GrSamplerState* sampler(int stage) {
239 GrAssert((unsigned)stage < kNumStages);
240 return fSamplerStates + stage;
241 }
242
243 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000244 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000245 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000246 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000247 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000248 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000249 fSamplerStates[i].preConcatMatrix(matrix);
250 }
251 }
252 }
253
bsalomon@google.come3d32162012-07-20 13:37:06 +0000254 /**
255 * Preconcats the matrix of all samplers in the mask with the inverse of a
256 * matrix. If the matrix inverse cannot be computed (and there is at least
257 * one enabled stage) then false is returned.
258 */
259 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
260 GrMatrix inv;
261 bool computed = false;
262 for (int i = 0; i < kNumStages; ++i) {
263 if (this->isStageEnabled(i)) {
264 if (!computed && !matrix.invert(&inv)) {
265 return false;
266 } else {
267 computed = true;
268 }
269 fSamplerStates[i].preConcatMatrix(inv);
270 }
271 }
272 return true;
273 }
274
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000275 /// @}
276
277 ///////////////////////////////////////////////////////////////////////////
278 /// @name Coverage / Color Stages
279 ////
280
281 /**
282 * A common pattern is to compute a color with the initial stages and then
283 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000284 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
285 * computed based on the pre-coverage-modulated color. The division of
286 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000287 * this method. Initially this is kNumStages (all stages
288 * are color-computing).
289 */
290 void setFirstCoverageStage(int firstCoverageStage) {
291 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000292 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000293 }
294
295 /**
296 * Gets the index of the first coverage-computing stage.
297 */
298 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000299 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000300 }
301
302 ///@}
303
304 ///////////////////////////////////////////////////////////////////////////
305 /// @name Blending
306 ////
307
308 /**
309 * Sets the blending function coeffecients.
310 *
311 * The blend function will be:
312 * D' = sat(S*srcCoef + D*dstCoef)
313 *
314 * where D is the existing destination color, S is the incoming source
315 * color, and D' is the new destination color that will be written. sat()
316 * is the saturation function.
317 *
318 * @param srcCoef coeffecient applied to the src color.
319 * @param dstCoef coeffecient applied to the dst color.
320 */
321 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
322 fSrcBlend = srcCoeff;
323 fDstBlend = dstCoeff;
324 #if GR_DEBUG
325 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000326 case kDC_GrBlendCoeff:
327 case kIDC_GrBlendCoeff:
328 case kDA_GrBlendCoeff:
329 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000330 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
331 "coverage stages.\n");
332 break;
333 default:
334 break;
335 }
336 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000337 case kSC_GrBlendCoeff:
338 case kISC_GrBlendCoeff:
339 case kSA_GrBlendCoeff:
340 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000341 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
342 "coverage stages.\n");
343 break;
344 default:
345 break;
346 }
347 #endif
348 }
349
350 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
351 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
352
353 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
354 GrBlendCoeff* dstBlendCoeff) const {
355 *srcBlendCoeff = fSrcBlend;
356 *dstBlendCoeff = fDstBlend;
357 }
358
359 /**
360 * Sets the blending function constant referenced by the following blending
361 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000362 * kConstC_GrBlendCoeff
363 * kIConstC_GrBlendCoeff
364 * kConstA_GrBlendCoeff
365 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000366 *
367 * @param constant the constant to set
368 */
369 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
370
371 /**
372 * Retrieves the last value set by setBlendConstant()
373 * @return the blending constant value
374 */
375 GrColor getBlendConstant() const { return fBlendConstant; }
376
377 /// @}
378
379 ///////////////////////////////////////////////////////////////////////////
380 /// @name View Matrix
381 ////
382
383 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000384 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000385 *
386 * In the post-view-matrix space the rectangle [0,w]x[0,h]
387 * fully covers the render target. (w and h are the width and height of the
388 * the rendertarget.)
389 */
390 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
391
392 /**
393 * Gets a writable pointer to the view matrix.
394 */
395 GrMatrix* viewMatrix() { return &fViewMatrix; }
396
397 /**
398 * Multiplies the current view matrix by a matrix
399 *
400 * After this call V' = V*m where V is the old view matrix,
401 * m is the parameter to this function, and V' is the new view matrix.
402 * (We consider positions to be column vectors so position vector p is
403 * transformed by matrix X as p' = X*p.)
404 *
405 * @param m the matrix used to modify the view matrix.
406 */
407 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
408
409 /**
410 * Multiplies the current view matrix by a matrix
411 *
412 * After this call V' = m*V where V is the old view matrix,
413 * m is the parameter to this function, and V' is the new view matrix.
414 * (We consider positions to be column vectors so position vector p is
415 * transformed by matrix X as p' = X*p.)
416 *
417 * @param m the matrix used to modify the view matrix.
418 */
419 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
420
421 /**
422 * Retrieves the current view matrix
423 * @return the current view matrix.
424 */
425 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
426
427 /**
428 * Retrieves the inverse of the current view matrix.
429 *
430 * If the current view matrix is invertible, return true, and if matrix
431 * is non-null, copy the inverse into it. If the current view matrix is
432 * non-invertible, return false and ignore the matrix parameter.
433 *
434 * @param matrix if not null, will receive a copy of the current inverse.
435 */
436 bool getViewInverse(GrMatrix* matrix) const {
437 // TODO: determine whether we really need to leave matrix unmodified
438 // at call sites when inversion fails.
439 GrMatrix inverse;
440 if (fViewMatrix.invert(&inverse)) {
441 if (matrix) {
442 *matrix = inverse;
443 }
444 return true;
445 }
446 return false;
447 }
448
449 class AutoViewMatrixRestore : public ::GrNoncopyable {
450 public:
451 AutoViewMatrixRestore() : fDrawState(NULL) {}
452 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
453 fDrawState = NULL;
454 this->set(ds, newMatrix);
455 }
456 AutoViewMatrixRestore(GrDrawState* ds) {
457 fDrawState = NULL;
458 this->set(ds);
459 }
460 ~AutoViewMatrixRestore() {
461 this->set(NULL, GrMatrix::I());
462 }
463 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
464 if (NULL != fDrawState) {
465 fDrawState->setViewMatrix(fSavedMatrix);
466 }
467 if (NULL != ds) {
468 fSavedMatrix = ds->getViewMatrix();
469 ds->setViewMatrix(newMatrix);
470 }
471 fDrawState = ds;
472 }
473 void set(GrDrawState* ds) {
474 if (NULL != fDrawState) {
475 fDrawState->setViewMatrix(fSavedMatrix);
476 }
477 if (NULL != ds) {
478 fSavedMatrix = ds->getViewMatrix();
479 }
480 fDrawState = ds;
481 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000482 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000483 private:
484 GrDrawState* fDrawState;
485 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000486 };
487
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000488 /// @}
489
490 ///////////////////////////////////////////////////////////////////////////
491 /// @name Render Target
492 ////
493
494 /**
495 * Sets the rendertarget used at the next drawing call
496 *
497 * @param target The render target to set.
498 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000499 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000500 GrSafeAssign(fRenderTarget, target);
501 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000502
503 /**
504 * Retrieves the currently set rendertarget.
505 *
506 * @return The currently set render target.
507 */
508 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
509 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
510
511 class AutoRenderTargetRestore : public ::GrNoncopyable {
512 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000513 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000514 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
515 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000516 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000517 this->set(ds, newTarget);
518 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000519 ~AutoRenderTargetRestore() { this->restore(); }
520
521 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000522 if (NULL != fDrawState) {
523 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000524 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000525 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000526 GrSafeSetNull(fSavedTarget);
527 }
528
529 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
530 this->restore();
531
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000532 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000533 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000534 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000535 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000536 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000537 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000538 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000539 }
540 private:
541 GrDrawState* fDrawState;
542 GrRenderTarget* fSavedTarget;
543 };
544
545 /// @}
546
547 ///////////////////////////////////////////////////////////////////////////
548 /// @name Stencil
549 ////
550
551 /**
552 * Sets the stencil settings to use for the next draw.
553 * Changing the clip has the side-effect of possibly zeroing
554 * out the client settable stencil bits. So multipass algorithms
555 * using stencil should not change the clip between passes.
556 * @param settings the stencil settings to use.
557 */
558 void setStencil(const GrStencilSettings& settings) {
559 fStencilSettings = settings;
560 }
561
562 /**
563 * Shortcut to disable stencil testing and ops.
564 */
565 void disableStencil() {
566 fStencilSettings.setDisabled();
567 }
568
569 const GrStencilSettings& getStencil() const { return fStencilSettings; }
570
571 GrStencilSettings* stencil() { return &fStencilSettings; }
572
573 /// @}
574
575 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000576 /// @name Color Matrix
577 ////
578
579 /**
580 * Sets the color matrix to use for the next draw.
581 * @param matrix the 5x4 matrix to apply to the incoming color
582 */
583 void setColorMatrix(const float matrix[20]) {
584 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
585 }
586
587 const float* getColorMatrix() const { return fColorMatrix; }
588
589 /// @}
590
591 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000593 // Edge equations can be specified to perform antialiasing. Because the
594 // edges are specified as per-vertex data, vertices that are shared by
595 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000597 ////
598
599 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000600 * When specifying edges as vertex data this enum specifies what type of
601 * edges are in use. The edges are always 4 GrScalars in memory, even when
602 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000603 *
604 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
605 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000606 */
607 enum VertexEdgeType {
608 /* 1-pixel wide line
609 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
610 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000611 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000612 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000613 being inside, positive outside. Edge specified in window space
614 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000615 kQuad_EdgeType,
616 /* Same as above but for hairline quadratics. Uses unsigned distance.
617 Coverage is min(0, 1-distance). */
618 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000619 /* Circle specified as center_x, center_y, outer_radius, inner_radius
620 all in window space (y-down). */
621 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000622
623 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000624 };
625
626 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000627 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
629 * are not specified the value of this setting has no effect.
630 */
631 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000632 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 fVertexEdgeType = type;
634 }
635
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000636 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000639
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000640 ///////////////////////////////////////////////////////////////////////////
641 /// @name State Flags
642 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000643
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000644 /**
645 * Flags that affect rendering. Controlled using enable/disableState(). All
646 * default to disabled.
647 */
648 enum StateBits {
649 /**
650 * Perform dithering. TODO: Re-evaluate whether we need this bit
651 */
652 kDither_StateBit = 0x01,
653 /**
654 * Perform HW anti-aliasing. This means either HW FSAA, if supported
655 * by the render target, or smooth-line rendering if a line primitive
656 * is drawn and line smoothing is supported by the 3D API.
657 */
658 kHWAntialias_StateBit = 0x02,
659 /**
660 * Draws will respect the clip, otherwise the clip is ignored.
661 */
662 kClip_StateBit = 0x04,
663 /**
664 * Disables writing to the color buffer. Useful when performing stencil
665 * operations.
666 */
667 kNoColorWrites_StateBit = 0x08,
668 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000669 * Draws will apply the color matrix, otherwise the color matrix is
670 * ignored.
671 */
bsalomon@google.com0342a852012-08-20 19:22:38 +0000672 kColorMatrix_StateBit = 0x10,
673
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000674 // Users of the class may add additional bits to the vector
675 kDummyStateBit,
676 kLastPublicStateBit = kDummyStateBit-1,
677 };
678
679 void resetStateFlags() {
680 fFlagBits = 0;
681 }
682
683 /**
684 * Enable render state settings.
685 *
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000686 * @param stateBits bitfield of StateBits specifing the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000687 */
688 void enableState(uint32_t stateBits) {
689 fFlagBits |= stateBits;
690 }
691
692 /**
693 * Disable render state settings.
694 *
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000695 * @param stateBits bitfield of StateBits specifing the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000696 */
697 void disableState(uint32_t stateBits) {
698 fFlagBits &= ~(stateBits);
699 }
700
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000701 /**
702 * Enable or disable stateBits based on a boolean.
703 *
704 * @param stateBits bitfield of StateBits to enable or disablt
705 * @param enable if true enable stateBits, otherwise disable
706 */
707 void setState(uint32_t stateBits, bool enable) {
708 if (enable) {
709 this->enableState(stateBits);
710 } else {
711 this->disableState(stateBits);
712 }
713 }
714
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000715 bool isDitherState() const {
716 return 0 != (fFlagBits & kDither_StateBit);
717 }
718
719 bool isHWAntialiasState() const {
720 return 0 != (fFlagBits & kHWAntialias_StateBit);
721 }
722
723 bool isClipState() const {
724 return 0 != (fFlagBits & kClip_StateBit);
725 }
726
727 bool isColorWriteDisabled() const {
728 return 0 != (fFlagBits & kNoColorWrites_StateBit);
729 }
730
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000731 bool isStateFlagEnabled(uint32_t stateBit) const {
732 return 0 != (stateBit & fFlagBits);
733 }
734
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735 /// @}
736
737 ///////////////////////////////////////////////////////////////////////////
738 /// @name Face Culling
739 ////
740
741 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000742 kInvalid_DrawFace = -1,
743
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000744 kBoth_DrawFace,
745 kCCW_DrawFace,
746 kCW_DrawFace,
747 };
748
749 /**
750 * Controls whether clockwise, counterclockwise, or both faces are drawn.
751 * @param face the face(s) to draw.
752 */
753 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000754 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000755 fDrawFace = face;
756 }
757
758 /**
759 * Gets whether the target is drawing clockwise, counterclockwise,
760 * or both faces.
761 * @return the current draw face(s).
762 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000763 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000764
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000765 /// @}
766
767 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000768
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000769 bool isStageEnabled(int s) const {
770 GrAssert((unsigned)s < kNumStages);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000771 return (NULL != fSamplerStates[s].getCustomStage());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000772 }
773
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000774 // Most stages are usually not used, so conditionals here
775 // reduce the expected number of bytes touched by 50%.
776 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000777 if (fColor != s.fColor ||
778 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
779 fRenderTarget != s.fRenderTarget ||
780 fSrcBlend != s.fSrcBlend ||
781 fDstBlend != s.fDstBlend ||
782 fBlendConstant != s.fBlendConstant ||
783 fFlagBits != s.fFlagBits ||
784 fVertexEdgeType != s.fVertexEdgeType ||
785 fStencilSettings != s.fStencilSettings ||
786 fFirstCoverageStage != s.fFirstCoverageStage ||
787 fCoverage != s.fCoverage ||
788 fColorFilterMode != s.fColorFilterMode ||
789 fColorFilterColor != s.fColorFilterColor ||
790 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000791 return false;
792 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000793
794 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000795 bool enabled = this->isStageEnabled(i);
796 if (enabled != s.isStageEnabled(i)) {
797 return false;
798 }
799 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000800 return false;
801 }
802 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000803 if (kColorMatrix_StateBit & s.fFlagBits) {
804 if (memcmp(fColorMatrix,
805 s.fColorMatrix,
806 sizeof(fColorMatrix))) {
807 return false;
808 }
809 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000810
811 return true;
812 }
813 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
814
rmistry@google.comd6176b02012-08-23 18:14:13 +0000815 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000816 // reduce the expected number of bytes touched by 50%.
817 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000818 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000819 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000820 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
821 fSrcBlend = s.fSrcBlend;
822 fDstBlend = s.fDstBlend;
823 fBlendConstant = s.fBlendConstant;
824 fFlagBits = s.fFlagBits;
825 fVertexEdgeType = s.fVertexEdgeType;
826 fStencilSettings = s.fStencilSettings;
827 fFirstCoverageStage = s.fFirstCoverageStage;
828 fCoverage = s.fCoverage;
829 fColorFilterMode = s.fColorFilterMode;
830 fColorFilterColor = s.fColorFilterColor;
831 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000832
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000833 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000834 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000835 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000836 }
837 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000838
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000839 if (kColorMatrix_StateBit & s.fFlagBits) {
840 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
841 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000842
843 return *this;
844 }
845
846private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000847
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000848 // These fields are roughly sorted by decreasing liklihood of being different in op==
849 GrColor fColor;
850 GrMatrix fViewMatrix;
851 GrRenderTarget* fRenderTarget;
852 GrBlendCoeff fSrcBlend;
853 GrBlendCoeff fDstBlend;
854 GrColor fBlendConstant;
855 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000856 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000857 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000858 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000859 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000860 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000861 GrColor fColorFilterColor;
862 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000863
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000864 // This field must be last; it will not be copied or compared
865 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000866 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000867 // only compared if the color matrix enable flag is set
868 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000869
reed@google.comfa35e3d2012-06-26 20:16:17 +0000870 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000871};
872
873#endif