blob: 79d6d483f122c54e43892f2fe0563b855d757934 [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"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000014#include "GrRefCnt.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000015#include "GrSamplerState.h"
16#include "GrStencil.h"
17
18#include "SkXfermode.h"
19
20class GrRenderTarget;
21class GrTexture;
22
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000023class GrDrawState : public GrRefCnt {
tomhudson@google.com93813632011-10-27 20:21:16 +000024
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025public:
tomhudson@google.com93813632011-10-27 20:21:16 +000026 /**
27 * Number of texture stages. Each stage takes as input a color and
28 * 2D texture coordinates. The color input to the first enabled stage is the
29 * per-vertex color or the constant color (setColor/setAlpha) if there are
30 * no per-vertex colors. For subsequent stages the input color is the output
31 * color from the previous enabled stage. The output color of each stage is
32 * the input color modulated with the result of a texture lookup. Texture
33 * lookups are specified by a texture a sampler (setSamplerState). Texture
34 * coordinates for each stage come from the vertices based on a
35 * GrVertexLayout bitfield. The output fragment color is the output color of
36 * the last enabled stage. The presence or absence of texture coordinates
37 * for each stage in the vertex layout indicates whether a stage is enabled
38 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000039 *
40 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
41 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
42 * through kNumStages-1 are earmarked for use by GrTextContext and
43 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000044 */
45 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000046 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000047 kMaxTexCoords = kNumStages
48 };
49
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000050 /**
51 * Bitfield used to indicate a set of stages.
52 */
53 typedef uint32_t StageMask;
54 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
55
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000056 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000057 this->reset();
58 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000059
60 GrDrawState(const GrDrawState& state) {
61 *this = state;
62 }
63
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000064 /**
65 * Resets to the default state. Sampler states will not be modified.
66 */
67 void reset() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000068 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000069 // all GrDrawState members should default to something valid by the
70 // the memset except those initialized individually below. There should
71 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000072 memset(this->podStart(), 0, this->memsetSize());
73
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000074 // pedantic assertion that our ptrs will
75 // be NULL (0 ptr is mem addr 0)
76 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000077 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000078 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079
80 // memset exceptions
81 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000082 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000083 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000084 fColorFilterMode = SkXfermode::kDst_Mode;
85 fSrcBlend = kOne_BlendCoeff;
86 fDstBlend = kZero_BlendCoeff;
87 fViewMatrix.reset();
robertphillips@google.com28b4bce2012-05-04 16:34:52 +000088 fBehaviorBits = 0;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000089
90 // ensure values that will be memcmp'ed in == but not memset in reset()
91 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000092 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +000093 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
bsalomon@google.com8fe84b52012-03-26 15:24:27 +000094 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000095 this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000096 }
97
98 ///////////////////////////////////////////////////////////////////////////
99 /// @name Color
100 ////
101
102 /**
103 * Sets color for next draw to a premultiplied-alpha color.
104 *
105 * @param color the color to set.
106 */
107 void setColor(GrColor color) { fColor = color; }
108
109 GrColor getColor() const { return fColor; }
110
111 /**
112 * Sets the color to be used for the next draw to be
113 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
114 *
115 * @param alpha The alpha value to set as the color.
116 */
117 void setAlpha(uint8_t a) {
118 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
119 }
120
121 /**
122 * Add a color filter that can be represented by a color and a mode. Applied
123 * after color-computing texture stages.
124 */
125 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
126 fColorFilterColor = c;
127 fColorFilterMode = mode;
128 }
129
130 GrColor getColorFilterColor() const { return fColorFilterColor; }
131 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
132
133 /// @}
134
135 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000136 /// @name Coverage
137 ////
138
139 /**
140 * Sets a constant fractional coverage to be applied to the draw. The
141 * initial value (after construction or reset()) is 0xff. The constant
142 * coverage is ignored when per-vertex coverage is provided.
143 */
144 void setCoverage(uint8_t coverage) {
145 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
146 }
147
148 /**
149 * Version of above that specifies 4 channel per-vertex color. The value
150 * should be premultiplied.
151 */
152 void setCoverage4(GrColor coverage) {
153 fCoverage = coverage;
154 }
155
156 GrColor getCoverage() const {
157 return fCoverage;
158 }
159
160 /// @}
161
162 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000163 /// @name Textures
164 ////
165
166 /**
167 * Sets the texture used at the next drawing call
168 *
169 * @param stage The texture stage for which the texture will be set
170 *
171 * @param texture The texture to set. Can be NULL though there is no
172 * advantage to settings a NULL texture if doing non-textured drawing
173 */
174 void setTexture(int stage, GrTexture* texture) {
175 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000176
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000177 if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) {
robertphillips@google.com1942c052012-05-03 17:58:27 +0000178 // If we don't clear out the current texture before unreffing
179 // it we can get into an infinite loop as the GrGLTexture's
180 // onRelease method recursively calls setTexture
181 GrTexture* temp = fTextures[stage];
182 fTextures[stage] = NULL;
183
184 SkSafeRef(texture);
185 SkSafeUnref(temp);
186 }
187
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000188 fTextures[stage] = texture;
189 }
190
191 /**
192 * Retrieves the currently set texture.
193 *
194 * @return The currently set texture. The return value will be NULL if no
195 * texture has been set, NULL was most recently passed to
196 * setTexture, or the last setTexture was destroyed.
197 */
198 const GrTexture* getTexture(int stage) const {
199 GrAssert((unsigned)stage < kNumStages);
200 return fTextures[stage];
201 }
202 GrTexture* getTexture(int stage) {
203 GrAssert((unsigned)stage < kNumStages);
204 return fTextures[stage];
205 }
206
207 /// @}
208
209 ///////////////////////////////////////////////////////////////////////////
210 /// @name Samplers
211 ////
212
213 /**
214 * Returns the current sampler for a stage.
215 */
216 const GrSamplerState& getSampler(int stage) const {
217 GrAssert((unsigned)stage < kNumStages);
218 return fSamplerStates[stage];
219 }
220
221 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000222 * Writable pointer to a stage's sampler.
223 */
224 GrSamplerState* sampler(int stage) {
225 GrAssert((unsigned)stage < kNumStages);
226 return fSamplerStates + stage;
227 }
228
229 /**
230 * Preconcats the matrix of all samplers in the mask with the same matrix.
231 */
232 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
233 GrAssert(!(stageMask & kIllegalStageMaskBits));
234 for (int i = 0; i < kNumStages; ++i) {
235 if ((1 << i) & stageMask) {
236 fSamplerStates[i].preConcatMatrix(matrix);
237 }
238 }
239 }
240
241 /// @}
242
243 ///////////////////////////////////////////////////////////////////////////
244 /// @name Coverage / Color Stages
245 ////
246
247 /**
248 * A common pattern is to compute a color with the initial stages and then
249 * modulate that color by a coverage value in later stage(s) (AA, mask-
250 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
251 * computed based on the pre-coverage-modulated color. The division of
252 * stages between color-computing and coverage-computing is specified by
253 * this method. Initially this is kNumStages (all stages
254 * are color-computing).
255 */
256 void setFirstCoverageStage(int firstCoverageStage) {
257 GrAssert((unsigned)firstCoverageStage <= kNumStages);
258 fFirstCoverageStage = firstCoverageStage;
259 }
260
261 /**
262 * Gets the index of the first coverage-computing stage.
263 */
264 int getFirstCoverageStage() const {
265 return fFirstCoverageStage;
266 }
267
268 ///@}
269
270 ///////////////////////////////////////////////////////////////////////////
271 /// @name Blending
272 ////
273
274 /**
275 * Sets the blending function coeffecients.
276 *
277 * The blend function will be:
278 * D' = sat(S*srcCoef + D*dstCoef)
279 *
280 * where D is the existing destination color, S is the incoming source
281 * color, and D' is the new destination color that will be written. sat()
282 * is the saturation function.
283 *
284 * @param srcCoef coeffecient applied to the src color.
285 * @param dstCoef coeffecient applied to the dst color.
286 */
287 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
288 fSrcBlend = srcCoeff;
289 fDstBlend = dstCoeff;
290 #if GR_DEBUG
291 switch (dstCoeff) {
292 case kDC_BlendCoeff:
293 case kIDC_BlendCoeff:
294 case kDA_BlendCoeff:
295 case kIDA_BlendCoeff:
296 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
297 "coverage stages.\n");
298 break;
299 default:
300 break;
301 }
302 switch (srcCoeff) {
303 case kSC_BlendCoeff:
304 case kISC_BlendCoeff:
305 case kSA_BlendCoeff:
306 case kISA_BlendCoeff:
307 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
308 "coverage stages.\n");
309 break;
310 default:
311 break;
312 }
313 #endif
314 }
315
316 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
317 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
318
319 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
320 GrBlendCoeff* dstBlendCoeff) const {
321 *srcBlendCoeff = fSrcBlend;
322 *dstBlendCoeff = fDstBlend;
323 }
324
325 /**
326 * Sets the blending function constant referenced by the following blending
327 * coeffecients:
328 * kConstC_BlendCoeff
329 * kIConstC_BlendCoeff
330 * kConstA_BlendCoeff
331 * kIConstA_BlendCoeff
332 *
333 * @param constant the constant to set
334 */
335 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
336
337 /**
338 * Retrieves the last value set by setBlendConstant()
339 * @return the blending constant value
340 */
341 GrColor getBlendConstant() const { return fBlendConstant; }
342
343 /// @}
344
345 ///////////////////////////////////////////////////////////////////////////
346 /// @name View Matrix
347 ////
348
349 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000350 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000351 *
352 * In the post-view-matrix space the rectangle [0,w]x[0,h]
353 * fully covers the render target. (w and h are the width and height of the
354 * the rendertarget.)
355 */
356 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
357
358 /**
359 * Gets a writable pointer to the view matrix.
360 */
361 GrMatrix* viewMatrix() { return &fViewMatrix; }
362
363 /**
364 * Multiplies the current view matrix by a matrix
365 *
366 * After this call V' = V*m where V is the old view matrix,
367 * m is the parameter to this function, and V' is the new view matrix.
368 * (We consider positions to be column vectors so position vector p is
369 * transformed by matrix X as p' = X*p.)
370 *
371 * @param m the matrix used to modify the view matrix.
372 */
373 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
374
375 /**
376 * Multiplies the current view matrix by a matrix
377 *
378 * After this call V' = m*V where V is the old view matrix,
379 * m is the parameter to this function, and V' is the new view matrix.
380 * (We consider positions to be column vectors so position vector p is
381 * transformed by matrix X as p' = X*p.)
382 *
383 * @param m the matrix used to modify the view matrix.
384 */
385 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
386
387 /**
388 * Retrieves the current view matrix
389 * @return the current view matrix.
390 */
391 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
392
393 /**
394 * Retrieves the inverse of the current view matrix.
395 *
396 * If the current view matrix is invertible, return true, and if matrix
397 * is non-null, copy the inverse into it. If the current view matrix is
398 * non-invertible, return false and ignore the matrix parameter.
399 *
400 * @param matrix if not null, will receive a copy of the current inverse.
401 */
402 bool getViewInverse(GrMatrix* matrix) const {
403 // TODO: determine whether we really need to leave matrix unmodified
404 // at call sites when inversion fails.
405 GrMatrix inverse;
406 if (fViewMatrix.invert(&inverse)) {
407 if (matrix) {
408 *matrix = inverse;
409 }
410 return true;
411 }
412 return false;
413 }
414
415 class AutoViewMatrixRestore : public ::GrNoncopyable {
416 public:
417 AutoViewMatrixRestore() : fDrawState(NULL) {}
418 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
419 fDrawState = NULL;
420 this->set(ds, newMatrix);
421 }
422 AutoViewMatrixRestore(GrDrawState* ds) {
423 fDrawState = NULL;
424 this->set(ds);
425 }
426 ~AutoViewMatrixRestore() {
427 this->set(NULL, GrMatrix::I());
428 }
429 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
430 if (NULL != fDrawState) {
431 fDrawState->setViewMatrix(fSavedMatrix);
432 }
433 if (NULL != ds) {
434 fSavedMatrix = ds->getViewMatrix();
435 ds->setViewMatrix(newMatrix);
436 }
437 fDrawState = ds;
438 }
439 void set(GrDrawState* ds) {
440 if (NULL != fDrawState) {
441 fDrawState->setViewMatrix(fSavedMatrix);
442 }
443 if (NULL != ds) {
444 fSavedMatrix = ds->getViewMatrix();
445 }
446 fDrawState = ds;
447 }
448 private:
449 GrDrawState* fDrawState;
450 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000451 };
452
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000453 /// @}
454
455 ///////////////////////////////////////////////////////////////////////////
456 /// @name Render Target
457 ////
458
459 /**
460 * Sets the rendertarget used at the next drawing call
461 *
462 * @param target The render target to set.
463 */
464 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
465
466 /**
467 * Retrieves the currently set rendertarget.
468 *
469 * @return The currently set render target.
470 */
471 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
472 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
473
474 class AutoRenderTargetRestore : public ::GrNoncopyable {
475 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000476 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000477 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
478 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000479 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000480 this->set(ds, newTarget);
481 }
482 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
483 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
484 if (NULL != fDrawState) {
485 fDrawState->setRenderTarget(fSavedTarget);
486 }
487 if (NULL != ds) {
488 fSavedTarget = ds->getRenderTarget();
489 ds->setRenderTarget(newTarget);
490 }
491 fDrawState = ds;
492 }
493 private:
494 GrDrawState* fDrawState;
495 GrRenderTarget* fSavedTarget;
496 };
497
498 /// @}
499
500 ///////////////////////////////////////////////////////////////////////////
501 /// @name Stencil
502 ////
503
504 /**
505 * Sets the stencil settings to use for the next draw.
506 * Changing the clip has the side-effect of possibly zeroing
507 * out the client settable stencil bits. So multipass algorithms
508 * using stencil should not change the clip between passes.
509 * @param settings the stencil settings to use.
510 */
511 void setStencil(const GrStencilSettings& settings) {
512 fStencilSettings = settings;
513 }
514
515 /**
516 * Shortcut to disable stencil testing and ops.
517 */
518 void disableStencil() {
519 fStencilSettings.setDisabled();
520 }
521
522 const GrStencilSettings& getStencil() const { return fStencilSettings; }
523
524 GrStencilSettings* stencil() { return &fStencilSettings; }
525
526 /// @}
527
528 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000529 /// @name Color Matrix
530 ////
531
532 /**
533 * Sets the color matrix to use for the next draw.
534 * @param matrix the 5x4 matrix to apply to the incoming color
535 */
536 void setColorMatrix(const float matrix[20]) {
537 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
538 }
539
540 const float* getColorMatrix() const { return fColorMatrix; }
541
542 /// @}
543
544 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000545 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000546 // Edge equations can be specified to perform antialiasing. Because the
547 // edges are specified as per-vertex data, vertices that are shared by
548 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000549 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000550 ////
551
552 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000553 * When specifying edges as vertex data this enum specifies what type of
554 * edges are in use. The edges are always 4 GrScalars in memory, even when
555 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000556 *
557 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
558 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000559 */
560 enum VertexEdgeType {
561 /* 1-pixel wide line
562 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
563 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000564 /* Quadratic specified by u^2-v canonical coords (only 2
565 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000566 being inside, positive outside. Edge specified in window space
567 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000568 kQuad_EdgeType,
569 /* Same as above but for hairline quadratics. Uses unsigned distance.
570 Coverage is min(0, 1-distance). */
571 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000572 /* Circle specified as center_x, center_y, outer_radius, inner_radius
573 all in window space (y-down). */
574 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000575
576 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000577 };
578
579 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580 * Determines the interpretation per-vertex edge data when the
581 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
582 * are not specified the value of this setting has no effect.
583 */
584 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000585 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000586 fVertexEdgeType = type;
587 }
588
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000589 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000590
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000592
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000593 ///////////////////////////////////////////////////////////////////////////
594 /// @name State Flags
595 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000596
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000597 /**
598 * Flags that affect rendering. Controlled using enable/disableState(). All
599 * default to disabled.
600 */
601 enum StateBits {
602 /**
603 * Perform dithering. TODO: Re-evaluate whether we need this bit
604 */
605 kDither_StateBit = 0x01,
606 /**
607 * Perform HW anti-aliasing. This means either HW FSAA, if supported
608 * by the render target, or smooth-line rendering if a line primitive
609 * is drawn and line smoothing is supported by the 3D API.
610 */
611 kHWAntialias_StateBit = 0x02,
612 /**
613 * Draws will respect the clip, otherwise the clip is ignored.
614 */
615 kClip_StateBit = 0x04,
616 /**
617 * Disables writing to the color buffer. Useful when performing stencil
618 * operations.
619 */
620 kNoColorWrites_StateBit = 0x08,
621 /**
622 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
623 * will test edge pairs for convexity when rasterizing. Set this if the
624 * source polygon is non-convex.
625 */
626 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000627 /**
628 * Draws will apply the color matrix, otherwise the color matrix is
629 * ignored.
630 */
631 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000632
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 // Users of the class may add additional bits to the vector
634 kDummyStateBit,
635 kLastPublicStateBit = kDummyStateBit-1,
636 };
637
638 void resetStateFlags() {
639 fFlagBits = 0;
640 }
641
642 /**
643 * Enable render state settings.
644 *
645 * @param flags bitfield of StateBits specifing the states to enable
646 */
647 void enableState(uint32_t stateBits) {
648 fFlagBits |= stateBits;
649 }
650
651 /**
652 * Disable render state settings.
653 *
654 * @param flags bitfield of StateBits specifing the states to disable
655 */
656 void disableState(uint32_t stateBits) {
657 fFlagBits &= ~(stateBits);
658 }
659
660 bool isDitherState() const {
661 return 0 != (fFlagBits & kDither_StateBit);
662 }
663
664 bool isHWAntialiasState() const {
665 return 0 != (fFlagBits & kHWAntialias_StateBit);
666 }
667
668 bool isClipState() const {
669 return 0 != (fFlagBits & kClip_StateBit);
670 }
671
672 bool isColorWriteDisabled() const {
673 return 0 != (fFlagBits & kNoColorWrites_StateBit);
674 }
675
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000676 bool isStateFlagEnabled(uint32_t stateBit) const {
677 return 0 != (stateBit & fFlagBits);
678 }
679
680 void copyStateFlags(const GrDrawState& ds) {
681 fFlagBits = ds.fFlagBits;
682 }
683
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000684 /**
685 * Flags that do not affect rendering.
686 */
687 enum GrBehaviorBits {
688 /**
689 * Calls to setTexture will ref/unref the texture
690 */
691 kTexturesNeedRef_BehaviorBit = 0x01,
692 };
693
694 void enableBehavior(uint32_t behaviorBits) {
695 fBehaviorBits |= behaviorBits;
696 }
697
698 void disableBehavior(uint32_t behaviorBits) {
699 fBehaviorBits &= ~(behaviorBits);
700 }
701
702 bool isBehaviorEnabled(uint32_t behaviorBits) const {
703 return 0 != (behaviorBits & fBehaviorBits);
704 }
705
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000706 /// @}
707
708 ///////////////////////////////////////////////////////////////////////////
709 /// @name Face Culling
710 ////
711
712 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000713 kInvalid_DrawFace = -1,
714
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000715 kBoth_DrawFace,
716 kCCW_DrawFace,
717 kCW_DrawFace,
718 };
719
720 /**
721 * Controls whether clockwise, counterclockwise, or both faces are drawn.
722 * @param face the face(s) to draw.
723 */
724 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000725 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000726 fDrawFace = face;
727 }
728
729 /**
730 * Gets whether the target is drawing clockwise, counterclockwise,
731 * or both faces.
732 * @return the current draw face(s).
733 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000734 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735
736 /// @}
737
738 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000739
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000740 // Most stages are usually not used, so conditionals here
741 // reduce the expected number of bytes touched by 50%.
742 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000743 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000744 return false;
745 }
746
747 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
748 return false;
749 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000750
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000751 // kTexturesNeedRef is an internal flag for altering the draw state's
752 // behavior rather than a property that will impact drawing - ignore it
753 // here
754 if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
755 (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
756 return false;
757 }
758
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000759 for (int i = 0; i < kNumStages; i++) {
760 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000761 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000762 return false;
763 }
764 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000765 if (kColorMatrix_StateBit & s.fFlagBits) {
766 if (memcmp(fColorMatrix,
767 s.fColorMatrix,
768 sizeof(fColorMatrix))) {
769 return false;
770 }
771 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000772
773 return true;
774 }
775 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
776
777 // Most stages are usually not used, so conditionals here
778 // reduce the expected number of bytes touched by 50%.
779 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000780 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000781
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000782 fViewMatrix = s.fViewMatrix;
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000783 fBehaviorBits = s.fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000784
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000785 for (int i = 0; i < kNumStages; i++) {
786 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000787 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000788 }
789 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000790 if (kColorMatrix_StateBit & s.fFlagBits) {
791 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
792 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000793
794 return *this;
795 }
796
797private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000798
799 const void* podStart() const {
800 return reinterpret_cast<const void*>(&fPodStartMarker);
801 }
802 void* podStart() {
803 return reinterpret_cast<void*>(&fPodStartMarker);
804 }
805 size_t memsetSize() const {
806 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
807 reinterpret_cast<size_t>(&fPodStartMarker) +
808 sizeof(fMemsetEndMarker);
809 }
810 size_t podSize() const {
811 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000812 return reinterpret_cast<size_t>(&fPodEndMarker) -
813 reinterpret_cast<size_t>(&fPodStartMarker) +
814 sizeof(fPodEndMarker);
815 }
816
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000817 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000818 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000819 union {
820 GrColor fBlendConstant;
821 GrColor fPodStartMarker;
822 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000823 GrTexture* fTextures[kNumStages];
824 GrColor fColorFilterColor;
825 uint32_t fFlagBits;
826 DrawFace fDrawFace;
827 VertexEdgeType fVertexEdgeType;
828 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000829 union {
830 GrRenderTarget* fRenderTarget;
831 GrRenderTarget* fMemsetEndMarker;
832 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000833 // @}
834
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000835 // @{ Initialized to values other than zero, but memcmp'ed in operator==
836 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000837 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000838 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000839 int fFirstCoverageStage;
840 SkXfermode::Mode fColorFilterMode;
841 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000842 union {
843 GrBlendCoeff fDstBlend;
844 GrBlendCoeff fPodEndMarker;
845 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000846 // @}
847
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000848 uint32_t fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000849 GrMatrix fViewMatrix;
850
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000851 // This field must be last; it will not be copied or compared
852 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000853 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000854 // only compared if the color matrix enable flag is set
855 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000856
tomhudson@google.com93813632011-10-27 20:21:16 +0000857};
858
859#endif