blob: 0d81019ebb26cf39597b4c94205f338b1764f43a [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)
27
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
43 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
44 * through kNumStages-1 are earmarked for use by GrTextContext and
45 * 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
robertphillips@google.com9ec07532012-06-22 12:01:30 +000052 GrDrawState()
53 : fRenderTarget(NULL) {
54
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000055 this->reset();
56 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000057
robertphillips@google.com9ec07532012-06-22 12:01:30 +000058 GrDrawState(const GrDrawState& state)
59 : 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.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000073 */
74 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 GrSafeSetNull(fRenderTarget);
78
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000079 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000080 // all GrDrawState members should default to something valid by the
81 // the memset except those initialized individually below. There should
82 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000083 memset(this->podStart(), 0, this->memsetSize());
84
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000085 // pedantic assertion that our ptrs will
86 // be NULL (0 ptr is mem addr 0)
87 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000088 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000089 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000090
91 // memset exceptions
92 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000093 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000094 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000095 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +000096 fSrcBlend = kOne_GrBlendCoeff;
97 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000098 fViewMatrix.reset();
99
100 // ensure values that will be memcmp'ed in == but not memset in reset()
101 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000102 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000103 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000104 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fRenderTarget) ==
105 this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000106 }
107
108 ///////////////////////////////////////////////////////////////////////////
109 /// @name Color
110 ////
111
112 /**
113 * Sets color for next draw to a premultiplied-alpha color.
114 *
115 * @param color the color to set.
116 */
117 void setColor(GrColor color) { fColor = color; }
118
119 GrColor getColor() const { return fColor; }
120
121 /**
122 * Sets the color to be used for the next draw to be
123 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
124 *
125 * @param alpha The alpha value to set as the color.
126 */
127 void setAlpha(uint8_t a) {
128 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
129 }
130
131 /**
132 * Add a color filter that can be represented by a color and a mode. Applied
133 * after color-computing texture stages.
134 */
135 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
136 fColorFilterColor = c;
137 fColorFilterMode = mode;
138 }
139
140 GrColor getColorFilterColor() const { return fColorFilterColor; }
141 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
142
143 /// @}
144
145 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000146 /// @name Coverage
147 ////
148
149 /**
150 * Sets a constant fractional coverage to be applied to the draw. The
151 * initial value (after construction or reset()) is 0xff. The constant
152 * coverage is ignored when per-vertex coverage is provided.
153 */
154 void setCoverage(uint8_t coverage) {
155 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
156 }
157
158 /**
159 * Version of above that specifies 4 channel per-vertex color. The value
160 * should be premultiplied.
161 */
162 void setCoverage4(GrColor coverage) {
163 fCoverage = coverage;
164 }
165
166 GrColor getCoverage() const {
167 return fCoverage;
168 }
169
170 /// @}
171
172 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000173 /// @name Textures
174 ////
175
176 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000177 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000178 */
179 void createTextureEffect(int stage, GrTexture* texture) {
180 GrAssert(!this->getSampler(stage).getCustomStage());
181 this->sampler(stage)->setCustomStage(
182 SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
183 }
184
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000185 bool stagesDisabled() {
186 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000187 if (NULL != fSamplerStates[i].getCustomStage()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000188 return false;
189 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000190 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000191 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000192 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000193
194 void disableStage(int index) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000195 fSamplerStates[index].setCustomStage(NULL);
196 }
197
robertphillips@google.com972265d2012-06-13 18:49:30 +0000198 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000199 * Release all the textures and custom stages referred to by this
200 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000201 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000202 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000203 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000204 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000205 }
206 }
207
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000208 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000209 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000210 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
211 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000212 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000213 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000214 }
215 }
216 private:
217 GrDrawState* fDrawState;
218 };
219
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000220 /// @}
221
222 ///////////////////////////////////////////////////////////////////////////
223 /// @name Samplers
224 ////
225
226 /**
227 * Returns the current sampler for a stage.
228 */
229 const GrSamplerState& getSampler(int stage) const {
230 GrAssert((unsigned)stage < kNumStages);
231 return fSamplerStates[stage];
232 }
233
234 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000235 * Writable pointer to a stage's sampler.
236 */
237 GrSamplerState* sampler(int stage) {
238 GrAssert((unsigned)stage < kNumStages);
239 return fSamplerStates + stage;
240 }
241
242 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000243 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000244 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000245 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000246 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000247 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000248 fSamplerStates[i].preConcatMatrix(matrix);
249 }
250 }
251 }
252
bsalomon@google.come3d32162012-07-20 13:37:06 +0000253 /**
254 * Preconcats the matrix of all samplers in the mask with the inverse of a
255 * matrix. If the matrix inverse cannot be computed (and there is at least
256 * one enabled stage) then false is returned.
257 */
258 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
259 GrMatrix inv;
260 bool computed = false;
261 for (int i = 0; i < kNumStages; ++i) {
262 if (this->isStageEnabled(i)) {
263 if (!computed && !matrix.invert(&inv)) {
264 return false;
265 } else {
266 computed = true;
267 }
268 fSamplerStates[i].preConcatMatrix(inv);
269 }
270 }
271 return true;
272 }
273
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000274 /// @}
275
276 ///////////////////////////////////////////////////////////////////////////
277 /// @name Coverage / Color Stages
278 ////
279
280 /**
281 * A common pattern is to compute a color with the initial stages and then
282 * modulate that color by a coverage value in later stage(s) (AA, mask-
283 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
284 * computed based on the pre-coverage-modulated color. The division of
285 * stages between color-computing and coverage-computing is specified by
286 * this method. Initially this is kNumStages (all stages
287 * are color-computing).
288 */
289 void setFirstCoverageStage(int firstCoverageStage) {
290 GrAssert((unsigned)firstCoverageStage <= kNumStages);
291 fFirstCoverageStage = firstCoverageStage;
292 }
293
294 /**
295 * Gets the index of the first coverage-computing stage.
296 */
297 int getFirstCoverageStage() const {
298 return fFirstCoverageStage;
299 }
300
301 ///@}
302
303 ///////////////////////////////////////////////////////////////////////////
304 /// @name Blending
305 ////
306
307 /**
308 * Sets the blending function coeffecients.
309 *
310 * The blend function will be:
311 * D' = sat(S*srcCoef + D*dstCoef)
312 *
313 * where D is the existing destination color, S is the incoming source
314 * color, and D' is the new destination color that will be written. sat()
315 * is the saturation function.
316 *
317 * @param srcCoef coeffecient applied to the src color.
318 * @param dstCoef coeffecient applied to the dst color.
319 */
320 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
321 fSrcBlend = srcCoeff;
322 fDstBlend = dstCoeff;
323 #if GR_DEBUG
324 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000325 case kDC_GrBlendCoeff:
326 case kIDC_GrBlendCoeff:
327 case kDA_GrBlendCoeff:
328 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000329 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
330 "coverage stages.\n");
331 break;
332 default:
333 break;
334 }
335 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000336 case kSC_GrBlendCoeff:
337 case kISC_GrBlendCoeff:
338 case kSA_GrBlendCoeff:
339 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000340 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
341 "coverage stages.\n");
342 break;
343 default:
344 break;
345 }
346 #endif
347 }
348
349 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
350 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
351
352 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
353 GrBlendCoeff* dstBlendCoeff) const {
354 *srcBlendCoeff = fSrcBlend;
355 *dstBlendCoeff = fDstBlend;
356 }
357
358 /**
359 * Sets the blending function constant referenced by the following blending
360 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000361 * kConstC_GrBlendCoeff
362 * kIConstC_GrBlendCoeff
363 * kConstA_GrBlendCoeff
364 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000365 *
366 * @param constant the constant to set
367 */
368 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
369
370 /**
371 * Retrieves the last value set by setBlendConstant()
372 * @return the blending constant value
373 */
374 GrColor getBlendConstant() const { return fBlendConstant; }
375
376 /// @}
377
378 ///////////////////////////////////////////////////////////////////////////
379 /// @name View Matrix
380 ////
381
382 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000383 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000384 *
385 * In the post-view-matrix space the rectangle [0,w]x[0,h]
386 * fully covers the render target. (w and h are the width and height of the
387 * the rendertarget.)
388 */
389 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
390
391 /**
392 * Gets a writable pointer to the view matrix.
393 */
394 GrMatrix* viewMatrix() { return &fViewMatrix; }
395
396 /**
397 * Multiplies the current view matrix by a matrix
398 *
399 * After this call V' = V*m where V is the old view matrix,
400 * m is the parameter to this function, and V' is the new view matrix.
401 * (We consider positions to be column vectors so position vector p is
402 * transformed by matrix X as p' = X*p.)
403 *
404 * @param m the matrix used to modify the view matrix.
405 */
406 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
407
408 /**
409 * Multiplies the current view matrix by a matrix
410 *
411 * After this call V' = m*V where V is the old view matrix,
412 * m is the parameter to this function, and V' is the new view matrix.
413 * (We consider positions to be column vectors so position vector p is
414 * transformed by matrix X as p' = X*p.)
415 *
416 * @param m the matrix used to modify the view matrix.
417 */
418 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
419
420 /**
421 * Retrieves the current view matrix
422 * @return the current view matrix.
423 */
424 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
425
426 /**
427 * Retrieves the inverse of the current view matrix.
428 *
429 * If the current view matrix is invertible, return true, and if matrix
430 * is non-null, copy the inverse into it. If the current view matrix is
431 * non-invertible, return false and ignore the matrix parameter.
432 *
433 * @param matrix if not null, will receive a copy of the current inverse.
434 */
435 bool getViewInverse(GrMatrix* matrix) const {
436 // TODO: determine whether we really need to leave matrix unmodified
437 // at call sites when inversion fails.
438 GrMatrix inverse;
439 if (fViewMatrix.invert(&inverse)) {
440 if (matrix) {
441 *matrix = inverse;
442 }
443 return true;
444 }
445 return false;
446 }
447
448 class AutoViewMatrixRestore : public ::GrNoncopyable {
449 public:
450 AutoViewMatrixRestore() : fDrawState(NULL) {}
451 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
452 fDrawState = NULL;
453 this->set(ds, newMatrix);
454 }
455 AutoViewMatrixRestore(GrDrawState* ds) {
456 fDrawState = NULL;
457 this->set(ds);
458 }
459 ~AutoViewMatrixRestore() {
460 this->set(NULL, GrMatrix::I());
461 }
462 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
463 if (NULL != fDrawState) {
464 fDrawState->setViewMatrix(fSavedMatrix);
465 }
466 if (NULL != ds) {
467 fSavedMatrix = ds->getViewMatrix();
468 ds->setViewMatrix(newMatrix);
469 }
470 fDrawState = ds;
471 }
472 void set(GrDrawState* ds) {
473 if (NULL != fDrawState) {
474 fDrawState->setViewMatrix(fSavedMatrix);
475 }
476 if (NULL != ds) {
477 fSavedMatrix = ds->getViewMatrix();
478 }
479 fDrawState = ds;
480 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000481 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000482 private:
483 GrDrawState* fDrawState;
484 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000485 };
486
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000487 /// @}
488
489 ///////////////////////////////////////////////////////////////////////////
490 /// @name Render Target
491 ////
492
493 /**
494 * Sets the rendertarget used at the next drawing call
495 *
496 * @param target The render target to set.
497 */
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000498 void setRenderTarget(GrRenderTarget* target) {
499 GrSafeAssign(fRenderTarget, target);
500 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000501
502 /**
503 * Retrieves the currently set rendertarget.
504 *
505 * @return The currently set render target.
506 */
507 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
508 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
509
510 class AutoRenderTargetRestore : public ::GrNoncopyable {
511 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000512 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000513 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
514 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000515 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000516 this->set(ds, newTarget);
517 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000518 ~AutoRenderTargetRestore() { this->restore(); }
519
520 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000521 if (NULL != fDrawState) {
522 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000523 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000524 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000525 GrSafeSetNull(fSavedTarget);
526 }
527
528 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
529 this->restore();
530
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000531 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000532 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000533 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000534 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000535 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000536 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000537 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000538 }
539 private:
540 GrDrawState* fDrawState;
541 GrRenderTarget* fSavedTarget;
542 };
543
544 /// @}
545
546 ///////////////////////////////////////////////////////////////////////////
547 /// @name Stencil
548 ////
549
550 /**
551 * Sets the stencil settings to use for the next draw.
552 * Changing the clip has the side-effect of possibly zeroing
553 * out the client settable stencil bits. So multipass algorithms
554 * using stencil should not change the clip between passes.
555 * @param settings the stencil settings to use.
556 */
557 void setStencil(const GrStencilSettings& settings) {
558 fStencilSettings = settings;
559 }
560
561 /**
562 * Shortcut to disable stencil testing and ops.
563 */
564 void disableStencil() {
565 fStencilSettings.setDisabled();
566 }
567
568 const GrStencilSettings& getStencil() const { return fStencilSettings; }
569
570 GrStencilSettings* stencil() { return &fStencilSettings; }
571
572 /// @}
573
574 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000575 /// @name Color Matrix
576 ////
577
578 /**
579 * Sets the color matrix to use for the next draw.
580 * @param matrix the 5x4 matrix to apply to the incoming color
581 */
582 void setColorMatrix(const float matrix[20]) {
583 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
584 }
585
586 const float* getColorMatrix() const { return fColorMatrix; }
587
588 /// @}
589
590 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000592 // Edge equations can be specified to perform antialiasing. Because the
593 // edges are specified as per-vertex data, vertices that are shared by
594 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000595 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 ////
597
598 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000599 * When specifying edges as vertex data this enum specifies what type of
600 * edges are in use. The edges are always 4 GrScalars in memory, even when
601 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000602 *
603 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
604 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000605 */
606 enum VertexEdgeType {
607 /* 1-pixel wide line
608 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
609 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000610 /* Quadratic specified by u^2-v canonical coords (only 2
611 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000612 being inside, positive outside. Edge specified in window space
613 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000614 kQuad_EdgeType,
615 /* Same as above but for hairline quadratics. Uses unsigned distance.
616 Coverage is min(0, 1-distance). */
617 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000618 /* Circle specified as center_x, center_y, outer_radius, inner_radius
619 all in window space (y-down). */
620 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000621
622 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000623 };
624
625 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000626 * Determines the interpretation per-vertex edge data when the
627 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
628 * are not specified the value of this setting has no effect.
629 */
630 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000631 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000632 fVertexEdgeType = type;
633 }
634
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000635 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000636
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000638
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000639 ///////////////////////////////////////////////////////////////////////////
640 /// @name State Flags
641 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000642
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000643 /**
644 * Flags that affect rendering. Controlled using enable/disableState(). All
645 * default to disabled.
646 */
647 enum StateBits {
648 /**
649 * Perform dithering. TODO: Re-evaluate whether we need this bit
650 */
651 kDither_StateBit = 0x01,
652 /**
653 * Perform HW anti-aliasing. This means either HW FSAA, if supported
654 * by the render target, or smooth-line rendering if a line primitive
655 * is drawn and line smoothing is supported by the 3D API.
656 */
657 kHWAntialias_StateBit = 0x02,
658 /**
659 * Draws will respect the clip, otherwise the clip is ignored.
660 */
661 kClip_StateBit = 0x04,
662 /**
663 * Disables writing to the color buffer. Useful when performing stencil
664 * operations.
665 */
666 kNoColorWrites_StateBit = 0x08,
667 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000668 * Draws will apply the color matrix, otherwise the color matrix is
669 * ignored.
670 */
671 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000672
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000673 // Users of the class may add additional bits to the vector
674 kDummyStateBit,
675 kLastPublicStateBit = kDummyStateBit-1,
676 };
677
678 void resetStateFlags() {
679 fFlagBits = 0;
680 }
681
682 /**
683 * Enable render state settings.
684 *
685 * @param flags bitfield of StateBits specifing the states to enable
686 */
687 void enableState(uint32_t stateBits) {
688 fFlagBits |= stateBits;
689 }
690
691 /**
692 * Disable render state settings.
693 *
694 * @param flags bitfield of StateBits specifing the states to disable
695 */
696 void disableState(uint32_t stateBits) {
697 fFlagBits &= ~(stateBits);
698 }
699
700 bool isDitherState() const {
701 return 0 != (fFlagBits & kDither_StateBit);
702 }
703
704 bool isHWAntialiasState() const {
705 return 0 != (fFlagBits & kHWAntialias_StateBit);
706 }
707
708 bool isClipState() const {
709 return 0 != (fFlagBits & kClip_StateBit);
710 }
711
712 bool isColorWriteDisabled() const {
713 return 0 != (fFlagBits & kNoColorWrites_StateBit);
714 }
715
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000716 bool isStateFlagEnabled(uint32_t stateBit) const {
717 return 0 != (stateBit & fFlagBits);
718 }
719
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000720 /// @}
721
722 ///////////////////////////////////////////////////////////////////////////
723 /// @name Face Culling
724 ////
725
726 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000727 kInvalid_DrawFace = -1,
728
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000729 kBoth_DrawFace,
730 kCCW_DrawFace,
731 kCW_DrawFace,
732 };
733
734 /**
735 * Controls whether clockwise, counterclockwise, or both faces are drawn.
736 * @param face the face(s) to draw.
737 */
738 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000739 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000740 fDrawFace = face;
741 }
742
743 /**
744 * Gets whether the target is drawing clockwise, counterclockwise,
745 * or both faces.
746 * @return the current draw face(s).
747 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000748 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000749
750 /// @}
751
752 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000753
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000754 bool isStageEnabled(int s) const {
755 GrAssert((unsigned)s < kNumStages);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000756 return (NULL != fSamplerStates[s].getCustomStage());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000757 }
758
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000759 // Most stages are usually not used, so conditionals here
760 // reduce the expected number of bytes touched by 50%.
761 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000762 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000763 return false;
764 }
765
766 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
767 return false;
768 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000769
770 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000771 bool enabled = this->isStageEnabled(i);
772 if (enabled != s.isStageEnabled(i)) {
773 return false;
774 }
775 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000776 return false;
777 }
778 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000779 if (kColorMatrix_StateBit & s.fFlagBits) {
780 if (memcmp(fColorMatrix,
781 s.fColorMatrix,
782 sizeof(fColorMatrix))) {
783 return false;
784 }
785 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000786
787 return true;
788 }
789 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
790
791 // Most stages are usually not used, so conditionals here
792 // reduce the expected number of bytes touched by 50%.
793 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000794 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000795
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000796 fViewMatrix = s.fViewMatrix;
797
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000798 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000799 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000800 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000801 }
802 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000803
804 SkSafeRef(fRenderTarget); // already copied by memcpy
805
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000806 if (kColorMatrix_StateBit & s.fFlagBits) {
807 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
808 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000809
810 return *this;
811 }
812
813private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000814
815 const void* podStart() const {
816 return reinterpret_cast<const void*>(&fPodStartMarker);
817 }
818 void* podStart() {
819 return reinterpret_cast<void*>(&fPodStartMarker);
820 }
821 size_t memsetSize() const {
822 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
823 reinterpret_cast<size_t>(&fPodStartMarker) +
824 sizeof(fMemsetEndMarker);
825 }
826 size_t podSize() const {
827 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000828 return reinterpret_cast<size_t>(&fPodEndMarker) -
829 reinterpret_cast<size_t>(&fPodStartMarker) +
830 sizeof(fPodEndMarker);
831 }
832
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000833 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000834 union {
835 GrColor fBlendConstant;
836 GrColor fPodStartMarker;
837 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000838 GrColor fColorFilterColor;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000839 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000840 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000841 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000842 union {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000843 uint32_t fFlagBits;
844 uint32_t fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000845 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000846 // @}
847
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000848 // @{ Initialized to values other than zero, but memcmp'ed in operator==
849 // and memcpy'ed in operator=.
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000850 GrRenderTarget* fRenderTarget;
851
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000852 int fFirstCoverageStage;
853
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000854 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000855 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000856 SkXfermode::Mode fColorFilterMode;
857 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000858 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000859 GrBlendCoeff fDstBlend;
860 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000861 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000862 // @}
863
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000864 GrMatrix fViewMatrix;
865
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000866 // This field must be last; it will not be copied or compared
867 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000868 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000869 // only compared if the color matrix enable flag is set
870 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000871
reed@google.comfa35e3d2012-06-26 20:16:17 +0000872 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000873};
874
875#endif