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