blob: df70bb25e7e56ac0655930ec730046deab2b352b [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 {
twiz@google.com58071162012-07-18 21:41:50 +000047 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000048 kMaxTexCoords = kNumStages
49 };
50
robertphillips@google.com9ec07532012-06-22 12:01:30 +000051 GrDrawState()
52 : fRenderTarget(NULL) {
53
54 for (int i = 0; i < kNumStages; ++i) {
55 fTextures[i] = NULL;
56 }
57
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000058 this->reset();
59 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000060
robertphillips@google.com9ec07532012-06-22 12:01:30 +000061 GrDrawState(const GrDrawState& state)
62 : fRenderTarget(NULL) {
63
64 for (int i = 0; i < kNumStages; ++i) {
65 fTextures[i] = NULL;
66 }
67
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000068 *this = state;
69 }
70
robertphillips@google.com9ec07532012-06-22 12:01:30 +000071 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000072 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000073 GrSafeSetNull(fRenderTarget);
74 }
75
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000076 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000077 * Resets to the default state.
78 * Sampler states *will* be modified: textures or CustomStage objects
79 * will be released.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000080 */
81 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000082
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000083 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000084 GrSafeSetNull(fRenderTarget);
85
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000086 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000087 // all GrDrawState members should default to something valid by the
88 // the memset except those initialized individually below. There should
89 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000090 memset(this->podStart(), 0, this->memsetSize());
91
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000092 // pedantic assertion that our ptrs will
93 // be NULL (0 ptr is mem addr 0)
94 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000095 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000096 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000097
98 // memset exceptions
99 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000100 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000101 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000102 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +0000103 fSrcBlend = kOne_GrBlendCoeff;
104 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000105 fViewMatrix.reset();
106
107 // ensure values that will be memcmp'ed in == but not memset in reset()
108 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000109 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000110 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000111 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fTextures) +
112 sizeof(fRenderTarget) == this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000113 }
114
115 ///////////////////////////////////////////////////////////////////////////
116 /// @name Color
117 ////
118
119 /**
120 * Sets color for next draw to a premultiplied-alpha color.
121 *
122 * @param color the color to set.
123 */
124 void setColor(GrColor color) { fColor = color; }
125
126 GrColor getColor() const { return fColor; }
127
128 /**
129 * Sets the color to be used for the next draw to be
130 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
131 *
132 * @param alpha The alpha value to set as the color.
133 */
134 void setAlpha(uint8_t a) {
135 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
136 }
137
138 /**
139 * Add a color filter that can be represented by a color and a mode. Applied
140 * after color-computing texture stages.
141 */
142 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
143 fColorFilterColor = c;
144 fColorFilterMode = mode;
145 }
146
147 GrColor getColorFilterColor() const { return fColorFilterColor; }
148 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
149
150 /// @}
151
152 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000153 /// @name Coverage
154 ////
155
156 /**
157 * Sets a constant fractional coverage to be applied to the draw. The
158 * initial value (after construction or reset()) is 0xff. The constant
159 * coverage is ignored when per-vertex coverage is provided.
160 */
161 void setCoverage(uint8_t coverage) {
162 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
163 }
164
165 /**
166 * Version of above that specifies 4 channel per-vertex color. The value
167 * should be premultiplied.
168 */
169 void setCoverage4(GrColor coverage) {
170 fCoverage = coverage;
171 }
172
173 GrColor getCoverage() const {
174 return fCoverage;
175 }
176
177 /// @}
178
179 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000180 /// @name Textures
181 ////
182
183 /**
184 * Sets the texture used at the next drawing call
185 *
186 * @param stage The texture stage for which the texture will be set
187 *
188 * @param texture The texture to set. Can be NULL though there is no
189 * advantage to settings a NULL texture if doing non-textured drawing
190 */
191 void setTexture(int stage, GrTexture* texture) {
192 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000193
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000194 GrSafeAssign(fTextures[stage], texture);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000195 }
196
197 /**
198 * Retrieves the currently set texture.
199 *
200 * @return The currently set texture. The return value will be NULL if no
201 * texture has been set, NULL was most recently passed to
202 * setTexture, or the last setTexture was destroyed.
203 */
204 const GrTexture* getTexture(int stage) const {
205 GrAssert((unsigned)stage < kNumStages);
tomhudson@google.come742bf02012-07-13 19:54:19 +0000206 GrAssert(!this->getSampler(stage).getCustomStage() ||
207 !fTextures[stage] ||
208 fTextures[stage] == this->getSampler(stage).getCustomStage()->texture(0));
209 if (this->getSampler(stage).getCustomStage()) {
210 return this->getSampler(stage).getCustomStage()->texture(0);
211 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000212 return fTextures[stage];
213 }
214 GrTexture* getTexture(int stage) {
215 GrAssert((unsigned)stage < kNumStages);
tomhudson@google.come742bf02012-07-13 19:54:19 +0000216 GrAssert(!this->getSampler(stage).getCustomStage() ||
217 !fTextures[stage] ||
218 fTextures[stage] == this->getSampler(stage).getCustomStage()->texture(0));
219 if (this->getSampler(stage).getCustomStage()) {
220 return this->getSampler(stage).getCustomStage()->texture(0);
221 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000222 return fTextures[stage];
223 }
224
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000225 bool stagesDisabled() {
226 for (int i = 0; i < kNumStages; ++i) {
227 if (NULL != fTextures[i] ||
228 NULL != fSamplerStates[i].getCustomStage()) {
229 return false;
230 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000231 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000232 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000233 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000234
235 void disableStage(int index) {
236 GrSafeSetNull(fTextures[index]);
237 fSamplerStates[index].setCustomStage(NULL);
238 }
239
robertphillips@google.com972265d2012-06-13 18:49:30 +0000240 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000241 * Release all the textures and custom stages referred to by this
242 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000243 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000244 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000245 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000246 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000247 }
248 }
249
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000250 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000251 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000252 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
253 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000254 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000255 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000256 }
257 }
258 private:
259 GrDrawState* fDrawState;
260 };
261
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000262 /// @}
263
264 ///////////////////////////////////////////////////////////////////////////
265 /// @name Samplers
266 ////
267
268 /**
269 * Returns the current sampler for a stage.
270 */
271 const GrSamplerState& getSampler(int stage) const {
272 GrAssert((unsigned)stage < kNumStages);
273 return fSamplerStates[stage];
274 }
275
276 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000277 * Writable pointer to a stage's sampler.
278 */
279 GrSamplerState* sampler(int stage) {
280 GrAssert((unsigned)stage < kNumStages);
281 return fSamplerStates + stage;
282 }
283
284 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000285 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000286 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000287 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000288 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000289 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000290 fSamplerStates[i].preConcatMatrix(matrix);
291 }
292 }
293 }
294
bsalomon@google.come3d32162012-07-20 13:37:06 +0000295 /**
296 * Preconcats the matrix of all samplers in the mask with the inverse of a
297 * matrix. If the matrix inverse cannot be computed (and there is at least
298 * one enabled stage) then false is returned.
299 */
300 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
301 GrMatrix inv;
302 bool computed = false;
303 for (int i = 0; i < kNumStages; ++i) {
304 if (this->isStageEnabled(i)) {
305 if (!computed && !matrix.invert(&inv)) {
306 return false;
307 } else {
308 computed = true;
309 }
310 fSamplerStates[i].preConcatMatrix(inv);
311 }
312 }
313 return true;
314 }
315
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000316 /// @}
317
318 ///////////////////////////////////////////////////////////////////////////
319 /// @name Coverage / Color Stages
320 ////
321
322 /**
323 * A common pattern is to compute a color with the initial stages and then
324 * modulate that color by a coverage value in later stage(s) (AA, mask-
325 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
326 * computed based on the pre-coverage-modulated color. The division of
327 * stages between color-computing and coverage-computing is specified by
328 * this method. Initially this is kNumStages (all stages
329 * are color-computing).
330 */
331 void setFirstCoverageStage(int firstCoverageStage) {
332 GrAssert((unsigned)firstCoverageStage <= kNumStages);
333 fFirstCoverageStage = firstCoverageStage;
334 }
335
336 /**
337 * Gets the index of the first coverage-computing stage.
338 */
339 int getFirstCoverageStage() const {
340 return fFirstCoverageStage;
341 }
342
343 ///@}
344
345 ///////////////////////////////////////////////////////////////////////////
346 /// @name Blending
347 ////
348
349 /**
350 * Sets the blending function coeffecients.
351 *
352 * The blend function will be:
353 * D' = sat(S*srcCoef + D*dstCoef)
354 *
355 * where D is the existing destination color, S is the incoming source
356 * color, and D' is the new destination color that will be written. sat()
357 * is the saturation function.
358 *
359 * @param srcCoef coeffecient applied to the src color.
360 * @param dstCoef coeffecient applied to the dst color.
361 */
362 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
363 fSrcBlend = srcCoeff;
364 fDstBlend = dstCoeff;
365 #if GR_DEBUG
366 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000367 case kDC_GrBlendCoeff:
368 case kIDC_GrBlendCoeff:
369 case kDA_GrBlendCoeff:
370 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000371 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
372 "coverage stages.\n");
373 break;
374 default:
375 break;
376 }
377 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000378 case kSC_GrBlendCoeff:
379 case kISC_GrBlendCoeff:
380 case kSA_GrBlendCoeff:
381 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000382 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
383 "coverage stages.\n");
384 break;
385 default:
386 break;
387 }
388 #endif
389 }
390
391 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
392 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
393
394 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
395 GrBlendCoeff* dstBlendCoeff) const {
396 *srcBlendCoeff = fSrcBlend;
397 *dstBlendCoeff = fDstBlend;
398 }
399
400 /**
401 * Sets the blending function constant referenced by the following blending
402 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000403 * kConstC_GrBlendCoeff
404 * kIConstC_GrBlendCoeff
405 * kConstA_GrBlendCoeff
406 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000407 *
408 * @param constant the constant to set
409 */
410 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
411
412 /**
413 * Retrieves the last value set by setBlendConstant()
414 * @return the blending constant value
415 */
416 GrColor getBlendConstant() const { return fBlendConstant; }
417
418 /// @}
419
420 ///////////////////////////////////////////////////////////////////////////
421 /// @name View Matrix
422 ////
423
424 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000425 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000426 *
427 * In the post-view-matrix space the rectangle [0,w]x[0,h]
428 * fully covers the render target. (w and h are the width and height of the
429 * the rendertarget.)
430 */
431 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
432
433 /**
434 * Gets a writable pointer to the view matrix.
435 */
436 GrMatrix* viewMatrix() { return &fViewMatrix; }
437
438 /**
439 * Multiplies the current view matrix by a matrix
440 *
441 * After this call V' = V*m where V is the old view matrix,
442 * m is the parameter to this function, and V' is the new view matrix.
443 * (We consider positions to be column vectors so position vector p is
444 * transformed by matrix X as p' = X*p.)
445 *
446 * @param m the matrix used to modify the view matrix.
447 */
448 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
449
450 /**
451 * Multiplies the current view matrix by a matrix
452 *
453 * After this call V' = m*V where V is the old view matrix,
454 * m is the parameter to this function, and V' is the new view matrix.
455 * (We consider positions to be column vectors so position vector p is
456 * transformed by matrix X as p' = X*p.)
457 *
458 * @param m the matrix used to modify the view matrix.
459 */
460 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
461
462 /**
463 * Retrieves the current view matrix
464 * @return the current view matrix.
465 */
466 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
467
468 /**
469 * Retrieves the inverse of the current view matrix.
470 *
471 * If the current view matrix is invertible, return true, and if matrix
472 * is non-null, copy the inverse into it. If the current view matrix is
473 * non-invertible, return false and ignore the matrix parameter.
474 *
475 * @param matrix if not null, will receive a copy of the current inverse.
476 */
477 bool getViewInverse(GrMatrix* matrix) const {
478 // TODO: determine whether we really need to leave matrix unmodified
479 // at call sites when inversion fails.
480 GrMatrix inverse;
481 if (fViewMatrix.invert(&inverse)) {
482 if (matrix) {
483 *matrix = inverse;
484 }
485 return true;
486 }
487 return false;
488 }
489
490 class AutoViewMatrixRestore : public ::GrNoncopyable {
491 public:
492 AutoViewMatrixRestore() : fDrawState(NULL) {}
493 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
494 fDrawState = NULL;
495 this->set(ds, newMatrix);
496 }
497 AutoViewMatrixRestore(GrDrawState* ds) {
498 fDrawState = NULL;
499 this->set(ds);
500 }
501 ~AutoViewMatrixRestore() {
502 this->set(NULL, GrMatrix::I());
503 }
504 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
505 if (NULL != fDrawState) {
506 fDrawState->setViewMatrix(fSavedMatrix);
507 }
508 if (NULL != ds) {
509 fSavedMatrix = ds->getViewMatrix();
510 ds->setViewMatrix(newMatrix);
511 }
512 fDrawState = ds;
513 }
514 void set(GrDrawState* ds) {
515 if (NULL != fDrawState) {
516 fDrawState->setViewMatrix(fSavedMatrix);
517 }
518 if (NULL != ds) {
519 fSavedMatrix = ds->getViewMatrix();
520 }
521 fDrawState = ds;
522 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000523 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000524 private:
525 GrDrawState* fDrawState;
526 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000527 };
528
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 /// @}
530
531 ///////////////////////////////////////////////////////////////////////////
532 /// @name Render Target
533 ////
534
535 /**
536 * Sets the rendertarget used at the next drawing call
537 *
538 * @param target The render target to set.
539 */
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000540 void setRenderTarget(GrRenderTarget* target) {
541 GrSafeAssign(fRenderTarget, target);
542 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000543
544 /**
545 * Retrieves the currently set rendertarget.
546 *
547 * @return The currently set render target.
548 */
549 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
550 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
551
552 class AutoRenderTargetRestore : public ::GrNoncopyable {
553 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000554 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000555 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
556 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000557 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000558 this->set(ds, newTarget);
559 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000560 ~AutoRenderTargetRestore() { this->restore(); }
561
562 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000563 if (NULL != fDrawState) {
564 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000565 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000566 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000567 GrSafeSetNull(fSavedTarget);
568 }
569
570 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
571 this->restore();
572
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000573 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000574 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000575 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000576 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000577 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000578 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000579 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580 }
581 private:
582 GrDrawState* fDrawState;
583 GrRenderTarget* fSavedTarget;
584 };
585
586 /// @}
587
588 ///////////////////////////////////////////////////////////////////////////
589 /// @name Stencil
590 ////
591
592 /**
593 * Sets the stencil settings to use for the next draw.
594 * Changing the clip has the side-effect of possibly zeroing
595 * out the client settable stencil bits. So multipass algorithms
596 * using stencil should not change the clip between passes.
597 * @param settings the stencil settings to use.
598 */
599 void setStencil(const GrStencilSettings& settings) {
600 fStencilSettings = settings;
601 }
602
603 /**
604 * Shortcut to disable stencil testing and ops.
605 */
606 void disableStencil() {
607 fStencilSettings.setDisabled();
608 }
609
610 const GrStencilSettings& getStencil() const { return fStencilSettings; }
611
612 GrStencilSettings* stencil() { return &fStencilSettings; }
613
614 /// @}
615
616 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000617 /// @name Color Matrix
618 ////
619
620 /**
621 * Sets the color matrix to use for the next draw.
622 * @param matrix the 5x4 matrix to apply to the incoming color
623 */
624 void setColorMatrix(const float matrix[20]) {
625 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
626 }
627
628 const float* getColorMatrix() const { return fColorMatrix; }
629
630 /// @}
631
632 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000634 // Edge equations can be specified to perform antialiasing. Because the
635 // edges are specified as per-vertex data, vertices that are shared by
636 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638 ////
639
640 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000641 * When specifying edges as vertex data this enum specifies what type of
642 * edges are in use. The edges are always 4 GrScalars in memory, even when
643 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000644 *
645 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
646 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000647 */
648 enum VertexEdgeType {
649 /* 1-pixel wide line
650 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
651 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000652 /* Quadratic specified by u^2-v canonical coords (only 2
653 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000654 being inside, positive outside. Edge specified in window space
655 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000656 kQuad_EdgeType,
657 /* Same as above but for hairline quadratics. Uses unsigned distance.
658 Coverage is min(0, 1-distance). */
659 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000660 /* Circle specified as center_x, center_y, outer_radius, inner_radius
661 all in window space (y-down). */
662 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000663
664 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000665 };
666
667 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000668 * Determines the interpretation per-vertex edge data when the
669 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
670 * are not specified the value of this setting has no effect.
671 */
672 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000673 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000674 fVertexEdgeType = type;
675 }
676
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000677 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000678
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000679 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000680
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000681 ///////////////////////////////////////////////////////////////////////////
682 /// @name State Flags
683 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000684
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000685 /**
686 * Flags that affect rendering. Controlled using enable/disableState(). All
687 * default to disabled.
688 */
689 enum StateBits {
690 /**
691 * Perform dithering. TODO: Re-evaluate whether we need this bit
692 */
693 kDither_StateBit = 0x01,
694 /**
695 * Perform HW anti-aliasing. This means either HW FSAA, if supported
696 * by the render target, or smooth-line rendering if a line primitive
697 * is drawn and line smoothing is supported by the 3D API.
698 */
699 kHWAntialias_StateBit = 0x02,
700 /**
701 * Draws will respect the clip, otherwise the clip is ignored.
702 */
703 kClip_StateBit = 0x04,
704 /**
705 * Disables writing to the color buffer. Useful when performing stencil
706 * operations.
707 */
708 kNoColorWrites_StateBit = 0x08,
709 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000710 * Draws will apply the color matrix, otherwise the color matrix is
711 * ignored.
712 */
713 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000714
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000715 // Users of the class may add additional bits to the vector
716 kDummyStateBit,
717 kLastPublicStateBit = kDummyStateBit-1,
718 };
719
720 void resetStateFlags() {
721 fFlagBits = 0;
722 }
723
724 /**
725 * Enable render state settings.
726 *
727 * @param flags bitfield of StateBits specifing the states to enable
728 */
729 void enableState(uint32_t stateBits) {
730 fFlagBits |= stateBits;
731 }
732
733 /**
734 * Disable render state settings.
735 *
736 * @param flags bitfield of StateBits specifing the states to disable
737 */
738 void disableState(uint32_t stateBits) {
739 fFlagBits &= ~(stateBits);
740 }
741
742 bool isDitherState() const {
743 return 0 != (fFlagBits & kDither_StateBit);
744 }
745
746 bool isHWAntialiasState() const {
747 return 0 != (fFlagBits & kHWAntialias_StateBit);
748 }
749
750 bool isClipState() const {
751 return 0 != (fFlagBits & kClip_StateBit);
752 }
753
754 bool isColorWriteDisabled() const {
755 return 0 != (fFlagBits & kNoColorWrites_StateBit);
756 }
757
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000758 bool isStateFlagEnabled(uint32_t stateBit) const {
759 return 0 != (stateBit & fFlagBits);
760 }
761
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000762 /// @}
763
764 ///////////////////////////////////////////////////////////////////////////
765 /// @name Face Culling
766 ////
767
768 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000769 kInvalid_DrawFace = -1,
770
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000771 kBoth_DrawFace,
772 kCCW_DrawFace,
773 kCW_DrawFace,
774 };
775
776 /**
777 * Controls whether clockwise, counterclockwise, or both faces are drawn.
778 * @param face the face(s) to draw.
779 */
780 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000781 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000782 fDrawFace = face;
783 }
784
785 /**
786 * Gets whether the target is drawing clockwise, counterclockwise,
787 * or both faces.
788 * @return the current draw face(s).
789 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000790 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791
792 /// @}
793
794 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000795
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000796 bool isStageEnabled(int s) const {
797 GrAssert((unsigned)s < kNumStages);
798 return (NULL != fTextures[s]) ||
799 (NULL != fSamplerStates[s].getCustomStage());
800 }
801
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000802 // Most stages are usually not used, so conditionals here
803 // reduce the expected number of bytes touched by 50%.
804 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000805 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000806 return false;
807 }
808
809 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
810 return false;
811 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000812
813 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000814 bool enabled = this->isStageEnabled(i);
815 if (enabled != s.isStageEnabled(i)) {
816 return false;
817 }
818 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000819 return false;
820 }
821 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000822 if (kColorMatrix_StateBit & s.fFlagBits) {
823 if (memcmp(fColorMatrix,
824 s.fColorMatrix,
825 sizeof(fColorMatrix))) {
826 return false;
827 }
828 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000829
830 return true;
831 }
832 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
833
834 // Most stages are usually not used, so conditionals here
835 // reduce the expected number of bytes touched by 50%.
836 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000837 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000838
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000839 fViewMatrix = s.fViewMatrix;
840
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000841 for (int i = 0; i < kNumStages; i++) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000842 SkSafeRef(fTextures[i]); // already copied by memcpy
tomhudson@google.come742bf02012-07-13 19:54:19 +0000843 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000844 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000845 }
846 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000847
848 SkSafeRef(fRenderTarget); // already copied by memcpy
849
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000850 if (kColorMatrix_StateBit & s.fFlagBits) {
851 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
852 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000853
854 return *this;
855 }
856
857private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000858
859 const void* podStart() const {
860 return reinterpret_cast<const void*>(&fPodStartMarker);
861 }
862 void* podStart() {
863 return reinterpret_cast<void*>(&fPodStartMarker);
864 }
865 size_t memsetSize() const {
866 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
867 reinterpret_cast<size_t>(&fPodStartMarker) +
868 sizeof(fMemsetEndMarker);
869 }
870 size_t podSize() const {
871 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000872 return reinterpret_cast<size_t>(&fPodEndMarker) -
873 reinterpret_cast<size_t>(&fPodStartMarker) +
874 sizeof(fPodEndMarker);
875 }
876
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000877 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000878 union {
879 GrColor fBlendConstant;
880 GrColor fPodStartMarker;
881 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000882 GrColor fColorFilterColor;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000883 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000884 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000885 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000886 union {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000887 uint32_t fFlagBits;
888 uint32_t fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000889 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000890 // @}
891
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000892 // @{ Initialized to values other than zero, but memcmp'ed in operator==
893 // and memcpy'ed in operator=.
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000894 GrTexture* fTextures[kNumStages];
895 GrRenderTarget* fRenderTarget;
896
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000897 int fFirstCoverageStage;
898
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000899 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000900 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000901 SkXfermode::Mode fColorFilterMode;
902 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000903 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000904 GrBlendCoeff fDstBlend;
905 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000906 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000907 // @}
908
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000909 GrMatrix fViewMatrix;
910
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000911 // This field must be last; it will not be copied or compared
912 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000913 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000914 // only compared if the color matrix enable flag is set
915 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000916
reed@google.comfa35e3d2012-06-26 20:16:17 +0000917 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000918};
919
920#endif