blob: 92ee2cbaadb9c051de5255e6e1d33be57d5cec88 [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"
tomhudson@google.com93813632011-10-27 20:21:16 +000014#include "GrSamplerState.h"
15#include "GrStencil.h"
16
17#include "SkXfermode.h"
18
19class GrRenderTarget;
20class GrTexture;
21
22struct GrDrawState {
23
24 /**
25 * Number of texture stages. Each stage takes as input a color and
26 * 2D texture coordinates. The color input to the first enabled stage is the
27 * per-vertex color or the constant color (setColor/setAlpha) if there are
28 * no per-vertex colors. For subsequent stages the input color is the output
29 * color from the previous enabled stage. The output color of each stage is
30 * the input color modulated with the result of a texture lookup. Texture
31 * lookups are specified by a texture a sampler (setSamplerState). Texture
32 * coordinates for each stage come from the vertices based on a
33 * GrVertexLayout bitfield. The output fragment color is the output color of
34 * the last enabled stage. The presence or absence of texture coordinates
35 * for each stage in the vertex layout indicates whether a stage is enabled
36 * or not.
37 */
38 enum {
39 kNumStages = 3,
40 kMaxTexCoords = kNumStages
41 };
42
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000043 /**
44 * Bitfield used to indicate a set of stages.
45 */
46 typedef uint32_t StageMask;
47 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
48
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000049 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000050 this->reset();
51 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000052
53 GrDrawState(const GrDrawState& state) {
54 *this = state;
55 }
56
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000057 /**
58 * Resets to the default state. Sampler states will not be modified.
59 */
60 void reset() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000061 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000062 // all GrDrawState members should default to something valid by the
63 // the memset except those initialized individually below. There should
64 // be no padding between the individually initialized members.
65 static const size_t kMemsetSize =
66 reinterpret_cast<intptr_t>(&fColor) -
67 reinterpret_cast<intptr_t>(this);
68 memset(this, 0, kMemsetSize);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000069 // pedantic assertion that our ptrs will
70 // be NULL (0 ptr is mem addr 0)
71 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000072 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000073 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000074
75 // memset exceptions
76 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000077 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000078 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079 fColorFilterMode = SkXfermode::kDst_Mode;
80 fSrcBlend = kOne_BlendCoeff;
81 fDstBlend = kZero_BlendCoeff;
82 fViewMatrix.reset();
83
84 // ensure values that will be memcmp'ed in == but not memset in reset()
85 // are tightly packed
bsalomon@google.com2401ae82012-01-17 21:03:05 +000086 GrAssert(kMemsetSize + sizeof(fColor) + sizeof(fCoverage) +
87 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
bsalomon@google.com8fe84b52012-03-26 15:24:27 +000088 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
89 reinterpret_cast<uintptr_t>(&fViewMatrix) -
bsalomon@google.com6f86c3e2012-03-22 21:29:10 +000090 reinterpret_cast<uintptr_t>(this));
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000091
92 fEdgeAANumEdges = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000093 }
94
95 ///////////////////////////////////////////////////////////////////////////
96 /// @name Color
97 ////
98
99 /**
100 * Sets color for next draw to a premultiplied-alpha color.
101 *
102 * @param color the color to set.
103 */
104 void setColor(GrColor color) { fColor = color; }
105
106 GrColor getColor() const { return fColor; }
107
108 /**
109 * Sets the color to be used for the next draw to be
110 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
111 *
112 * @param alpha The alpha value to set as the color.
113 */
114 void setAlpha(uint8_t a) {
115 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
116 }
117
118 /**
119 * Add a color filter that can be represented by a color and a mode. Applied
120 * after color-computing texture stages.
121 */
122 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
123 fColorFilterColor = c;
124 fColorFilterMode = mode;
125 }
126
127 GrColor getColorFilterColor() const { return fColorFilterColor; }
128 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
129
130 /// @}
131
132 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000133 /// @name Coverage
134 ////
135
136 /**
137 * Sets a constant fractional coverage to be applied to the draw. The
138 * initial value (after construction or reset()) is 0xff. The constant
139 * coverage is ignored when per-vertex coverage is provided.
140 */
141 void setCoverage(uint8_t coverage) {
142 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
143 }
144
145 /**
146 * Version of above that specifies 4 channel per-vertex color. The value
147 * should be premultiplied.
148 */
149 void setCoverage4(GrColor coverage) {
150 fCoverage = coverage;
151 }
152
153 GrColor getCoverage() const {
154 return fCoverage;
155 }
156
157 /// @}
158
159 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000160 /// @name Textures
161 ////
162
163 /**
164 * Sets the texture used at the next drawing call
165 *
166 * @param stage The texture stage for which the texture will be set
167 *
168 * @param texture The texture to set. Can be NULL though there is no
169 * advantage to settings a NULL texture if doing non-textured drawing
170 */
171 void setTexture(int stage, GrTexture* texture) {
172 GrAssert((unsigned)stage < kNumStages);
173 fTextures[stage] = texture;
174 }
175
176 /**
177 * Retrieves the currently set texture.
178 *
179 * @return The currently set texture. The return value will be NULL if no
180 * texture has been set, NULL was most recently passed to
181 * setTexture, or the last setTexture was destroyed.
182 */
183 const GrTexture* getTexture(int stage) const {
184 GrAssert((unsigned)stage < kNumStages);
185 return fTextures[stage];
186 }
187 GrTexture* getTexture(int stage) {
188 GrAssert((unsigned)stage < kNumStages);
189 return fTextures[stage];
190 }
191
192 /// @}
193
194 ///////////////////////////////////////////////////////////////////////////
195 /// @name Samplers
196 ////
197
198 /**
199 * Returns the current sampler for a stage.
200 */
201 const GrSamplerState& getSampler(int stage) const {
202 GrAssert((unsigned)stage < kNumStages);
203 return fSamplerStates[stage];
204 }
205
206 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000207 * Writable pointer to a stage's sampler.
208 */
209 GrSamplerState* sampler(int stage) {
210 GrAssert((unsigned)stage < kNumStages);
211 return fSamplerStates + stage;
212 }
213
214 /**
215 * Preconcats the matrix of all samplers in the mask with the same matrix.
216 */
217 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
218 GrAssert(!(stageMask & kIllegalStageMaskBits));
219 for (int i = 0; i < kNumStages; ++i) {
220 if ((1 << i) & stageMask) {
221 fSamplerStates[i].preConcatMatrix(matrix);
222 }
223 }
224 }
225
226 /// @}
227
228 ///////////////////////////////////////////////////////////////////////////
229 /// @name Coverage / Color Stages
230 ////
231
232 /**
233 * A common pattern is to compute a color with the initial stages and then
234 * modulate that color by a coverage value in later stage(s) (AA, mask-
235 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
236 * computed based on the pre-coverage-modulated color. The division of
237 * stages between color-computing and coverage-computing is specified by
238 * this method. Initially this is kNumStages (all stages
239 * are color-computing).
240 */
241 void setFirstCoverageStage(int firstCoverageStage) {
242 GrAssert((unsigned)firstCoverageStage <= kNumStages);
243 fFirstCoverageStage = firstCoverageStage;
244 }
245
246 /**
247 * Gets the index of the first coverage-computing stage.
248 */
249 int getFirstCoverageStage() const {
250 return fFirstCoverageStage;
251 }
252
253 ///@}
254
255 ///////////////////////////////////////////////////////////////////////////
256 /// @name Blending
257 ////
258
259 /**
260 * Sets the blending function coeffecients.
261 *
262 * The blend function will be:
263 * D' = sat(S*srcCoef + D*dstCoef)
264 *
265 * where D is the existing destination color, S is the incoming source
266 * color, and D' is the new destination color that will be written. sat()
267 * is the saturation function.
268 *
269 * @param srcCoef coeffecient applied to the src color.
270 * @param dstCoef coeffecient applied to the dst color.
271 */
272 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
273 fSrcBlend = srcCoeff;
274 fDstBlend = dstCoeff;
275 #if GR_DEBUG
276 switch (dstCoeff) {
277 case kDC_BlendCoeff:
278 case kIDC_BlendCoeff:
279 case kDA_BlendCoeff:
280 case kIDA_BlendCoeff:
281 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
282 "coverage stages.\n");
283 break;
284 default:
285 break;
286 }
287 switch (srcCoeff) {
288 case kSC_BlendCoeff:
289 case kISC_BlendCoeff:
290 case kSA_BlendCoeff:
291 case kISA_BlendCoeff:
292 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
293 "coverage stages.\n");
294 break;
295 default:
296 break;
297 }
298 #endif
299 }
300
301 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
302 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
303
304 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
305 GrBlendCoeff* dstBlendCoeff) const {
306 *srcBlendCoeff = fSrcBlend;
307 *dstBlendCoeff = fDstBlend;
308 }
309
310 /**
311 * Sets the blending function constant referenced by the following blending
312 * coeffecients:
313 * kConstC_BlendCoeff
314 * kIConstC_BlendCoeff
315 * kConstA_BlendCoeff
316 * kIConstA_BlendCoeff
317 *
318 * @param constant the constant to set
319 */
320 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
321
322 /**
323 * Retrieves the last value set by setBlendConstant()
324 * @return the blending constant value
325 */
326 GrColor getBlendConstant() const { return fBlendConstant; }
327
328 /// @}
329
330 ///////////////////////////////////////////////////////////////////////////
331 /// @name View Matrix
332 ////
333
334 /**
335 * Sets the matrix applied to veretx positions.
336 *
337 * In the post-view-matrix space the rectangle [0,w]x[0,h]
338 * fully covers the render target. (w and h are the width and height of the
339 * the rendertarget.)
340 */
341 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
342
343 /**
344 * Gets a writable pointer to the view matrix.
345 */
346 GrMatrix* viewMatrix() { return &fViewMatrix; }
347
348 /**
349 * Multiplies the current view matrix by a matrix
350 *
351 * After this call V' = V*m where V is the old view matrix,
352 * m is the parameter to this function, and V' is the new view matrix.
353 * (We consider positions to be column vectors so position vector p is
354 * transformed by matrix X as p' = X*p.)
355 *
356 * @param m the matrix used to modify the view matrix.
357 */
358 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
359
360 /**
361 * Multiplies the current view matrix by a matrix
362 *
363 * After this call V' = m*V where V is the old view matrix,
364 * m is the parameter to this function, and V' is the new view matrix.
365 * (We consider positions to be column vectors so position vector p is
366 * transformed by matrix X as p' = X*p.)
367 *
368 * @param m the matrix used to modify the view matrix.
369 */
370 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
371
372 /**
373 * Retrieves the current view matrix
374 * @return the current view matrix.
375 */
376 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
377
378 /**
379 * Retrieves the inverse of the current view matrix.
380 *
381 * If the current view matrix is invertible, return true, and if matrix
382 * is non-null, copy the inverse into it. If the current view matrix is
383 * non-invertible, return false and ignore the matrix parameter.
384 *
385 * @param matrix if not null, will receive a copy of the current inverse.
386 */
387 bool getViewInverse(GrMatrix* matrix) const {
388 // TODO: determine whether we really need to leave matrix unmodified
389 // at call sites when inversion fails.
390 GrMatrix inverse;
391 if (fViewMatrix.invert(&inverse)) {
392 if (matrix) {
393 *matrix = inverse;
394 }
395 return true;
396 }
397 return false;
398 }
399
400 class AutoViewMatrixRestore : public ::GrNoncopyable {
401 public:
402 AutoViewMatrixRestore() : fDrawState(NULL) {}
403 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
404 fDrawState = NULL;
405 this->set(ds, newMatrix);
406 }
407 AutoViewMatrixRestore(GrDrawState* ds) {
408 fDrawState = NULL;
409 this->set(ds);
410 }
411 ~AutoViewMatrixRestore() {
412 this->set(NULL, GrMatrix::I());
413 }
414 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
415 if (NULL != fDrawState) {
416 fDrawState->setViewMatrix(fSavedMatrix);
417 }
418 if (NULL != ds) {
419 fSavedMatrix = ds->getViewMatrix();
420 ds->setViewMatrix(newMatrix);
421 }
422 fDrawState = ds;
423 }
424 void set(GrDrawState* ds) {
425 if (NULL != fDrawState) {
426 fDrawState->setViewMatrix(fSavedMatrix);
427 }
428 if (NULL != ds) {
429 fSavedMatrix = ds->getViewMatrix();
430 }
431 fDrawState = ds;
432 }
433 private:
434 GrDrawState* fDrawState;
435 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000436 };
437
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000438 /// @}
439
440 ///////////////////////////////////////////////////////////////////////////
441 /// @name Render Target
442 ////
443
444 /**
445 * Sets the rendertarget used at the next drawing call
446 *
447 * @param target The render target to set.
448 */
449 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
450
451 /**
452 * Retrieves the currently set rendertarget.
453 *
454 * @return The currently set render target.
455 */
456 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
457 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
458
459 class AutoRenderTargetRestore : public ::GrNoncopyable {
460 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000461 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000462 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
463 fDrawState = NULL;
464 this->set(ds, newTarget);
465 }
466 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
467 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
468 if (NULL != fDrawState) {
469 fDrawState->setRenderTarget(fSavedTarget);
470 }
471 if (NULL != ds) {
472 fSavedTarget = ds->getRenderTarget();
473 ds->setRenderTarget(newTarget);
474 }
475 fDrawState = ds;
476 }
477 private:
478 GrDrawState* fDrawState;
479 GrRenderTarget* fSavedTarget;
480 };
481
482 /// @}
483
484 ///////////////////////////////////////////////////////////////////////////
485 /// @name Stencil
486 ////
487
488 /**
489 * Sets the stencil settings to use for the next draw.
490 * Changing the clip has the side-effect of possibly zeroing
491 * out the client settable stencil bits. So multipass algorithms
492 * using stencil should not change the clip between passes.
493 * @param settings the stencil settings to use.
494 */
495 void setStencil(const GrStencilSettings& settings) {
496 fStencilSettings = settings;
497 }
498
499 /**
500 * Shortcut to disable stencil testing and ops.
501 */
502 void disableStencil() {
503 fStencilSettings.setDisabled();
504 }
505
506 const GrStencilSettings& getStencil() const { return fStencilSettings; }
507
508 GrStencilSettings* stencil() { return &fStencilSettings; }
509
510 /// @}
511
512 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000513 /// @name Color Matrix
514 ////
515
516 /**
517 * Sets the color matrix to use for the next draw.
518 * @param matrix the 5x4 matrix to apply to the incoming color
519 */
520 void setColorMatrix(const float matrix[20]) {
521 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
522 }
523
524 const float* getColorMatrix() const { return fColorMatrix; }
525
526 /// @}
527
528 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 // @name Edge AA
530 // There are two ways to perform antialiasing using edge equations. One
531 // is to specify an (linear or quadratic) edge eq per-vertex. This requires
532 // splitting vertices shared by primitives.
533 //
534 // The other is via setEdgeAAData which sets a set of edges and each
535 // is tested against all the edges.
536 ////
537
538 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000539 * When specifying edges as vertex data this enum specifies what type of
540 * edges are in use. The edges are always 4 GrScalars in memory, even when
541 * the edge type requires fewer than 4.
542 */
543 enum VertexEdgeType {
544 /* 1-pixel wide line
545 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
546 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000547 /* Quadratic specified by u^2-v canonical coords (only 2
548 components used). Coverage based on signed distance with negative
549 being inside, positive outside.*/
550 kQuad_EdgeType,
551 /* Same as above but for hairline quadratics. Uses unsigned distance.
552 Coverage is min(0, 1-distance). */
553 kHairQuad_EdgeType,
554
555 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000556 };
557
558 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000559 * Determines the interpretation per-vertex edge data when the
560 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
561 * are not specified the value of this setting has no effect.
562 */
563 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000564 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000565 fVertexEdgeType = type;
566 }
567
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000568 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000569
570 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000571 * The absolute maximum number of edges that may be specified for
572 * a single draw call when performing edge antialiasing. This is used for
573 * the size of several static buffers, so implementations of getMaxEdges()
574 * (below) should clamp to this value.
575 */
576 enum {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000577 // TODO: this should be 32 when GrTesselatedPathRenderer is used
578 // Visual Studio 2010 does not permit a member array of size 0.
579 kMaxEdges = 1
tomhudson@google.com93813632011-10-27 20:21:16 +0000580 };
581
582 class Edge {
583 public:
584 Edge() {}
585 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
586 GrPoint intersect(const Edge& other) {
587 return GrPoint::Make(
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000588 SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
589 (fX * other.fY - other.fX * fY)),
590 SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
591 (other.fX * fY - fX * other.fY)));
tomhudson@google.com93813632011-10-27 20:21:16 +0000592 }
593 float fX, fY, fZ;
594 };
595
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 /**
597 * Sets the edge data required for edge antialiasing.
598 *
599 * @param edges 3 * numEdges float values, representing the edge
600 * equations in Ax + By + C form
601 */
602 void setEdgeAAData(const Edge* edges, int numEdges) {
603 GrAssert(numEdges <= GrDrawState::kMaxEdges);
604 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
605 fEdgeAANumEdges = numEdges;
tomhudson@google.com93813632011-10-27 20:21:16 +0000606 }
607
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 int getNumAAEdges() const { return fEdgeAANumEdges; }
tomhudson@google.com93813632011-10-27 20:21:16 +0000609
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000610 const Edge* getAAEdges() const { return fEdgeAAEdges; }
tomhudson@google.com62b09682011-11-09 16:39:17 +0000611
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000613
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000614 ///////////////////////////////////////////////////////////////////////////
615 /// @name State Flags
616 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000617
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000618 /**
619 * Flags that affect rendering. Controlled using enable/disableState(). All
620 * default to disabled.
621 */
622 enum StateBits {
623 /**
624 * Perform dithering. TODO: Re-evaluate whether we need this bit
625 */
626 kDither_StateBit = 0x01,
627 /**
628 * Perform HW anti-aliasing. This means either HW FSAA, if supported
629 * by the render target, or smooth-line rendering if a line primitive
630 * is drawn and line smoothing is supported by the 3D API.
631 */
632 kHWAntialias_StateBit = 0x02,
633 /**
634 * Draws will respect the clip, otherwise the clip is ignored.
635 */
636 kClip_StateBit = 0x04,
637 /**
638 * Disables writing to the color buffer. Useful when performing stencil
639 * operations.
640 */
641 kNoColorWrites_StateBit = 0x08,
642 /**
643 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
644 * will test edge pairs for convexity when rasterizing. Set this if the
645 * source polygon is non-convex.
646 */
647 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000648 /**
649 * Draws will apply the color matrix, otherwise the color matrix is
650 * ignored.
651 */
652 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000653
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 // Users of the class may add additional bits to the vector
655 kDummyStateBit,
656 kLastPublicStateBit = kDummyStateBit-1,
657 };
658
659 void resetStateFlags() {
660 fFlagBits = 0;
661 }
662
663 /**
664 * Enable render state settings.
665 *
666 * @param flags bitfield of StateBits specifing the states to enable
667 */
668 void enableState(uint32_t stateBits) {
669 fFlagBits |= stateBits;
670 }
671
672 /**
673 * Disable render state settings.
674 *
675 * @param flags bitfield of StateBits specifing the states to disable
676 */
677 void disableState(uint32_t stateBits) {
678 fFlagBits &= ~(stateBits);
679 }
680
681 bool isDitherState() const {
682 return 0 != (fFlagBits & kDither_StateBit);
683 }
684
685 bool isHWAntialiasState() const {
686 return 0 != (fFlagBits & kHWAntialias_StateBit);
687 }
688
689 bool isClipState() const {
690 return 0 != (fFlagBits & kClip_StateBit);
691 }
692
693 bool isColorWriteDisabled() const {
694 return 0 != (fFlagBits & kNoColorWrites_StateBit);
695 }
696
697 bool isConcaveEdgeAAState() const {
698 return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
699 }
700
701 bool isStateFlagEnabled(uint32_t stateBit) const {
702 return 0 != (stateBit & fFlagBits);
703 }
704
705 void copyStateFlags(const GrDrawState& ds) {
706 fFlagBits = ds.fFlagBits;
707 }
708
709 /// @}
710
711 ///////////////////////////////////////////////////////////////////////////
712 /// @name Face Culling
713 ////
714
715 enum DrawFace {
716 kBoth_DrawFace,
717 kCCW_DrawFace,
718 kCW_DrawFace,
719 };
720
721 /**
722 * Controls whether clockwise, counterclockwise, or both faces are drawn.
723 * @param face the face(s) to draw.
724 */
725 void setDrawFace(DrawFace face) {
726 fDrawFace = face;
727 }
728
729 /**
730 * Gets whether the target is drawing clockwise, counterclockwise,
731 * or both faces.
732 * @return the current draw face(s).
733 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000734 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735
736 /// @}
737
738 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000739
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000740 // Most stages are usually not used, so conditionals here
741 // reduce the expected number of bytes touched by 50%.
742 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000743 if (memcmp(this, &s, this->leadingBytes())) {
744 return false;
745 }
746
747 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
748 return false;
749 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000750
751 for (int i = 0; i < kNumStages; i++) {
752 if (fTextures[i] &&
753 memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i],
754 sizeof(GrSamplerState))) {
755 return false;
756 }
757 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000758 if (kColorMatrix_StateBit & s.fFlagBits) {
759 if (memcmp(fColorMatrix,
760 s.fColorMatrix,
761 sizeof(fColorMatrix))) {
762 return false;
763 }
764 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000765
766 return true;
767 }
768 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
769
770 // Most stages are usually not used, so conditionals here
771 // reduce the expected number of bytes touched by 50%.
772 GrDrawState& operator =(const GrDrawState& s) {
773 memcpy(this, &s, this->leadingBytes());
774
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000775 fViewMatrix = s.fViewMatrix;
776
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000777 for (int i = 0; i < kNumStages; i++) {
778 if (s.fTextures[i]) {
779 memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i],
780 sizeof(GrSamplerState));
781 }
782 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000783 if (kColorMatrix_StateBit & s.fFlagBits) {
784 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
785 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000786
787 return *this;
788 }
789
790private:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000792 // @{ these fields can be initialized with memset to 0
793 GrColor fBlendConstant;
794 GrTexture* fTextures[kNumStages];
795 GrColor fColorFilterColor;
796 uint32_t fFlagBits;
797 DrawFace fDrawFace;
798 VertexEdgeType fVertexEdgeType;
799 GrStencilSettings fStencilSettings;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000800 GrRenderTarget* fRenderTarget;
801 // @}
802
803 // @{ Initialized to values other than zero
804 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000805 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000806 int fFirstCoverageStage;
807 SkXfermode::Mode fColorFilterMode;
808 GrBlendCoeff fSrcBlend;
809 GrBlendCoeff fDstBlend;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000810 // @}
811
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000812 GrMatrix fViewMatrix;
813
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000814 // @{ Data for GrTesselatedPathRenderer
815 // TODO: currently ignored in copying & comparison for performance.
816 // Must be considered if GrTesselatedPathRenderer is being used.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000817 int fEdgeAANumEdges;
818 Edge fEdgeAAEdges[kMaxEdges];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000819 // @}
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000820
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000821 // This field must be last; it will not be copied or compared
822 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000823 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000824 // only compared if the color matrix enable flag is set
825 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000826
tomhudson@google.com62b09682011-11-09 16:39:17 +0000827 size_t leadingBytes() const {
828 // Can't use offsetof() with non-POD types, so stuck with pointer math.
829 // TODO: ignores GrTesselatedPathRenderer data structures. We don't
830 // have a compile-time flag that lets us know if it's being used, and
831 // checking at runtime seems to cost 5% performance.
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000832 return (size_t) ((unsigned char*)&fViewMatrix -
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000833 (unsigned char*)&fBlendConstant);
tomhudson@google.com62b09682011-11-09 16:39:17 +0000834 }
835
tomhudson@google.com93813632011-10-27 20:21:16 +0000836};
837
838#endif