blob: a56baec799ce3f006d57dd55788e3dae8b167706 [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 {
tomhudson@google.com93813632011-10-27 20:21:16 +000024
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025public:
tomhudson@google.com93813632011-10-27 20:21:16 +000026 /**
27 * Number of texture stages. Each stage takes as input a color and
28 * 2D texture coordinates. The color input to the first enabled stage is the
29 * per-vertex color or the constant color (setColor/setAlpha) if there are
30 * no per-vertex colors. For subsequent stages the input color is the output
31 * color from the previous enabled stage. The output color of each stage is
32 * the input color modulated with the result of a texture lookup. Texture
33 * lookups are specified by a texture a sampler (setSamplerState). Texture
34 * coordinates for each stage come from the vertices based on a
35 * GrVertexLayout bitfield. The output fragment color is the output color of
36 * the last enabled stage. The presence or absence of texture coordinates
37 * for each stage in the vertex layout indicates whether a stage is enabled
38 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000039 *
40 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
41 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
42 * through kNumStages-1 are earmarked for use by GrTextContext and
43 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000044 */
45 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000046 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000047 kMaxTexCoords = kNumStages
48 };
49
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000050 /**
51 * Bitfield used to indicate a set of stages.
52 */
53 typedef uint32_t StageMask;
54 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
55
robertphillips@google.com9ec07532012-06-22 12:01:30 +000056 GrDrawState()
57 : fRenderTarget(NULL) {
58
59 for (int i = 0; i < kNumStages; ++i) {
60 fTextures[i] = NULL;
61 }
62
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000063 this->reset();
64 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000065
robertphillips@google.com9ec07532012-06-22 12:01:30 +000066 GrDrawState(const GrDrawState& state)
67 : fRenderTarget(NULL) {
68
69 for (int i = 0; i < kNumStages; ++i) {
70 fTextures[i] = NULL;
71 }
72
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000073 *this = state;
74 }
75
robertphillips@google.com9ec07532012-06-22 12:01:30 +000076 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000077 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000078 GrSafeSetNull(fRenderTarget);
79 }
80
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000081 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000082 * Resets to the default state.
83 * Sampler states *will* be modified: textures or CustomStage objects
84 * will be released.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000085 */
86 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000087
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000088 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000089 GrSafeSetNull(fRenderTarget);
90
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000091 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000092 // all GrDrawState members should default to something valid by the
93 // the memset except those initialized individually below. There should
94 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000095 memset(this->podStart(), 0, this->memsetSize());
96
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000097 // pedantic assertion that our ptrs will
98 // be NULL (0 ptr is mem addr 0)
99 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000100 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000101 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000102
103 // memset exceptions
104 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000105 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000106 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000107 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +0000108 fSrcBlend = kOne_GrBlendCoeff;
109 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000110 fViewMatrix.reset();
111
112 // ensure values that will be memcmp'ed in == but not memset in reset()
113 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000114 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000115 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000116 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fTextures) +
117 sizeof(fRenderTarget) == this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000118 }
119
120 ///////////////////////////////////////////////////////////////////////////
121 /// @name Color
122 ////
123
124 /**
125 * Sets color for next draw to a premultiplied-alpha color.
126 *
127 * @param color the color to set.
128 */
129 void setColor(GrColor color) { fColor = color; }
130
131 GrColor getColor() const { return fColor; }
132
133 /**
134 * Sets the color to be used for the next draw to be
135 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
136 *
137 * @param alpha The alpha value to set as the color.
138 */
139 void setAlpha(uint8_t a) {
140 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
141 }
142
143 /**
144 * Add a color filter that can be represented by a color and a mode. Applied
145 * after color-computing texture stages.
146 */
147 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
148 fColorFilterColor = c;
149 fColorFilterMode = mode;
150 }
151
152 GrColor getColorFilterColor() const { return fColorFilterColor; }
153 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
154
155 /// @}
156
157 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000158 /// @name Coverage
159 ////
160
161 /**
162 * Sets a constant fractional coverage to be applied to the draw. The
163 * initial value (after construction or reset()) is 0xff. The constant
164 * coverage is ignored when per-vertex coverage is provided.
165 */
166 void setCoverage(uint8_t coverage) {
167 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
168 }
169
170 /**
171 * Version of above that specifies 4 channel per-vertex color. The value
172 * should be premultiplied.
173 */
174 void setCoverage4(GrColor coverage) {
175 fCoverage = coverage;
176 }
177
178 GrColor getCoverage() const {
179 return fCoverage;
180 }
181
182 /// @}
183
184 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000185 /// @name Textures
186 ////
187
188 /**
189 * Sets the texture used at the next drawing call
190 *
191 * @param stage The texture stage for which the texture will be set
192 *
193 * @param texture The texture to set. Can be NULL though there is no
194 * advantage to settings a NULL texture if doing non-textured drawing
195 */
196 void setTexture(int stage, GrTexture* texture) {
197 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000198
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000199 GrSafeAssign(fTextures[stage], texture);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000200 }
201
202 /**
203 * Retrieves the currently set texture.
204 *
205 * @return The currently set texture. The return value will be NULL if no
206 * texture has been set, NULL was most recently passed to
207 * setTexture, or the last setTexture was destroyed.
208 */
209 const GrTexture* getTexture(int stage) const {
210 GrAssert((unsigned)stage < kNumStages);
211 return fTextures[stage];
212 }
213 GrTexture* getTexture(int stage) {
214 GrAssert((unsigned)stage < kNumStages);
215 return fTextures[stage];
216 }
217
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000218 bool stagesDisabled() {
219 for (int i = 0; i < kNumStages; ++i) {
220 if (NULL != fTextures[i] ||
221 NULL != fSamplerStates[i].getCustomStage()) {
222 return false;
223 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000224 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000225 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000226 }
robertphillips@google.com972265d2012-06-13 18:49:30 +0000227 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000228 * Release all the textures and custom stages referred to by this
229 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000230 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000231 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000232 for (int i = 0; i < kNumStages; ++i) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000233 GrSafeSetNull(fTextures[i]);
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000234 fSamplerStates[i].setCustomStage(NULL);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000235 }
236 }
237
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000238 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000239 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000240 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
241 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000242 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000243 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000244 }
245 }
246 private:
247 GrDrawState* fDrawState;
248 };
249
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000250 /// @}
251
252 ///////////////////////////////////////////////////////////////////////////
253 /// @name Samplers
254 ////
255
256 /**
257 * Returns the current sampler for a stage.
258 */
259 const GrSamplerState& getSampler(int stage) const {
260 GrAssert((unsigned)stage < kNumStages);
261 return fSamplerStates[stage];
262 }
263
264 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000265 * Writable pointer to a stage's sampler.
266 */
267 GrSamplerState* sampler(int stage) {
268 GrAssert((unsigned)stage < kNumStages);
269 return fSamplerStates + stage;
270 }
271
272 /**
273 * Preconcats the matrix of all samplers in the mask with the same matrix.
274 */
275 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
276 GrAssert(!(stageMask & kIllegalStageMaskBits));
277 for (int i = 0; i < kNumStages; ++i) {
278 if ((1 << i) & stageMask) {
279 fSamplerStates[i].preConcatMatrix(matrix);
280 }
281 }
282 }
283
284 /// @}
285
286 ///////////////////////////////////////////////////////////////////////////
287 /// @name Coverage / Color Stages
288 ////
289
290 /**
291 * A common pattern is to compute a color with the initial stages and then
292 * modulate that color by a coverage value in later stage(s) (AA, mask-
293 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
294 * computed based on the pre-coverage-modulated color. The division of
295 * stages between color-computing and coverage-computing is specified by
296 * this method. Initially this is kNumStages (all stages
297 * are color-computing).
298 */
299 void setFirstCoverageStage(int firstCoverageStage) {
300 GrAssert((unsigned)firstCoverageStage <= kNumStages);
301 fFirstCoverageStage = firstCoverageStage;
302 }
303
304 /**
305 * Gets the index of the first coverage-computing stage.
306 */
307 int getFirstCoverageStage() const {
308 return fFirstCoverageStage;
309 }
310
311 ///@}
312
313 ///////////////////////////////////////////////////////////////////////////
314 /// @name Blending
315 ////
316
317 /**
318 * Sets the blending function coeffecients.
319 *
320 * The blend function will be:
321 * D' = sat(S*srcCoef + D*dstCoef)
322 *
323 * where D is the existing destination color, S is the incoming source
324 * color, and D' is the new destination color that will be written. sat()
325 * is the saturation function.
326 *
327 * @param srcCoef coeffecient applied to the src color.
328 * @param dstCoef coeffecient applied to the dst color.
329 */
330 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
331 fSrcBlend = srcCoeff;
332 fDstBlend = dstCoeff;
333 #if GR_DEBUG
334 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000335 case kDC_GrBlendCoeff:
336 case kIDC_GrBlendCoeff:
337 case kDA_GrBlendCoeff:
338 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000339 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
340 "coverage stages.\n");
341 break;
342 default:
343 break;
344 }
345 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000346 case kSC_GrBlendCoeff:
347 case kISC_GrBlendCoeff:
348 case kSA_GrBlendCoeff:
349 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000350 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
351 "coverage stages.\n");
352 break;
353 default:
354 break;
355 }
356 #endif
357 }
358
359 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
360 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
361
362 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
363 GrBlendCoeff* dstBlendCoeff) const {
364 *srcBlendCoeff = fSrcBlend;
365 *dstBlendCoeff = fDstBlend;
366 }
367
368 /**
369 * Sets the blending function constant referenced by the following blending
370 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000371 * kConstC_GrBlendCoeff
372 * kIConstC_GrBlendCoeff
373 * kConstA_GrBlendCoeff
374 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000375 *
376 * @param constant the constant to set
377 */
378 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
379
380 /**
381 * Retrieves the last value set by setBlendConstant()
382 * @return the blending constant value
383 */
384 GrColor getBlendConstant() const { return fBlendConstant; }
385
386 /// @}
387
388 ///////////////////////////////////////////////////////////////////////////
389 /// @name View Matrix
390 ////
391
392 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000393 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000394 *
395 * In the post-view-matrix space the rectangle [0,w]x[0,h]
396 * fully covers the render target. (w and h are the width and height of the
397 * the rendertarget.)
398 */
399 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
400
401 /**
402 * Gets a writable pointer to the view matrix.
403 */
404 GrMatrix* viewMatrix() { return &fViewMatrix; }
405
406 /**
407 * Multiplies the current view matrix by a matrix
408 *
409 * After this call V' = V*m where V is the old view matrix,
410 * m is the parameter to this function, and V' is the new view matrix.
411 * (We consider positions to be column vectors so position vector p is
412 * transformed by matrix X as p' = X*p.)
413 *
414 * @param m the matrix used to modify the view matrix.
415 */
416 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
417
418 /**
419 * Multiplies the current view matrix by a matrix
420 *
421 * After this call V' = m*V where V is the old view matrix,
422 * m is the parameter to this function, and V' is the new view matrix.
423 * (We consider positions to be column vectors so position vector p is
424 * transformed by matrix X as p' = X*p.)
425 *
426 * @param m the matrix used to modify the view matrix.
427 */
428 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
429
430 /**
431 * Retrieves the current view matrix
432 * @return the current view matrix.
433 */
434 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
435
436 /**
437 * Retrieves the inverse of the current view matrix.
438 *
439 * If the current view matrix is invertible, return true, and if matrix
440 * is non-null, copy the inverse into it. If the current view matrix is
441 * non-invertible, return false and ignore the matrix parameter.
442 *
443 * @param matrix if not null, will receive a copy of the current inverse.
444 */
445 bool getViewInverse(GrMatrix* matrix) const {
446 // TODO: determine whether we really need to leave matrix unmodified
447 // at call sites when inversion fails.
448 GrMatrix inverse;
449 if (fViewMatrix.invert(&inverse)) {
450 if (matrix) {
451 *matrix = inverse;
452 }
453 return true;
454 }
455 return false;
456 }
457
458 class AutoViewMatrixRestore : public ::GrNoncopyable {
459 public:
460 AutoViewMatrixRestore() : fDrawState(NULL) {}
461 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
462 fDrawState = NULL;
463 this->set(ds, newMatrix);
464 }
465 AutoViewMatrixRestore(GrDrawState* ds) {
466 fDrawState = NULL;
467 this->set(ds);
468 }
469 ~AutoViewMatrixRestore() {
470 this->set(NULL, GrMatrix::I());
471 }
472 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
473 if (NULL != fDrawState) {
474 fDrawState->setViewMatrix(fSavedMatrix);
475 }
476 if (NULL != ds) {
477 fSavedMatrix = ds->getViewMatrix();
478 ds->setViewMatrix(newMatrix);
479 }
480 fDrawState = ds;
481 }
482 void set(GrDrawState* ds) {
483 if (NULL != fDrawState) {
484 fDrawState->setViewMatrix(fSavedMatrix);
485 }
486 if (NULL != ds) {
487 fSavedMatrix = ds->getViewMatrix();
488 }
489 fDrawState = ds;
490 }
491 private:
492 GrDrawState* fDrawState;
493 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000494 };
495
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000496 /// @}
497
498 ///////////////////////////////////////////////////////////////////////////
499 /// @name Render Target
500 ////
501
502 /**
503 * Sets the rendertarget used at the next drawing call
504 *
505 * @param target The render target to set.
506 */
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000507 void setRenderTarget(GrRenderTarget* target) {
508 GrSafeAssign(fRenderTarget, target);
509 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000510
511 /**
512 * Retrieves the currently set rendertarget.
513 *
514 * @return The currently set render target.
515 */
516 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
517 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
518
519 class AutoRenderTargetRestore : public ::GrNoncopyable {
520 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000521 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000522 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
523 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000524 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000525 this->set(ds, newTarget);
526 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000527 ~AutoRenderTargetRestore() { this->restore(); }
528
529 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000530 if (NULL != fDrawState) {
531 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000532 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000533 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000534 GrSafeSetNull(fSavedTarget);
535 }
536
537 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
538 this->restore();
539
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000541 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000542 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000543 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000544 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000545 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000546 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000547 }
548 private:
549 GrDrawState* fDrawState;
550 GrRenderTarget* fSavedTarget;
551 };
552
553 /// @}
554
555 ///////////////////////////////////////////////////////////////////////////
556 /// @name Stencil
557 ////
558
559 /**
560 * Sets the stencil settings to use for the next draw.
561 * Changing the clip has the side-effect of possibly zeroing
562 * out the client settable stencil bits. So multipass algorithms
563 * using stencil should not change the clip between passes.
564 * @param settings the stencil settings to use.
565 */
566 void setStencil(const GrStencilSettings& settings) {
567 fStencilSettings = settings;
568 }
569
570 /**
571 * Shortcut to disable stencil testing and ops.
572 */
573 void disableStencil() {
574 fStencilSettings.setDisabled();
575 }
576
577 const GrStencilSettings& getStencil() const { return fStencilSettings; }
578
579 GrStencilSettings* stencil() { return &fStencilSettings; }
580
581 /// @}
582
583 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000584 /// @name Color Matrix
585 ////
586
587 /**
588 * Sets the color matrix to use for the next draw.
589 * @param matrix the 5x4 matrix to apply to the incoming color
590 */
591 void setColorMatrix(const float matrix[20]) {
592 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
593 }
594
595 const float* getColorMatrix() const { return fColorMatrix; }
596
597 /// @}
598
599 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000601 // Edge equations can be specified to perform antialiasing. Because the
602 // edges are specified as per-vertex data, vertices that are shared by
603 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000604 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000605 ////
606
607 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000608 * When specifying edges as vertex data this enum specifies what type of
609 * edges are in use. The edges are always 4 GrScalars in memory, even when
610 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000611 *
612 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
613 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000614 */
615 enum VertexEdgeType {
616 /* 1-pixel wide line
617 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
618 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000619 /* Quadratic specified by u^2-v canonical coords (only 2
620 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000621 being inside, positive outside. Edge specified in window space
622 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000623 kQuad_EdgeType,
624 /* Same as above but for hairline quadratics. Uses unsigned distance.
625 Coverage is min(0, 1-distance). */
626 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000627 /* Circle specified as center_x, center_y, outer_radius, inner_radius
628 all in window space (y-down). */
629 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000630
631 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000632 };
633
634 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000635 * Determines the interpretation per-vertex edge data when the
636 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
637 * are not specified the value of this setting has no effect.
638 */
639 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000640 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000641 fVertexEdgeType = type;
642 }
643
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000644 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000645
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000647
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000648 ///////////////////////////////////////////////////////////////////////////
649 /// @name State Flags
650 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000651
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000652 /**
653 * Flags that affect rendering. Controlled using enable/disableState(). All
654 * default to disabled.
655 */
656 enum StateBits {
657 /**
658 * Perform dithering. TODO: Re-evaluate whether we need this bit
659 */
660 kDither_StateBit = 0x01,
661 /**
662 * Perform HW anti-aliasing. This means either HW FSAA, if supported
663 * by the render target, or smooth-line rendering if a line primitive
664 * is drawn and line smoothing is supported by the 3D API.
665 */
666 kHWAntialias_StateBit = 0x02,
667 /**
668 * Draws will respect the clip, otherwise the clip is ignored.
669 */
670 kClip_StateBit = 0x04,
671 /**
672 * Disables writing to the color buffer. Useful when performing stencil
673 * operations.
674 */
675 kNoColorWrites_StateBit = 0x08,
676 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000677 * Draws will apply the color matrix, otherwise the color matrix is
678 * ignored.
679 */
680 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000681
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000682 // Users of the class may add additional bits to the vector
683 kDummyStateBit,
684 kLastPublicStateBit = kDummyStateBit-1,
685 };
686
687 void resetStateFlags() {
688 fFlagBits = 0;
689 }
690
691 /**
692 * Enable render state settings.
693 *
694 * @param flags bitfield of StateBits specifing the states to enable
695 */
696 void enableState(uint32_t stateBits) {
697 fFlagBits |= stateBits;
698 }
699
700 /**
701 * Disable render state settings.
702 *
703 * @param flags bitfield of StateBits specifing the states to disable
704 */
705 void disableState(uint32_t stateBits) {
706 fFlagBits &= ~(stateBits);
707 }
708
709 bool isDitherState() const {
710 return 0 != (fFlagBits & kDither_StateBit);
711 }
712
713 bool isHWAntialiasState() const {
714 return 0 != (fFlagBits & kHWAntialias_StateBit);
715 }
716
717 bool isClipState() const {
718 return 0 != (fFlagBits & kClip_StateBit);
719 }
720
721 bool isColorWriteDisabled() const {
722 return 0 != (fFlagBits & kNoColorWrites_StateBit);
723 }
724
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000725 bool isStateFlagEnabled(uint32_t stateBit) const {
726 return 0 != (stateBit & fFlagBits);
727 }
728
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000729 /// @}
730
731 ///////////////////////////////////////////////////////////////////////////
732 /// @name Face Culling
733 ////
734
735 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000736 kInvalid_DrawFace = -1,
737
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000738 kBoth_DrawFace,
739 kCCW_DrawFace,
740 kCW_DrawFace,
741 };
742
743 /**
744 * Controls whether clockwise, counterclockwise, or both faces are drawn.
745 * @param face the face(s) to draw.
746 */
747 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000748 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000749 fDrawFace = face;
750 }
751
752 /**
753 * Gets whether the target is drawing clockwise, counterclockwise,
754 * or both faces.
755 * @return the current draw face(s).
756 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000757 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000758
759 /// @}
760
761 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000762
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000763 // Most stages are usually not used, so conditionals here
764 // reduce the expected number of bytes touched by 50%.
765 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000766 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000767 return false;
768 }
769
770 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
771 return false;
772 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000773
774 for (int i = 0; i < kNumStages; i++) {
775 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000776 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000777 return false;
778 }
779 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000780 if (kColorMatrix_StateBit & s.fFlagBits) {
781 if (memcmp(fColorMatrix,
782 s.fColorMatrix,
783 sizeof(fColorMatrix))) {
784 return false;
785 }
786 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000787
788 return true;
789 }
790 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
791
792 // Most stages are usually not used, so conditionals here
793 // reduce the expected number of bytes touched by 50%.
794 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000795 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000796
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000797 fViewMatrix = s.fViewMatrix;
798
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000799 for (int i = 0; i < kNumStages; i++) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000800 SkSafeRef(fTextures[i]); // already copied by memcpy
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000801 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000802 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000803 }
804 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000805
806 SkSafeRef(fRenderTarget); // already copied by memcpy
807
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000808 if (kColorMatrix_StateBit & s.fFlagBits) {
809 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
810 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000811
812 return *this;
813 }
814
815private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000816
817 const void* podStart() const {
818 return reinterpret_cast<const void*>(&fPodStartMarker);
819 }
820 void* podStart() {
821 return reinterpret_cast<void*>(&fPodStartMarker);
822 }
823 size_t memsetSize() const {
824 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
825 reinterpret_cast<size_t>(&fPodStartMarker) +
826 sizeof(fMemsetEndMarker);
827 }
828 size_t podSize() const {
829 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000830 return reinterpret_cast<size_t>(&fPodEndMarker) -
831 reinterpret_cast<size_t>(&fPodStartMarker) +
832 sizeof(fPodEndMarker);
833 }
834
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000835 static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000836 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000837 union {
838 GrColor fBlendConstant;
839 GrColor fPodStartMarker;
840 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000841 GrColor fColorFilterColor;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000842 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000843 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000844 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000845 union {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000846 uint32_t fFlagBits;
847 uint32_t fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000848 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000849 // @}
850
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000851 int fFirstCoverageStage;
852
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000853 // @{ Initialized to values other than zero, but memcmp'ed in operator==
854 // and memcpy'ed in operator=.
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000855 GrTexture* fTextures[kNumStages];
856 GrRenderTarget* fRenderTarget;
857
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000858 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000859 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000860 SkXfermode::Mode fColorFilterMode;
861 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000862 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000863 GrBlendCoeff fDstBlend;
864 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000865 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000866 // @}
867
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000868 GrMatrix fViewMatrix;
869
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870 // This field must be last; it will not be copied or compared
871 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000872 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000873 // only compared if the color matrix enable flag is set
874 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000875
tomhudson@google.com93813632011-10-27 20:21:16 +0000876};
877
878#endif