blob: 3de33d82a78ac571930339de2a4090f50dfc0c09 [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.com93813632011-10-27 20:21:16 +000019
20#include "SkXfermode.h"
21
tomhudson@google.com93813632011-10-27 20:21:16 +000022
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000023class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000024public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000025 SK_DECLARE_INST_COUNT(GrDrawState)
26
tomhudson@google.com93813632011-10-27 20:21:16 +000027 /**
28 * Number of texture stages. Each stage takes as input a color and
29 * 2D texture coordinates. The color input to the first enabled stage is the
30 * per-vertex color or the constant color (setColor/setAlpha) if there are
31 * no per-vertex colors. For subsequent stages the input color is the output
32 * color from the previous enabled stage. The output color of each stage is
33 * the input color modulated with the result of a texture lookup. Texture
34 * lookups are specified by a texture a sampler (setSamplerState). Texture
35 * coordinates for each stage come from the vertices based on a
36 * GrVertexLayout bitfield. The output fragment color is the output color of
37 * the last enabled stage. The presence or absence of texture coordinates
38 * for each stage in the vertex layout indicates whether a stage is enabled
39 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000040 *
41 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
42 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
43 * through kNumStages-1 are earmarked for use by GrTextContext and
44 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000045 */
46 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000047 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000048 kMaxTexCoords = kNumStages
49 };
50
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000051 /**
52 * Bitfield used to indicate a set of stages.
53 */
54 typedef uint32_t StageMask;
55 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
56
robertphillips@google.com9ec07532012-06-22 12:01:30 +000057 GrDrawState()
58 : fRenderTarget(NULL) {
59
60 for (int i = 0; i < kNumStages; ++i) {
61 fTextures[i] = NULL;
62 }
63
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000064 this->reset();
65 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000066
robertphillips@google.com9ec07532012-06-22 12:01:30 +000067 GrDrawState(const GrDrawState& state)
68 : fRenderTarget(NULL) {
69
70 for (int i = 0; i < kNumStages; ++i) {
71 fTextures[i] = NULL;
72 }
73
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000074 *this = state;
75 }
76
robertphillips@google.com9ec07532012-06-22 12:01:30 +000077 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000078 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000079 GrSafeSetNull(fRenderTarget);
80 }
81
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000082 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000083 * Resets to the default state.
84 * Sampler states *will* be modified: textures or CustomStage objects
85 * will be released.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000086 */
87 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000088
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000089 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000090 GrSafeSetNull(fRenderTarget);
91
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000092 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000093 // all GrDrawState members should default to something valid by the
94 // the memset except those initialized individually below. There should
95 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000096 memset(this->podStart(), 0, this->memsetSize());
97
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000098 // pedantic assertion that our ptrs will
99 // be NULL (0 ptr is mem addr 0)
100 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000101 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000102 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000103
104 // memset exceptions
105 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000106 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000107 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000108 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +0000109 fSrcBlend = kOne_GrBlendCoeff;
110 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000111 fViewMatrix.reset();
112
113 // ensure values that will be memcmp'ed in == but not memset in reset()
114 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000115 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000116 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000117 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fTextures) +
118 sizeof(fRenderTarget) == this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000119 }
120
121 ///////////////////////////////////////////////////////////////////////////
122 /// @name Color
123 ////
124
125 /**
126 * Sets color for next draw to a premultiplied-alpha color.
127 *
128 * @param color the color to set.
129 */
130 void setColor(GrColor color) { fColor = color; }
131
132 GrColor getColor() const { return fColor; }
133
134 /**
135 * Sets the color to be used for the next draw to be
136 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
137 *
138 * @param alpha The alpha value to set as the color.
139 */
140 void setAlpha(uint8_t a) {
141 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
142 }
143
144 /**
145 * Add a color filter that can be represented by a color and a mode. Applied
146 * after color-computing texture stages.
147 */
148 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
149 fColorFilterColor = c;
150 fColorFilterMode = mode;
151 }
152
153 GrColor getColorFilterColor() const { return fColorFilterColor; }
154 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
155
156 /// @}
157
158 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000159 /// @name Coverage
160 ////
161
162 /**
163 * Sets a constant fractional coverage to be applied to the draw. The
164 * initial value (after construction or reset()) is 0xff. The constant
165 * coverage is ignored when per-vertex coverage is provided.
166 */
167 void setCoverage(uint8_t coverage) {
168 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
169 }
170
171 /**
172 * Version of above that specifies 4 channel per-vertex color. The value
173 * should be premultiplied.
174 */
175 void setCoverage4(GrColor coverage) {
176 fCoverage = coverage;
177 }
178
179 GrColor getCoverage() const {
180 return fCoverage;
181 }
182
183 /// @}
184
185 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000186 /// @name Textures
187 ////
188
189 /**
190 * Sets the texture used at the next drawing call
191 *
192 * @param stage The texture stage for which the texture will be set
193 *
194 * @param texture The texture to set. Can be NULL though there is no
195 * advantage to settings a NULL texture if doing non-textured drawing
196 */
197 void setTexture(int stage, GrTexture* texture) {
198 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000199
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000200 GrSafeAssign(fTextures[stage], texture);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000201 }
202
203 /**
204 * Retrieves the currently set texture.
205 *
206 * @return The currently set texture. The return value will be NULL if no
207 * texture has been set, NULL was most recently passed to
208 * setTexture, or the last setTexture was destroyed.
209 */
210 const GrTexture* getTexture(int stage) const {
211 GrAssert((unsigned)stage < kNumStages);
tomhudson@google.come742bf02012-07-13 19:54:19 +0000212 GrAssert(!this->getSampler(stage).getCustomStage() ||
213 !fTextures[stage] ||
214 fTextures[stage] == this->getSampler(stage).getCustomStage()->texture(0));
215 if (this->getSampler(stage).getCustomStage()) {
216 return this->getSampler(stage).getCustomStage()->texture(0);
217 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000218 return fTextures[stage];
219 }
220 GrTexture* getTexture(int stage) {
221 GrAssert((unsigned)stage < kNumStages);
tomhudson@google.come742bf02012-07-13 19:54:19 +0000222 GrAssert(!this->getSampler(stage).getCustomStage() ||
223 !fTextures[stage] ||
224 fTextures[stage] == this->getSampler(stage).getCustomStage()->texture(0));
225 if (this->getSampler(stage).getCustomStage()) {
226 return this->getSampler(stage).getCustomStage()->texture(0);
227 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000228 return fTextures[stage];
229 }
230
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000231 bool stagesDisabled() {
232 for (int i = 0; i < kNumStages; ++i) {
233 if (NULL != fTextures[i] ||
234 NULL != fSamplerStates[i].getCustomStage()) {
235 return false;
236 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000237 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000238 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000239 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000240
241 void disableStage(int index) {
242 GrSafeSetNull(fTextures[index]);
243 fSamplerStates[index].setCustomStage(NULL);
244 }
245
robertphillips@google.com972265d2012-06-13 18:49:30 +0000246 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000247 * Release all the textures and custom stages referred to by this
248 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000249 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000250 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000251 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000252 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000253 }
254 }
255
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000256 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000257 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000258 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
259 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000260 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000261 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000262 }
263 }
264 private:
265 GrDrawState* fDrawState;
266 };
267
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000268 /// @}
269
270 ///////////////////////////////////////////////////////////////////////////
271 /// @name Samplers
272 ////
273
274 /**
275 * Returns the current sampler for a stage.
276 */
277 const GrSamplerState& getSampler(int stage) const {
278 GrAssert((unsigned)stage < kNumStages);
279 return fSamplerStates[stage];
280 }
281
282 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000283 * Writable pointer to a stage's sampler.
284 */
285 GrSamplerState* sampler(int stage) {
286 GrAssert((unsigned)stage < kNumStages);
287 return fSamplerStates + stage;
288 }
289
290 /**
291 * Preconcats the matrix of all samplers in the mask with the same matrix.
292 */
293 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
294 GrAssert(!(stageMask & kIllegalStageMaskBits));
295 for (int i = 0; i < kNumStages; ++i) {
296 if ((1 << i) & stageMask) {
297 fSamplerStates[i].preConcatMatrix(matrix);
298 }
299 }
300 }
301
302 /// @}
303
304 ///////////////////////////////////////////////////////////////////////////
305 /// @name Coverage / Color Stages
306 ////
307
308 /**
309 * A common pattern is to compute a color with the initial stages and then
310 * modulate that color by a coverage value in later stage(s) (AA, mask-
311 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
312 * computed based on the pre-coverage-modulated color. The division of
313 * stages between color-computing and coverage-computing is specified by
314 * this method. Initially this is kNumStages (all stages
315 * are color-computing).
316 */
317 void setFirstCoverageStage(int firstCoverageStage) {
318 GrAssert((unsigned)firstCoverageStage <= kNumStages);
319 fFirstCoverageStage = firstCoverageStage;
320 }
321
322 /**
323 * Gets the index of the first coverage-computing stage.
324 */
325 int getFirstCoverageStage() const {
326 return fFirstCoverageStage;
327 }
328
329 ///@}
330
331 ///////////////////////////////////////////////////////////////////////////
332 /// @name Blending
333 ////
334
335 /**
336 * Sets the blending function coeffecients.
337 *
338 * The blend function will be:
339 * D' = sat(S*srcCoef + D*dstCoef)
340 *
341 * where D is the existing destination color, S is the incoming source
342 * color, and D' is the new destination color that will be written. sat()
343 * is the saturation function.
344 *
345 * @param srcCoef coeffecient applied to the src color.
346 * @param dstCoef coeffecient applied to the dst color.
347 */
348 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
349 fSrcBlend = srcCoeff;
350 fDstBlend = dstCoeff;
351 #if GR_DEBUG
352 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000353 case kDC_GrBlendCoeff:
354 case kIDC_GrBlendCoeff:
355 case kDA_GrBlendCoeff:
356 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000357 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
358 "coverage stages.\n");
359 break;
360 default:
361 break;
362 }
363 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000364 case kSC_GrBlendCoeff:
365 case kISC_GrBlendCoeff:
366 case kSA_GrBlendCoeff:
367 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000368 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
369 "coverage stages.\n");
370 break;
371 default:
372 break;
373 }
374 #endif
375 }
376
377 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
378 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
379
380 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
381 GrBlendCoeff* dstBlendCoeff) const {
382 *srcBlendCoeff = fSrcBlend;
383 *dstBlendCoeff = fDstBlend;
384 }
385
386 /**
387 * Sets the blending function constant referenced by the following blending
388 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000389 * kConstC_GrBlendCoeff
390 * kIConstC_GrBlendCoeff
391 * kConstA_GrBlendCoeff
392 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000393 *
394 * @param constant the constant to set
395 */
396 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
397
398 /**
399 * Retrieves the last value set by setBlendConstant()
400 * @return the blending constant value
401 */
402 GrColor getBlendConstant() const { return fBlendConstant; }
403
404 /// @}
405
406 ///////////////////////////////////////////////////////////////////////////
407 /// @name View Matrix
408 ////
409
410 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000411 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000412 *
413 * In the post-view-matrix space the rectangle [0,w]x[0,h]
414 * fully covers the render target. (w and h are the width and height of the
415 * the rendertarget.)
416 */
417 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
418
419 /**
420 * Gets a writable pointer to the view matrix.
421 */
422 GrMatrix* viewMatrix() { return &fViewMatrix; }
423
424 /**
425 * Multiplies the current view matrix by a matrix
426 *
427 * After this call V' = V*m where V is the old view matrix,
428 * m is the parameter to this function, and V' is the new view matrix.
429 * (We consider positions to be column vectors so position vector p is
430 * transformed by matrix X as p' = X*p.)
431 *
432 * @param m the matrix used to modify the view matrix.
433 */
434 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
435
436 /**
437 * Multiplies the current view matrix by a matrix
438 *
439 * After this call V' = m*V where V is the old view matrix,
440 * m is the parameter to this function, and V' is the new view matrix.
441 * (We consider positions to be column vectors so position vector p is
442 * transformed by matrix X as p' = X*p.)
443 *
444 * @param m the matrix used to modify the view matrix.
445 */
446 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
447
448 /**
449 * Retrieves the current view matrix
450 * @return the current view matrix.
451 */
452 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
453
454 /**
455 * Retrieves the inverse of the current view matrix.
456 *
457 * If the current view matrix is invertible, return true, and if matrix
458 * is non-null, copy the inverse into it. If the current view matrix is
459 * non-invertible, return false and ignore the matrix parameter.
460 *
461 * @param matrix if not null, will receive a copy of the current inverse.
462 */
463 bool getViewInverse(GrMatrix* matrix) const {
464 // TODO: determine whether we really need to leave matrix unmodified
465 // at call sites when inversion fails.
466 GrMatrix inverse;
467 if (fViewMatrix.invert(&inverse)) {
468 if (matrix) {
469 *matrix = inverse;
470 }
471 return true;
472 }
473 return false;
474 }
475
476 class AutoViewMatrixRestore : public ::GrNoncopyable {
477 public:
478 AutoViewMatrixRestore() : fDrawState(NULL) {}
479 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
480 fDrawState = NULL;
481 this->set(ds, newMatrix);
482 }
483 AutoViewMatrixRestore(GrDrawState* ds) {
484 fDrawState = NULL;
485 this->set(ds);
486 }
487 ~AutoViewMatrixRestore() {
488 this->set(NULL, GrMatrix::I());
489 }
490 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
491 if (NULL != fDrawState) {
492 fDrawState->setViewMatrix(fSavedMatrix);
493 }
494 if (NULL != ds) {
495 fSavedMatrix = ds->getViewMatrix();
496 ds->setViewMatrix(newMatrix);
497 }
498 fDrawState = ds;
499 }
500 void set(GrDrawState* ds) {
501 if (NULL != fDrawState) {
502 fDrawState->setViewMatrix(fSavedMatrix);
503 }
504 if (NULL != ds) {
505 fSavedMatrix = ds->getViewMatrix();
506 }
507 fDrawState = ds;
508 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000509 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000510 private:
511 GrDrawState* fDrawState;
512 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000513 };
514
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000515 /// @}
516
517 ///////////////////////////////////////////////////////////////////////////
518 /// @name Render Target
519 ////
520
521 /**
522 * Sets the rendertarget used at the next drawing call
523 *
524 * @param target The render target to set.
525 */
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000526 void setRenderTarget(GrRenderTarget* target) {
527 GrSafeAssign(fRenderTarget, target);
528 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529
530 /**
531 * Retrieves the currently set rendertarget.
532 *
533 * @return The currently set render target.
534 */
535 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
536 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
537
538 class AutoRenderTargetRestore : public ::GrNoncopyable {
539 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000540 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000541 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
542 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000543 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000544 this->set(ds, newTarget);
545 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000546 ~AutoRenderTargetRestore() { this->restore(); }
547
548 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000549 if (NULL != fDrawState) {
550 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000551 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000552 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000553 GrSafeSetNull(fSavedTarget);
554 }
555
556 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
557 this->restore();
558
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000559 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000560 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000561 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000562 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000563 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000564 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000565 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000566 }
567 private:
568 GrDrawState* fDrawState;
569 GrRenderTarget* fSavedTarget;
570 };
571
572 /// @}
573
574 ///////////////////////////////////////////////////////////////////////////
575 /// @name Stencil
576 ////
577
578 /**
579 * Sets the stencil settings to use for the next draw.
580 * Changing the clip has the side-effect of possibly zeroing
581 * out the client settable stencil bits. So multipass algorithms
582 * using stencil should not change the clip between passes.
583 * @param settings the stencil settings to use.
584 */
585 void setStencil(const GrStencilSettings& settings) {
586 fStencilSettings = settings;
587 }
588
589 /**
590 * Shortcut to disable stencil testing and ops.
591 */
592 void disableStencil() {
593 fStencilSettings.setDisabled();
594 }
595
596 const GrStencilSettings& getStencil() const { return fStencilSettings; }
597
598 GrStencilSettings* stencil() { return &fStencilSettings; }
599
600 /// @}
601
602 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000603 /// @name Color Matrix
604 ////
605
606 /**
607 * Sets the color matrix to use for the next draw.
608 * @param matrix the 5x4 matrix to apply to the incoming color
609 */
610 void setColorMatrix(const float matrix[20]) {
611 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
612 }
613
614 const float* getColorMatrix() const { return fColorMatrix; }
615
616 /// @}
617
618 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000620 // Edge equations can be specified to perform antialiasing. Because the
621 // edges are specified as per-vertex data, vertices that are shared by
622 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000623 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000624 ////
625
626 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000627 * When specifying edges as vertex data this enum specifies what type of
628 * edges are in use. The edges are always 4 GrScalars in memory, even when
629 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000630 *
631 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
632 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000633 */
634 enum VertexEdgeType {
635 /* 1-pixel wide line
636 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
637 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000638 /* Quadratic specified by u^2-v canonical coords (only 2
639 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000640 being inside, positive outside. Edge specified in window space
641 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000642 kQuad_EdgeType,
643 /* Same as above but for hairline quadratics. Uses unsigned distance.
644 Coverage is min(0, 1-distance). */
645 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000646 /* Circle specified as center_x, center_y, outer_radius, inner_radius
647 all in window space (y-down). */
648 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000649
650 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000651 };
652
653 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 * Determines the interpretation per-vertex edge data when the
655 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
656 * are not specified the value of this setting has no effect.
657 */
658 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000659 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000660 fVertexEdgeType = type;
661 }
662
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000663 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000664
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000665 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000666
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000667 ///////////////////////////////////////////////////////////////////////////
668 /// @name State Flags
669 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000670
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000671 /**
672 * Flags that affect rendering. Controlled using enable/disableState(). All
673 * default to disabled.
674 */
675 enum StateBits {
676 /**
677 * Perform dithering. TODO: Re-evaluate whether we need this bit
678 */
679 kDither_StateBit = 0x01,
680 /**
681 * Perform HW anti-aliasing. This means either HW FSAA, if supported
682 * by the render target, or smooth-line rendering if a line primitive
683 * is drawn and line smoothing is supported by the 3D API.
684 */
685 kHWAntialias_StateBit = 0x02,
686 /**
687 * Draws will respect the clip, otherwise the clip is ignored.
688 */
689 kClip_StateBit = 0x04,
690 /**
691 * Disables writing to the color buffer. Useful when performing stencil
692 * operations.
693 */
694 kNoColorWrites_StateBit = 0x08,
695 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000696 * Draws will apply the color matrix, otherwise the color matrix is
697 * ignored.
698 */
699 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000700
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000701 // Users of the class may add additional bits to the vector
702 kDummyStateBit,
703 kLastPublicStateBit = kDummyStateBit-1,
704 };
705
706 void resetStateFlags() {
707 fFlagBits = 0;
708 }
709
710 /**
711 * Enable render state settings.
712 *
713 * @param flags bitfield of StateBits specifing the states to enable
714 */
715 void enableState(uint32_t stateBits) {
716 fFlagBits |= stateBits;
717 }
718
719 /**
720 * Disable render state settings.
721 *
722 * @param flags bitfield of StateBits specifing the states to disable
723 */
724 void disableState(uint32_t stateBits) {
725 fFlagBits &= ~(stateBits);
726 }
727
728 bool isDitherState() const {
729 return 0 != (fFlagBits & kDither_StateBit);
730 }
731
732 bool isHWAntialiasState() const {
733 return 0 != (fFlagBits & kHWAntialias_StateBit);
734 }
735
736 bool isClipState() const {
737 return 0 != (fFlagBits & kClip_StateBit);
738 }
739
740 bool isColorWriteDisabled() const {
741 return 0 != (fFlagBits & kNoColorWrites_StateBit);
742 }
743
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000744 bool isStateFlagEnabled(uint32_t stateBit) const {
745 return 0 != (stateBit & fFlagBits);
746 }
747
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000748 /// @}
749
750 ///////////////////////////////////////////////////////////////////////////
751 /// @name Face Culling
752 ////
753
754 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000755 kInvalid_DrawFace = -1,
756
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000757 kBoth_DrawFace,
758 kCCW_DrawFace,
759 kCW_DrawFace,
760 };
761
762 /**
763 * Controls whether clockwise, counterclockwise, or both faces are drawn.
764 * @param face the face(s) to draw.
765 */
766 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000767 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000768 fDrawFace = face;
769 }
770
771 /**
772 * Gets whether the target is drawing clockwise, counterclockwise,
773 * or both faces.
774 * @return the current draw face(s).
775 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000776 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000777
778 /// @}
779
780 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000781
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000782 bool isStageEnabled(int s) const {
783 GrAssert((unsigned)s < kNumStages);
784 return (NULL != fTextures[s]) ||
785 (NULL != fSamplerStates[s].getCustomStage());
786 }
787
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000788 // Most stages are usually not used, so conditionals here
789 // reduce the expected number of bytes touched by 50%.
790 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000791 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000792 return false;
793 }
794
795 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
796 return false;
797 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000798
799 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000800 if (this->isStageEnabled(i) &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000801 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000802 return false;
803 }
804 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000805 if (kColorMatrix_StateBit & s.fFlagBits) {
806 if (memcmp(fColorMatrix,
807 s.fColorMatrix,
808 sizeof(fColorMatrix))) {
809 return false;
810 }
811 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000812
813 return true;
814 }
815 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
816
817 // Most stages are usually not used, so conditionals here
818 // reduce the expected number of bytes touched by 50%.
819 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000820 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000821
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000822 fViewMatrix = s.fViewMatrix;
823
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000824 for (int i = 0; i < kNumStages; i++) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000825 SkSafeRef(fTextures[i]); // already copied by memcpy
tomhudson@google.come742bf02012-07-13 19:54:19 +0000826 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000827 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000828 }
829 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000830
831 SkSafeRef(fRenderTarget); // already copied by memcpy
832
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000833 if (kColorMatrix_StateBit & s.fFlagBits) {
834 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
835 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000836
837 return *this;
838 }
839
840private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000841
842 const void* podStart() const {
843 return reinterpret_cast<const void*>(&fPodStartMarker);
844 }
845 void* podStart() {
846 return reinterpret_cast<void*>(&fPodStartMarker);
847 }
848 size_t memsetSize() const {
849 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
850 reinterpret_cast<size_t>(&fPodStartMarker) +
851 sizeof(fMemsetEndMarker);
852 }
853 size_t podSize() const {
854 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000855 return reinterpret_cast<size_t>(&fPodEndMarker) -
856 reinterpret_cast<size_t>(&fPodStartMarker) +
857 sizeof(fPodEndMarker);
858 }
859
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000860 static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000861 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000862 union {
863 GrColor fBlendConstant;
864 GrColor fPodStartMarker;
865 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000866 GrColor fColorFilterColor;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000867 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000868 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000869 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000870 union {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000871 uint32_t fFlagBits;
872 uint32_t fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000873 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000874 // @}
875
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000876 // @{ Initialized to values other than zero, but memcmp'ed in operator==
877 // and memcpy'ed in operator=.
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000878 GrTexture* fTextures[kNumStages];
879 GrRenderTarget* fRenderTarget;
880
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000881 int fFirstCoverageStage;
882
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000883 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000884 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000885 SkXfermode::Mode fColorFilterMode;
886 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000887 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000888 GrBlendCoeff fDstBlend;
889 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000890 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000891 // @}
892
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000893 GrMatrix fViewMatrix;
894
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000895 // This field must be last; it will not be copied or compared
896 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000897 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000898 // only compared if the color matrix enable flag is set
899 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000900
reed@google.comfa35e3d2012-06-26 20:16:17 +0000901 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000902};
903
904#endif