blob: 51443cb0fced80cc8af62548eb28accb6b79db94 [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() {
50 // make sure any pad is zero for memcmp
51 // all GrDrawState members should default to something
52 // valid by the memset
53 memset(this, 0, sizeof(GrDrawState));
54
55 // memset exceptions
56 fColorFilterMode = SkXfermode::kDstIn_Mode;
57 fFirstCoverageStage = kNumStages;
58
59 // pedantic assertion that our ptrs will
60 // be NULL (0 ptr is mem addr 0)
61 GrAssert((intptr_t)(void*)NULL == 0LL);
62
63 GrAssert(fStencilSettings.isDisabled());
64 fFirstCoverageStage = kNumStages;
65 }
66
67 ///////////////////////////////////////////////////////////////////////////
68 /// @name Color
69 ////
70
71 /**
72 * Sets color for next draw to a premultiplied-alpha color.
73 *
74 * @param color the color to set.
75 */
76 void setColor(GrColor color) { fColor = color; }
77
78 GrColor getColor() const { return fColor; }
79
80 /**
81 * Sets the color to be used for the next draw to be
82 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
83 *
84 * @param alpha The alpha value to set as the color.
85 */
86 void setAlpha(uint8_t a) {
87 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
88 }
89
90 /**
91 * Add a color filter that can be represented by a color and a mode. Applied
92 * after color-computing texture stages.
93 */
94 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
95 fColorFilterColor = c;
96 fColorFilterMode = mode;
97 }
98
99 GrColor getColorFilterColor() const { return fColorFilterColor; }
100 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
101
102 /// @}
103
104 ///////////////////////////////////////////////////////////////////////////
105 /// @name Textures
106 ////
107
108 /**
109 * Sets the texture used at the next drawing call
110 *
111 * @param stage The texture stage for which the texture will be set
112 *
113 * @param texture The texture to set. Can be NULL though there is no
114 * advantage to settings a NULL texture if doing non-textured drawing
115 */
116 void setTexture(int stage, GrTexture* texture) {
117 GrAssert((unsigned)stage < kNumStages);
118 fTextures[stage] = texture;
119 }
120
121 /**
122 * Retrieves the currently set texture.
123 *
124 * @return The currently set texture. The return value will be NULL if no
125 * texture has been set, NULL was most recently passed to
126 * setTexture, or the last setTexture was destroyed.
127 */
128 const GrTexture* getTexture(int stage) const {
129 GrAssert((unsigned)stage < kNumStages);
130 return fTextures[stage];
131 }
132 GrTexture* getTexture(int stage) {
133 GrAssert((unsigned)stage < kNumStages);
134 return fTextures[stage];
135 }
136
137 /// @}
138
139 ///////////////////////////////////////////////////////////////////////////
140 /// @name Samplers
141 ////
142
143 /**
144 * Returns the current sampler for a stage.
145 */
146 const GrSamplerState& getSampler(int stage) const {
147 GrAssert((unsigned)stage < kNumStages);
148 return fSamplerStates[stage];
149 }
150
151 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000152 * Writable pointer to a stage's sampler.
153 */
154 GrSamplerState* sampler(int stage) {
155 GrAssert((unsigned)stage < kNumStages);
156 return fSamplerStates + stage;
157 }
158
159 /**
160 * Preconcats the matrix of all samplers in the mask with the same matrix.
161 */
162 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
163 GrAssert(!(stageMask & kIllegalStageMaskBits));
164 for (int i = 0; i < kNumStages; ++i) {
165 if ((1 << i) & stageMask) {
166 fSamplerStates[i].preConcatMatrix(matrix);
167 }
168 }
169 }
170
171 /// @}
172
173 ///////////////////////////////////////////////////////////////////////////
174 /// @name Coverage / Color Stages
175 ////
176
177 /**
178 * A common pattern is to compute a color with the initial stages and then
179 * modulate that color by a coverage value in later stage(s) (AA, mask-
180 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
181 * computed based on the pre-coverage-modulated color. The division of
182 * stages between color-computing and coverage-computing is specified by
183 * this method. Initially this is kNumStages (all stages
184 * are color-computing).
185 */
186 void setFirstCoverageStage(int firstCoverageStage) {
187 GrAssert((unsigned)firstCoverageStage <= kNumStages);
188 fFirstCoverageStage = firstCoverageStage;
189 }
190
191 /**
192 * Gets the index of the first coverage-computing stage.
193 */
194 int getFirstCoverageStage() const {
195 return fFirstCoverageStage;
196 }
197
198 ///@}
199
200 ///////////////////////////////////////////////////////////////////////////
201 /// @name Blending
202 ////
203
204 /**
205 * Sets the blending function coeffecients.
206 *
207 * The blend function will be:
208 * D' = sat(S*srcCoef + D*dstCoef)
209 *
210 * where D is the existing destination color, S is the incoming source
211 * color, and D' is the new destination color that will be written. sat()
212 * is the saturation function.
213 *
214 * @param srcCoef coeffecient applied to the src color.
215 * @param dstCoef coeffecient applied to the dst color.
216 */
217 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
218 fSrcBlend = srcCoeff;
219 fDstBlend = dstCoeff;
220 #if GR_DEBUG
221 switch (dstCoeff) {
222 case kDC_BlendCoeff:
223 case kIDC_BlendCoeff:
224 case kDA_BlendCoeff:
225 case kIDA_BlendCoeff:
226 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
227 "coverage stages.\n");
228 break;
229 default:
230 break;
231 }
232 switch (srcCoeff) {
233 case kSC_BlendCoeff:
234 case kISC_BlendCoeff:
235 case kSA_BlendCoeff:
236 case kISA_BlendCoeff:
237 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
238 "coverage stages.\n");
239 break;
240 default:
241 break;
242 }
243 #endif
244 }
245
246 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
247 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
248
249 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
250 GrBlendCoeff* dstBlendCoeff) const {
251 *srcBlendCoeff = fSrcBlend;
252 *dstBlendCoeff = fDstBlend;
253 }
254
255 /**
256 * Sets the blending function constant referenced by the following blending
257 * coeffecients:
258 * kConstC_BlendCoeff
259 * kIConstC_BlendCoeff
260 * kConstA_BlendCoeff
261 * kIConstA_BlendCoeff
262 *
263 * @param constant the constant to set
264 */
265 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
266
267 /**
268 * Retrieves the last value set by setBlendConstant()
269 * @return the blending constant value
270 */
271 GrColor getBlendConstant() const { return fBlendConstant; }
272
273 /// @}
274
275 ///////////////////////////////////////////////////////////////////////////
276 /// @name View Matrix
277 ////
278
279 /**
280 * Sets the matrix applied to veretx positions.
281 *
282 * In the post-view-matrix space the rectangle [0,w]x[0,h]
283 * fully covers the render target. (w and h are the width and height of the
284 * the rendertarget.)
285 */
286 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
287
288 /**
289 * Gets a writable pointer to the view matrix.
290 */
291 GrMatrix* viewMatrix() { return &fViewMatrix; }
292
293 /**
294 * Multiplies the current view matrix by a matrix
295 *
296 * After this call V' = V*m where V is the old view matrix,
297 * m is the parameter to this function, and V' is the new view matrix.
298 * (We consider positions to be column vectors so position vector p is
299 * transformed by matrix X as p' = X*p.)
300 *
301 * @param m the matrix used to modify the view matrix.
302 */
303 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
304
305 /**
306 * Multiplies the current view matrix by a matrix
307 *
308 * After this call V' = m*V where V is the old view matrix,
309 * m is the parameter to this function, and V' is the new view matrix.
310 * (We consider positions to be column vectors so position vector p is
311 * transformed by matrix X as p' = X*p.)
312 *
313 * @param m the matrix used to modify the view matrix.
314 */
315 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
316
317 /**
318 * Retrieves the current view matrix
319 * @return the current view matrix.
320 */
321 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
322
323 /**
324 * Retrieves the inverse of the current view matrix.
325 *
326 * If the current view matrix is invertible, return true, and if matrix
327 * is non-null, copy the inverse into it. If the current view matrix is
328 * non-invertible, return false and ignore the matrix parameter.
329 *
330 * @param matrix if not null, will receive a copy of the current inverse.
331 */
332 bool getViewInverse(GrMatrix* matrix) const {
333 // TODO: determine whether we really need to leave matrix unmodified
334 // at call sites when inversion fails.
335 GrMatrix inverse;
336 if (fViewMatrix.invert(&inverse)) {
337 if (matrix) {
338 *matrix = inverse;
339 }
340 return true;
341 }
342 return false;
343 }
344
345 class AutoViewMatrixRestore : public ::GrNoncopyable {
346 public:
347 AutoViewMatrixRestore() : fDrawState(NULL) {}
348 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
349 fDrawState = NULL;
350 this->set(ds, newMatrix);
351 }
352 AutoViewMatrixRestore(GrDrawState* ds) {
353 fDrawState = NULL;
354 this->set(ds);
355 }
356 ~AutoViewMatrixRestore() {
357 this->set(NULL, GrMatrix::I());
358 }
359 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
360 if (NULL != fDrawState) {
361 fDrawState->setViewMatrix(fSavedMatrix);
362 }
363 if (NULL != ds) {
364 fSavedMatrix = ds->getViewMatrix();
365 ds->setViewMatrix(newMatrix);
366 }
367 fDrawState = ds;
368 }
369 void set(GrDrawState* ds) {
370 if (NULL != fDrawState) {
371 fDrawState->setViewMatrix(fSavedMatrix);
372 }
373 if (NULL != ds) {
374 fSavedMatrix = ds->getViewMatrix();
375 }
376 fDrawState = ds;
377 }
378 private:
379 GrDrawState* fDrawState;
380 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000381 };
382
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000383 /// @}
384
385 ///////////////////////////////////////////////////////////////////////////
386 /// @name Render Target
387 ////
388
389 /**
390 * Sets the rendertarget used at the next drawing call
391 *
392 * @param target The render target to set.
393 */
394 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
395
396 /**
397 * Retrieves the currently set rendertarget.
398 *
399 * @return The currently set render target.
400 */
401 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
402 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
403
404 class AutoRenderTargetRestore : public ::GrNoncopyable {
405 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000406 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000407 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
408 fDrawState = NULL;
409 this->set(ds, newTarget);
410 }
411 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
412 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
413 if (NULL != fDrawState) {
414 fDrawState->setRenderTarget(fSavedTarget);
415 }
416 if (NULL != ds) {
417 fSavedTarget = ds->getRenderTarget();
418 ds->setRenderTarget(newTarget);
419 }
420 fDrawState = ds;
421 }
422 private:
423 GrDrawState* fDrawState;
424 GrRenderTarget* fSavedTarget;
425 };
426
427 /// @}
428
429 ///////////////////////////////////////////////////////////////////////////
430 /// @name Stencil
431 ////
432
433 /**
434 * Sets the stencil settings to use for the next draw.
435 * Changing the clip has the side-effect of possibly zeroing
436 * out the client settable stencil bits. So multipass algorithms
437 * using stencil should not change the clip between passes.
438 * @param settings the stencil settings to use.
439 */
440 void setStencil(const GrStencilSettings& settings) {
441 fStencilSettings = settings;
442 }
443
444 /**
445 * Shortcut to disable stencil testing and ops.
446 */
447 void disableStencil() {
448 fStencilSettings.setDisabled();
449 }
450
451 const GrStencilSettings& getStencil() const { return fStencilSettings; }
452
453 GrStencilSettings* stencil() { return &fStencilSettings; }
454
455 /// @}
456
457 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000458 /// @name Color Matrix
459 ////
460
461 /**
462 * Sets the color matrix to use for the next draw.
463 * @param matrix the 5x4 matrix to apply to the incoming color
464 */
465 void setColorMatrix(const float matrix[20]) {
466 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
467 }
468
469 const float* getColorMatrix() const { return fColorMatrix; }
470
471 /// @}
472
473 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000474 // @name Edge AA
475 // There are two ways to perform antialiasing using edge equations. One
476 // is to specify an (linear or quadratic) edge eq per-vertex. This requires
477 // splitting vertices shared by primitives.
478 //
479 // The other is via setEdgeAAData which sets a set of edges and each
480 // is tested against all the edges.
481 ////
482
483 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000484 * When specifying edges as vertex data this enum specifies what type of
485 * edges are in use. The edges are always 4 GrScalars in memory, even when
486 * the edge type requires fewer than 4.
487 */
488 enum VertexEdgeType {
489 /* 1-pixel wide line
490 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
491 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000492 /* Quadratic specified by u^2-v canonical coords (only 2
493 components used). Coverage based on signed distance with negative
494 being inside, positive outside.*/
495 kQuad_EdgeType,
496 /* Same as above but for hairline quadratics. Uses unsigned distance.
497 Coverage is min(0, 1-distance). */
498 kHairQuad_EdgeType,
499
500 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000501 };
502
503 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000504 * Determines the interpretation per-vertex edge data when the
505 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
506 * are not specified the value of this setting has no effect.
507 */
508 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000509 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000510 fVertexEdgeType = type;
511 }
512
513 VertexEdgeType getVertexEdgeType() const {
514 return fVertexEdgeType;
515 }
516
517 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000518 * The absolute maximum number of edges that may be specified for
519 * a single draw call when performing edge antialiasing. This is used for
520 * the size of several static buffers, so implementations of getMaxEdges()
521 * (below) should clamp to this value.
522 */
523 enum {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000524 // TODO: this should be 32 when GrTesselatedPathRenderer is used
525 // Visual Studio 2010 does not permit a member array of size 0.
526 kMaxEdges = 1
tomhudson@google.com93813632011-10-27 20:21:16 +0000527 };
528
529 class Edge {
530 public:
531 Edge() {}
532 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
533 GrPoint intersect(const Edge& other) {
534 return GrPoint::Make(
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000535 SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
536 (fX * other.fY - other.fX * fY)),
537 SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
538 (other.fX * fY - fX * other.fY)));
tomhudson@google.com93813632011-10-27 20:21:16 +0000539 }
540 float fX, fY, fZ;
541 };
542
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000543 /**
544 * Sets the edge data required for edge antialiasing.
545 *
546 * @param edges 3 * numEdges float values, representing the edge
547 * equations in Ax + By + C form
548 */
549 void setEdgeAAData(const Edge* edges, int numEdges) {
550 GrAssert(numEdges <= GrDrawState::kMaxEdges);
551 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
552 fEdgeAANumEdges = numEdges;
tomhudson@google.com93813632011-10-27 20:21:16 +0000553 }
554
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000555 int getNumAAEdges() const { return fEdgeAANumEdges; }
tomhudson@google.com93813632011-10-27 20:21:16 +0000556
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000557 const Edge* getAAEdges() const { return fEdgeAAEdges; }
tomhudson@google.com62b09682011-11-09 16:39:17 +0000558
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000559 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000560
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000561 ///////////////////////////////////////////////////////////////////////////
562 /// @name State Flags
563 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000564
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000565 /**
566 * Flags that affect rendering. Controlled using enable/disableState(). All
567 * default to disabled.
568 */
569 enum StateBits {
570 /**
571 * Perform dithering. TODO: Re-evaluate whether we need this bit
572 */
573 kDither_StateBit = 0x01,
574 /**
575 * Perform HW anti-aliasing. This means either HW FSAA, if supported
576 * by the render target, or smooth-line rendering if a line primitive
577 * is drawn and line smoothing is supported by the 3D API.
578 */
579 kHWAntialias_StateBit = 0x02,
580 /**
581 * Draws will respect the clip, otherwise the clip is ignored.
582 */
583 kClip_StateBit = 0x04,
584 /**
585 * Disables writing to the color buffer. Useful when performing stencil
586 * operations.
587 */
588 kNoColorWrites_StateBit = 0x08,
589 /**
590 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
591 * will test edge pairs for convexity when rasterizing. Set this if the
592 * source polygon is non-convex.
593 */
594 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000595 /**
596 * Draws will apply the color matrix, otherwise the color matrix is
597 * ignored.
598 */
599 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000600
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000601 // Users of the class may add additional bits to the vector
602 kDummyStateBit,
603 kLastPublicStateBit = kDummyStateBit-1,
604 };
605
606 void resetStateFlags() {
607 fFlagBits = 0;
608 }
609
610 /**
611 * Enable render state settings.
612 *
613 * @param flags bitfield of StateBits specifing the states to enable
614 */
615 void enableState(uint32_t stateBits) {
616 fFlagBits |= stateBits;
617 }
618
619 /**
620 * Disable render state settings.
621 *
622 * @param flags bitfield of StateBits specifing the states to disable
623 */
624 void disableState(uint32_t stateBits) {
625 fFlagBits &= ~(stateBits);
626 }
627
628 bool isDitherState() const {
629 return 0 != (fFlagBits & kDither_StateBit);
630 }
631
632 bool isHWAntialiasState() const {
633 return 0 != (fFlagBits & kHWAntialias_StateBit);
634 }
635
636 bool isClipState() const {
637 return 0 != (fFlagBits & kClip_StateBit);
638 }
639
640 bool isColorWriteDisabled() const {
641 return 0 != (fFlagBits & kNoColorWrites_StateBit);
642 }
643
644 bool isConcaveEdgeAAState() const {
645 return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
646 }
647
648 bool isStateFlagEnabled(uint32_t stateBit) const {
649 return 0 != (stateBit & fFlagBits);
650 }
651
652 void copyStateFlags(const GrDrawState& ds) {
653 fFlagBits = ds.fFlagBits;
654 }
655
656 /// @}
657
658 ///////////////////////////////////////////////////////////////////////////
659 /// @name Face Culling
660 ////
661
662 enum DrawFace {
663 kBoth_DrawFace,
664 kCCW_DrawFace,
665 kCW_DrawFace,
666 };
667
668 /**
669 * Controls whether clockwise, counterclockwise, or both faces are drawn.
670 * @param face the face(s) to draw.
671 */
672 void setDrawFace(DrawFace face) {
673 fDrawFace = face;
674 }
675
676 /**
677 * Gets whether the target is drawing clockwise, counterclockwise,
678 * or both faces.
679 * @return the current draw face(s).
680 */
681 DrawFace getDrawFace() const {
682 return fDrawFace;
683 }
684
685 /// @}
686
687 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000688
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000689 // Most stages are usually not used, so conditionals here
690 // reduce the expected number of bytes touched by 50%.
691 bool operator ==(const GrDrawState& s) const {
692 if (memcmp(this, &s, this->leadingBytes())) return false;
693
694 for (int i = 0; i < kNumStages; i++) {
695 if (fTextures[i] &&
696 memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i],
697 sizeof(GrSamplerState))) {
698 return false;
699 }
700 }
701
702 return true;
703 }
704 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
705
706 // Most stages are usually not used, so conditionals here
707 // reduce the expected number of bytes touched by 50%.
708 GrDrawState& operator =(const GrDrawState& s) {
709 memcpy(this, &s, this->leadingBytes());
710
711 for (int i = 0; i < kNumStages; i++) {
712 if (s.fTextures[i]) {
713 memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i],
714 sizeof(GrSamplerState));
715 }
716 }
717
718 return *this;
719 }
720
721private:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000722 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
723 uint8_t fFlagBits;
724 GrBlendCoeff fSrcBlend : 8;
725 GrBlendCoeff fDstBlend : 8;
726 DrawFace fDrawFace : 8;
727 uint8_t fFirstCoverageStage;
728 SkXfermode::Mode fColorFilterMode : 8;
729 GrColor fBlendConstant;
730 GrTexture* fTextures[kNumStages];
731 GrRenderTarget* fRenderTarget;
732 GrColor fColor;
733 GrColor fColorFilterColor;
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000734 float fColorMatrix[20];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735 GrStencilSettings fStencilSettings;
736 GrMatrix fViewMatrix;
737 // @{ Data for GrTesselatedPathRenderer
738 // TODO: currently ignored in copying & comparison for performance.
739 // Must be considered if GrTesselatedPathRenderer is being used.
740
741 VertexEdgeType fVertexEdgeType;
742 int fEdgeAANumEdges;
743 Edge fEdgeAAEdges[kMaxEdges];
744
745 // @}
746 // This field must be last; it will not be copied or compared
747 // if the corresponding fTexture[] is NULL.
748 GrSamplerState fSamplerStates[kNumStages];
749
tomhudson@google.com62b09682011-11-09 16:39:17 +0000750 size_t leadingBytes() const {
751 // Can't use offsetof() with non-POD types, so stuck with pointer math.
752 // TODO: ignores GrTesselatedPathRenderer data structures. We don't
753 // have a compile-time flag that lets us know if it's being used, and
754 // checking at runtime seems to cost 5% performance.
755 return (size_t) ((unsigned char*)&fEdgeAANumEdges -
756 (unsigned char*)&fFlagBits);
757 }
758
tomhudson@google.com93813632011-10-27 20:21:16 +0000759};
760
761#endif