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