blob: 7526b9fe4f190a5e96d521c90e9a2cbf798b85dc [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 /**
152 * Sets the sampler. This will be removed soon in favor of direct access.
153 */
154 void setSampler(int stage, const GrSamplerState& sampler) {
155 GrAssert((unsigned)stage < kNumStages);
156 fSamplerStates[stage] = sampler;
157 }
158
159 /**
160 * Writable pointer to a stage's sampler.
161 */
162 GrSamplerState* sampler(int stage) {
163 GrAssert((unsigned)stage < kNumStages);
164 return fSamplerStates + stage;
165 }
166
167 /**
168 * Preconcats the matrix of all samplers in the mask with the same matrix.
169 */
170 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
171 GrAssert(!(stageMask & kIllegalStageMaskBits));
172 for (int i = 0; i < kNumStages; ++i) {
173 if ((1 << i) & stageMask) {
174 fSamplerStates[i].preConcatMatrix(matrix);
175 }
176 }
177 }
178
179 /// @}
180
181 ///////////////////////////////////////////////////////////////////////////
182 /// @name Coverage / Color Stages
183 ////
184
185 /**
186 * A common pattern is to compute a color with the initial stages and then
187 * modulate that color by a coverage value in later stage(s) (AA, mask-
188 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
189 * computed based on the pre-coverage-modulated color. The division of
190 * stages between color-computing and coverage-computing is specified by
191 * this method. Initially this is kNumStages (all stages
192 * are color-computing).
193 */
194 void setFirstCoverageStage(int firstCoverageStage) {
195 GrAssert((unsigned)firstCoverageStage <= kNumStages);
196 fFirstCoverageStage = firstCoverageStage;
197 }
198
199 /**
200 * Gets the index of the first coverage-computing stage.
201 */
202 int getFirstCoverageStage() const {
203 return fFirstCoverageStage;
204 }
205
206 ///@}
207
208 ///////////////////////////////////////////////////////////////////////////
209 /// @name Blending
210 ////
211
212 /**
213 * Sets the blending function coeffecients.
214 *
215 * The blend function will be:
216 * D' = sat(S*srcCoef + D*dstCoef)
217 *
218 * where D is the existing destination color, S is the incoming source
219 * color, and D' is the new destination color that will be written. sat()
220 * is the saturation function.
221 *
222 * @param srcCoef coeffecient applied to the src color.
223 * @param dstCoef coeffecient applied to the dst color.
224 */
225 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
226 fSrcBlend = srcCoeff;
227 fDstBlend = dstCoeff;
228 #if GR_DEBUG
229 switch (dstCoeff) {
230 case kDC_BlendCoeff:
231 case kIDC_BlendCoeff:
232 case kDA_BlendCoeff:
233 case kIDA_BlendCoeff:
234 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
235 "coverage stages.\n");
236 break;
237 default:
238 break;
239 }
240 switch (srcCoeff) {
241 case kSC_BlendCoeff:
242 case kISC_BlendCoeff:
243 case kSA_BlendCoeff:
244 case kISA_BlendCoeff:
245 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
246 "coverage stages.\n");
247 break;
248 default:
249 break;
250 }
251 #endif
252 }
253
254 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
255 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
256
257 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
258 GrBlendCoeff* dstBlendCoeff) const {
259 *srcBlendCoeff = fSrcBlend;
260 *dstBlendCoeff = fDstBlend;
261 }
262
263 /**
264 * Sets the blending function constant referenced by the following blending
265 * coeffecients:
266 * kConstC_BlendCoeff
267 * kIConstC_BlendCoeff
268 * kConstA_BlendCoeff
269 * kIConstA_BlendCoeff
270 *
271 * @param constant the constant to set
272 */
273 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
274
275 /**
276 * Retrieves the last value set by setBlendConstant()
277 * @return the blending constant value
278 */
279 GrColor getBlendConstant() const { return fBlendConstant; }
280
281 /// @}
282
283 ///////////////////////////////////////////////////////////////////////////
284 /// @name View Matrix
285 ////
286
287 /**
288 * Sets the matrix applied to veretx positions.
289 *
290 * In the post-view-matrix space the rectangle [0,w]x[0,h]
291 * fully covers the render target. (w and h are the width and height of the
292 * the rendertarget.)
293 */
294 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
295
296 /**
297 * Gets a writable pointer to the view matrix.
298 */
299 GrMatrix* viewMatrix() { return &fViewMatrix; }
300
301 /**
302 * Multiplies the current view matrix by a matrix
303 *
304 * After this call V' = V*m where V is the old view matrix,
305 * m is the parameter to this function, and V' is the new view matrix.
306 * (We consider positions to be column vectors so position vector p is
307 * transformed by matrix X as p' = X*p.)
308 *
309 * @param m the matrix used to modify the view matrix.
310 */
311 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
312
313 /**
314 * Multiplies the current view matrix by a matrix
315 *
316 * After this call V' = m*V where V is the old view matrix,
317 * m is the parameter to this function, and V' is the new view matrix.
318 * (We consider positions to be column vectors so position vector p is
319 * transformed by matrix X as p' = X*p.)
320 *
321 * @param m the matrix used to modify the view matrix.
322 */
323 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
324
325 /**
326 * Retrieves the current view matrix
327 * @return the current view matrix.
328 */
329 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
330
331 /**
332 * Retrieves the inverse of the current view matrix.
333 *
334 * If the current view matrix is invertible, return true, and if matrix
335 * is non-null, copy the inverse into it. If the current view matrix is
336 * non-invertible, return false and ignore the matrix parameter.
337 *
338 * @param matrix if not null, will receive a copy of the current inverse.
339 */
340 bool getViewInverse(GrMatrix* matrix) const {
341 // TODO: determine whether we really need to leave matrix unmodified
342 // at call sites when inversion fails.
343 GrMatrix inverse;
344 if (fViewMatrix.invert(&inverse)) {
345 if (matrix) {
346 *matrix = inverse;
347 }
348 return true;
349 }
350 return false;
351 }
352
353 class AutoViewMatrixRestore : public ::GrNoncopyable {
354 public:
355 AutoViewMatrixRestore() : fDrawState(NULL) {}
356 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
357 fDrawState = NULL;
358 this->set(ds, newMatrix);
359 }
360 AutoViewMatrixRestore(GrDrawState* ds) {
361 fDrawState = NULL;
362 this->set(ds);
363 }
364 ~AutoViewMatrixRestore() {
365 this->set(NULL, GrMatrix::I());
366 }
367 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
368 if (NULL != fDrawState) {
369 fDrawState->setViewMatrix(fSavedMatrix);
370 }
371 if (NULL != ds) {
372 fSavedMatrix = ds->getViewMatrix();
373 ds->setViewMatrix(newMatrix);
374 }
375 fDrawState = ds;
376 }
377 void set(GrDrawState* ds) {
378 if (NULL != fDrawState) {
379 fDrawState->setViewMatrix(fSavedMatrix);
380 }
381 if (NULL != ds) {
382 fSavedMatrix = ds->getViewMatrix();
383 }
384 fDrawState = ds;
385 }
386 private:
387 GrDrawState* fDrawState;
388 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000389 };
390
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000391 /// @}
392
393 ///////////////////////////////////////////////////////////////////////////
394 /// @name Render Target
395 ////
396
397 /**
398 * Sets the rendertarget used at the next drawing call
399 *
400 * @param target The render target to set.
401 */
402 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
403
404 /**
405 * Retrieves the currently set rendertarget.
406 *
407 * @return The currently set render target.
408 */
409 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
410 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
411
412 class AutoRenderTargetRestore : public ::GrNoncopyable {
413 public:
414 AutoRenderTargetRestore() : fDrawState(NULL) {}
415 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
416 fDrawState = NULL;
417 this->set(ds, newTarget);
418 }
419 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
420 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
421 if (NULL != fDrawState) {
422 fDrawState->setRenderTarget(fSavedTarget);
423 }
424 if (NULL != ds) {
425 fSavedTarget = ds->getRenderTarget();
426 ds->setRenderTarget(newTarget);
427 }
428 fDrawState = ds;
429 }
430 private:
431 GrDrawState* fDrawState;
432 GrRenderTarget* fSavedTarget;
433 };
434
435 /// @}
436
437 ///////////////////////////////////////////////////////////////////////////
438 /// @name Stencil
439 ////
440
441 /**
442 * Sets the stencil settings to use for the next draw.
443 * Changing the clip has the side-effect of possibly zeroing
444 * out the client settable stencil bits. So multipass algorithms
445 * using stencil should not change the clip between passes.
446 * @param settings the stencil settings to use.
447 */
448 void setStencil(const GrStencilSettings& settings) {
449 fStencilSettings = settings;
450 }
451
452 /**
453 * Shortcut to disable stencil testing and ops.
454 */
455 void disableStencil() {
456 fStencilSettings.setDisabled();
457 }
458
459 const GrStencilSettings& getStencil() const { return fStencilSettings; }
460
461 GrStencilSettings* stencil() { return &fStencilSettings; }
462
463 /// @}
464
465 ///////////////////////////////////////////////////////////////////////////
466 // @name Edge AA
467 // There are two ways to perform antialiasing using edge equations. One
468 // is to specify an (linear or quadratic) edge eq per-vertex. This requires
469 // splitting vertices shared by primitives.
470 //
471 // The other is via setEdgeAAData which sets a set of edges and each
472 // is tested against all the edges.
473 ////
474
475 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000476 * When specifying edges as vertex data this enum specifies what type of
477 * edges are in use. The edges are always 4 GrScalars in memory, even when
478 * the edge type requires fewer than 4.
479 */
480 enum VertexEdgeType {
481 /* 1-pixel wide line
482 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
483 kHairLine_EdgeType,
484 /* 1-pixel wide quadratic
485 u^2-v canonical coords (only 2 components used) */
486 kHairQuad_EdgeType
487 };
488
489 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000490 * Determines the interpretation per-vertex edge data when the
491 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
492 * are not specified the value of this setting has no effect.
493 */
494 void setVertexEdgeType(VertexEdgeType type) {
495 fVertexEdgeType = type;
496 }
497
498 VertexEdgeType getVertexEdgeType() const {
499 return fVertexEdgeType;
500 }
501
502 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000503 * The absolute maximum number of edges that may be specified for
504 * a single draw call when performing edge antialiasing. This is used for
505 * the size of several static buffers, so implementations of getMaxEdges()
506 * (below) should clamp to this value.
507 */
508 enum {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000509 // TODO: this should be 32 when GrTesselatedPathRenderer is used
510 // Visual Studio 2010 does not permit a member array of size 0.
511 kMaxEdges = 1
tomhudson@google.com93813632011-10-27 20:21:16 +0000512 };
513
514 class Edge {
515 public:
516 Edge() {}
517 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
518 GrPoint intersect(const Edge& other) {
519 return GrPoint::Make(
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000520 SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
521 (fX * other.fY - other.fX * fY)),
522 SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
523 (other.fX * fY - fX * other.fY)));
tomhudson@google.com93813632011-10-27 20:21:16 +0000524 }
525 float fX, fY, fZ;
526 };
527
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000528 /**
529 * Sets the edge data required for edge antialiasing.
530 *
531 * @param edges 3 * numEdges float values, representing the edge
532 * equations in Ax + By + C form
533 */
534 void setEdgeAAData(const Edge* edges, int numEdges) {
535 GrAssert(numEdges <= GrDrawState::kMaxEdges);
536 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
537 fEdgeAANumEdges = numEdges;
tomhudson@google.com93813632011-10-27 20:21:16 +0000538 }
539
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 int getNumAAEdges() const { return fEdgeAANumEdges; }
tomhudson@google.com93813632011-10-27 20:21:16 +0000541
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000542 const Edge* getAAEdges() const { return fEdgeAAEdges; }
tomhudson@google.com62b09682011-11-09 16:39:17 +0000543
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000544 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000545
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000546 ///////////////////////////////////////////////////////////////////////////
547 /// @name State Flags
548 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000549
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000550 /**
551 * Flags that affect rendering. Controlled using enable/disableState(). All
552 * default to disabled.
553 */
554 enum StateBits {
555 /**
556 * Perform dithering. TODO: Re-evaluate whether we need this bit
557 */
558 kDither_StateBit = 0x01,
559 /**
560 * Perform HW anti-aliasing. This means either HW FSAA, if supported
561 * by the render target, or smooth-line rendering if a line primitive
562 * is drawn and line smoothing is supported by the 3D API.
563 */
564 kHWAntialias_StateBit = 0x02,
565 /**
566 * Draws will respect the clip, otherwise the clip is ignored.
567 */
568 kClip_StateBit = 0x04,
569 /**
570 * Disables writing to the color buffer. Useful when performing stencil
571 * operations.
572 */
573 kNoColorWrites_StateBit = 0x08,
574 /**
575 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
576 * will test edge pairs for convexity when rasterizing. Set this if the
577 * source polygon is non-convex.
578 */
579 kEdgeAAConcave_StateBit = 0x10,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000580
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000581 // Users of the class may add additional bits to the vector
582 kDummyStateBit,
583 kLastPublicStateBit = kDummyStateBit-1,
584 };
585
586 void resetStateFlags() {
587 fFlagBits = 0;
588 }
589
590 /**
591 * Enable render state settings.
592 *
593 * @param flags bitfield of StateBits specifing the states to enable
594 */
595 void enableState(uint32_t stateBits) {
596 fFlagBits |= stateBits;
597 }
598
599 /**
600 * Disable render state settings.
601 *
602 * @param flags bitfield of StateBits specifing the states to disable
603 */
604 void disableState(uint32_t stateBits) {
605 fFlagBits &= ~(stateBits);
606 }
607
608 bool isDitherState() const {
609 return 0 != (fFlagBits & kDither_StateBit);
610 }
611
612 bool isHWAntialiasState() const {
613 return 0 != (fFlagBits & kHWAntialias_StateBit);
614 }
615
616 bool isClipState() const {
617 return 0 != (fFlagBits & kClip_StateBit);
618 }
619
620 bool isColorWriteDisabled() const {
621 return 0 != (fFlagBits & kNoColorWrites_StateBit);
622 }
623
624 bool isConcaveEdgeAAState() const {
625 return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
626 }
627
628 bool isStateFlagEnabled(uint32_t stateBit) const {
629 return 0 != (stateBit & fFlagBits);
630 }
631
632 void copyStateFlags(const GrDrawState& ds) {
633 fFlagBits = ds.fFlagBits;
634 }
635
636 /// @}
637
638 ///////////////////////////////////////////////////////////////////////////
639 /// @name Face Culling
640 ////
641
642 enum DrawFace {
643 kBoth_DrawFace,
644 kCCW_DrawFace,
645 kCW_DrawFace,
646 };
647
648 /**
649 * Controls whether clockwise, counterclockwise, or both faces are drawn.
650 * @param face the face(s) to draw.
651 */
652 void setDrawFace(DrawFace face) {
653 fDrawFace = face;
654 }
655
656 /**
657 * Gets whether the target is drawing clockwise, counterclockwise,
658 * or both faces.
659 * @return the current draw face(s).
660 */
661 DrawFace getDrawFace() const {
662 return fDrawFace;
663 }
664
665 /// @}
666
667 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000668
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000669 // Most stages are usually not used, so conditionals here
670 // reduce the expected number of bytes touched by 50%.
671 bool operator ==(const GrDrawState& s) const {
672 if (memcmp(this, &s, this->leadingBytes())) return false;
673
674 for (int i = 0; i < kNumStages; i++) {
675 if (fTextures[i] &&
676 memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i],
677 sizeof(GrSamplerState))) {
678 return false;
679 }
680 }
681
682 return true;
683 }
684 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
685
686 // Most stages are usually not used, so conditionals here
687 // reduce the expected number of bytes touched by 50%.
688 GrDrawState& operator =(const GrDrawState& s) {
689 memcpy(this, &s, this->leadingBytes());
690
691 for (int i = 0; i < kNumStages; i++) {
692 if (s.fTextures[i]) {
693 memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i],
694 sizeof(GrSamplerState));
695 }
696 }
697
698 return *this;
699 }
700
701private:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000702 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
703 uint8_t fFlagBits;
704 GrBlendCoeff fSrcBlend : 8;
705 GrBlendCoeff fDstBlend : 8;
706 DrawFace fDrawFace : 8;
707 uint8_t fFirstCoverageStage;
708 SkXfermode::Mode fColorFilterMode : 8;
709 GrColor fBlendConstant;
710 GrTexture* fTextures[kNumStages];
711 GrRenderTarget* fRenderTarget;
712 GrColor fColor;
713 GrColor fColorFilterColor;
714 GrStencilSettings fStencilSettings;
715 GrMatrix fViewMatrix;
716 // @{ Data for GrTesselatedPathRenderer
717 // TODO: currently ignored in copying & comparison for performance.
718 // Must be considered if GrTesselatedPathRenderer is being used.
719
720 VertexEdgeType fVertexEdgeType;
721 int fEdgeAANumEdges;
722 Edge fEdgeAAEdges[kMaxEdges];
723
724 // @}
725 // This field must be last; it will not be copied or compared
726 // if the corresponding fTexture[] is NULL.
727 GrSamplerState fSamplerStates[kNumStages];
728
tomhudson@google.com62b09682011-11-09 16:39:17 +0000729 size_t leadingBytes() const {
730 // Can't use offsetof() with non-POD types, so stuck with pointer math.
731 // TODO: ignores GrTesselatedPathRenderer data structures. We don't
732 // have a compile-time flag that lets us know if it's being used, and
733 // checking at runtime seems to cost 5% performance.
734 return (size_t) ((unsigned char*)&fEdgeAANumEdges -
735 (unsigned char*)&fFlagBits);
736 }
737
tomhudson@google.com93813632011-10-27 20:21:16 +0000738};
739
740#endif